1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qvncclient.h"
41 #include "qvnc_p.h"
42 
43 #include <QtNetwork/QTcpSocket>
44 #include <QtCore/QCoreApplication>
45 
46 #include <qpa/qwindowsysteminterface.h>
47 #include <QtGui/qguiapplication.h>
48 
49 #ifdef Q_OS_WIN
50 #include <Winsock2.h>
51 #else
52 #include <arpa/inet.h>
53 #endif
54 
55 QT_BEGIN_NAMESPACE
56 
QVncClient(QTcpSocket * clientSocket,QVncServer * server)57 QVncClient::QVncClient(QTcpSocket *clientSocket, QVncServer *server)
58     : QObject(server)
59     , m_server(server)
60     , m_clientSocket(clientSocket)
61     , m_encoder(nullptr)
62     , m_msgType(0)
63     , m_handleMsg(false)
64     , m_encodingsPending(0)
65     , m_cutTextPending(0)
66     , m_supportHextile(false)
67     , m_wantUpdate(false)
68     , m_dirtyCursor(false)
69     , m_updatePending(false)
70     , m_protocolVersion(V3_3)
71 {
72     connect(m_clientSocket,SIGNAL(readyRead()),this,SLOT(readClient()));
73     connect(m_clientSocket,SIGNAL(disconnected()),this,SLOT(discardClient()));
74 
75     // send protocol version
76     const char *proto = "RFB 003.003\n";
77     m_clientSocket->write(proto, 12);
78     m_state = Protocol;
79 }
80 
~QVncClient()81 QVncClient::~QVncClient()
82 {
83     delete m_encoder;
84 }
85 
clientSocket() const86 QTcpSocket *QVncClient::clientSocket() const
87 {
88     return m_clientSocket;
89 }
90 
setDirty(const QRegion & region)91 void QVncClient::setDirty(const QRegion &region)
92 {
93     m_dirtyRegion += region;
94     if (m_state == Connected &&
95         ((m_server->dirtyMap()->numDirty > 0) || m_dirtyCursor)) {
96         scheduleUpdate();
97     }
98 }
99 
convertPixels(char * dst,const char * src,int count) const100 void QVncClient::convertPixels(char *dst, const char *src, int count) const
101 {
102     const int screendepth = m_server->screen()->depth();
103 
104     // cutoffs
105 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
106     if (!m_swapBytes)
107 #endif
108     if (m_sameEndian) {
109         if (screendepth == m_pixelFormat.bitsPerPixel) { // memcpy cutoffs
110 
111             switch (screendepth) {
112             case 32:
113                 memcpy(dst, src, count * sizeof(quint32));
114                 return;
115             case 16:
116                 if (m_pixelFormat.redBits == 5
117                     && m_pixelFormat.greenBits == 6
118                     && m_pixelFormat.blueBits == 5)
119                 {
120                     memcpy(dst, src, count * sizeof(quint16));
121                     return;
122                 }
123             }
124         }
125     }
126 
127     const int bytesPerPixel = (m_pixelFormat.bitsPerPixel + 7) / 8;
128 
129     for (int i = 0; i < count; ++i) {
130         int r, g, b;
131 
132         switch (screendepth) {
133         case 8: {
134             QRgb rgb = m_server->screen()->image()->colorTable()[int(*src)];
135             r = qRed(rgb);
136             g = qGreen(rgb);
137             b = qBlue(rgb);
138             src++;
139             break;
140         }
141         case 16: {
142             quint16 p = *reinterpret_cast<const quint16*>(src);
143 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
144             if (m_swapBytes)
145                 p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8);
146 #endif
147             r = (p >> 11) & 0x1f;
148             g = (p >> 5) & 0x3f;
149             b = p & 0x1f;
150             r <<= 3;
151             g <<= 2;
152             b <<= 3;
153             src += sizeof(quint16);
154             break;
155         }
156         case 32: {
157             quint32 p = *reinterpret_cast<const quint32*>(src);
158             r = (p >> 16) & 0xff;
159             g = (p >> 8) & 0xff;
160             b = p & 0xff;
161             src += sizeof(quint32);
162             break;
163         }
164         default: {
165             r = g = b = 0;
166             qWarning("QVNCServer: don't support %dbpp display", screendepth);
167             return;
168         }
169         }
170 
171 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
172         if (m_swapBytes)
173             qSwap(r, b);
174 #endif
175 
176         r >>= (8 - m_pixelFormat.redBits);
177         g >>= (8 - m_pixelFormat.greenBits);
178         b >>= (8 - m_pixelFormat.blueBits);
179 
180         int pixel = (r << m_pixelFormat.redShift) |
181                     (g << m_pixelFormat.greenShift) |
182                     (b << m_pixelFormat.blueShift);
183 
184         if (m_sameEndian || m_pixelFormat.bitsPerPixel == 8) {
185             memcpy(dst, &pixel, bytesPerPixel);
186             dst += bytesPerPixel;
187             continue;
188         }
189 
190 
191         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
192             switch (m_pixelFormat.bitsPerPixel) {
193             case 16:
194                 pixel = (((pixel & 0x0000ff00) << 8)  |
195                          ((pixel & 0x000000ff) << 24));
196                 break;
197             case 32:
198                 pixel = (((pixel & 0xff000000) >> 24) |
199                          ((pixel & 0x00ff0000) >> 8)  |
200                          ((pixel & 0x0000ff00) << 8)  |
201                          ((pixel & 0x000000ff) << 24));
202                 break;
203             default:
204                 qWarning("Cannot handle %d bpp client", m_pixelFormat.bitsPerPixel);
205             }
206         } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian
207             switch (m_pixelFormat.bitsPerPixel) {
208             case 16:
209                 pixel = (((pixel & 0xff000000) >> 8) |
210                          ((pixel & 0x00ff0000) << 8));
211                 break;
212             case 32:
213                 pixel = (((pixel & 0xff000000) >> 24) |
214                          ((pixel & 0x00ff0000) >> 8)  |
215                          ((pixel & 0x0000ff00) << 8)  |
216                          ((pixel & 0x000000ff) << 24));
217                 break;
218             default:
219                 qWarning("Cannot handle %d bpp client",
220                        m_pixelFormat.bitsPerPixel);
221                 break;
222             }
223         }
224         memcpy(dst, &pixel, bytesPerPixel);
225         dst += bytesPerPixel;
226     }
227 }
228 
readClient()229 void QVncClient::readClient()
230 {
231     qCDebug(lcVnc) << "readClient" << m_state;
232     switch (m_state) {
233         case Disconnected:
234 
235             break;
236         case Protocol:
237             if (m_clientSocket->bytesAvailable() >= 12) {
238                 char proto[13];
239                 m_clientSocket->read(proto, 12);
240                 proto[12] = '\0';
241                 qCDebug(lcVnc, "Client protocol version %s", proto);
242                 if (!strcmp(proto, "RFB 003.008\n")) {
243                     m_protocolVersion = V3_8;
244                 } else if (!strcmp(proto, "RFB 003.007\n")) {
245                     m_protocolVersion = V3_7;
246                 } else {
247                     m_protocolVersion = V3_3;
248                 }
249 
250                 if (m_protocolVersion == V3_3) {
251                     // No authentication
252                     quint32 auth = htonl(1);
253                     m_clientSocket->write((char *) &auth, sizeof(auth));
254                     m_state = Init;
255                 }
256             }
257             break;
258         case Authentication:
259 
260             break;
261         case Init:
262             if (m_clientSocket->bytesAvailable() >= 1) {
263                 quint8 shared;
264                 m_clientSocket->read((char *) &shared, 1);
265 
266                 // Server Init msg
267                 QRfbServerInit sim;
268                 QRfbPixelFormat &format = sim.format;
269                 switch (m_server->screen()->depth()) {
270                 case 32:
271                     format.bitsPerPixel = 32;
272                     format.depth = 32;
273                     format.bigEndian = 0;
274                     format.trueColor = true;
275                     format.redBits = 8;
276                     format.greenBits = 8;
277                     format.blueBits = 8;
278                     format.redShift = 16;
279                     format.greenShift = 8;
280                     format.blueShift = 0;
281                     break;
282 
283                 case 24:
284                     format.bitsPerPixel = 24;
285                     format.depth = 24;
286                     format.bigEndian = 0;
287                     format.trueColor = true;
288                     format.redBits = 8;
289                     format.greenBits = 8;
290                     format.blueBits = 8;
291                     format.redShift = 16;
292                     format.greenShift = 8;
293                     format.blueShift = 0;
294                     break;
295 
296                 case 18:
297                     format.bitsPerPixel = 24;
298                     format.depth = 18;
299                     format.bigEndian = 0;
300                     format.trueColor = true;
301                     format.redBits = 6;
302                     format.greenBits = 6;
303                     format.blueBits = 6;
304                     format.redShift = 12;
305                     format.greenShift = 6;
306                     format.blueShift = 0;
307                     break;
308 
309                 case 16:
310                     format.bitsPerPixel = 16;
311                     format.depth = 16;
312                     format.bigEndian = 0;
313                     format.trueColor = true;
314                     format.redBits = 5;
315                     format.greenBits = 6;
316                     format.blueBits = 5;
317                     format.redShift = 11;
318                     format.greenShift = 5;
319                     format.blueShift = 0;
320                     break;
321 
322                 case 15:
323                     format.bitsPerPixel = 16;
324                     format.depth = 15;
325                     format.bigEndian = 0;
326                     format.trueColor = true;
327                     format.redBits = 5;
328                     format.greenBits = 5;
329                     format.blueBits = 5;
330                     format.redShift = 10;
331                     format.greenShift = 5;
332                     format.blueShift = 0;
333                     break;
334 
335                 case 12:
336                     format.bitsPerPixel = 16;
337                     format.depth = 12;
338                     format.bigEndian = 0;
339                     format.trueColor = true;
340                     format.redBits = 4;
341                     format.greenBits = 4;
342                     format.blueBits = 4;
343                     format.redShift = 8;
344                     format.greenShift = 4;
345                     format.blueShift = 0;
346                     break;
347 
348                 case 8:
349                 case 4:
350                     format.bitsPerPixel = 8;
351                     format.depth = 8;
352                     format.bigEndian = 0;
353                     format.trueColor = false;
354                     format.redBits = 0;
355                     format.greenBits = 0;
356                     format.blueBits = 0;
357                     format.redShift = 0;
358                     format.greenShift = 0;
359                     format.blueShift = 0;
360                     break;
361 
362                 default:
363                     qWarning("QVNC cannot drive depth %d", m_server->screen()->depth());
364                     discardClient();
365                     return;
366                 }
367                 sim.width = m_server->screen()->geometry().width();
368                 sim.height = m_server->screen()->geometry().height();
369                 sim.setName("Qt for Embedded Linux VNC Server");
370                 sim.write(m_clientSocket);
371                 m_state = Connected;
372             }
373             break;
374 
375         case Connected:
376             do {
377                 if (!m_handleMsg) {
378                     m_clientSocket->read((char *)&m_msgType, 1);
379                     m_handleMsg = true;
380                 }
381                 if (m_handleMsg) {
382                     switch (m_msgType ) {
383                     case SetPixelFormat:
384                         setPixelFormat();
385                         break;
386                     case FixColourMapEntries:
387                         qWarning("Not supported: FixColourMapEntries");
388                         m_handleMsg = false;
389                         break;
390                     case SetEncodings:
391                         setEncodings();
392                         break;
393                     case FramebufferUpdateRequest:
394                         frameBufferUpdateRequest();
395                         break;
396                     case KeyEvent:
397                         keyEvent();
398                         break;
399                     case PointerEvent:
400                         pointerEvent();
401                         break;
402                     case ClientCutText:
403                         clientCutText();
404                         break;
405                     default:
406                         qWarning("Unknown message type: %d", (int)m_msgType);
407                         m_handleMsg = false;
408                     }
409                 }
410             } while (!m_handleMsg && m_clientSocket->bytesAvailable());
411             break;
412     default:
413         break;
414     }
415 }
416 
discardClient()417 void QVncClient::discardClient()
418 {
419     m_state = Disconnected;
420     m_server->discardClient(this);
421 }
422 
checkUpdate()423 void QVncClient::checkUpdate()
424 {
425     if (!m_wantUpdate)
426         return;
427 #if QT_CONFIG(cursor)
428     if (m_dirtyCursor) {
429         m_server->screen()->clientCursor->write(this);
430         m_dirtyCursor = false;
431         m_wantUpdate = false;
432         return;
433     }
434 #endif
435     if (!m_dirtyRegion.isEmpty()) {
436         if (m_encoder)
437             m_encoder->write();
438         m_wantUpdate = false;
439         m_dirtyRegion = QRegion();
440     }
441 }
442 
scheduleUpdate()443 void QVncClient::scheduleUpdate()
444 {
445     if (!m_updatePending) {
446         m_updatePending = true;
447         QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
448     }
449 }
450 
event(QEvent * event)451 bool QVncClient::event(QEvent *event)
452 {
453     if (event->type() == QEvent::UpdateRequest) {
454         m_updatePending = false;
455         checkUpdate();
456         return true;
457     }
458     return QObject::event(event);
459 }
460 
setPixelFormat()461 void QVncClient::setPixelFormat()
462 {
463     if (m_clientSocket->bytesAvailable() >= 19) {
464         char buf[3];
465         m_clientSocket->read(buf, 3); // just padding
466         m_pixelFormat.read(m_clientSocket);
467         qCDebug(lcVnc, "Want format: %d %d %d %d %d %d %d %d %d %d",
468             int(m_pixelFormat.bitsPerPixel),
469             int(m_pixelFormat.depth),
470             int(m_pixelFormat.bigEndian),
471             int(m_pixelFormat.trueColor),
472             int(m_pixelFormat.redBits),
473             int(m_pixelFormat.greenBits),
474             int(m_pixelFormat.blueBits),
475             int(m_pixelFormat.redShift),
476             int(m_pixelFormat.greenShift),
477             int(m_pixelFormat.blueShift));
478         if (!m_pixelFormat.trueColor) {
479             qWarning("Can only handle true color clients");
480             discardClient();
481         }
482         m_handleMsg = false;
483         m_sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!m_pixelFormat.bigEndian;
484         m_needConversion = pixelConversionNeeded();
485 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
486         m_swapBytes = server()->screen()->swapBytes();
487 #endif
488     }
489 }
490 
setEncodings()491 void QVncClient::setEncodings()
492 {
493     QRfbSetEncodings enc;
494 
495     if (!m_encodingsPending && enc.read(m_clientSocket)) {
496         m_encodingsPending = enc.count;
497         if (!m_encodingsPending)
498             m_handleMsg = false;
499     }
500 
501     if (m_encoder) {
502         delete m_encoder;
503         m_encoder = nullptr;
504     }
505 
506     enum Encodings {
507         Raw = 0,
508         CopyRect = 1,
509         RRE = 2,
510         CoRRE = 4,
511         Hextile = 5,
512         ZRLE = 16,
513         Cursor = -239,
514         DesktopSize = -223
515     };
516 
517     if (m_encodingsPending && (unsigned)m_clientSocket->bytesAvailable() >=
518                                 m_encodingsPending * sizeof(quint32)) {
519         for (int i = 0; i < m_encodingsPending; ++i) {
520             qint32 enc;
521             m_clientSocket->read((char *)&enc, sizeof(qint32));
522             enc = ntohl(enc);
523             qCDebug(lcVnc, "QVncServer::setEncodings: %d", enc);
524             switch (enc) {
525             case Raw:
526                 if (!m_encoder) {
527                     m_encoder = new QRfbRawEncoder(this);
528                     qCDebug(lcVnc, "QVncServer::setEncodings: using raw");
529                 }
530                break;
531             case CopyRect:
532                 m_supportCopyRect = true;
533                 break;
534             case RRE:
535                 m_supportRRE = true;
536                 break;
537             case CoRRE:
538                 m_supportCoRRE = true;
539                 break;
540             case Hextile:
541                 m_supportHextile = true;
542                 if (m_encoder)
543                     break;
544                 break;
545             case ZRLE:
546                 m_supportZRLE = true;
547                 break;
548             case Cursor:
549                 m_supportCursor = true;
550                 m_server->screen()->enableClientCursor(this);
551                 break;
552             case DesktopSize:
553                 m_supportDesktopSize = true;
554                 break;
555             default:
556                 break;
557             }
558         }
559         m_handleMsg = false;
560         m_encodingsPending = 0;
561     }
562 
563     if (!m_encoder) {
564         m_encoder = new QRfbRawEncoder(this);
565         qCDebug(lcVnc, "QVncServer::setEncodings: fallback using raw");
566     }
567 }
568 
frameBufferUpdateRequest()569 void QVncClient::frameBufferUpdateRequest()
570 {
571     qCDebug(lcVnc) << "FramebufferUpdateRequest";
572     QRfbFrameBufferUpdateRequest ev;
573 
574     if (ev.read(m_clientSocket)) {
575         if (!ev.incremental) {
576             QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h);
577             r.translate(m_server->screen()->geometry().topLeft());
578             setDirty(r);
579         }
580         m_wantUpdate = true;
581         checkUpdate();
582         m_handleMsg = false;
583     }
584 }
585 
pointerEvent()586 void QVncClient::pointerEvent()
587 {
588     QRfbPointerEvent ev;
589     static int buttonState = Qt::NoButton;
590     if (ev.read(m_clientSocket)) {
591         const QPointF pos = m_server->screen()->geometry().topLeft() + QPoint(ev.x, ev.y);
592         int buttonStateChange = buttonState ^ int(ev.buttons);
593         QEvent::Type type = QEvent::MouseMove;
594         if (int(ev.buttons) > buttonState)
595             type = QEvent::MouseButtonPress;
596         else if (int(ev.buttons) < buttonState)
597             type = QEvent::MouseButtonRelease;
598         QWindowSystemInterface::handleMouseEvent(nullptr, pos, pos, ev.buttons, Qt::MouseButton(buttonStateChange),
599                                                  type, QGuiApplication::keyboardModifiers());
600         buttonState = int(ev.buttons);
601         m_handleMsg = false;
602     }
603 }
604 
keyEvent()605 void QVncClient::keyEvent()
606 {
607     QRfbKeyEvent ev;
608 
609     if (ev.read(m_clientSocket)) {
610         if (ev.keycode == Qt::Key_Shift)
611             m_keymod = ev.down ? m_keymod | Qt::ShiftModifier :
612                                  m_keymod & ~Qt::ShiftModifier;
613         else if (ev.keycode == Qt::Key_Control)
614             m_keymod = ev.down ? m_keymod | Qt::ControlModifier :
615                                  m_keymod & ~Qt::ControlModifier;
616         else if (ev.keycode == Qt::Key_Alt)
617             m_keymod = ev.down ? m_keymod | Qt::AltModifier :
618                                  m_keymod & ~Qt::AltModifier;
619         if (ev.unicode || ev.keycode)
620             QWindowSystemInterface::handleKeyEvent(nullptr, ev.down ? QEvent::KeyPress : QEvent::KeyRelease, ev.keycode, m_keymod, QString(ev.unicode));
621         m_handleMsg = false;
622     }
623 }
624 
clientCutText()625 void QVncClient::clientCutText()
626 {
627     QRfbClientCutText ev;
628 
629     if (m_cutTextPending == 0 && ev.read(m_clientSocket)) {
630         m_cutTextPending = ev.length;
631         if (!m_cutTextPending)
632             m_handleMsg = false;
633     }
634 
635     if (m_cutTextPending && m_clientSocket->bytesAvailable() >= m_cutTextPending) {
636         char *text = new char [m_cutTextPending+1];
637         m_clientSocket->read(text, m_cutTextPending);
638         delete [] text;
639         m_cutTextPending = 0;
640         m_handleMsg = false;
641     }
642 }
643 
pixelConversionNeeded() const644 bool QVncClient::pixelConversionNeeded() const
645 {
646     if (!m_sameEndian)
647         return true;
648 
649 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
650     if (server()->screen()->swapBytes())
651         return true;
652 #endif
653 
654     const int screendepth = m_server->screen()->depth();
655     if (screendepth != m_pixelFormat.bitsPerPixel)
656         return true;
657 
658     switch (screendepth) {
659     case 32:
660     case 24:
661         return false;
662     case 16:
663         return (m_pixelFormat.redBits == 5
664                 && m_pixelFormat.greenBits == 6
665                 && m_pixelFormat.blueBits == 5);
666     }
667     return true;
668 }
669 
670 QT_END_NAMESPACE
671