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