blob: 392d0cfe56be9835d72f39a21e1db2a56870defb [file] [log] [blame]
San Mehata430b2b2014-09-23 08:30:51 -07001/*
2 * rfbserver.c - deal with server-side of the RFB protocol.
3 */
4
5/*
6 * Copyright (C) 2011-2012 D. R. Commander
7 * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
8 * Copyright (C) 2002 RealVNC Ltd.
9 * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
10 * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
11 * All Rights Reserved.
12 *
13 * This is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This software is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this software; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 * USA.
27 */
28
29#ifdef __STRICT_ANSI__
30#define _BSD_SOURCE
31#endif
32#include <string.h>
33#include <rfb/rfb.h>
34#include <rfb/rfbregion.h>
35#include "private.h"
36
37#ifdef LIBVNCSERVER_HAVE_FCNTL_H
38#include <fcntl.h>
39#endif
40
41#ifdef WIN32
42#define write(sock,buf,len) send(sock,buf,len,0)
43#else
44#ifdef LIBVNCSERVER_HAVE_UNISTD_H
45#include <unistd.h>
46#endif
47#include <pwd.h>
48#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
49#include <sys/socket.h>
50#endif
51#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
52#include <netinet/in.h>
53#include <netinet/tcp.h>
54#include <netdb.h>
55#include <arpa/inet.h>
56#endif
57#endif
58
59#ifdef DEBUGPROTO
60#undef DEBUGPROTO
61#define DEBUGPROTO(x) x
62#else
63#define DEBUGPROTO(x)
64#endif
65#include <stdarg.h>
66#include <scale.h>
67/* stst() */
68#include <sys/types.h>
69#include <sys/stat.h>
70#include <unistd.h>
71/* readdir() */
72#include <dirent.h>
73/* errno */
74#include <errno.h>
75/* strftime() */
76#include <time.h>
77
78#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
79#include "rfbssl.h"
80#endif
81
82#ifdef __MINGW32__
83static int compat_mkdir(const char *path, int mode)
84{
85 return mkdir(path);
86}
87#define mkdir compat_mkdir
88#endif
89
90#ifdef LIBVNCSERVER_HAVE_LIBJPEG
91/*
92 * Map of quality levels to provide compatibility with TightVNC/TigerVNC
93 * clients. This emulates the behavior of the TigerVNC Server.
94 */
95
96static const int tight2turbo_qual[10] = {
97 15, 29, 41, 42, 62, 77, 79, 86, 92, 100
98};
99
100static const int tight2turbo_subsamp[10] = {
101 1, 1, 1, 2, 2, 2, 0, 0, 0, 0
102};
103#endif
104
105static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
106static void rfbProcessClientNormalMessage(rfbClientPtr cl);
107static void rfbProcessClientInitMessage(rfbClientPtr cl);
108
109#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
110void rfbIncrClientRef(rfbClientPtr cl)
111{
112 LOCK(cl->refCountMutex);
113 cl->refCount++;
114 UNLOCK(cl->refCountMutex);
115}
116
117void rfbDecrClientRef(rfbClientPtr cl)
118{
119 LOCK(cl->refCountMutex);
120 cl->refCount--;
121 if(cl->refCount<=0) /* just to be sure also < 0 */
122 TSIGNAL(cl->deleteCond);
123 UNLOCK(cl->refCountMutex);
124}
125#else
126void rfbIncrClientRef(rfbClientPtr cl) {}
127void rfbDecrClientRef(rfbClientPtr cl) {}
128#endif
129
130#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
131static MUTEX(rfbClientListMutex);
132#endif
133
134struct rfbClientIterator {
135 rfbClientPtr next;
136 rfbScreenInfoPtr screen;
137 rfbBool closedToo;
138};
139
140void
141rfbClientListInit(rfbScreenInfoPtr rfbScreen)
142{
143 if(sizeof(rfbBool)!=1) {
144 /* a sanity check */
145 fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool));
146 /* we cannot continue, because rfbBool is supposed to be char everywhere */
147 exit(1);
148 }
149 rfbScreen->clientHead = NULL;
150 INIT_MUTEX(rfbClientListMutex);
151}
152
153rfbClientIteratorPtr
154rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
155{
156 rfbClientIteratorPtr i =
157 (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
158 i->next = NULL;
159 i->screen = rfbScreen;
160 i->closedToo = FALSE;
161 return i;
162}
163
164rfbClientIteratorPtr
165rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen)
166{
167 rfbClientIteratorPtr i =
168 (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
169 i->next = NULL;
170 i->screen = rfbScreen;
171 i->closedToo = TRUE;
172 return i;
173}
174
175rfbClientPtr
176rfbClientIteratorHead(rfbClientIteratorPtr i)
177{
178#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
179 if(i->next != 0) {
180 rfbDecrClientRef(i->next);
181 rfbIncrClientRef(i->screen->clientHead);
182 }
183#endif
184 LOCK(rfbClientListMutex);
185 i->next = i->screen->clientHead;
186 UNLOCK(rfbClientListMutex);
187 return i->next;
188}
189
190rfbClientPtr
191rfbClientIteratorNext(rfbClientIteratorPtr i)
192{
193 if(i->next == 0) {
194 LOCK(rfbClientListMutex);
195 i->next = i->screen->clientHead;
196 UNLOCK(rfbClientListMutex);
197 } else {
198 IF_PTHREADS(rfbClientPtr cl = i->next);
199 i->next = i->next->next;
200 IF_PTHREADS(rfbDecrClientRef(cl));
201 }
202
203#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
204 if(!i->closedToo)
205 while(i->next && i->next->sock<0)
206 i->next = i->next->next;
207 if(i->next)
208 rfbIncrClientRef(i->next);
209#endif
210
211 return i->next;
212}
213
214void
215rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
216{
217 IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
218 free(iterator);
219}
220
221
222/*
223 * rfbNewClientConnection is called from sockets.c when a new connection
224 * comes in.
225 */
226
227void
228rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,
229 int sock)
230{
231 rfbNewClient(rfbScreen,sock);
232}
233
234
235/*
236 * rfbReverseConnection is called to make an outward
237 * connection to a "listening" RFB client.
238 */
239
240rfbClientPtr
241rfbReverseConnection(rfbScreenInfoPtr rfbScreen,
242 char *host,
243 int port)
244{
245 int sock;
246 rfbClientPtr cl;
247
248 if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
249 return (rfbClientPtr)NULL;
250
251 cl = rfbNewClient(rfbScreen, sock);
252
253 if (cl) {
254 cl->reverseConnection = TRUE;
255 }
256
257 return cl;
258}
259
260
261void
262rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_)
263{
264 /* Permit the server to set the version to report */
265 /* TODO: sanity checking */
266 if ((major_==3) && (minor_ > 2 && minor_ < 9))
267 {
268 rfbScreen->protocolMajorVersion = major_;
269 rfbScreen->protocolMinorVersion = minor_;
270 }
271 else
272 rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_);
273}
274
275/*
276 * rfbNewClient is called when a new connection has been made by whatever
277 * means.
278 */
279
280static rfbClientPtr
281rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
282 int sock,
283 rfbBool isUDP)
284{
285 rfbProtocolVersionMsg pv;
286 rfbClientIteratorPtr iterator;
287 rfbClientPtr cl,cl_;
288#ifdef LIBVNCSERVER_IPv6
289 struct sockaddr_storage addr;
290#else
291 struct sockaddr_in addr;
292#endif
293 socklen_t addrlen = sizeof(addr);
294 rfbProtocolExtension* extension;
295
296 cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
297
298 cl->screen = rfbScreen;
299 cl->sock = sock;
300 cl->viewOnly = FALSE;
301 /* setup pseudo scaling */
302 cl->scaledScreen = rfbScreen;
303 cl->scaledScreen->scaledScreenRefCount++;
304
305 rfbResetStats(cl);
306
307 cl->clientData = NULL;
308 cl->clientGoneHook = rfbDoNothingWithClient;
309
310 if(isUDP) {
311 rfbLog(" accepted UDP client\n");
312 } else {
313 int one=1;
314
315 getpeername(sock, (struct sockaddr *)&addr, &addrlen);
316#ifdef LIBVNCSERVER_IPv6
317 char host[1024];
318 if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
319 rfbLogPerror("rfbNewClient: error in getnameinfo");
320 cl->host = strdup("");
321 }
322 else
323 cl->host = strdup(host);
324#else
325 cl->host = strdup(inet_ntoa(addr.sin_addr));
326#endif
327
328 rfbLog(" other clients:\n");
329 iterator = rfbGetClientIterator(rfbScreen);
330 while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
331 rfbLog(" %s\n",cl_->host);
332 }
333 rfbReleaseClientIterator(iterator);
334
335 if(!rfbSetNonBlocking(sock)) {
336 close(sock);
337 return NULL;
338 }
339
340 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
341 (char *)&one, sizeof(one)) < 0) {
342 rfbLogPerror("setsockopt failed");
343 close(sock);
344 return NULL;
345 }
346
347 FD_SET(sock,&(rfbScreen->allFds));
348 rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
349
350 INIT_MUTEX(cl->outputMutex);
351 INIT_MUTEX(cl->refCountMutex);
352 INIT_MUTEX(cl->sendMutex);
353 INIT_COND(cl->deleteCond);
354
355 cl->state = RFB_PROTOCOL_VERSION;
356
357 cl->reverseConnection = FALSE;
358 cl->readyForSetColourMapEntries = FALSE;
359 cl->useCopyRect = FALSE;
360 cl->preferredEncoding = -1;
361 cl->correMaxWidth = 48;
362 cl->correMaxHeight = 48;
363#ifdef LIBVNCSERVER_HAVE_LIBZ
364 cl->zrleData = NULL;
365#endif
366
367 cl->copyRegion = sraRgnCreate();
368 cl->copyDX = 0;
369 cl->copyDY = 0;
370
371 cl->modifiedRegion =
372 sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
373
374 INIT_MUTEX(cl->updateMutex);
375 INIT_COND(cl->updateCond);
376
377 cl->requestedRegion = sraRgnCreate();
378
379 cl->format = cl->screen->serverFormat;
380 cl->translateFn = rfbTranslateNone;
381 cl->translateLookupTable = NULL;
382
383 LOCK(rfbClientListMutex);
384
385 IF_PTHREADS(cl->refCount = 0);
386 cl->next = rfbScreen->clientHead;
387 cl->prev = NULL;
388 if (rfbScreen->clientHead)
389 rfbScreen->clientHead->prev = cl;
390
391 rfbScreen->clientHead = cl;
392 UNLOCK(rfbClientListMutex);
393
394#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
395 cl->tightQualityLevel = -1;
396#ifdef LIBVNCSERVER_HAVE_LIBJPEG
397 cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
398 cl->turboSubsampLevel = TURBO_DEFAULT_SUBSAMP;
399 {
400 int i;
401 for (i = 0; i < 4; i++)
402 cl->zsActive[i] = FALSE;
403 }
404#endif
405#endif
406
407 cl->fileTransfer.fd = -1;
408
409 cl->enableCursorShapeUpdates = FALSE;
410 cl->enableCursorPosUpdates = FALSE;
411 cl->useRichCursorEncoding = FALSE;
412 cl->enableLastRectEncoding = FALSE;
413 cl->enableKeyboardLedState = FALSE;
414 cl->enableSupportedMessages = FALSE;
415 cl->enableSupportedEncodings = FALSE;
416 cl->enableServerIdentity = FALSE;
417 cl->lastKeyboardLedState = -1;
418 cl->cursorX = rfbScreen->cursorX;
419 cl->cursorY = rfbScreen->cursorY;
420 cl->useNewFBSize = FALSE;
421
422#ifdef LIBVNCSERVER_HAVE_LIBZ
423 cl->compStreamInited = FALSE;
424 cl->compStream.total_in = 0;
425 cl->compStream.total_out = 0;
426 cl->compStream.zalloc = Z_NULL;
427 cl->compStream.zfree = Z_NULL;
428 cl->compStream.opaque = Z_NULL;
429
430 cl->zlibCompressLevel = 5;
431#endif
432
433 cl->progressiveSliceY = 0;
434
435 cl->extensions = NULL;
436
437 cl->lastPtrX = -1;
438
439#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
440 /*
441 * Wait a few ms for the client to send one of:
442 * - Flash policy request
443 * - WebSockets connection (TLS/SSL or plain)
444 */
445 if (!webSocketsCheck(cl)) {
446 /* Error reporting handled in webSocketsHandshake */
447 rfbCloseClient(cl);
448 rfbClientConnectionGone(cl);
449 return NULL;
450 }
451#endif
452
453 sprintf(pv,rfbProtocolVersionFormat,rfbScreen->protocolMajorVersion,
454 rfbScreen->protocolMinorVersion);
455
456 if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
457 rfbLogPerror("rfbNewClient: write");
458 rfbCloseClient(cl);
459 rfbClientConnectionGone(cl);
460 return NULL;
461 }
462 }
463
464 for(extension = rfbGetExtensionIterator(); extension;
465 extension=extension->next) {
466 void* data = NULL;
467 /* if the extension does not have a newClient method, it wants
468 * to be initialized later. */
469 if(extension->newClient && extension->newClient(cl, &data))
470 rfbEnableExtension(cl, extension, data);
471 }
472 rfbReleaseExtensionIterator();
473
474 switch (cl->screen->newClientHook(cl)) {
475 case RFB_CLIENT_ON_HOLD:
476 cl->onHold = TRUE;
477 break;
478 case RFB_CLIENT_ACCEPT:
479 cl->onHold = FALSE;
480 break;
481 case RFB_CLIENT_REFUSE:
482 rfbCloseClient(cl);
483 rfbClientConnectionGone(cl);
484 cl = NULL;
485 break;
486 }
487 return cl;
488}
489
490rfbClientPtr
491rfbNewClient(rfbScreenInfoPtr rfbScreen,
492 int sock)
493{
494 return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
495}
496
497rfbClientPtr
498rfbNewUDPClient(rfbScreenInfoPtr rfbScreen)
499{
500 return((rfbScreen->udpClient=
501 rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
502}
503
504/*
505 * rfbClientConnectionGone is called from sockets.c just after a connection
506 * has gone away.
507 */
508
509void
510rfbClientConnectionGone(rfbClientPtr cl)
511{
512#if defined(LIBVNCSERVER_HAVE_LIBZ) && defined(LIBVNCSERVER_HAVE_LIBJPEG)
513 int i;
514#endif
515
516 LOCK(rfbClientListMutex);
517
518 if (cl->prev)
519 cl->prev->next = cl->next;
520 else
521 cl->screen->clientHead = cl->next;
522 if (cl->next)
523 cl->next->prev = cl->prev;
524
525 UNLOCK(rfbClientListMutex);
526
527#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
528 if(cl->screen->backgroundLoop != FALSE) {
529 int i;
530 do {
531 LOCK(cl->refCountMutex);
532 i=cl->refCount;
533 if(i>0)
534 WAIT(cl->deleteCond,cl->refCountMutex);
535 UNLOCK(cl->refCountMutex);
536 } while(i>0);
537 }
538#endif
539
540 if(cl->sock>=0)
541 close(cl->sock);
542
543 if (cl->scaledScreen!=NULL)
544 cl->scaledScreen->scaledScreenRefCount--;
545
546#ifdef LIBVNCSERVER_HAVE_LIBZ
547 rfbFreeZrleData(cl);
548#endif
549
550 rfbFreeUltraData(cl);
551
552 /* free buffers holding pixel data before and after encoding */
553 free(cl->beforeEncBuf);
554 free(cl->afterEncBuf);
555
556 if(cl->sock>=0)
557 FD_CLR(cl->sock,&(cl->screen->allFds));
558
559 cl->clientGoneHook(cl);
560
561 rfbLog("Client %s gone\n",cl->host);
562 free(cl->host);
563
564#ifdef LIBVNCSERVER_HAVE_LIBZ
565 /* Release the compression state structures if any. */
566 if ( cl->compStreamInited ) {
567 deflateEnd( &(cl->compStream) );
568 }
569
570#ifdef LIBVNCSERVER_HAVE_LIBJPEG
571 for (i = 0; i < 4; i++) {
572 if (cl->zsActive[i])
573 deflateEnd(&cl->zsStruct[i]);
574 }
575#endif
576#endif
577
578 if (cl->screen->pointerClient == cl)
579 cl->screen->pointerClient = NULL;
580
581 sraRgnDestroy(cl->modifiedRegion);
582 sraRgnDestroy(cl->requestedRegion);
583 sraRgnDestroy(cl->copyRegion);
584
585 if (cl->translateLookupTable) free(cl->translateLookupTable);
586
587 TINI_COND(cl->updateCond);
588 TINI_MUTEX(cl->updateMutex);
589
590 /* make sure outputMutex is unlocked before destroying */
591 LOCK(cl->outputMutex);
592 UNLOCK(cl->outputMutex);
593 TINI_MUTEX(cl->outputMutex);
594
595 LOCK(cl->sendMutex);
596 UNLOCK(cl->sendMutex);
597 TINI_MUTEX(cl->sendMutex);
598
599 rfbPrintStats(cl);
600 rfbResetStats(cl);
601
602 free(cl);
603}
604
605
606/*
607 * rfbProcessClientMessage is called when there is data to read from a client.
608 */
609
610void
611rfbProcessClientMessage(rfbClientPtr cl)
612{
613 switch (cl->state) {
614 case RFB_PROTOCOL_VERSION:
615 rfbProcessClientProtocolVersion(cl);
616 return;
617 case RFB_SECURITY_TYPE:
618 rfbProcessClientSecurityType(cl);
619 return;
620 case RFB_AUTHENTICATION:
621 rfbAuthProcessClientMessage(cl);
622 return;
623 case RFB_INITIALISATION:
624 case RFB_INITIALISATION_SHARED:
625 rfbProcessClientInitMessage(cl);
626 return;
627 default:
628 rfbProcessClientNormalMessage(cl);
629 return;
630 }
631}
632
633
634/*
635 * rfbProcessClientProtocolVersion is called when the client sends its
636 * protocol version.
637 */
638
639static void
640rfbProcessClientProtocolVersion(rfbClientPtr cl)
641{
642 rfbProtocolVersionMsg pv;
643 int n, major_, minor_;
644
645 if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
646 if (n == 0)
647 rfbLog("rfbProcessClientProtocolVersion: client gone\n");
648 else
649 rfbLogPerror("rfbProcessClientProtocolVersion: read");
650 rfbCloseClient(cl);
651 return;
652 }
653
654 pv[sz_rfbProtocolVersionMsg] = 0;
655 if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
656 rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv);
657 rfbCloseClient(cl);
658 return;
659 }
660 rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
661
662 if (major_ != rfbProtocolMajorVersion) {
663 rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
664 cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion,
665 major_,minor_);
666 rfbCloseClient(cl);
667 return;
668 }
669
670 /* Check for the minor version use either of the two standard version of RFB */
671 /*
672 * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions
673 * 3.4, 3.6, 3.14, 3.16
674 * It's a bad method, but it is what they use to enable features...
675 * maintaining RFB version compatibility across multiple servers is a pain
676 * Should use something like ServerIdentity encoding
677 */
678 cl->protocolMajorVersion = major_;
679 cl->protocolMinorVersion = minor_;
680
681 rfbLog("Protocol version sent %d.%d, using %d.%d\n",
682 major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion);
683
684 rfbAuthNewClient(cl);
685}
686
687
688void
689rfbClientSendString(rfbClientPtr cl, const char *reason)
690{
691 char *buf;
692 int len = strlen(reason);
693
694 rfbLog("rfbClientSendString(\"%s\")\n", reason);
695
696 buf = (char *)malloc(4 + len);
697 ((uint32_t *)buf)[0] = Swap32IfLE(len);
698 memcpy(buf + 4, reason, len);
699
700 if (rfbWriteExact(cl, buf, 4 + len) < 0)
701 rfbLogPerror("rfbClientSendString: write");
702 free(buf);
703
704 rfbCloseClient(cl);
705}
706
707/*
708 * rfbClientConnFailed is called when a client connection has failed either
709 * because it talks the wrong protocol or it has failed authentication.
710 */
711
712void
713rfbClientConnFailed(rfbClientPtr cl,
714 const char *reason)
715{
716 char *buf;
717 int len = strlen(reason);
718
719 rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
720
721 buf = (char *)malloc(8 + len);
722 ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
723 ((uint32_t *)buf)[1] = Swap32IfLE(len);
724 memcpy(buf + 8, reason, len);
725
726 if (rfbWriteExact(cl, buf, 8 + len) < 0)
727 rfbLogPerror("rfbClientConnFailed: write");
728 free(buf);
729
730 rfbCloseClient(cl);
731}
732
733
734/*
735 * rfbProcessClientInitMessage is called when the client sends its
736 * initialisation message.
737 */
738
739static void
740rfbProcessClientInitMessage(rfbClientPtr cl)
741{
742 rfbClientInitMsg ci;
743 union {
744 char buf[256];
745 rfbServerInitMsg si;
746 } u;
747 int len, n;
748 rfbClientIteratorPtr iterator;
749 rfbClientPtr otherCl;
750 rfbExtensionData* extension;
751
752 if (cl->state == RFB_INITIALISATION_SHARED) {
753 /* In this case behave as though an implicit ClientInit message has
754 * already been received with a shared-flag of true. */
755 ci.shared = 1;
756 /* Avoid the possibility of exposing the RFB_INITIALISATION_SHARED
757 * state to calling software. */
758 cl->state = RFB_INITIALISATION;
759 } else {
760 if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
761 if (n == 0)
762 rfbLog("rfbProcessClientInitMessage: client gone\n");
763 else
764 rfbLogPerror("rfbProcessClientInitMessage: read");
765 rfbCloseClient(cl);
766 return;
767 }
768 }
769
770 memset(u.buf,0,sizeof(u.buf));
771
772 u.si.framebufferWidth = Swap16IfLE(cl->screen->width);
773 u.si.framebufferHeight = Swap16IfLE(cl->screen->height);
774 u.si.format = cl->screen->serverFormat;
775 u.si.format.redMax = Swap16IfLE(u.si.format.redMax);
776 u.si.format.greenMax = Swap16IfLE(u.si.format.greenMax);
777 u.si.format.blueMax = Swap16IfLE(u.si.format.blueMax);
778
779 strncpy(u.buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
780 len = strlen(u.buf + sz_rfbServerInitMsg);
781 u.si.nameLength = Swap32IfLE(len);
782
783 if (rfbWriteExact(cl, u.buf, sz_rfbServerInitMsg + len) < 0) {
784 rfbLogPerror("rfbProcessClientInitMessage: write");
785 rfbCloseClient(cl);
786 return;
787 }
788
789 for(extension = cl->extensions; extension;) {
790 rfbExtensionData* next = extension->next;
791 if(extension->extension->init &&
792 !extension->extension->init(cl, extension->data))
793 /* extension requested that it be removed */
794 rfbDisableExtension(cl, extension->extension);
795 extension = next;
796 }
797
798 cl->state = RFB_NORMAL;
799
800 if (!cl->reverseConnection &&
801 (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) {
802
803 if (cl->screen->dontDisconnect) {
804 iterator = rfbGetClientIterator(cl->screen);
805 while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
806 if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
807 rfbLog("-dontdisconnect: Not shared & existing client\n");
808 rfbLog(" refusing new client %s\n", cl->host);
809 rfbCloseClient(cl);
810 rfbReleaseClientIterator(iterator);
811 return;
812 }
813 }
814 rfbReleaseClientIterator(iterator);
815 } else {
816 iterator = rfbGetClientIterator(cl->screen);
817 while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
818 if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
819 rfbLog("Not shared - closing connection to client %s\n",
820 otherCl->host);
821 rfbCloseClient(otherCl);
822 }
823 }
824 rfbReleaseClientIterator(iterator);
825 }
826 }
827}
828
829/* The values come in based on the scaled screen, we need to convert them to
830 * values based on the man screen's coordinate system
831 */
832static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
833 rfbClientPtr cl)
834{
835 int x1=Swap16IfLE(*x);
836 int y1=Swap16IfLE(*y);
837 int w1=Swap16IfLE(*w);
838 int h1=Swap16IfLE(*h);
839
840 rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip");
841 *x = x1;
842 *y = y1;
843 *w = w1;
844 *h = h1;
845
846 if(*w>cl->screen->width-*x)
847 *w=cl->screen->width-*x;
848 /* possible underflow */
849 if(*w>cl->screen->width-*x)
850 return FALSE;
851 if(*h>cl->screen->height-*y)
852 *h=cl->screen->height-*y;
853 if(*h>cl->screen->height-*y)
854 return FALSE;
855
856 return TRUE;
857}
858
859/*
860 * Send keyboard state (PointerPos pseudo-encoding).
861 */
862
863rfbBool
864rfbSendKeyboardLedState(rfbClientPtr cl)
865{
866 rfbFramebufferUpdateRectHeader rect;
867
868 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
869 if (!rfbSendUpdateBuf(cl))
870 return FALSE;
871 }
872
873 rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState);
874 rect.r.x = Swap16IfLE(cl->lastKeyboardLedState);
875 rect.r.y = 0;
876 rect.r.w = 0;
877 rect.r.h = 0;
878
879 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
880 sz_rfbFramebufferUpdateRectHeader);
881 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
882
883 rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
884
885 if (!rfbSendUpdateBuf(cl))
886 return FALSE;
887
888 return TRUE;
889}
890
891
892#define rfbSetBit(buffer, position) (buffer[(position & 255) / 8] |= (1 << (position % 8)))
893
894/*
895 * Send rfbEncodingSupportedMessages.
896 */
897
898rfbBool
899rfbSendSupportedMessages(rfbClientPtr cl)
900{
901 rfbFramebufferUpdateRectHeader rect;
902 rfbSupportedMessages msgs;
903
904 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
905 + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) {
906 if (!rfbSendUpdateBuf(cl))
907 return FALSE;
908 }
909
910 rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages);
911 rect.r.x = 0;
912 rect.r.y = 0;
913 rect.r.w = Swap16IfLE(sz_rfbSupportedMessages);
914 rect.r.h = 0;
915
916 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
917 sz_rfbFramebufferUpdateRectHeader);
918 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
919
920 memset((char *)&msgs, 0, sz_rfbSupportedMessages);
921 rfbSetBit(msgs.client2server, rfbSetPixelFormat);
922 rfbSetBit(msgs.client2server, rfbFixColourMapEntries);
923 rfbSetBit(msgs.client2server, rfbSetEncodings);
924 rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest);
925 rfbSetBit(msgs.client2server, rfbKeyEvent);
926 rfbSetBit(msgs.client2server, rfbPointerEvent);
927 rfbSetBit(msgs.client2server, rfbClientCutText);
928 rfbSetBit(msgs.client2server, rfbFileTransfer);
929 rfbSetBit(msgs.client2server, rfbSetScale);
930 /*rfbSetBit(msgs.client2server, rfbSetServerInput); */
931 /*rfbSetBit(msgs.client2server, rfbSetSW); */
932 rfbSetBit(msgs.client2server, rfbTextChat);
933 rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);
934 rfbSetBit(msgs.client2server, rfbXvp);
935
936 rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
937 rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
938 rfbSetBit(msgs.server2client, rfbBell);
939 rfbSetBit(msgs.server2client, rfbServerCutText);
940 rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
941 rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
942 rfbSetBit(msgs.server2client, rfbXvp);
943
944 memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
945 cl->ublen += sz_rfbSupportedMessages;
946
947 rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages,
948 sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages,
949 sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages);
950 if (!rfbSendUpdateBuf(cl))
951 return FALSE;
952
953 return TRUE;
954}
955
956
957
958/*
959 * Send rfbEncodingSupportedEncodings.
960 */
961
962rfbBool
963rfbSendSupportedEncodings(rfbClientPtr cl)
964{
965 rfbFramebufferUpdateRectHeader rect;
966 static uint32_t supported[] = {
967 rfbEncodingRaw,
968 rfbEncodingCopyRect,
969 rfbEncodingRRE,
970 rfbEncodingCoRRE,
971 rfbEncodingHextile,
972#ifdef LIBVNCSERVER_HAVE_LIBZ
973 rfbEncodingZlib,
974 rfbEncodingZRLE,
975 rfbEncodingZYWRLE,
976#endif
977#ifdef LIBVNCSERVER_HAVE_LIBJPEG
978 rfbEncodingTight,
979#endif
980#ifdef LIBVNCSERVER_HAVE_LIBPNG
981 rfbEncodingTightPng,
982#endif
983 rfbEncodingUltra,
984 rfbEncodingUltraZip,
985 rfbEncodingXCursor,
986 rfbEncodingRichCursor,
987 rfbEncodingPointerPos,
988 rfbEncodingLastRect,
989 rfbEncodingNewFBSize,
990 rfbEncodingKeyboardLedState,
991 rfbEncodingSupportedMessages,
992 rfbEncodingSupportedEncodings,
993 rfbEncodingServerIdentity,
994 };
995 uint32_t nEncodings = sizeof(supported) / sizeof(supported[0]), i;
996
997 /* think rfbSetEncodingsMsg */
998
999 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
1000 + (nEncodings * sizeof(uint32_t)) > UPDATE_BUF_SIZE) {
1001 if (!rfbSendUpdateBuf(cl))
1002 return FALSE;
1003 }
1004
1005 rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings);
1006 rect.r.x = 0;
1007 rect.r.y = 0;
1008 rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t));
1009 rect.r.h = Swap16IfLE(nEncodings);
1010
1011 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1012 sz_rfbFramebufferUpdateRectHeader);
1013 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1014
1015 for (i = 0; i < nEncodings; i++) {
1016 uint32_t encoding = Swap32IfLE(supported[i]);
1017 memcpy(&cl->updateBuf[cl->ublen], (char *)&encoding, sizeof(encoding));
1018 cl->ublen += sizeof(encoding);
1019 }
1020
1021 rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings,
1022 sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)),
1023 sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)));
1024
1025 if (!rfbSendUpdateBuf(cl))
1026 return FALSE;
1027
1028 return TRUE;
1029}
1030
1031
1032void
1033rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...)
1034{
1035 char buffer[256];
1036 va_list ap;
1037
1038 va_start(ap, fmt);
1039 vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
1040 va_end(ap);
1041
1042 if (screen->versionString!=NULL) free(screen->versionString);
1043 screen->versionString = strdup(buffer);
1044}
1045
1046/*
1047 * Send rfbEncodingServerIdentity.
1048 */
1049
1050rfbBool
1051rfbSendServerIdentity(rfbClientPtr cl)
1052{
1053 rfbFramebufferUpdateRectHeader rect;
1054 char buffer[512];
1055
1056 /* tack on our library version */
1057 snprintf(buffer,sizeof(buffer)-1, "%s (%s)",
1058 (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString),
1059 LIBVNCSERVER_PACKAGE_STRING);
1060
1061 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
1062 + (strlen(buffer)+1) > UPDATE_BUF_SIZE) {
1063 if (!rfbSendUpdateBuf(cl))
1064 return FALSE;
1065 }
1066
1067 rect.encoding = Swap32IfLE(rfbEncodingServerIdentity);
1068 rect.r.x = 0;
1069 rect.r.y = 0;
1070 rect.r.w = Swap16IfLE(strlen(buffer)+1);
1071 rect.r.h = 0;
1072
1073 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1074 sz_rfbFramebufferUpdateRectHeader);
1075 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1076
1077 memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1);
1078 cl->ublen += strlen(buffer)+1;
1079
1080 rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity,
1081 sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1,
1082 sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1);
1083
1084
1085 if (!rfbSendUpdateBuf(cl))
1086 return FALSE;
1087
1088 return TRUE;
1089}
1090
1091/*
1092 * Send an xvp server message
1093 */
1094
1095rfbBool
1096rfbSendXvp(rfbClientPtr cl, uint8_t version, uint8_t code)
1097{
1098 rfbXvpMsg xvp;
1099
1100 xvp.type = rfbXvp;
1101 xvp.pad = 0;
1102 xvp.version = version;
1103 xvp.code = code;
1104
1105 LOCK(cl->sendMutex);
1106 if (rfbWriteExact(cl, (char *)&xvp, sz_rfbXvpMsg) < 0) {
1107 rfbLogPerror("rfbSendXvp: write");
1108 rfbCloseClient(cl);
1109 }
1110 UNLOCK(cl->sendMutex);
1111
1112 rfbStatRecordMessageSent(cl, rfbXvp, sz_rfbXvpMsg, sz_rfbXvpMsg);
1113
1114 return TRUE;
1115}
1116
1117
1118rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer)
1119{
1120 rfbTextChatMsg tc;
1121 int bytesToSend=0;
1122
1123 memset((char *)&tc, 0, sizeof(tc));
1124 tc.type = rfbTextChat;
1125 tc.length = Swap32IfLE(length);
1126
1127 switch(length) {
1128 case rfbTextChatOpen:
1129 case rfbTextChatClose:
1130 case rfbTextChatFinished:
1131 bytesToSend=0;
1132 break;
1133 default:
1134 bytesToSend=length;
1135 if (bytesToSend>rfbTextMaxSize)
1136 bytesToSend=rfbTextMaxSize;
1137 }
1138
1139 if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) {
1140 if (!rfbSendUpdateBuf(cl))
1141 return FALSE;
1142 }
1143
1144 memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg);
1145 cl->ublen += sz_rfbTextChatMsg;
1146 if (bytesToSend>0) {
1147 memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend);
1148 cl->ublen += bytesToSend;
1149 }
1150 rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend);
1151
1152 if (!rfbSendUpdateBuf(cl))
1153 return FALSE;
1154
1155 return TRUE;
1156}
1157
1158#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
1159 if ((cl->screen->getFileTransferPermission != NULL \
1160 && cl->screen->getFileTransferPermission(cl) != TRUE) \
1161 || cl->screen->permitFileTransfer != TRUE) { \
1162 rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
1163 rfbCloseClient(cl); \
1164 return ret; \
1165 }
1166
1167int DB = 1;
1168
1169rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, const char *buffer)
1170{
1171 rfbFileTransferMsg ft;
1172 ft.type = rfbFileTransfer;
1173 ft.contentType = contentType;
1174 ft.contentParam = contentParam;
1175 ft.pad = 0; /* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */
1176 ft.size = Swap32IfLE(size);
1177 ft.length = Swap32IfLE(length);
1178
1179 FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1180 /*
1181 rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer);
1182 */
1183 LOCK(cl->sendMutex);
1184 if (rfbWriteExact(cl, (char *)&ft, sz_rfbFileTransferMsg) < 0) {
1185 rfbLogPerror("rfbSendFileTransferMessage: write");
1186 rfbCloseClient(cl);
1187 UNLOCK(cl->sendMutex);
1188 return FALSE;
1189 }
1190
1191 if (length>0)
1192 {
1193 if (rfbWriteExact(cl, buffer, length) < 0) {
1194 rfbLogPerror("rfbSendFileTransferMessage: write");
1195 rfbCloseClient(cl);
1196 UNLOCK(cl->sendMutex);
1197 return FALSE;
1198 }
1199 }
1200 UNLOCK(cl->sendMutex);
1201
1202 rfbStatRecordMessageSent(cl, rfbFileTransfer, sz_rfbFileTransferMsg+length, sz_rfbFileTransferMsg+length);
1203
1204 return TRUE;
1205}
1206
1207
1208/*
1209 * UltraVNC uses Windows Structures
1210 */
1211#define MAX_PATH 260
1212
1213typedef struct {
1214 uint32_t dwLowDateTime;
1215 uint32_t dwHighDateTime;
1216} RFB_FILETIME;
1217
1218typedef struct {
1219 uint32_t dwFileAttributes;
1220 RFB_FILETIME ftCreationTime;
1221 RFB_FILETIME ftLastAccessTime;
1222 RFB_FILETIME ftLastWriteTime;
1223 uint32_t nFileSizeHigh;
1224 uint32_t nFileSizeLow;
1225 uint32_t dwReserved0;
1226 uint32_t dwReserved1;
1227 uint8_t cFileName[ MAX_PATH ];
1228 uint8_t cAlternateFileName[ 14 ];
1229} RFB_FIND_DATA;
1230
1231#define RFB_FILE_ATTRIBUTE_READONLY 0x1
1232#define RFB_FILE_ATTRIBUTE_HIDDEN 0x2
1233#define RFB_FILE_ATTRIBUTE_SYSTEM 0x4
1234#define RFB_FILE_ATTRIBUTE_DIRECTORY 0x10
1235#define RFB_FILE_ATTRIBUTE_ARCHIVE 0x20
1236#define RFB_FILE_ATTRIBUTE_NORMAL 0x80
1237#define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100
1238#define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800
1239
1240rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath)
1241{
1242 int x;
1243 char *home=NULL;
1244
1245 FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1246
1247 /* C: */
1248 if (path[0]=='C' && path[1]==':')
1249 strcpy(unixPath, &path[2]);
1250 else
1251 {
1252 home = getenv("HOME");
1253 if (home!=NULL)
1254 {
1255 strcpy(unixPath, home);
1256 strcat(unixPath,"/");
1257 strcat(unixPath, path);
1258 }
1259 else
1260 strcpy(unixPath, path);
1261 }
1262 for (x=0;x<strlen(unixPath);x++)
1263 if (unixPath[x]=='\\') unixPath[x]='/';
1264 return TRUE;
1265}
1266
1267rfbBool rfbFilenameTranslate2DOS(rfbClientPtr cl, char *unixPath, char *path)
1268{
1269 int x;
1270
1271 FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1272
1273 sprintf(path,"C:%s", unixPath);
1274 for (x=2;x<strlen(path);x++)
1275 if (path[x]=='/') path[x]='\\';
1276 return TRUE;
1277}
1278
1279rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
1280{
1281 char retfilename[MAX_PATH];
1282 char path[MAX_PATH];
1283 struct stat statbuf;
1284 RFB_FIND_DATA win32filename;
1285 int nOptLen = 0, retval=0;
1286 DIR *dirp=NULL;
1287 struct dirent *direntp=NULL;
1288
1289 FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1290
1291 /* Client thinks we are Winblows */
1292 rfbFilenameTranslate2UNIX(cl, buffer, path);
1293
1294 if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
1295
1296 dirp=opendir(path);
1297 if (dirp==NULL)
1298 return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL);
1299 /* send back the path name (necessary for links) */
1300 if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE;
1301 for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp))
1302 {
1303 /* get stats */
1304 snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
1305 retval = stat(retfilename, &statbuf);
1306
1307 if (retval==0)
1308 {
1309 memset((char *)&win32filename, 0, sizeof(win32filename));
1310 win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL);
1311 if (S_ISDIR(statbuf.st_mode))
1312 win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
1313 win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime); /* Intel Order */
1314 win32filename.ftCreationTime.dwHighDateTime = 0;
1315 win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */
1316 win32filename.ftLastAccessTime.dwHighDateTime = 0;
1317 win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime); /* Intel Order */
1318 win32filename.ftLastWriteTime.dwHighDateTime = 0;
1319 win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */
1320 win32filename.nFileSizeHigh = 0;
1321 win32filename.dwReserved0 = 0;
1322 win32filename.dwReserved1 = 0;
1323
1324 /* If this had the full path, we would need to translate to DOS format ("C:\") */
1325 /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
1326 strcpy((char *)win32filename.cFileName, direntp->d_name);
1327
1328 /* Do not show hidden files (but show how to move up the tree) */
1329 if ((strcmp(direntp->d_name, "..")==0) || (direntp->d_name[0]!='.'))
1330 {
1331 nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName);
1332 /*
1333 rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName);
1334 */
1335 if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE)
1336 {
1337 closedir(dirp);
1338 return FALSE;
1339 }
1340 }
1341 }
1342 }
1343 closedir(dirp);
1344 /* End of the transfer */
1345 return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL);
1346}
1347
1348
1349char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length)
1350{
1351 char *buffer=NULL;
1352 int n=0;
1353
1354 FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL);
1355 /*
1356 rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length);
1357 */
1358 if (length>0) {
1359 buffer=malloc(length+1);
1360 if (buffer!=NULL) {
1361 if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) {
1362 if (n != 0)
1363 rfbLogPerror("rfbProcessFileTransferReadBuffer: read");
1364 rfbCloseClient(cl);
1365 /* NOTE: don't forget to free(buffer) if you return early! */
1366 if (buffer!=NULL) free(buffer);
1367 return NULL;
1368 }
1369 /* Null Terminate */
1370 buffer[length]=0;
1371 }
1372 }
1373 return buffer;
1374}
1375
1376
1377rfbBool rfbSendFileTransferChunk(rfbClientPtr cl)
1378{
1379 /* Allocate buffer for compression */
1380 unsigned char readBuf[sz_rfbBlockSize];
1381 int bytesRead=0;
1382 int retval=0;
1383 fd_set wfds;
1384 struct timeval tv;
1385 int n;
1386#ifdef LIBVNCSERVER_HAVE_LIBZ
1387 unsigned char compBuf[sz_rfbBlockSize + 1024];
1388 unsigned long nMaxCompSize = sizeof(compBuf);
1389 int nRetC = 0;
1390#endif
1391
1392 /*
1393 * Don't close the client if we get into this one because
1394 * it is called from many places to service file transfers.
1395 * Note that permitFileTransfer is checked first.
1396 */
1397 if (cl->screen->permitFileTransfer != TRUE ||
1398 (cl->screen->getFileTransferPermission != NULL
1399 && cl->screen->getFileTransferPermission(cl) != TRUE)) {
1400 return TRUE;
1401 }
1402
1403 /* If not sending, or no file open... Return as if we sent something! */
1404 if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
1405 {
1406 FD_ZERO(&wfds);
1407 FD_SET(cl->sock, &wfds);
1408
1409 /* return immediately */
1410 tv.tv_sec = 0;
1411 tv.tv_usec = 0;
1412 n = select(cl->sock + 1, NULL, &wfds, NULL, &tv);
1413
1414 if (n<0) {
1415#ifdef WIN32
1416 errno=WSAGetLastError();
1417#endif
1418 rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno));
1419 }
1420 /* We have space on the transmit queue */
1421 if (n > 0)
1422 {
1423 bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize);
1424 switch (bytesRead) {
1425 case 0:
1426 /*
1427 rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n");
1428 */
1429 retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL);
1430 close(cl->fileTransfer.fd);
1431 cl->fileTransfer.fd = -1;
1432 cl->fileTransfer.sending = 0;
1433 cl->fileTransfer.receiving = 0;
1434 return retval;
1435 case -1:
1436 /* TODO : send an error msg to the client... */
1437#ifdef WIN32
1438 errno=WSAGetLastError();
1439#endif
1440 rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno));
1441 retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL);
1442 close(cl->fileTransfer.fd);
1443 cl->fileTransfer.fd = -1;
1444 cl->fileTransfer.sending = 0;
1445 cl->fileTransfer.receiving = 0;
1446 return retval;
1447 default:
1448 /*
1449 rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead);
1450 */
1451 if (!cl->fileTransfer.compressionEnabled)
1452 return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
1453 else
1454 {
1455#ifdef LIBVNCSERVER_HAVE_LIBZ
1456 nRetC = compress(compBuf, &nMaxCompSize, readBuf, bytesRead);
1457 /*
1458 rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead);
1459 */
1460
1461 if ((nRetC==0) && (nMaxCompSize<bytesRead))
1462 return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 1, nMaxCompSize, (char *)compBuf);
1463 else
1464 return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
1465#else
1466 /* We do not support compression of the data stream */
1467 return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
1468#endif
1469 }
1470 }
1471 }
1472 }
1473 return TRUE;
1474}
1475
1476rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length)
1477{
1478 char *buffer=NULL, *p=NULL;
1479 int retval=0;
1480 char filename1[MAX_PATH];
1481 char filename2[MAX_PATH];
1482 char szFileTime[MAX_PATH];
1483 struct stat statbuf;
1484 uint32_t sizeHtmp=0;
1485 int n=0;
1486 char timespec[64];
1487#ifdef LIBVNCSERVER_HAVE_LIBZ
1488 unsigned char compBuff[sz_rfbBlockSize];
1489 unsigned long nRawBytes = sz_rfbBlockSize;
1490 int nRet = 0;
1491#endif
1492
1493 FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1494
1495 /*
1496 rfbLog("rfbProcessFileTransfer(%dtype, %dparam, %dsize, %dlen)\n", contentType, contentParam, size, length);
1497 */
1498
1499 switch (contentType) {
1500 case rfbDirContentRequest:
1501 switch (contentParam) {
1502 case rfbRDrivesList: /* Client requests the List of Local Drives */
1503 /*
1504 rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDrivesList:\n");
1505 */
1506 /* Format when filled : "C:\<NULL>D:\<NULL>....Z:\<NULL><NULL>
1507 *
1508 * We replace the "\" char following the drive letter and ":"
1509 * with a char corresponding to the type of drive
1510 * We obtain something like "C:l<NULL>D:c<NULL>....Z:n\<NULL><NULL>"
1511 * Isn't it ugly ?
1512 * DRIVE_FIXED = 'l' (local?)
1513 * DRIVE_REMOVABLE = 'f' (floppy?)
1514 * DRIVE_CDROM = 'c'
1515 * DRIVE_REMOTE = 'n'
1516 */
1517
1518 /* in unix, there are no 'drives' (We could list mount points though)
1519 * We fake the root as a "C:" for the Winblows users
1520 */
1521 filename2[0]='C';
1522 filename2[1]=':';
1523 filename2[2]='l';
1524 filename2[3]=0;
1525 filename2[4]=0;
1526 retval = rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADrivesList, 0, 5, filename2);
1527 if (buffer!=NULL) free(buffer);
1528 return retval;
1529 break;
1530 case rfbRDirContent: /* Client requests the content of a directory */
1531 /*
1532 rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n");
1533 */
1534 if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1535 retval = rfbSendDirContent(cl, length, buffer);
1536 if (buffer!=NULL) free(buffer);
1537 return retval;
1538 }
1539 break;
1540
1541 case rfbDirPacket:
1542 rfbLog("rfbProcessFileTransfer() rfbDirPacket\n");
1543 break;
1544 case rfbFileAcceptHeader:
1545 rfbLog("rfbProcessFileTransfer() rfbFileAcceptHeader\n");
1546 break;
1547 case rfbCommandReturn:
1548 rfbLog("rfbProcessFileTransfer() rfbCommandReturn\n");
1549 break;
1550 case rfbFileChecksums:
1551 /* Destination file already exists - the viewer sends the checksums */
1552 rfbLog("rfbProcessFileTransfer() rfbFileChecksums\n");
1553 break;
1554 case rfbFileTransferAccess:
1555 rfbLog("rfbProcessFileTransfer() rfbFileTransferAccess\n");
1556 break;
1557
1558 /*
1559 * sending from the server to the viewer
1560 */
1561
1562 case rfbFileTransferRequest:
1563 /*
1564 rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n");
1565 */
1566 /* add some space to the end of the buffer as we will be adding a timespec to it */
1567 if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1568 /* The client requests a File */
1569 rfbFilenameTranslate2UNIX(cl, buffer, filename1);
1570 cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744);
1571
1572 /*
1573 */
1574 if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), cl->fileTransfer.fd);
1575
1576 if (cl->fileTransfer.fd!=-1) {
1577 if (fstat(cl->fileTransfer.fd, &statbuf)!=0) {
1578 close(cl->fileTransfer.fd);
1579 cl->fileTransfer.fd=-1;
1580 }
1581 else
1582 {
1583 /* Add the File Time Stamp to the filename */
1584 strftime(timespec, sizeof(timespec), "%m/%d/%Y %H:%M",gmtime(&statbuf.st_ctime));
1585 buffer=realloc(buffer, length + strlen(timespec) + 2); /* comma, and Null term */
1586 if (buffer==NULL) {
1587 rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes\n", length + strlen(timespec) + 2);
1588 return FALSE;
1589 }
1590 strcat(buffer,",");
1591 strcat(buffer, timespec);
1592 length = strlen(buffer);
1593 if (DB) rfbLog("rfbProcessFileTransfer() buffer is now: \"%s\"\n", buffer);
1594 }
1595 }
1596
1597 /* The viewer supports compression if size==1 */
1598 cl->fileTransfer.compressionEnabled = (size==1);
1599
1600 /*
1601 rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" <Compression Enabled>":""));
1602 */
1603
1604 /* File Size in bytes, 0xFFFFFFFF (-1) means error */
1605 retval = rfbSendFileTransferMessage(cl, rfbFileHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : statbuf.st_size), length, buffer);
1606
1607 if (cl->fileTransfer.fd==-1)
1608 {
1609 if (buffer!=NULL) free(buffer);
1610 return retval;
1611 }
1612 /* setup filetransfer stuff */
1613 cl->fileTransfer.fileSize = statbuf.st_size;
1614 cl->fileTransfer.numPackets = statbuf.st_size / sz_rfbBlockSize;
1615 cl->fileTransfer.receiving = 0;
1616 cl->fileTransfer.sending = 0; /* set when we receive a rfbFileHeader: */
1617
1618 /* TODO: finish 64-bit file size support */
1619 sizeHtmp = 0;
1620 LOCK(cl->sendMutex);
1621 if (rfbWriteExact(cl, (char *)&sizeHtmp, 4) < 0) {
1622 rfbLogPerror("rfbProcessFileTransfer: write");
1623 rfbCloseClient(cl);
1624 UNLOCK(cl->sendMutex);
1625 if (buffer!=NULL) free(buffer);
1626 return FALSE;
1627 }
1628 UNLOCK(cl->sendMutex);
1629 break;
1630
1631 case rfbFileHeader:
1632 /* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */
1633 if (size==-1) {
1634 rfbLog("rfbProcessFileTransfer() rfbFileHeader (error, aborting)\n");
1635 close(cl->fileTransfer.fd);
1636 cl->fileTransfer.fd=-1;
1637 return TRUE;
1638 }
1639
1640 /*
1641 rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size);
1642 */
1643
1644 /* Starts the transfer! */
1645 cl->fileTransfer.sending=1;
1646 return rfbSendFileTransferChunk(cl);
1647 break;
1648
1649
1650 /*
1651 * sending from the viewer to the server
1652 */
1653
1654 case rfbFileTransferOffer:
1655 /* client is sending a file to us */
1656 /* buffer contains full path name (plus FileTime) */
1657 /* size contains size of the file */
1658 /*
1659 rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n");
1660 */
1661 if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1662
1663 /* Parse the FileTime */
1664 p = strrchr(buffer, ',');
1665 if (p!=NULL) {
1666 *p = '\0';
1667 strcpy(szFileTime, p+1);
1668 } else
1669 szFileTime[0]=0;
1670
1671
1672
1673 /* Need to read in sizeHtmp */
1674 if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) {
1675 if (n != 0)
1676 rfbLogPerror("rfbProcessFileTransfer: read sizeHtmp");
1677 rfbCloseClient(cl);
1678 /* NOTE: don't forget to free(buffer) if you return early! */
1679 if (buffer!=NULL) free(buffer);
1680 return FALSE;
1681 }
1682 sizeHtmp = Swap32IfLE(sizeHtmp);
1683
1684 rfbFilenameTranslate2UNIX(cl, buffer, filename1);
1685
1686 /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
1687 /* TODO: Delta Transfer */
1688
1689 cl->fileTransfer.fd=open(filename1, O_CREAT|O_WRONLY|O_TRUNC, 0744);
1690 if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer(\"%s\"->\"%s\") %s %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), (cl->fileTransfer.fd==-1?strerror(errno):""), cl->fileTransfer.fd);
1691 /*
1692 */
1693
1694 /* File Size in bytes, 0xFFFFFFFF (-1) means error */
1695 retval = rfbSendFileTransferMessage(cl, rfbFileAcceptHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : 0), length, buffer);
1696 if (cl->fileTransfer.fd==-1) {
1697 free(buffer);
1698 return retval;
1699 }
1700
1701 /* setup filetransfer stuff */
1702 cl->fileTransfer.fileSize = size;
1703 cl->fileTransfer.numPackets = size / sz_rfbBlockSize;
1704 cl->fileTransfer.receiving = 1;
1705 cl->fileTransfer.sending = 0;
1706 break;
1707
1708 case rfbFilePacket:
1709 /*
1710 rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n");
1711 */
1712 if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1713 if (cl->fileTransfer.fd!=-1) {
1714 /* buffer contains the contents of the file */
1715 if (size==0)
1716 retval=write(cl->fileTransfer.fd, buffer, length);
1717 else
1718 {
1719#ifdef LIBVNCSERVER_HAVE_LIBZ
1720 /* compressed packet */
1721 nRet = uncompress(compBuff,&nRawBytes,(const unsigned char*)buffer, length);
1722 if(nRet == Z_OK)
1723 retval=write(cl->fileTransfer.fd, (char*)compBuff, nRawBytes);
1724 else
1725 retval = -1;
1726#else
1727 /* Write the file out as received... */
1728 retval=write(cl->fileTransfer.fd, buffer, length);
1729#endif
1730 }
1731 if (retval==-1)
1732 {
1733 close(cl->fileTransfer.fd);
1734 cl->fileTransfer.fd=-1;
1735 cl->fileTransfer.sending = 0;
1736 cl->fileTransfer.receiving = 0;
1737 }
1738 }
1739 break;
1740
1741 case rfbEndOfFile:
1742 if (DB) rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n");
1743 /*
1744 */
1745 if (cl->fileTransfer.fd!=-1)
1746 close(cl->fileTransfer.fd);
1747 cl->fileTransfer.fd=-1;
1748 cl->fileTransfer.sending = 0;
1749 cl->fileTransfer.receiving = 0;
1750 break;
1751
1752 case rfbAbortFileTransfer:
1753 if (DB) rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n");
1754 /*
1755 */
1756 if (cl->fileTransfer.fd!=-1)
1757 {
1758 close(cl->fileTransfer.fd);
1759 cl->fileTransfer.fd=-1;
1760 cl->fileTransfer.sending = 0;
1761 cl->fileTransfer.receiving = 0;
1762 }
1763 else
1764 {
1765 /* We use this message for FileTransfer rights (<=RC18 versions)
1766 * The client asks for FileTransfer permission
1767 */
1768 if (contentParam == 0)
1769 {
1770 rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)\n");
1771 /* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/
1772 return rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, -1, 0, "");
1773 }
1774 /* New method is allowed */
1775 if (cl->screen->getFileTransferPermission!=NULL)
1776 {
1777 if (cl->screen->getFileTransferPermission(cl)==TRUE)
1778 {
1779 rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
1780 return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
1781 }
1782 else
1783 {
1784 rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED!\n");
1785 return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* Deny */
1786 }
1787 }
1788 else
1789 {
1790 if (cl->screen->permitFileTransfer)
1791 {
1792 rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
1793 return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
1794 }
1795 else
1796 {
1797 rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED by default!\n");
1798 return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* DEFAULT: DENY (for security) */
1799 }
1800
1801 }
1802 }
1803 break;
1804
1805
1806 case rfbCommand:
1807 /*
1808 rfbLog("rfbProcessFileTransfer() rfbCommand:\n");
1809 */
1810 if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1811 switch (contentParam) {
1812 case rfbCDirCreate: /* Client requests the creation of a directory */
1813 rfbFilenameTranslate2UNIX(cl, buffer, filename1);
1814 retval = mkdir(filename1, 0755);
1815 if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
1816 /*
1817 */
1818 retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbADirCreate, retval, length, buffer);
1819 if (buffer!=NULL) free(buffer);
1820 return retval;
1821 case rfbCFileDelete: /* Client requests the deletion of a file */
1822 rfbFilenameTranslate2UNIX(cl, buffer, filename1);
1823 if (stat(filename1,&statbuf)==0)
1824 {
1825 if (S_ISDIR(statbuf.st_mode))
1826 retval = rmdir(filename1);
1827 else
1828 retval = unlink(filename1);
1829 }
1830 else retval=-1;
1831 retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileDelete, retval, length, buffer);
1832 if (buffer!=NULL) free(buffer);
1833 return retval;
1834 case rfbCFileRename: /* Client requests the Renaming of a file/directory */
1835 p = strrchr(buffer, '*');
1836 if (p != NULL)
1837 {
1838 /* Split into 2 filenames ('*' is a seperator) */
1839 *p = '\0';
1840 rfbFilenameTranslate2UNIX(cl, buffer, filename1);
1841 rfbFilenameTranslate2UNIX(cl, p+1, filename2);
1842 retval = rename(filename1,filename2);
1843 if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
1844 /*
1845 */
1846 /* Restore the buffer so the reply is good */
1847 *p = '*';
1848 retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileRename, retval, length, buffer);
1849 if (buffer!=NULL) free(buffer);
1850 return retval;
1851 }
1852 break;
1853 }
1854
1855 break;
1856 }
1857
1858 /* NOTE: don't forget to free(buffer) if you return early! */
1859 if (buffer!=NULL) free(buffer);
1860 return TRUE;
1861}
1862
1863/*
1864 * rfbProcessClientNormalMessage is called when the client has sent a normal
1865 * protocol message.
1866 */
1867
1868static void
1869rfbProcessClientNormalMessage(rfbClientPtr cl)
1870{
1871 int n=0;
1872 rfbClientToServerMsg msg;
1873 char *str;
1874 int i;
1875 uint32_t enc=0;
1876 uint32_t lastPreferredEncoding = -1;
1877 char encBuf[64];
1878 char encBuf2[64];
1879
1880#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
1881 if (cl->wsctx && webSocketCheckDisconnect(cl))
1882 return;
1883#endif
1884
1885 if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) {
1886 if (n != 0)
1887 rfbLogPerror("rfbProcessClientNormalMessage: read");
1888 rfbCloseClient(cl);
1889 return;
1890 }
1891
1892 switch (msg.type) {
1893
1894 case rfbSetPixelFormat:
1895
1896 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
1897 sz_rfbSetPixelFormatMsg - 1)) <= 0) {
1898 if (n != 0)
1899 rfbLogPerror("rfbProcessClientNormalMessage: read");
1900 rfbCloseClient(cl);
1901 return;
1902 }
1903
1904 cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
1905 cl->format.depth = msg.spf.format.depth;
1906 cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
1907 cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
1908 cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
1909 cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
1910 cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
1911 cl->format.redShift = msg.spf.format.redShift;
1912 cl->format.greenShift = msg.spf.format.greenShift;
1913 cl->format.blueShift = msg.spf.format.blueShift;
1914
1915 cl->readyForSetColourMapEntries = TRUE;
1916 cl->screen->setTranslateFunction(cl);
1917
1918 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
1919
1920 return;
1921
1922
1923 case rfbFixColourMapEntries:
1924 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
1925 sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
1926 if (n != 0)
1927 rfbLogPerror("rfbProcessClientNormalMessage: read");
1928 rfbCloseClient(cl);
1929 return;
1930 }
1931 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
1932 rfbLog("rfbProcessClientNormalMessage: %s",
1933 "FixColourMapEntries unsupported\n");
1934 rfbCloseClient(cl);
1935 return;
1936
1937
1938 /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features...
1939 * We may want to look into this...
1940 * Example:
1941 * case rfbEncodingXCursor:
1942 * cl->enableCursorShapeUpdates = TRUE;
1943 *
1944 * Currently: cl->enableCursorShapeUpdates can *never* be turned off...
1945 */
1946 case rfbSetEncodings:
1947 {
1948
1949 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
1950 sz_rfbSetEncodingsMsg - 1)) <= 0) {
1951 if (n != 0)
1952 rfbLogPerror("rfbProcessClientNormalMessage: read");
1953 rfbCloseClient(cl);
1954 return;
1955 }
1956
1957 msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
1958
1959 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4));
1960
1961 /*
1962 * UltraVNC Client has the ability to adapt to changing network environments
1963 * So, let's give it a change to tell us what it wants now!
1964 */
1965 if (cl->preferredEncoding!=-1)
1966 lastPreferredEncoding = cl->preferredEncoding;
1967
1968 /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */
1969 cl->preferredEncoding=-1;
1970 cl->useCopyRect = FALSE;
1971 cl->useNewFBSize = FALSE;
1972 cl->cursorWasChanged = FALSE;
1973 cl->useRichCursorEncoding = FALSE;
1974 cl->enableCursorPosUpdates = FALSE;
1975 cl->enableCursorShapeUpdates = FALSE;
1976 cl->enableCursorShapeUpdates = FALSE;
1977 cl->enableLastRectEncoding = FALSE;
1978 cl->enableKeyboardLedState = FALSE;
1979 cl->enableSupportedMessages = FALSE;
1980 cl->enableSupportedEncodings = FALSE;
1981 cl->enableServerIdentity = FALSE;
1982#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
1983 cl->tightQualityLevel = -1;
1984#ifdef LIBVNCSERVER_HAVE_LIBJPEG
1985 cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
1986 cl->turboSubsampLevel = TURBO_DEFAULT_SUBSAMP;
1987 cl->turboQualityLevel = -1;
1988#endif
1989#endif
1990
1991
1992 for (i = 0; i < msg.se.nEncodings; i++) {
1993 if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) {
1994 if (n != 0)
1995 rfbLogPerror("rfbProcessClientNormalMessage: read");
1996 rfbCloseClient(cl);
1997 return;
1998 }
1999 enc = Swap32IfLE(enc);
2000
2001 switch (enc) {
2002
2003 case rfbEncodingCopyRect:
2004 cl->useCopyRect = TRUE;
2005 break;
2006 case rfbEncodingRaw:
2007 case rfbEncodingRRE:
2008 case rfbEncodingCoRRE:
2009 case rfbEncodingHextile:
2010 case rfbEncodingUltra:
2011#ifdef LIBVNCSERVER_HAVE_LIBZ
2012 case rfbEncodingZlib:
2013 case rfbEncodingZRLE:
2014 case rfbEncodingZYWRLE:
2015#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2016 case rfbEncodingTight:
2017#endif
2018#endif
2019#ifdef LIBVNCSERVER_HAVE_LIBPNG
2020 case rfbEncodingTightPng:
2021#endif
2022 /* The first supported encoding is the 'preferred' encoding */
2023 if (cl->preferredEncoding == -1)
2024 cl->preferredEncoding = enc;
2025
2026
2027 break;
2028 case rfbEncodingXCursor:
2029 if(!cl->screen->dontConvertRichCursorToXCursor) {
2030 rfbLog("Enabling X-style cursor updates for client %s\n",
2031 cl->host);
2032 /* if cursor was drawn, hide the cursor */
2033 if(!cl->enableCursorShapeUpdates)
2034 rfbRedrawAfterHideCursor(cl,NULL);
2035
2036 cl->enableCursorShapeUpdates = TRUE;
2037 cl->cursorWasChanged = TRUE;
2038 }
2039 break;
2040 case rfbEncodingRichCursor:
2041 rfbLog("Enabling full-color cursor updates for client %s\n",
2042 cl->host);
2043 /* if cursor was drawn, hide the cursor */
2044 if(!cl->enableCursorShapeUpdates)
2045 rfbRedrawAfterHideCursor(cl,NULL);
2046
2047 cl->enableCursorShapeUpdates = TRUE;
2048 cl->useRichCursorEncoding = TRUE;
2049 cl->cursorWasChanged = TRUE;
2050 break;
2051 case rfbEncodingPointerPos:
2052 if (!cl->enableCursorPosUpdates) {
2053 rfbLog("Enabling cursor position updates for client %s\n",
2054 cl->host);
2055 cl->enableCursorPosUpdates = TRUE;
2056 cl->cursorWasMoved = TRUE;
2057 }
2058 break;
2059 case rfbEncodingLastRect:
2060 if (!cl->enableLastRectEncoding) {
2061 rfbLog("Enabling LastRect protocol extension for client "
2062 "%s\n", cl->host);
2063 cl->enableLastRectEncoding = TRUE;
2064 }
2065 break;
2066 case rfbEncodingNewFBSize:
2067 if (!cl->useNewFBSize) {
2068 rfbLog("Enabling NewFBSize protocol extension for client "
2069 "%s\n", cl->host);
2070 cl->useNewFBSize = TRUE;
2071 }
2072 break;
2073 case rfbEncodingKeyboardLedState:
2074 if (!cl->enableKeyboardLedState) {
2075 rfbLog("Enabling KeyboardLedState protocol extension for client "
2076 "%s\n", cl->host);
2077 cl->enableKeyboardLedState = TRUE;
2078 }
2079 break;
2080 case rfbEncodingSupportedMessages:
2081 if (!cl->enableSupportedMessages) {
2082 rfbLog("Enabling SupportedMessages protocol extension for client "
2083 "%s\n", cl->host);
2084 cl->enableSupportedMessages = TRUE;
2085 }
2086 break;
2087 case rfbEncodingSupportedEncodings:
2088 if (!cl->enableSupportedEncodings) {
2089 rfbLog("Enabling SupportedEncodings protocol extension for client "
2090 "%s\n", cl->host);
2091 cl->enableSupportedEncodings = TRUE;
2092 }
2093 break;
2094 case rfbEncodingServerIdentity:
2095 if (!cl->enableServerIdentity) {
2096 rfbLog("Enabling ServerIdentity protocol extension for client "
2097 "%s\n", cl->host);
2098 cl->enableServerIdentity = TRUE;
2099 }
2100 break;
2101 case rfbEncodingXvp:
2102 rfbLog("Enabling Xvp protocol extension for client "
2103 "%s\n", cl->host);
2104 if (!rfbSendXvp(cl, 1, rfbXvp_Init)) {
2105 rfbCloseClient(cl);
2106 return;
2107 }
2108 break;
2109 default:
2110#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
2111 if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
2112 enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
2113 cl->zlibCompressLevel = enc & 0x0F;
2114#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2115 cl->tightCompressLevel = enc & 0x0F;
2116 rfbLog("Using compression level %d for client %s\n",
2117 cl->tightCompressLevel, cl->host);
2118#endif
2119 } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
2120 enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
2121 cl->tightQualityLevel = enc & 0x0F;
2122 rfbLog("Using image quality level %d for client %s\n",
2123 cl->tightQualityLevel, cl->host);
2124#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2125 cl->turboQualityLevel = tight2turbo_qual[enc & 0x0F];
2126 cl->turboSubsampLevel = tight2turbo_subsamp[enc & 0x0F];
2127 rfbLog("Using JPEG subsampling %d, Q%d for client %s\n",
2128 cl->turboSubsampLevel, cl->turboQualityLevel, cl->host);
2129 } else if ( enc >= (uint32_t)rfbEncodingFineQualityLevel0 + 1 &&
2130 enc <= (uint32_t)rfbEncodingFineQualityLevel100 ) {
2131 cl->turboQualityLevel = enc & 0xFF;
2132 rfbLog("Using fine quality level %d for client %s\n",
2133 cl->turboQualityLevel, cl->host);
2134 } else if ( enc >= (uint32_t)rfbEncodingSubsamp1X &&
2135 enc <= (uint32_t)rfbEncodingSubsampGray ) {
2136 cl->turboSubsampLevel = enc & 0xFF;
2137 rfbLog("Using subsampling level %d for client %s\n",
2138 cl->turboSubsampLevel, cl->host);
2139#endif
2140 } else
2141#endif
2142 {
2143 rfbExtensionData* e;
2144 for(e = cl->extensions; e;) {
2145 rfbExtensionData* next = e->next;
2146 if(e->extension->enablePseudoEncoding &&
2147 e->extension->enablePseudoEncoding(cl,
2148 &e->data, (int)enc))
2149 /* ext handles this encoding */
2150 break;
2151 e = next;
2152 }
2153 if(e == NULL) {
2154 rfbBool handled = FALSE;
2155 /* if the pseudo encoding is not handled by the
2156 enabled extensions, search through all
2157 extensions. */
2158 rfbProtocolExtension* e;
2159
2160 for(e = rfbGetExtensionIterator(); e;) {
2161 int* encs = e->pseudoEncodings;
2162 while(encs && *encs!=0) {
2163 if(*encs==(int)enc) {
2164 void* data = NULL;
2165 if(!e->enablePseudoEncoding(cl, &data, (int)enc)) {
2166 rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc);
2167 } else {
2168 rfbEnableExtension(cl, e, data);
2169 handled = TRUE;
2170 e = NULL;
2171 break;
2172 }
2173 }
2174 encs++;
2175 }
2176
2177 if(e)
2178 e = e->next;
2179 }
2180 rfbReleaseExtensionIterator();
2181
2182 if(!handled)
2183 rfbLog("rfbProcessClientNormalMessage: "
2184 "ignoring unsupported encoding type %s\n",
2185 encodingName(enc,encBuf,sizeof(encBuf)));
2186 }
2187 }
2188 }
2189 }
2190
2191
2192
2193 if (cl->preferredEncoding == -1) {
2194 if (lastPreferredEncoding==-1) {
2195 cl->preferredEncoding = rfbEncodingRaw;
2196 rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
2197 }
2198 else {
2199 cl->preferredEncoding = lastPreferredEncoding;
2200 rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
2201 }
2202 }
2203 else
2204 {
2205 if (lastPreferredEncoding==-1) {
2206 rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
2207 } else {
2208 rfbLog("Switching from %s to %s Encoding for client %s\n",
2209 encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)),
2210 encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host);
2211 }
2212 }
2213
2214 if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
2215 rfbLog("Disabling cursor position updates for client %s\n",
2216 cl->host);
2217 cl->enableCursorPosUpdates = FALSE;
2218 }
2219
2220 return;
2221 }
2222
2223
2224 case rfbFramebufferUpdateRequest:
2225 {
2226 sraRegionPtr tmpRegion;
2227
2228 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2229 sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
2230 if (n != 0)
2231 rfbLogPerror("rfbProcessClientNormalMessage: read");
2232 rfbCloseClient(cl);
2233 return;
2234 }
2235
2236 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbFramebufferUpdateRequestMsg,sz_rfbFramebufferUpdateRequestMsg);
2237
2238 /* The values come in based on the scaled screen, we need to convert them to
2239 * values based on the main screen's coordinate system
2240 */
2241 if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,cl))
2242 {
2243 rfbLog("Warning, ignoring rfbFramebufferUpdateRequest: %dXx%dY-%dWx%dH\n",msg.fur.x, msg.fur.y, msg.fur.w, msg.fur.h);
2244 return;
2245 }
2246
2247
2248 tmpRegion =
2249 sraRgnCreateRect(msg.fur.x,
2250 msg.fur.y,
2251 msg.fur.x+msg.fur.w,
2252 msg.fur.y+msg.fur.h);
2253
2254 LOCK(cl->updateMutex);
2255 sraRgnOr(cl->requestedRegion,tmpRegion);
2256
2257 if (!cl->readyForSetColourMapEntries) {
2258 /* client hasn't sent a SetPixelFormat so is using server's */
2259 cl->readyForSetColourMapEntries = TRUE;
2260 if (!cl->format.trueColour) {
2261 if (!rfbSetClientColourMap(cl, 0, 0)) {
2262 sraRgnDestroy(tmpRegion);
2263 TSIGNAL(cl->updateCond);
2264 UNLOCK(cl->updateMutex);
2265 return;
2266 }
2267 }
2268 }
2269
2270 if (!msg.fur.incremental) {
2271 sraRgnOr(cl->modifiedRegion,tmpRegion);
2272 sraRgnSubtract(cl->copyRegion,tmpRegion);
2273 }
2274 TSIGNAL(cl->updateCond);
2275 UNLOCK(cl->updateMutex);
2276
2277 sraRgnDestroy(tmpRegion);
2278
2279 return;
2280 }
2281
2282 case rfbKeyEvent:
2283
2284 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2285 sz_rfbKeyEventMsg - 1)) <= 0) {
2286 if (n != 0)
2287 rfbLogPerror("rfbProcessClientNormalMessage: read");
2288 rfbCloseClient(cl);
2289 return;
2290 }
2291
2292 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbKeyEventMsg, sz_rfbKeyEventMsg);
2293
2294 if(!cl->viewOnly) {
2295 cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
2296 }
2297
2298 return;
2299
2300
2301 case rfbPointerEvent:
2302
2303 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2304 sz_rfbPointerEventMsg - 1)) <= 0) {
2305 if (n != 0)
2306 rfbLogPerror("rfbProcessClientNormalMessage: read");
2307 rfbCloseClient(cl);
2308 return;
2309 }
2310
2311 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbPointerEventMsg, sz_rfbPointerEventMsg);
2312
2313 if (cl->screen->pointerClient && cl->screen->pointerClient != cl)
2314 return;
2315
2316 if (msg.pe.buttonMask == 0)
2317 cl->screen->pointerClient = NULL;
2318 else
2319 cl->screen->pointerClient = cl;
2320
2321 if(!cl->viewOnly) {
2322 if (msg.pe.buttonMask != cl->lastPtrButtons ||
2323 cl->screen->deferPtrUpdateTime == 0) {
2324 cl->screen->ptrAddEvent(msg.pe.buttonMask,
2325 ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)),
2326 ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)),
2327 cl);
2328 cl->lastPtrButtons = msg.pe.buttonMask;
2329 } else {
2330 cl->lastPtrX = ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x));
2331 cl->lastPtrY = ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y));
2332 cl->lastPtrButtons = msg.pe.buttonMask;
2333 }
2334 }
2335 return;
2336
2337
2338 case rfbFileTransfer:
2339 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2340 sz_rfbFileTransferMsg - 1)) <= 0) {
2341 if (n != 0)
2342 rfbLogPerror("rfbProcessClientNormalMessage: read");
2343 rfbCloseClient(cl);
2344 return;
2345 }
2346 msg.ft.size = Swap32IfLE(msg.ft.size);
2347 msg.ft.length = Swap32IfLE(msg.ft.length);
2348 /* record statistics in rfbProcessFileTransfer as length is filled with garbage when it is not valid */
2349 rfbProcessFileTransfer(cl, msg.ft.contentType, msg.ft.contentParam, msg.ft.size, msg.ft.length);
2350 return;
2351
2352 case rfbSetSW:
2353 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2354 sz_rfbSetSWMsg - 1)) <= 0) {
2355 if (n != 0)
2356 rfbLogPerror("rfbProcessClientNormalMessage: read");
2357 rfbCloseClient(cl);
2358 return;
2359 }
2360 msg.sw.x = Swap16IfLE(msg.sw.x);
2361 msg.sw.y = Swap16IfLE(msg.sw.y);
2362 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetSWMsg, sz_rfbSetSWMsg);
2363 /* msg.sw.status is not initialized in the ultraVNC viewer and contains random numbers (why???) */
2364
2365 rfbLog("Received a rfbSetSingleWindow(%d x, %d y)\n", msg.sw.x, msg.sw.y);
2366 if (cl->screen->setSingleWindow!=NULL)
2367 cl->screen->setSingleWindow(cl, msg.sw.x, msg.sw.y);
2368 return;
2369
2370 case rfbSetServerInput:
2371 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2372 sz_rfbSetServerInputMsg - 1)) <= 0) {
2373 if (n != 0)
2374 rfbLogPerror("rfbProcessClientNormalMessage: read");
2375 rfbCloseClient(cl);
2376 return;
2377 }
2378 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetServerInputMsg, sz_rfbSetServerInputMsg);
2379
2380 /* msg.sim.pad is not initialized in the ultraVNC viewer and contains random numbers (why???) */
2381 /* msg.sim.pad = Swap16IfLE(msg.sim.pad); */
2382
2383 rfbLog("Received a rfbSetServerInput(%d status)\n", msg.sim.status);
2384 if (cl->screen->setServerInput!=NULL)
2385 cl->screen->setServerInput(cl, msg.sim.status);
2386 return;
2387
2388 case rfbTextChat:
2389 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2390 sz_rfbTextChatMsg - 1)) <= 0) {
2391 if (n != 0)
2392 rfbLogPerror("rfbProcessClientNormalMessage: read");
2393 rfbCloseClient(cl);
2394 return;
2395 }
2396
2397 msg.tc.pad2 = Swap16IfLE(msg.tc.pad2);
2398 msg.tc.length = Swap32IfLE(msg.tc.length);
2399
2400 switch (msg.tc.length) {
2401 case rfbTextChatOpen:
2402 case rfbTextChatClose:
2403 case rfbTextChatFinished:
2404 /* commands do not have text following */
2405 /* Why couldn't they have used the pad byte??? */
2406 str=NULL;
2407 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg, sz_rfbTextChatMsg);
2408 break;
2409 default:
2410 if ((msg.tc.length>0) && (msg.tc.length<rfbTextMaxSize))
2411 {
2412 str = (char *)malloc(msg.tc.length);
2413 if (str==NULL)
2414 {
2415 rfbLog("Unable to malloc %d bytes for a TextChat Message\n", msg.tc.length);
2416 rfbCloseClient(cl);
2417 return;
2418 }
2419 if ((n = rfbReadExact(cl, str, msg.tc.length)) <= 0) {
2420 if (n != 0)
2421 rfbLogPerror("rfbProcessClientNormalMessage: read");
2422 free(str);
2423 rfbCloseClient(cl);
2424 return;
2425 }
2426 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg+msg.tc.length, sz_rfbTextChatMsg+msg.tc.length);
2427 }
2428 else
2429 {
2430 /* This should never happen */
2431 rfbLog("client sent us a Text Message that is too big %d>%d\n", msg.tc.length, rfbTextMaxSize);
2432 rfbCloseClient(cl);
2433 return;
2434 }
2435 }
2436
2437 /* Note: length can be commands: rfbTextChatOpen, rfbTextChatClose, and rfbTextChatFinished
2438 * at which point, the str is NULL (as it is not sent)
2439 */
2440 if (cl->screen->setTextChat!=NULL)
2441 cl->screen->setTextChat(cl, msg.tc.length, str);
2442
2443 free(str);
2444 return;
2445
2446
2447 case rfbClientCutText:
2448
2449 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2450 sz_rfbClientCutTextMsg - 1)) <= 0) {
2451 if (n != 0)
2452 rfbLogPerror("rfbProcessClientNormalMessage: read");
2453 rfbCloseClient(cl);
2454 return;
2455 }
2456
2457 msg.cct.length = Swap32IfLE(msg.cct.length);
2458
2459 str = (char *)malloc(msg.cct.length);
2460
2461 if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) {
2462 if (n != 0)
2463 rfbLogPerror("rfbProcessClientNormalMessage: read");
2464 free(str);
2465 rfbCloseClient(cl);
2466 return;
2467 }
2468 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbClientCutTextMsg+msg.cct.length, sz_rfbClientCutTextMsg+msg.cct.length);
2469 if(!cl->viewOnly) {
2470 cl->screen->setXCutText(str, msg.cct.length, cl);
2471 }
2472 free(str);
2473
2474 return;
2475
2476 case rfbPalmVNCSetScaleFactor:
2477 cl->PalmVNC = TRUE;
2478 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2479 sz_rfbSetScaleMsg - 1)) <= 0) {
2480 if (n != 0)
2481 rfbLogPerror("rfbProcessClientNormalMessage: read");
2482 rfbCloseClient(cl);
2483 return;
2484 }
2485 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg);
2486 rfbLog("rfbSetScale(%d)\n", msg.ssc.scale);
2487 rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale);
2488
2489 rfbSendNewScaleSize(cl);
2490 return;
2491
2492 case rfbSetScale:
2493
2494 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2495 sz_rfbSetScaleMsg - 1)) <= 0) {
2496 if (n != 0)
2497 rfbLogPerror("rfbProcessClientNormalMessage: read");
2498 rfbCloseClient(cl);
2499 return;
2500 }
2501 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg);
2502 rfbLog("rfbSetScale(%d)\n", msg.ssc.scale);
2503 rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale);
2504
2505 rfbSendNewScaleSize(cl);
2506 return;
2507
2508 case rfbXvp:
2509
2510 if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2511 sz_rfbXvpMsg - 1)) <= 0) {
2512 if (n != 0)
2513 rfbLogPerror("rfbProcessClientNormalMessage: read");
2514 rfbCloseClient(cl);
2515 return;
2516 }
2517 rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbXvpMsg, sz_rfbXvpMsg);
2518
2519 /* only version when is defined, so echo back a fail */
2520 if(msg.xvp.version != 1) {
2521 rfbSendXvp(cl, msg.xvp.version, rfbXvp_Fail);
2522 }
2523 else {
2524 /* if the hook exists and fails, send a fail msg */
2525 if(cl->screen->xvpHook && !cl->screen->xvpHook(cl, msg.xvp.version, msg.xvp.code))
2526 rfbSendXvp(cl, 1, rfbXvp_Fail);
2527 }
2528 return;
2529
2530 default:
2531 {
2532 rfbExtensionData *e,*next;
2533
2534 for(e=cl->extensions; e;) {
2535 next = e->next;
2536 if(e->extension->handleMessage &&
2537 e->extension->handleMessage(cl, e->data, &msg))
2538 {
2539 rfbStatRecordMessageRcvd(cl, msg.type, 0, 0); /* Extension should handle this */
2540 return;
2541 }
2542 e = next;
2543 }
2544
2545 rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
2546 msg.type);
2547 rfbLog(" ... closing connection\n");
2548 rfbCloseClient(cl);
2549 return;
2550 }
2551 }
2552}
2553
2554
2555
2556/*
2557 * rfbSendFramebufferUpdate - send the currently pending framebuffer update to
2558 * the RFB client.
2559 * givenUpdateRegion is not changed.
2560 */
2561
2562rfbBool
2563rfbSendFramebufferUpdate(rfbClientPtr cl,
2564 sraRegionPtr givenUpdateRegion)
2565{
2566 sraRectangleIterator* i=NULL;
2567 sraRect rect;
2568 int nUpdateRegionRects;
2569 rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
2570 sraRegionPtr updateRegion,updateCopyRegion,tmpRegion;
2571 int dx, dy;
2572 rfbBool sendCursorShape = FALSE;
2573 rfbBool sendCursorPos = FALSE;
2574 rfbBool sendKeyboardLedState = FALSE;
2575 rfbBool sendSupportedMessages = FALSE;
2576 rfbBool sendSupportedEncodings = FALSE;
2577 rfbBool sendServerIdentity = FALSE;
2578 rfbBool result = TRUE;
2579
2580
2581 if(cl->screen->displayHook)
2582 cl->screen->displayHook(cl);
2583
2584 /*
2585 * If framebuffer size was changed and the client supports NewFBSize
2586 * encoding, just send NewFBSize marker and return.
2587 */
2588
2589 if (cl->useNewFBSize && cl->newFBSizePending) {
2590 LOCK(cl->updateMutex);
2591 cl->newFBSizePending = FALSE;
2592 UNLOCK(cl->updateMutex);
2593 fu->type = rfbFramebufferUpdate;
2594 fu->nRects = Swap16IfLE(1);
2595 cl->ublen = sz_rfbFramebufferUpdateMsg;
2596 if (!rfbSendNewFBSize(cl, cl->scaledScreen->width, cl->scaledScreen->height)) {
2597 if(cl->screen->displayFinishedHook)
2598 cl->screen->displayFinishedHook(cl, FALSE);
2599 return FALSE;
2600 }
2601 result = rfbSendUpdateBuf(cl);
2602 if(cl->screen->displayFinishedHook)
2603 cl->screen->displayFinishedHook(cl, result);
2604 return result;
2605 }
2606
2607 /*
2608 * If this client understands cursor shape updates, cursor should be
2609 * removed from the framebuffer. Otherwise, make sure it's put up.
2610 */
2611
2612 if (cl->enableCursorShapeUpdates) {
2613 if (cl->cursorWasChanged && cl->readyForSetColourMapEntries)
2614 sendCursorShape = TRUE;
2615 }
2616
2617 /*
2618 * Do we plan to send cursor position update?
2619 */
2620
2621 if (cl->enableCursorPosUpdates && cl->cursorWasMoved)
2622 sendCursorPos = TRUE;
2623
2624 /*
2625 * Do we plan to send a keyboard state update?
2626 */
2627 if ((cl->enableKeyboardLedState) &&
2628 (cl->screen->getKeyboardLedStateHook!=NULL))
2629 {
2630 int x;
2631 x=cl->screen->getKeyboardLedStateHook(cl->screen);
2632 if (x!=cl->lastKeyboardLedState)
2633 {
2634 sendKeyboardLedState = TRUE;
2635 cl->lastKeyboardLedState=x;
2636 }
2637 }
2638
2639 /*
2640 * Do we plan to send a rfbEncodingSupportedMessages?
2641 */
2642 if (cl->enableSupportedMessages)
2643 {
2644 sendSupportedMessages = TRUE;
2645 /* We only send this message ONCE <per setEncodings message received>
2646 * (We disable it here)
2647 */
2648 cl->enableSupportedMessages = FALSE;
2649 }
2650 /*
2651 * Do we plan to send a rfbEncodingSupportedEncodings?
2652 */
2653 if (cl->enableSupportedEncodings)
2654 {
2655 sendSupportedEncodings = TRUE;
2656 /* We only send this message ONCE <per setEncodings message received>
2657 * (We disable it here)
2658 */
2659 cl->enableSupportedEncodings = FALSE;
2660 }
2661 /*
2662 * Do we plan to send a rfbEncodingServerIdentity?
2663 */
2664 if (cl->enableServerIdentity)
2665 {
2666 sendServerIdentity = TRUE;
2667 /* We only send this message ONCE <per setEncodings message received>
2668 * (We disable it here)
2669 */
2670 cl->enableServerIdentity = FALSE;
2671 }
2672
2673 LOCK(cl->updateMutex);
2674
2675 /*
2676 * The modifiedRegion may overlap the destination copyRegion. We remove
2677 * any overlapping bits from the copyRegion (since they'd only be
2678 * overwritten anyway).
2679 */
2680
2681 sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
2682
2683 /*
2684 * The client is interested in the region requestedRegion. The region
2685 * which should be updated now is the intersection of requestedRegion
2686 * and the union of modifiedRegion and copyRegion. If it's empty then
2687 * no update is needed.
2688 */
2689
2690 updateRegion = sraRgnCreateRgn(givenUpdateRegion);
2691 if(cl->screen->progressiveSliceHeight>0) {
2692 int height=cl->screen->progressiveSliceHeight,
2693 y=cl->progressiveSliceY;
2694 sraRegionPtr bbox=sraRgnBBox(updateRegion);
2695 sraRect rect;
2696 if(sraRgnPopRect(bbox,&rect,0)) {
2697 sraRegionPtr slice;
2698 if(y<rect.y1 || y>=rect.y2)
2699 y=rect.y1;
2700 slice=sraRgnCreateRect(0,y,cl->screen->width,y+height);
2701 sraRgnAnd(updateRegion,slice);
2702 sraRgnDestroy(slice);
2703 }
2704 sraRgnDestroy(bbox);
2705 y+=height;
2706 if(y>=cl->screen->height)
2707 y=0;
2708 cl->progressiveSliceY=y;
2709 }
2710
2711 sraRgnOr(updateRegion,cl->copyRegion);
2712 if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
2713 sraRgnEmpty(updateRegion) &&
2714 (cl->enableCursorShapeUpdates ||
2715 (cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) &&
2716 !sendCursorShape && !sendCursorPos && !sendKeyboardLedState &&
2717 !sendSupportedMessages && !sendSupportedEncodings && !sendServerIdentity) {
2718 sraRgnDestroy(updateRegion);
2719 UNLOCK(cl->updateMutex);
2720 if(cl->screen->displayFinishedHook)
2721 cl->screen->displayFinishedHook(cl, TRUE);
2722 return TRUE;
2723 }
2724
2725 /*
2726 * We assume that the client doesn't have any pixel data outside the
2727 * requestedRegion. In other words, both the source and destination of a
2728 * copy must lie within requestedRegion. So the region we can send as a
2729 * copy is the intersection of the copyRegion with both the requestedRegion
2730 * and the requestedRegion translated by the amount of the copy. We set
2731 * updateCopyRegion to this.
2732 */
2733
2734 updateCopyRegion = sraRgnCreateRgn(cl->copyRegion);
2735 sraRgnAnd(updateCopyRegion,cl->requestedRegion);
2736 tmpRegion = sraRgnCreateRgn(cl->requestedRegion);
2737 sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY);
2738 sraRgnAnd(updateCopyRegion,tmpRegion);
2739 sraRgnDestroy(tmpRegion);
2740 dx = cl->copyDX;
2741 dy = cl->copyDY;
2742
2743 /*
2744 * Next we remove updateCopyRegion from updateRegion so that updateRegion
2745 * is the part of this update which is sent as ordinary pixel data (i.e not
2746 * a copy).
2747 */
2748
2749 sraRgnSubtract(updateRegion,updateCopyRegion);
2750
2751 /*
2752 * Finally we leave modifiedRegion to be the remainder (if any) of parts of
2753 * the screen which are modified but outside the requestedRegion. We also
2754 * empty both the requestedRegion and the copyRegion - note that we never
2755 * carry over a copyRegion for a future update.
2756 */
2757
2758 sraRgnOr(cl->modifiedRegion,cl->copyRegion);
2759 sraRgnSubtract(cl->modifiedRegion,updateRegion);
2760 sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
2761
2762 sraRgnMakeEmpty(cl->requestedRegion);
2763 sraRgnMakeEmpty(cl->copyRegion);
2764 cl->copyDX = 0;
2765 cl->copyDY = 0;
2766
2767 UNLOCK(cl->updateMutex);
2768
2769 if (!cl->enableCursorShapeUpdates) {
2770 if(cl->cursorX != cl->screen->cursorX || cl->cursorY != cl->screen->cursorY) {
2771 rfbRedrawAfterHideCursor(cl,updateRegion);
2772 LOCK(cl->screen->cursorMutex);
2773 cl->cursorX = cl->screen->cursorX;
2774 cl->cursorY = cl->screen->cursorY;
2775 UNLOCK(cl->screen->cursorMutex);
2776 rfbRedrawAfterHideCursor(cl,updateRegion);
2777 }
2778 rfbShowCursor(cl);
2779 }
2780
2781 /*
2782 * Now send the update.
2783 */
2784
2785 rfbStatRecordMessageSent(cl, rfbFramebufferUpdate, 0, 0);
2786 if (cl->preferredEncoding == rfbEncodingCoRRE) {
2787 nUpdateRegionRects = 0;
2788
2789 for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2790 int x = rect.x1;
2791 int y = rect.y1;
2792 int w = rect.x2 - x;
2793 int h = rect.y2 - y;
2794 int rectsPerRow, rows;
2795 /* We need to count the number of rects in the scaled screen */
2796 if (cl->screen!=cl->scaledScreen)
2797 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2798 rectsPerRow = (w-1)/cl->correMaxWidth+1;
2799 rows = (h-1)/cl->correMaxHeight+1;
2800 nUpdateRegionRects += rectsPerRow*rows;
2801 }
2802 sraRgnReleaseIterator(i); i=NULL;
2803 } else if (cl->preferredEncoding == rfbEncodingUltra) {
2804 nUpdateRegionRects = 0;
2805
2806 for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2807 int x = rect.x1;
2808 int y = rect.y1;
2809 int w = rect.x2 - x;
2810 int h = rect.y2 - y;
2811 /* We need to count the number of rects in the scaled screen */
2812 if (cl->screen!=cl->scaledScreen)
2813 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2814 nUpdateRegionRects += (((h-1) / (ULTRA_MAX_SIZE( w ) / w)) + 1);
2815 }
2816 sraRgnReleaseIterator(i); i=NULL;
2817#ifdef LIBVNCSERVER_HAVE_LIBZ
2818 } else if (cl->preferredEncoding == rfbEncodingZlib) {
2819 nUpdateRegionRects = 0;
2820
2821 for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2822 int x = rect.x1;
2823 int y = rect.y1;
2824 int w = rect.x2 - x;
2825 int h = rect.y2 - y;
2826 /* We need to count the number of rects in the scaled screen */
2827 if (cl->screen!=cl->scaledScreen)
2828 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2829 nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
2830 }
2831 sraRgnReleaseIterator(i); i=NULL;
2832#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2833 } else if (cl->preferredEncoding == rfbEncodingTight) {
2834 nUpdateRegionRects = 0;
2835
2836 for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2837 int x = rect.x1;
2838 int y = rect.y1;
2839 int w = rect.x2 - x;
2840 int h = rect.y2 - y;
2841 int n;
2842 /* We need to count the number of rects in the scaled screen */
2843 if (cl->screen!=cl->scaledScreen)
2844 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2845 n = rfbNumCodedRectsTight(cl, x, y, w, h);
2846 if (n == 0) {
2847 nUpdateRegionRects = 0xFFFF;
2848 break;
2849 }
2850 nUpdateRegionRects += n;
2851 }
2852 sraRgnReleaseIterator(i); i=NULL;
2853#endif
2854#endif
2855#if defined(LIBVNCSERVER_HAVE_LIBJPEG) && defined(LIBVNCSERVER_HAVE_LIBPNG)
2856 } else if (cl->preferredEncoding == rfbEncodingTightPng) {
2857 nUpdateRegionRects = 0;
2858
2859 for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2860 int x = rect.x1;
2861 int y = rect.y1;
2862 int w = rect.x2 - x;
2863 int h = rect.y2 - y;
2864 int n;
2865 /* We need to count the number of rects in the scaled screen */
2866 if (cl->screen!=cl->scaledScreen)
2867 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2868 n = rfbNumCodedRectsTight(cl, x, y, w, h);
2869 if (n == 0) {
2870 nUpdateRegionRects = 0xFFFF;
2871 break;
2872 }
2873 nUpdateRegionRects += n;
2874 }
2875 sraRgnReleaseIterator(i); i=NULL;
2876#endif
2877 } else {
2878 nUpdateRegionRects = sraRgnCountRects(updateRegion);
2879 }
2880
2881 fu->type = rfbFramebufferUpdate;
2882 if (nUpdateRegionRects != 0xFFFF) {
2883 if(cl->screen->maxRectsPerUpdate>0
2884 /* CoRRE splits the screen into smaller squares */
2885 && cl->preferredEncoding != rfbEncodingCoRRE
2886 /* Ultra encoding splits rectangles up into smaller chunks */
2887 && cl->preferredEncoding != rfbEncodingUltra
2888#ifdef LIBVNCSERVER_HAVE_LIBZ
2889 /* Zlib encoding splits rectangles up into smaller chunks */
2890 && cl->preferredEncoding != rfbEncodingZlib
2891#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2892 /* Tight encoding counts the rectangles differently */
2893 && cl->preferredEncoding != rfbEncodingTight
2894#endif
2895#endif
2896#ifdef LIBVNCSERVER_HAVE_LIBPNG
2897 /* Tight encoding counts the rectangles differently */
2898 && cl->preferredEncoding != rfbEncodingTightPng
2899#endif
2900 && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
2901 sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
2902 sraRgnDestroy(updateRegion);
2903 updateRegion = newUpdateRegion;
2904 nUpdateRegionRects = sraRgnCountRects(updateRegion);
2905 }
2906 fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
2907 nUpdateRegionRects +
2908 !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState +
2909 !!sendSupportedMessages + !!sendSupportedEncodings + !!sendServerIdentity));
2910 } else {
2911 fu->nRects = 0xFFFF;
2912 }
2913 cl->ublen = sz_rfbFramebufferUpdateMsg;
2914
2915 if (sendCursorShape) {
2916 cl->cursorWasChanged = FALSE;
2917 if (!rfbSendCursorShape(cl))
2918 goto updateFailed;
2919 }
2920
2921 if (sendCursorPos) {
2922 cl->cursorWasMoved = FALSE;
2923 if (!rfbSendCursorPos(cl))
2924 goto updateFailed;
2925 }
2926
2927 if (sendKeyboardLedState) {
2928 if (!rfbSendKeyboardLedState(cl))
2929 goto updateFailed;
2930 }
2931
2932 if (sendSupportedMessages) {
2933 if (!rfbSendSupportedMessages(cl))
2934 goto updateFailed;
2935 }
2936 if (sendSupportedEncodings) {
2937 if (!rfbSendSupportedEncodings(cl))
2938 goto updateFailed;
2939 }
2940 if (sendServerIdentity) {
2941 if (!rfbSendServerIdentity(cl))
2942 goto updateFailed;
2943 }
2944
2945 if (!sraRgnEmpty(updateCopyRegion)) {
2946 if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))
2947 goto updateFailed;
2948 }
2949
2950 for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2951 int x = rect.x1;
2952 int y = rect.y1;
2953 int w = rect.x2 - x;
2954 int h = rect.y2 - y;
2955
2956 /* We need to count the number of rects in the scaled screen */
2957 if (cl->screen!=cl->scaledScreen)
2958 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2959
2960 switch (cl->preferredEncoding) {
2961 case -1:
2962 case rfbEncodingRaw:
2963 if (!rfbSendRectEncodingRaw(cl, x, y, w, h))
2964 goto updateFailed;
2965 break;
2966 case rfbEncodingRRE:
2967 if (!rfbSendRectEncodingRRE(cl, x, y, w, h))
2968 goto updateFailed;
2969 break;
2970 case rfbEncodingCoRRE:
2971 if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h))
2972 goto updateFailed;
2973 break;
2974 case rfbEncodingHextile:
2975 if (!rfbSendRectEncodingHextile(cl, x, y, w, h))
2976 goto updateFailed;
2977 break;
2978 case rfbEncodingUltra:
2979 if (!rfbSendRectEncodingUltra(cl, x, y, w, h))
2980 goto updateFailed;
2981 break;
2982#ifdef LIBVNCSERVER_HAVE_LIBZ
2983 case rfbEncodingZlib:
2984 if (!rfbSendRectEncodingZlib(cl, x, y, w, h))
2985 goto updateFailed;
2986 break;
2987 case rfbEncodingZRLE:
2988 case rfbEncodingZYWRLE:
2989 if (!rfbSendRectEncodingZRLE(cl, x, y, w, h))
2990 goto updateFailed;
2991 break;
2992#endif
2993#if defined(LIBVNCSERVER_HAVE_LIBJPEG) && (defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG))
2994 case rfbEncodingTight:
2995 if (!rfbSendRectEncodingTight(cl, x, y, w, h))
2996 goto updateFailed;
2997 break;
2998#ifdef LIBVNCSERVER_HAVE_LIBPNG
2999 case rfbEncodingTightPng:
3000 if (!rfbSendRectEncodingTightPng(cl, x, y, w, h))
3001 goto updateFailed;
3002 break;
3003#endif
3004#endif
3005 }
3006 }
3007 if (i) {
3008 sraRgnReleaseIterator(i);
3009 i = NULL;
3010 }
3011
3012 if ( nUpdateRegionRects == 0xFFFF &&
3013 !rfbSendLastRectMarker(cl) )
3014 goto updateFailed;
3015
3016 if (!rfbSendUpdateBuf(cl)) {
3017updateFailed:
3018 result = FALSE;
3019 }
3020
3021 if (!cl->enableCursorShapeUpdates) {
3022 rfbHideCursor(cl);
3023 }
3024
3025 if(i)
3026 sraRgnReleaseIterator(i);
3027 sraRgnDestroy(updateRegion);
3028 sraRgnDestroy(updateCopyRegion);
3029
3030 if(cl->screen->displayFinishedHook)
3031 cl->screen->displayFinishedHook(cl, result);
3032 return result;
3033}
3034
3035
3036/*
3037 * Send the copy region as a string of CopyRect encoded rectangles.
3038 * The only slightly tricky thing is that we should send the messages in
3039 * the correct order so that an earlier CopyRect will not corrupt the source
3040 * of a later one.
3041 */
3042
3043rfbBool
3044rfbSendCopyRegion(rfbClientPtr cl,
3045 sraRegionPtr reg,
3046 int dx,
3047 int dy)
3048{
3049 int x, y, w, h;
3050 rfbFramebufferUpdateRectHeader rect;
3051 rfbCopyRect cr;
3052 sraRectangleIterator* i;
3053 sraRect rect1;
3054
3055 /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
3056 i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
3057
3058 /* correct for the scale of the screen */
3059 dx = ScaleX(cl->screen, cl->scaledScreen, dx);
3060 dy = ScaleX(cl->screen, cl->scaledScreen, dy);
3061
3062 while(sraRgnIteratorNext(i,&rect1)) {
3063 x = rect1.x1;
3064 y = rect1.y1;
3065 w = rect1.x2 - x;
3066 h = rect1.y2 - y;
3067
3068 /* correct for scaling (if necessary) */
3069 rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "copyrect");
3070
3071 rect.r.x = Swap16IfLE(x);
3072 rect.r.y = Swap16IfLE(y);
3073 rect.r.w = Swap16IfLE(w);
3074 rect.r.h = Swap16IfLE(h);
3075 rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
3076
3077 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
3078 sz_rfbFramebufferUpdateRectHeader);
3079 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3080
3081 cr.srcX = Swap16IfLE(x - dx);
3082 cr.srcY = Swap16IfLE(y - dy);
3083
3084 memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
3085 cl->ublen += sz_rfbCopyRect;
3086
3087 rfbStatRecordEncodingSent(cl, rfbEncodingCopyRect, sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect,
3088 w * h * (cl->scaledScreen->bitsPerPixel / 8));
3089 }
3090 sraRgnReleaseIterator(i);
3091
3092 return TRUE;
3093}
3094
3095/*
3096 * Send a given rectangle in raw encoding (rfbEncodingRaw).
3097 */
3098
3099rfbBool
3100rfbSendRectEncodingRaw(rfbClientPtr cl,
3101 int x,
3102 int y,
3103 int w,
3104 int h)
3105{
3106 rfbFramebufferUpdateRectHeader rect;
3107 int nlines;
3108 int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
3109 char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
3110 + (x * (cl->scaledScreen->bitsPerPixel / 8)));
3111
3112 /* Flush the buffer to guarantee correct alignment for translateFn(). */
3113 if (cl->ublen > 0) {
3114 if (!rfbSendUpdateBuf(cl))
3115 return FALSE;
3116 }
3117
3118 rect.r.x = Swap16IfLE(x);
3119 rect.r.y = Swap16IfLE(y);
3120 rect.r.w = Swap16IfLE(w);
3121 rect.r.h = Swap16IfLE(h);
3122 rect.encoding = Swap32IfLE(rfbEncodingRaw);
3123
3124 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
3125 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3126
3127
3128 rfbStatRecordEncodingSent(cl, rfbEncodingRaw, sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h,
3129 sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h);
3130
3131 nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
3132
3133 while (TRUE) {
3134 if (nlines > h)
3135 nlines = h;
3136
3137 (*cl->translateFn)(cl->translateLookupTable,
3138 &(cl->screen->serverFormat),
3139 &cl->format, fbptr, &cl->updateBuf[cl->ublen],
3140 cl->scaledScreen->paddedWidthInBytes, w, nlines);
3141
3142 cl->ublen += nlines * bytesPerLine;
3143 h -= nlines;
3144
3145 if (h == 0) /* rect fitted in buffer, do next one */
3146 return TRUE;
3147
3148 /* buffer full - flush partial rect and do another nlines */
3149
3150 if (!rfbSendUpdateBuf(cl))
3151 return FALSE;
3152
3153 fbptr += (cl->scaledScreen->paddedWidthInBytes * nlines);
3154
3155 nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
3156 if (nlines == 0) {
3157 rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
3158 "bytes per line\n", bytesPerLine);
3159 rfbCloseClient(cl);
3160 return FALSE;
3161 }
3162 }
3163}
3164
3165
3166
3167/*
3168 * Send an empty rectangle with encoding field set to value of
3169 * rfbEncodingLastRect to notify client that this is the last
3170 * rectangle in framebuffer update ("LastRect" extension of RFB
3171 * protocol).
3172 */
3173
3174rfbBool
3175rfbSendLastRectMarker(rfbClientPtr cl)
3176{
3177 rfbFramebufferUpdateRectHeader rect;
3178
3179 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
3180 if (!rfbSendUpdateBuf(cl))
3181 return FALSE;
3182 }
3183
3184 rect.encoding = Swap32IfLE(rfbEncodingLastRect);
3185 rect.r.x = 0;
3186 rect.r.y = 0;
3187 rect.r.w = 0;
3188 rect.r.h = 0;
3189
3190 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
3191 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3192
3193
3194 rfbStatRecordEncodingSent(cl, rfbEncodingLastRect, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
3195
3196 return TRUE;
3197}
3198
3199
3200/*
3201 * Send NewFBSize pseudo-rectangle. This tells the client to change
3202 * its framebuffer size.
3203 */
3204
3205rfbBool
3206rfbSendNewFBSize(rfbClientPtr cl,
3207 int w,
3208 int h)
3209{
3210 rfbFramebufferUpdateRectHeader rect;
3211
3212 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
3213 if (!rfbSendUpdateBuf(cl))
3214 return FALSE;
3215 }
3216
3217 if (cl->PalmVNC==TRUE)
3218 rfbLog("Sending rfbEncodingNewFBSize in response to a PalmVNC style framebuffer resize (%dx%d)\n", w, h);
3219 else
3220 rfbLog("Sending rfbEncodingNewFBSize for resize to (%dx%d)\n", w, h);
3221
3222 rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
3223 rect.r.x = 0;
3224 rect.r.y = 0;
3225 rect.r.w = Swap16IfLE(w);
3226 rect.r.h = Swap16IfLE(h);
3227
3228 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
3229 sz_rfbFramebufferUpdateRectHeader);
3230 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3231
3232 rfbStatRecordEncodingSent(cl, rfbEncodingNewFBSize, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
3233
3234 return TRUE;
3235}
3236
3237
3238/*
3239 * Send the contents of cl->updateBuf. Returns 1 if successful, -1 if
3240 * not (errno should be set).
3241 */
3242
3243rfbBool
3244rfbSendUpdateBuf(rfbClientPtr cl)
3245{
3246 if(cl->sock<0)
3247 return FALSE;
3248
3249 if (rfbWriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
3250 rfbLogPerror("rfbSendUpdateBuf: write");
3251 rfbCloseClient(cl);
3252 return FALSE;
3253 }
3254
3255 cl->ublen = 0;
3256 return TRUE;
3257}
3258
3259/*
3260 * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
3261 * client, using values from the currently installed colormap.
3262 */
3263
3264rfbBool
3265rfbSendSetColourMapEntries(rfbClientPtr cl,
3266 int firstColour,
3267 int nColours)
3268{
3269 char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
3270 char *wbuf = buf;
3271 rfbSetColourMapEntriesMsg *scme;
3272 uint16_t *rgb;
3273 rfbColourMap* cm = &cl->screen->colourMap;
3274 int i, len;
3275
3276 if (nColours > 256) {
3277 /* some rare hardware has, e.g., 4096 colors cells: PseudoColor:12 */
3278 wbuf = (char *) malloc(sz_rfbSetColourMapEntriesMsg + nColours * 3 * 2);
3279 }
3280
3281 scme = (rfbSetColourMapEntriesMsg *)wbuf;
3282 rgb = (uint16_t *)(&wbuf[sz_rfbSetColourMapEntriesMsg]);
3283
3284 scme->type = rfbSetColourMapEntries;
3285
3286 scme->firstColour = Swap16IfLE(firstColour);
3287 scme->nColours = Swap16IfLE(nColours);
3288
3289 len = sz_rfbSetColourMapEntriesMsg;
3290
3291 for (i = 0; i < nColours; i++) {
3292 if(i<(int)cm->count) {
3293 if(cm->is16) {
3294 rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
3295 rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
3296 rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
3297 } else {
3298 rgb[i*3] = Swap16IfLE((unsigned short)cm->data.bytes[i*3]);
3299 rgb[i*3+1] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+1]);
3300 rgb[i*3+2] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+2]);
3301 }
3302 }
3303 }
3304
3305 len += nColours * 3 * 2;
3306
3307 LOCK(cl->sendMutex);
3308 if (rfbWriteExact(cl, wbuf, len) < 0) {
3309 rfbLogPerror("rfbSendSetColourMapEntries: write");
3310 rfbCloseClient(cl);
3311 if (wbuf != buf) free(wbuf);
3312 UNLOCK(cl->sendMutex);
3313 return FALSE;
3314 }
3315 UNLOCK(cl->sendMutex);
3316
3317 rfbStatRecordMessageSent(cl, rfbSetColourMapEntries, len, len);
3318 if (wbuf != buf) free(wbuf);
3319 return TRUE;
3320}
3321
3322/*
3323 * rfbSendBell sends a Bell message to all the clients.
3324 */
3325
3326void
3327rfbSendBell(rfbScreenInfoPtr rfbScreen)
3328{
3329 rfbClientIteratorPtr i;
3330 rfbClientPtr cl;
3331 rfbBellMsg b;
3332
3333 i = rfbGetClientIterator(rfbScreen);
3334 while((cl=rfbClientIteratorNext(i))) {
3335 b.type = rfbBell;
3336 LOCK(cl->sendMutex);
3337 if (rfbWriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
3338 rfbLogPerror("rfbSendBell: write");
3339 rfbCloseClient(cl);
3340 }
3341 UNLOCK(cl->sendMutex);
3342 }
3343 rfbStatRecordMessageSent(cl, rfbBell, sz_rfbBellMsg, sz_rfbBellMsg);
3344 rfbReleaseClientIterator(i);
3345}
3346
3347
3348/*
3349 * rfbSendServerCutText sends a ServerCutText message to all the clients.
3350 */
3351
3352void
3353rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
3354{
3355 rfbClientPtr cl;
3356 rfbServerCutTextMsg sct;
3357 rfbClientIteratorPtr iterator;
3358
3359 iterator = rfbGetClientIterator(rfbScreen);
3360 while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
3361 sct.type = rfbServerCutText;
3362 sct.length = Swap32IfLE(len);
3363 LOCK(cl->sendMutex);
3364 if (rfbWriteExact(cl, (char *)&sct,
3365 sz_rfbServerCutTextMsg) < 0) {
3366 rfbLogPerror("rfbSendServerCutText: write");
3367 rfbCloseClient(cl);
3368 UNLOCK(cl->sendMutex);
3369 continue;
3370 }
3371 if (rfbWriteExact(cl, str, len) < 0) {
3372 rfbLogPerror("rfbSendServerCutText: write");
3373 rfbCloseClient(cl);
3374 }
3375 UNLOCK(cl->sendMutex);
3376 rfbStatRecordMessageSent(cl, rfbServerCutText, sz_rfbServerCutTextMsg+len, sz_rfbServerCutTextMsg+len);
3377 }
3378 rfbReleaseClientIterator(iterator);
3379}
3380
3381/*****************************************************************************
3382 *
3383 * UDP can be used for keyboard and pointer events when the underlying
3384 * network is highly reliable. This is really here to support ORL's
3385 * videotile, whose TCP implementation doesn't like sending lots of small
3386 * packets (such as 100s of pen readings per second!).
3387 */
3388
3389static unsigned char ptrAcceleration = 50;
3390
3391void
3392rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,
3393 int sock)
3394{
3395 if (write(sock, (char*) &ptrAcceleration, 1) < 0) {
3396 rfbLogPerror("rfbNewUDPConnection: write");
3397 }
3398}
3399
3400/*
3401 * Because UDP is a message based service, we can't read the first byte and
3402 * then the rest of the packet separately like we do with TCP. We will always
3403 * get a whole packet delivered in one go, so we ask read() for the maximum
3404 * number of bytes we can possibly get.
3405 */
3406
3407void
3408rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen)
3409{
3410 int n;
3411 rfbClientPtr cl=rfbScreen->udpClient;
3412 rfbClientToServerMsg msg;
3413
3414 if((!cl) || cl->onHold)
3415 return;
3416
3417 if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) {
3418 if (n < 0) {
3419 rfbLogPerror("rfbProcessUDPInput: read");
3420 }
3421 rfbDisconnectUDPSock(rfbScreen);
3422 return;
3423 }
3424
3425 switch (msg.type) {
3426
3427 case rfbKeyEvent:
3428 if (n != sz_rfbKeyEventMsg) {
3429 rfbErr("rfbProcessUDPInput: key event incorrect length\n");
3430 rfbDisconnectUDPSock(rfbScreen);
3431 return;
3432 }
3433 cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
3434 break;
3435
3436 case rfbPointerEvent:
3437 if (n != sz_rfbPointerEventMsg) {
3438 rfbErr("rfbProcessUDPInput: ptr event incorrect length\n");
3439 rfbDisconnectUDPSock(rfbScreen);
3440 return;
3441 }
3442 cl->screen->ptrAddEvent(msg.pe.buttonMask,
3443 Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
3444 break;
3445
3446 default:
3447 rfbErr("rfbProcessUDPInput: unknown message type %d\n",
3448 msg.type);
3449 rfbDisconnectUDPSock(rfbScreen);
3450 }
3451}
3452
3453