LibVNCServer/LibVNCClient
main.c
Go to the documentation of this file.
1 /*
2  * This file is called main.c, because it contains most of the new functions
3  * for use with LibVNCServer.
4  *
5  * LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
6  * Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
7  * Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
8  * All Rights Reserved.
9  *
10  * see GPL (latest version) for full details
11  */
12 
13 #ifdef __STRICT_ANSI__
14 #define _BSD_SOURCE
15 #endif
16 #include <rfb/rfb.h>
17 #include <rfb/rfbregion.h>
18 #include "private.h"
19 
20 #include <stdarg.h>
21 #include <errno.h>
22 
23 #ifndef false
24 #define false 0
25 #define true -1
26 #endif
27 
28 #ifdef LIBVNCSERVER_HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #endif
31 
32 #ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35 
36 #ifdef LIBVNCSERVER_HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif
39 
40 #include <signal.h>
41 #include <time.h>
42 
43 static int extMutex_initialized = 0;
44 static int logMutex_initialized = 0;
45 #if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
46 static MUTEX(logMutex);
47 static MUTEX(extMutex);
48 #endif
49 
50 static int rfbEnableLogging=1;
51 
52 #ifdef LIBVNCSERVER_WORDS_BIGENDIAN
53 char rfbEndianTest = (1==0);
54 #else
55 char rfbEndianTest = (1==1);
56 #endif
57 
58 /*
59  * Protocol extensions
60  */
61 
62 static rfbProtocolExtension* rfbExtensionHead = NULL;
63 
64 /*
65  * This method registers a list of new extensions.
66  * It avoids same extension getting registered multiple times.
67  * The order is not preserved if multiple extensions are
68  * registered at one-go.
69  */
70 void
72 {
73  rfbProtocolExtension *head = rfbExtensionHead, *next = NULL;
74 
75  if(extension == NULL)
76  return;
77 
78  next = extension->next;
79 
80  if (! extMutex_initialized) {
81  INIT_MUTEX(extMutex);
82  extMutex_initialized = 1;
83  }
84 
85  LOCK(extMutex);
86 
87  while(head != NULL) {
88  if(head == extension) {
89  UNLOCK(extMutex);
91  return;
92  }
93 
94  head = head->next;
95  }
96 
97  extension->next = rfbExtensionHead;
98  rfbExtensionHead = extension;
99 
100  UNLOCK(extMutex);
102 }
103 
104 /*
105  * This method unregisters a list of extensions.
106  * These extensions won't be available for any new
107  * client connection.
108  */
109 void
111 {
112 
113  rfbProtocolExtension *cur = NULL, *pre = NULL;
114 
115  if(extension == NULL)
116  return;
117 
118  if (! extMutex_initialized) {
119  INIT_MUTEX(extMutex);
120  extMutex_initialized = 1;
121  }
122 
123  LOCK(extMutex);
124 
125  if(rfbExtensionHead == extension) {
126  rfbExtensionHead = rfbExtensionHead->next;
127  UNLOCK(extMutex);
129  return;
130  }
131 
132  cur = pre = rfbExtensionHead;
133 
134  while(cur) {
135  if(cur == extension) {
136  pre->next = cur->next;
137  break;
138  }
139  pre = cur;
140  cur = cur->next;
141  }
142 
143  UNLOCK(extMutex);
144 
146 }
147 
149 {
150  if (! extMutex_initialized) {
151  INIT_MUTEX(extMutex);
152  extMutex_initialized = 1;
153  }
154 
155  LOCK(extMutex);
156  return rfbExtensionHead;
157 }
158 
160 {
161  UNLOCK(extMutex);
162 }
163 
164 rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension,
165  void* data)
166 {
167  rfbExtensionData* extData;
168 
169  /* make sure extension is not yet enabled. */
170  for(extData = cl->extensions; extData; extData = extData->next)
171  if(extData->extension == extension)
172  return FALSE;
173 
174  extData = calloc(sizeof(rfbExtensionData),1);
175  if(!extData)
176  return FALSE;
177  extData->extension = extension;
178  extData->data = data;
179  extData->next = cl->extensions;
180  cl->extensions = extData;
181 
182  return TRUE;
183 }
184 
186 {
187  rfbExtensionData* extData;
188  rfbExtensionData* prevData = NULL;
189 
190  for(extData = cl->extensions; extData; extData = extData->next) {
191  if(extData->extension == extension) {
192  if(extData->data)
193  free(extData->data);
194  if(prevData == NULL)
195  cl->extensions = extData->next;
196  else
197  prevData->next = extData->next;
198  return TRUE;
199  }
200  prevData = extData;
201  }
202 
203  return FALSE;
204 }
205 
206 void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension)
207 {
208  rfbExtensionData* data = cl->extensions;
209 
210  while(data && data->extension != extension)
211  data = data->next;
212 
213  if(data == NULL) {
214  rfbLog("Extension is not enabled !\n");
215  /* rfbCloseClient(cl); */
216  return NULL;
217  }
218 
219  return data->data;
220 }
221 
222 /*
223  * Logging
224  */
225 
226 void rfbLogEnable(int enabled) {
227  rfbEnableLogging=enabled;
228 }
229 
230 /*
231  * rfbLog prints a time-stamped message to the log file (stderr).
232  */
233 
234 static void
235 rfbDefaultLog(const char *format, ...)
236 {
237  va_list args;
238  char buf[256];
239  time_t log_clock;
240 
241  if(!rfbEnableLogging)
242  return;
243 
244  if (! logMutex_initialized) {
245  INIT_MUTEX(logMutex);
246  logMutex_initialized = 1;
247  }
248 
249  LOCK(logMutex);
250  va_start(args, format);
251 
252  time(&log_clock);
253  strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
254  fprintf(stderr, "%s", buf);
255 
256  vfprintf(stderr, format, args);
257  fflush(stderr);
258 
259  va_end(args);
260  UNLOCK(logMutex);
261 }
262 
263 rfbLogProc rfbLog=rfbDefaultLog;
264 rfbLogProc rfbErr=rfbDefaultLog;
265 
266 void rfbLogPerror(const char *str)
267 {
268 #ifdef WIN32
269  wchar_t *s = NULL;
270  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
271  NULL, errno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
272  (LPWSTR)&s, 0, NULL);
273  rfbErr("%s: %S\n", str, s);
274  LocalFree(s);
275 #else
276  rfbErr("%s: %s\n", str, strerror(errno));
277 #endif
278 }
279 
280 void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
281 {
282  rfbClientIteratorPtr iterator;
283  rfbClientPtr cl;
284 
285  iterator=rfbGetClientIterator(rfbScreen);
286  while((cl=rfbClientIteratorNext(iterator))) {
287  LOCK(cl->updateMutex);
288  if(cl->useCopyRect) {
289  sraRegionPtr modifiedRegionBackup;
290  if(!sraRgnEmpty(cl->copyRegion)) {
291  if(cl->copyDX!=dx || cl->copyDY!=dy) {
292  /* if a copyRegion was not yet executed, treat it as a
293  * modifiedRegion. The idea: in this case it could be
294  * source of the new copyRect or modified anyway. */
295  sraRgnOr(cl->modifiedRegion,cl->copyRegion);
296  sraRgnMakeEmpty(cl->copyRegion);
297  } else {
298  /* we have to set the intersection of the source of the copy
299  * and the old copy to modified. */
300  modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
301  sraRgnOffset(modifiedRegionBackup,-dx,-dy);
302  sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
303  sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
304  sraRgnDestroy(modifiedRegionBackup);
305  }
306  }
307 
308  sraRgnOr(cl->copyRegion,copyRegion);
309  cl->copyDX = dx;
310  cl->copyDY = dy;
311 
312  /* if there were modified regions, which are now copied,
313  * mark them as modified, because the source of these can be overlapped
314  * either by new modified or now copied regions. */
315  modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
316  sraRgnOffset(modifiedRegionBackup,dx,dy);
317  sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
318  sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
319  sraRgnDestroy(modifiedRegionBackup);
320 
321  if(!cl->enableCursorShapeUpdates) {
322  /*
323  * n.b. (dx, dy) is the vector pointing in the direction the
324  * copyrect displacement will take place. copyRegion is the
325  * destination rectangle (say), not the source rectangle.
326  */
327  sraRegionPtr cursorRegion;
328  int x = cl->cursorX - cl->screen->cursor->xhot;
329  int y = cl->cursorY - cl->screen->cursor->yhot;
330  int w = cl->screen->cursor->width;
331  int h = cl->screen->cursor->height;
332 
333  cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
334  sraRgnAnd(cursorRegion, cl->copyRegion);
335  if(!sraRgnEmpty(cursorRegion)) {
336  /*
337  * current cursor rect overlaps with the copy region *dest*,
338  * mark it as modified since we won't copy-rect stuff to it.
339  */
340  sraRgnOr(cl->modifiedRegion, cursorRegion);
341  }
342  sraRgnDestroy(cursorRegion);
343 
344  cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
345  /* displace it to check for overlap with copy region source: */
346  sraRgnOffset(cursorRegion, dx, dy);
347  sraRgnAnd(cursorRegion, cl->copyRegion);
348  if(!sraRgnEmpty(cursorRegion)) {
349  /*
350  * current cursor rect overlaps with the copy region *source*,
351  * mark the *displaced* cursorRegion as modified since we
352  * won't copyrect stuff to it.
353  */
354  sraRgnOr(cl->modifiedRegion, cursorRegion);
355  }
356  sraRgnDestroy(cursorRegion);
357  }
358 
359  } else {
360  sraRgnOr(cl->modifiedRegion,copyRegion);
361  }
362  TSIGNAL(cl->updateCond);
363  UNLOCK(cl->updateMutex);
364  }
365 
366  rfbReleaseClientIterator(iterator);
367 }
368 
369 void rfbDoCopyRegion(rfbScreenInfoPtr screen,sraRegionPtr copyRegion,int dx,int dy)
370 {
372  sraRect rect;
373  int j,widthInBytes,bpp=screen->serverFormat.bitsPerPixel/8,
374  rowstride=screen->paddedWidthInBytes;
375  char *in,*out;
376 
377  /* copy it, really */
378  i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0);
379  while(sraRgnIteratorNext(i,&rect)) {
380  widthInBytes = (rect.x2-rect.x1)*bpp;
381  out = screen->frameBuffer+rect.x1*bpp+rect.y1*rowstride;
382  in = screen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride;
383  if(dy<0)
384  for(j=rect.y1;j<rect.y2;j++,out+=rowstride,in+=rowstride)
385  memmove(out,in,widthInBytes);
386  else {
387  out += rowstride*(rect.y2-rect.y1-1);
388  in += rowstride*(rect.y2-rect.y1-1);
389  for(j=rect.y2-1;j>=rect.y1;j--,out-=rowstride,in-=rowstride)
390  memmove(out,in,widthInBytes);
391  }
392  }
394 
395  rfbScheduleCopyRegion(screen,copyRegion,dx,dy);
396 }
397 
398 void rfbDoCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy)
399 {
400  sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
401  rfbDoCopyRegion(screen,region,dx,dy);
402  sraRgnDestroy(region);
403 }
404 
405 void rfbScheduleCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy)
406 {
407  sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
408  rfbScheduleCopyRegion(screen,region,dx,dy);
409  sraRgnDestroy(region);
410 }
411 
412 void rfbMarkRegionAsModified(rfbScreenInfoPtr screen,sraRegionPtr modRegion)
413 {
414  rfbClientIteratorPtr iterator;
415  rfbClientPtr cl;
416 
417  iterator=rfbGetClientIterator(screen);
418  while((cl=rfbClientIteratorNext(iterator))) {
419  LOCK(cl->updateMutex);
420  sraRgnOr(cl->modifiedRegion,modRegion);
421  TSIGNAL(cl->updateCond);
422  UNLOCK(cl->updateMutex);
423  }
424 
425  rfbReleaseClientIterator(iterator);
426 }
427 
428 void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
429 void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2)
430 {
431  sraRegionPtr region;
432  int i;
433 
434  if(x1>x2) { i=x1; x1=x2; x2=i; }
435  if(x1<0) x1=0;
436  if(x2>screen->width) x2=screen->width;
437  if(x1==x2) return;
438 
439  if(y1>y2) { i=y1; y1=y2; y2=i; }
440  if(y1<0) y1=0;
441  if(y2>screen->height) y2=screen->height;
442  if(y1==y2) return;
443 
444  /* update scaled copies for this rectangle */
445  rfbScaledScreenUpdate(screen,x1,y1,x2,y2);
446 
447  region = sraRgnCreateRect(x1,y1,x2,y2);
448  rfbMarkRegionAsModified(screen,region);
449  sraRgnDestroy(region);
450 }
451 
452 #if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
453 
454 static THREAD_ROUTINE_RETURN_TYPE
455 clientOutput(void *data)
456 {
457  rfbClientPtr cl = (rfbClientPtr)data;
458  rfbBool haveUpdate;
459  sraRegion* updateRegion;
460 
461  while (1) {
462  haveUpdate = false;
463  while (!haveUpdate) {
464  if (cl->sock == RFB_INVALID_SOCKET) {
465  /* Client has disconnected. */
466  return THREAD_ROUTINE_RETURN_VALUE;
467  }
468  if (cl->state != RFB_NORMAL || cl->onHold) {
469  /* just sleep until things get normal */
470  THREAD_SLEEP_MS(cl->screen->deferUpdateTime);
471  continue;
472  }
473 
474  LOCK(cl->updateMutex);
475 
476  if (sraRgnEmpty(cl->requestedRegion)) {
477  ; /* always require a FB Update Request (otherwise can crash.) */
478  } else {
479  haveUpdate = FB_UPDATE_PENDING(cl);
480  if(!haveUpdate) {
481  updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
482  haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion);
483  sraRgnDestroy(updateRegion);
484  }
485  }
486 
487  if (!haveUpdate) {
488  WAIT(cl->updateCond, cl->updateMutex);
489  }
490 
491  UNLOCK(cl->updateMutex);
492  }
493 
494  /* OK, now, to save bandwidth, wait a little while for more
495  updates to come along. */
496  THREAD_SLEEP_MS(cl->screen->deferUpdateTime);
497 
498  /* Now, get the region we're going to update, and remove
499  it from cl->modifiedRegion _before_ we send the update.
500  That way, if anything that overlaps the region we're sending
501  is updated, we'll be sure to do another update later. */
502  LOCK(cl->updateMutex);
503  updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
504  UNLOCK(cl->updateMutex);
505 
506  /* Now actually send the update. */
507  rfbIncrClientRef(cl);
508  LOCK(cl->sendMutex);
509  rfbSendFramebufferUpdate(cl, updateRegion);
510  UNLOCK(cl->sendMutex);
511  rfbDecrClientRef(cl);
512 
513  sraRgnDestroy(updateRegion);
514  }
515 
516  /* Not reached. */
517  return THREAD_ROUTINE_RETURN_VALUE;
518 }
519 
520 static THREAD_ROUTINE_RETURN_TYPE
521 clientInput(void *data)
522 {
523  rfbClientPtr cl = (rfbClientPtr)data;
524 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
525  pthread_t output_thread;
526  pthread_create(&output_thread, NULL, clientOutput, (void *)cl);
527 #elif defined(LIBVNCSERVER_HAVE_WIN32THREADS)
528  uintptr_t output_thread = _beginthread(clientOutput, 0, cl);
529 #endif
530 
531  while (1) {
532  fd_set rfds, wfds, efds;
533  struct timeval tv;
534  int n;
535 
536  if (cl->sock == RFB_INVALID_SOCKET) {
537  /* Client has disconnected. */
538  break;
539  }
540 
541  FD_ZERO(&rfds);
542  FD_SET(cl->sock, &rfds);
543 #ifndef WIN32
544  FD_SET(cl->pipe_notify_client_thread[0], &rfds);
545 #endif
546  FD_ZERO(&efds);
547  FD_SET(cl->sock, &efds);
548 
549  /* Are we transferring a file in the background? */
550  FD_ZERO(&wfds);
551  if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
552  FD_SET(cl->sock, &wfds);
553 
554 #ifndef WIN32
555  int nfds = cl->pipe_notify_client_thread[0] > cl->sock ? cl->pipe_notify_client_thread[0] : cl->sock;
556 #else
557  int nfds = cl->sock;
558 #endif
559 
560  tv.tv_sec = 60; /* 1 minute */
561  tv.tv_usec = 0;
562 
563  n = select(nfds + 1, &rfds, &wfds, &efds, &tv);
564 
565  if (n < 0) {
566  rfbLogPerror("ReadExact: select");
567  break;
568  }
569  if (n == 0) /* timeout */
570  {
572  continue;
573  }
574 
575  /* We have some space on the transmit queue, send some data */
576  if (FD_ISSET(cl->sock, &wfds))
578 
579 #ifndef WIN32
580  if (FD_ISSET(cl->pipe_notify_client_thread[0], &rfds))
581  {
582  /* Reset the pipe */
583  char buf;
584  while (read(cl->pipe_notify_client_thread[0], &buf, sizeof(buf)) == sizeof(buf));
585  }
586 #endif
587 
588  if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds))
589  {
590 #ifdef LIBVNCSERVER_WITH_WEBSOCKETS
591  do {
593  } while (webSocketsHasDataInBuffer(cl));
594 #else
596 #endif
597  }
598  }
599 
600  /* Get rid of the output thread. */
601  LOCK(cl->updateMutex);
602  TSIGNAL(cl->updateCond);
603  UNLOCK(cl->updateMutex);
604  THREAD_JOIN(output_thread);
605 
607 
608  return THREAD_ROUTINE_RETURN_VALUE;
609 }
610 
611 
612 static THREAD_ROUTINE_RETURN_TYPE
613 listenerRun(void *data)
614 {
615  rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data;
616  int client_fd;
617  struct sockaddr_storage peer;
618  rfbClientPtr cl = NULL;
619  socklen_t len;
620  fd_set listen_fds; /* temp file descriptor list for select() */
621 
622  /* TODO: this thread won't die by restarting the server */
623  /* TODO: HTTP is not handled */
624  while (1) {
625  client_fd = -1;
626  FD_ZERO(&listen_fds);
627  if(screen->listenSock != RFB_INVALID_SOCKET)
628  FD_SET(screen->listenSock, &listen_fds);
629  if(screen->listen6Sock != RFB_INVALID_SOCKET)
630  FD_SET(screen->listen6Sock, &listen_fds);
631 
632  if (select(screen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) {
633  rfbLogPerror("listenerRun: error in select");
634  return THREAD_ROUTINE_RETURN_VALUE;
635  }
636 
637  /* there is something on the listening sockets, handle new connections */
638  len = sizeof (peer);
639  if (FD_ISSET(screen->listenSock, &listen_fds))
640  client_fd = accept(screen->listenSock, (struct sockaddr*)&peer, &len);
641  else if (FD_ISSET(screen->listen6Sock, &listen_fds))
642  client_fd = accept(screen->listen6Sock, (struct sockaddr*)&peer, &len);
643 
644  if(client_fd >= 0)
645  cl = rfbNewClient(screen,client_fd);
646  if (cl && !cl->onHold )
648  }
649  return THREAD_ROUTINE_RETURN_VALUE;
650 }
651 
652 #endif
653 
654 void
655 rfbStartOnHoldClient(rfbClientPtr cl)
656 {
657  cl->onHold = FALSE;
658 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
659  if(cl->screen->backgroundLoop) {
660 #ifndef WIN32
661  if (pipe(cl->pipe_notify_client_thread) == -1) {
662  cl->pipe_notify_client_thread[0] = -1;
663  cl->pipe_notify_client_thread[1] = -1;
664  }
665  fcntl(cl->pipe_notify_client_thread[0], F_SETFL, O_NONBLOCK);
666 #endif
667  pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl);
668  }
669 #elif defined(LIBVNCSERVER_HAVE_WIN32THREADS)
670  if(cl->screen->backgroundLoop) {
671  cl->client_thread = _beginthread(clientInput, 0, cl);
672  }
673 #endif
674 }
675 
676 
677 void
678 rfbRefuseOnHoldClient(rfbClientPtr cl)
679 {
680  rfbCloseClient(cl);
682 }
683 
684 static void
685 rfbDefaultKbdAddEvent(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
686 {
687 }
688 
689 void
690 rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
691 {
692  rfbClientIteratorPtr iterator;
693  rfbClientPtr other_client;
694  rfbScreenInfoPtr s = cl->screen;
695 
696  if (x != s->cursorX || y != s->cursorY) {
697  LOCK(s->cursorMutex);
698  s->cursorX = x;
699  s->cursorY = y;
700  UNLOCK(s->cursorMutex);
701 
702  /* The cursor was moved by this client, so don't send CursorPos. */
703  if (cl->enableCursorPosUpdates)
704  cl->cursorWasMoved = FALSE;
705 
706  /* But inform all remaining clients about this cursor movement. */
707  iterator = rfbGetClientIterator(s);
708  while ((other_client = rfbClientIteratorNext(iterator)) != NULL) {
709  if (other_client != cl && other_client->enableCursorPosUpdates) {
710  other_client->cursorWasMoved = TRUE;
711  }
712  }
713  rfbReleaseClientIterator(iterator);
714  }
715 }
716 
717 static void rfbDefaultSetXCutText(char* text, int len, rfbClientPtr cl)
718 {
719 }
720 
721 /* TODO: add a nice VNC or RFB cursor */
722 
723 #if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI)
724 static rfbCursor myCursor =
725 {
726  FALSE, FALSE, FALSE, FALSE,
727  (unsigned char*)"\000\102\044\030\044\102\000",
728  (unsigned char*)"\347\347\176\074\176\347\347",
729  8, 7, 3, 3,
730  0, 0, 0,
731  0xffff, 0xffff, 0xffff,
732  NULL
733 };
734 #else
735 static rfbCursor myCursor =
736 {
737  cleanup: FALSE,
738  cleanupSource: FALSE,
739  cleanupMask: FALSE,
740  cleanupRichSource: FALSE,
741  source: "\000\102\044\030\044\102\000",
742  mask: "\347\347\176\074\176\347\347",
743  width: 8, height: 7, xhot: 3, yhot: 3,
744  foreRed: 0, foreGreen: 0, foreBlue: 0,
745  backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
746  richSource: NULL
747 };
748 #endif
749 
750 static rfbCursorPtr rfbDefaultGetCursorPtr(rfbClientPtr cl)
751 {
752  return(cl->screen->cursor);
753 }
754 
755 /* response is cl->authChallenge vncEncrypted with passwd */
756 static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
757 {
758  int i;
759  char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData);
760 
761  if(!passwd) {
762  rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData);
763  return(FALSE);
764  }
765 
766  rfbEncryptBytes(cl->authChallenge, passwd);
767 
768  /* Lose the password from memory */
769  for (i = strlen(passwd); i >= 0; i--) {
770  passwd[i] = '\0';
771  }
772 
773  free(passwd);
774 
775  if (memcmp(cl->authChallenge, response, len) != 0) {
776  rfbErr("authProcessClientMessage: authentication failed from %s\n",
777  cl->host);
778  return(FALSE);
779  }
780 
781  return(TRUE);
782 }
783 
784 /* for this method, authPasswdData is really a pointer to an array
785  of char*'s, where the last pointer is 0. */
786 rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len)
787 {
788  char **passwds;
789  int i=0;
790 
791  for(passwds=(char**)cl->screen->authPasswdData;*passwds;passwds++,i++) {
792  uint8_t auth_tmp[CHALLENGESIZE];
793  memcpy((char *)auth_tmp, (char *)cl->authChallenge, CHALLENGESIZE);
794  rfbEncryptBytes(auth_tmp, *passwds);
795 
796  if (memcmp(auth_tmp, response, len) == 0) {
797  if(i>=cl->screen->authPasswdFirstViewOnly)
798  cl->viewOnly=TRUE;
799  return(TRUE);
800  }
801  }
802 
803  rfbErr("authProcessClientMessage: authentication failed from %s\n",
804  cl->host);
805  return(FALSE);
806 }
807 
808 void rfbDoNothingWithClient(rfbClientPtr cl)
809 {
810 }
811 
812 static enum rfbNewClientAction rfbDefaultNewClientHook(rfbClientPtr cl)
813 {
814  return RFB_CLIENT_ACCEPT;
815 }
816 
817 static int rfbDefaultNumberOfExtDesktopScreens(rfbClientPtr cl)
818 {
819  return 1;
820 }
821 
822 static rfbBool rfbDefaultGetExtDesktopScreen(int seqnumber, rfbExtDesktopScreen* s, rfbClientPtr cl)
823 {
824  if (seqnumber != 0)
825  return FALSE;
826 
827  /* Populate the provided rfbExtDesktopScreen structure */
828  s->id = 1;
829  s->width = cl->scaledScreen->width;
830  s->height = cl->scaledScreen->height;
831  s->x = 0;
832  s->y = 0;
833  s->flags = 0;
834 
835  return TRUE;
836 }
837 
838 static int rfbDefaultSetDesktopSize(int width, int height, int numScreens, rfbExtDesktopScreen* extDesktopScreens, rfbClientPtr cl)
839 {
841 }
842 
843 /*
844  * Update server's pixel format in screenInfo structure. This
845  * function is called from rfbGetScreen() and rfbNewFramebuffer().
846  */
847 
848 static void rfbInitServerFormat(rfbScreenInfoPtr screen, int bitsPerSample)
849 {
850  rfbPixelFormat* format=&screen->serverFormat;
851 
852  format->bitsPerPixel = screen->bitsPerPixel;
853  format->depth = screen->depth;
854  format->bigEndian = rfbEndianTest?FALSE:TRUE;
855  format->trueColour = TRUE;
856  screen->colourMap.count = 0;
857  screen->colourMap.is16 = 0;
858  screen->colourMap.data.bytes = NULL;
859 
860  if (format->bitsPerPixel == 8) {
861  format->redMax = 7;
862  format->greenMax = 7;
863  format->blueMax = 3;
864  format->redShift = 0;
865  format->greenShift = 3;
866  format->blueShift = 6;
867  } else {
868  format->redMax = (1 << bitsPerSample) - 1;
869  format->greenMax = (1 << bitsPerSample) - 1;
870  format->blueMax = (1 << bitsPerSample) - 1;
871  if(rfbEndianTest) {
872  format->redShift = 0;
873  format->greenShift = bitsPerSample;
874  format->blueShift = bitsPerSample * 2;
875  } else {
876  if(format->bitsPerPixel==8*3) {
877  format->redShift = bitsPerSample*2;
878  format->greenShift = bitsPerSample*1;
879  format->blueShift = 0;
880  } else {
881  format->redShift = bitsPerSample*3;
882  format->greenShift = bitsPerSample*2;
883  format->blueShift = bitsPerSample;
884  }
885  }
886  }
887 }
888 
889 rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
890  int width,int height,int bitsPerSample,int samplesPerPixel,
891  int bytesPerPixel)
892 {
893  rfbScreenInfoPtr screen=calloc(sizeof(rfbScreenInfo),1);
894  if (!screen)
895  return NULL;
896 
897  if (! logMutex_initialized) {
898  INIT_MUTEX(logMutex);
899  logMutex_initialized = 1;
900  }
901 
902 
903  if(width&3)
904  rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
905 
906  screen->autoPort=FALSE;
907  screen->clientHead=NULL;
908  screen->pointerClient=NULL;
909  screen->port=5900;
910  screen->ipv6port=5900;
911  screen->socketState=RFB_SOCKET_INIT;
912 
913  screen->inetdInitDone = FALSE;
914  screen->inetdSock=RFB_INVALID_SOCKET;
915 
916  screen->udpSock=RFB_INVALID_SOCKET;
917  screen->udpSockConnected=FALSE;
918  screen->udpPort=0;
919  screen->udpClient=NULL;
920 
921  screen->maxFd=0;
922  screen->listenSock=RFB_INVALID_SOCKET;
923  screen->listen6Sock=RFB_INVALID_SOCKET;
924 
925  screen->fdQuota = 0.5;
926 
927  screen->httpInitDone=FALSE;
928  screen->httpEnableProxyConnect=FALSE;
929  screen->httpPort=0;
930  screen->http6Port=0;
931  screen->httpDir=NULL;
932  screen->httpListenSock=RFB_INVALID_SOCKET;
933  screen->httpListen6Sock=RFB_INVALID_SOCKET;
934  screen->httpSock=RFB_INVALID_SOCKET;
935 
936  screen->desktopName = "LibVNCServer";
937  screen->alwaysShared = FALSE;
938  screen->neverShared = FALSE;
939  screen->dontDisconnect = FALSE;
940  screen->authPasswdData = NULL;
941  screen->authPasswdFirstViewOnly = 1;
942 
943  screen->width = width;
944  screen->height = height;
945  screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
946 
947  screen->passwordCheck = rfbDefaultPasswordCheck;
948 
949  screen->ignoreSIGPIPE = TRUE;
950 
951  /* disable progressive updating per default */
952  screen->progressiveSliceHeight = 0;
953 
954  screen->listenInterface = htonl(INADDR_ANY);
955 
956  screen->deferUpdateTime=5;
957  screen->maxRectsPerUpdate=50;
958 
959  screen->handleEventsEagerly = FALSE;
960 
961  screen->protocolMajorVersion = rfbProtocolMajorVersion;
962  screen->protocolMinorVersion = rfbProtocolMinorVersion;
963 
964  screen->permitFileTransfer = FALSE;
965 
966  if(!rfbProcessArguments(screen,argc,argv)) {
967  free(screen);
968  return NULL;
969  }
970 
971 #ifdef WIN32
972  {
973  DWORD dummy=255;
974  GetComputerName(screen->thisHost,&dummy);
975  }
976 #else
977  gethostname(screen->thisHost, 255);
978 #endif
979 
980  screen->paddedWidthInBytes = width*bytesPerPixel;
981 
982  /* format */
983 
984  rfbInitServerFormat(screen, bitsPerSample);
985 
986  /* cursor */
987 
988  screen->cursorX=screen->cursorY=screen->underCursorBufferLen=0;
989  screen->underCursorBuffer=NULL;
990  screen->dontConvertRichCursorToXCursor = FALSE;
991  screen->cursor = &myCursor;
992  INIT_MUTEX(screen->cursorMutex);
993 
994 #if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
995  screen->backgroundLoop = FALSE;
996 #endif
997 
998  /* proc's and hook's */
999 
1000  screen->kbdAddEvent = rfbDefaultKbdAddEvent;
1001  screen->kbdReleaseAllKeys = rfbDoNothingWithClient;
1002  screen->ptrAddEvent = rfbDefaultPtrAddEvent;
1003  screen->setXCutText = rfbDefaultSetXCutText;
1004  screen->getCursorPtr = rfbDefaultGetCursorPtr;
1005  screen->setTranslateFunction = rfbSetTranslateFunction;
1006  screen->newClientHook = rfbDefaultNewClientHook;
1007  screen->displayHook = NULL;
1008  screen->displayFinishedHook = NULL;
1009  screen->getKeyboardLedStateHook = NULL;
1010  screen->xvpHook = NULL;
1011  screen->setDesktopSizeHook = rfbDefaultSetDesktopSize;
1012  screen->numberOfExtDesktopScreensHook = rfbDefaultNumberOfExtDesktopScreens;
1013  screen->getExtDesktopScreenHook = rfbDefaultGetExtDesktopScreen;
1014 
1015  /* initialize client list and iterator mutex */
1016  rfbClientListInit(screen);
1017 
1018  return(screen);
1019 }
1020 
1021 /*
1022  * Switch to another framebuffer (maybe of different size and color
1023  * format). Clients supporting NewFBSize pseudo-encoding will change
1024  * their local framebuffer dimensions if necessary.
1025  * NOTE: Rich cursor data should be converted to new pixel format by
1026  * the caller.
1027  */
1028 
1029 void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer,
1030  int width, int height,
1031  int bitsPerSample, int samplesPerPixel,
1032  int bytesPerPixel)
1033 {
1034  rfbPixelFormat old_format;
1035  rfbBool format_changed = FALSE;
1036  rfbClientIteratorPtr iterator;
1037  rfbClientPtr cl;
1038 
1039  /* Update information in the screenInfo structure */
1040 
1041  old_format = screen->serverFormat;
1042 
1043  if (width & 3)
1044  rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width);
1045 
1046  screen->width = width;
1047  screen->height = height;
1048  screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
1049  screen->paddedWidthInBytes = width*bytesPerPixel;
1050 
1051  rfbInitServerFormat(screen, bitsPerSample);
1052 
1053  if (memcmp(&screen->serverFormat, &old_format,
1054  sizeof(rfbPixelFormat)) != 0) {
1055  format_changed = TRUE;
1056  }
1057 
1058  screen->frameBuffer = framebuffer;
1059 
1060  /* Adjust pointer position if necessary */
1061 
1062  if (screen->cursorX >= width)
1063  screen->cursorX = width - 1;
1064  if (screen->cursorY >= height)
1065  screen->cursorY = height - 1;
1066 
1067  /* For each client: */
1068  iterator = rfbGetClientIterator(screen);
1069  while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
1070 
1071  /* Re-install color translation tables if necessary */
1072 
1073  if (format_changed)
1074  screen->setTranslateFunction(cl);
1075 
1076  /* Mark the screen contents as changed, and schedule sending
1077  NewFBSize message if supported by this client. */
1078 
1079  LOCK(cl->updateMutex);
1080  sraRgnDestroy(cl->modifiedRegion);
1081  cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
1082  sraRgnMakeEmpty(cl->copyRegion);
1083  cl->copyDX = 0;
1084  cl->copyDY = 0;
1085 
1086  if (cl->useNewFBSize)
1087  cl->newFBSizePending = TRUE;
1088 
1089  TSIGNAL(cl->updateCond);
1090  UNLOCK(cl->updateMutex);
1091  }
1092  rfbReleaseClientIterator(iterator);
1093 }
1094 
1095 /* hang up on all clients and free all reserved memory */
1096 
1097 void rfbScreenCleanup(rfbScreenInfoPtr screen)
1098 {
1099  rfbClientIteratorPtr i=rfbGetClientIterator(screen);
1100  rfbClientPtr cl,cl1=rfbClientIteratorNext(i);
1101  while(cl1) {
1102  cl=rfbClientIteratorNext(i);
1104  cl1=cl;
1105  }
1107 
1108 #define FREE_IF(x) if(screen->x) free(screen->x)
1109  FREE_IF(colourMap.data.bytes);
1110  FREE_IF(underCursorBuffer);
1111  TINI_MUTEX(screen->cursorMutex);
1112 
1113  rfbFreeCursor(screen->cursor);
1114 
1115 #ifdef LIBVNCSERVER_HAVE_LIBZ
1116  rfbZlibCleanup(screen);
1117 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
1118  rfbTightCleanup(screen);
1119 #endif
1120 
1121  /* free all 'scaled' versions of this screen */
1122  while (screen->scaledScreenNext!=NULL)
1123  {
1124  rfbScreenInfoPtr ptr;
1125  ptr = screen->scaledScreenNext;
1126  screen->scaledScreenNext = ptr->scaledScreenNext;
1127  free(ptr->frameBuffer);
1128  free(ptr);
1129  }
1130 
1131 #endif
1132  free(screen);
1133 }
1134 
1135 void rfbInitServer(rfbScreenInfoPtr screen)
1136 {
1137  rfbInitSockets(screen);
1138  rfbHttpInitSockets(screen);
1139 #ifndef WIN32
1140  if(screen->ignoreSIGPIPE)
1141  signal(SIGPIPE,SIG_IGN);
1142 #endif
1143 }
1144 
1145 void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) {
1146  if(disconnectClients) {
1147  rfbClientIteratorPtr iter = rfbGetClientIterator(screen);
1148  rfbClientPtr nextCl, currentCl = rfbClientIteratorNext(iter);
1149 
1150  while(currentCl) {
1151  nextCl = rfbClientIteratorNext(iter);
1152  if (currentCl->sock != RFB_INVALID_SOCKET) {
1153  /* we don't care about maxfd here, because the server goes away */
1154  rfbCloseClient(currentCl);
1155  }
1156 
1157 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
1158  if(currentCl->screen->backgroundLoop) {
1159  /*
1160  Notify the thread. This simply writes a NULL byte to the notify pipe in order to get past the select()
1161  in clientInput(), the loop in there will then break because the rfbCloseClient() above has set
1162  currentCl->sock to -1.
1163  */
1164  write(currentCl->pipe_notify_client_thread[1], "\x00", 1);
1165  /* And wait for it to finish. */
1166  pthread_join(currentCl->client_thread, NULL);
1167  } else {
1168  rfbClientConnectionGone(currentCl);
1169  }
1170 #else
1171  rfbClientConnectionGone(currentCl);
1172 #endif
1173 
1174  currentCl = nextCl;
1175  }
1176 
1178  }
1179 
1180  rfbHttpShutdownSockets(screen);
1181  rfbShutdownSockets(screen);
1182 }
1183 
1184 #if !defined LIBVNCSERVER_HAVE_GETTIMEOFDAY && defined WIN32
1185 #include <fcntl.h>
1186 #include <conio.h>
1187 #include <sys/timeb.h>
1188 
1189 static void gettimeofday(struct timeval* tv,char* dummy)
1190 {
1191  SYSTEMTIME t;
1192  GetSystemTime(&t);
1193  tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond;
1194  tv->tv_usec=t.wMilliseconds*1000;
1195 }
1196 #endif
1197 
1198 rfbBool
1199 rfbProcessEvents(rfbScreenInfoPtr screen,long usec)
1200 {
1201  rfbClientIteratorPtr i;
1202  rfbClientPtr cl,clPrev;
1203  rfbBool result=FALSE;
1204  extern rfbClientIteratorPtr
1205  rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen);
1206 
1207  if(usec<0)
1208  usec=screen->deferUpdateTime*1000;
1209 
1210  rfbCheckFds(screen,usec);
1211  rfbHttpCheckFds(screen);
1212 
1213  i = rfbGetClientIteratorWithClosed(screen);
1214  cl=rfbClientIteratorHead(i);
1215  while(cl) {
1216  result = rfbUpdateClient(cl);
1217  clPrev=cl;
1218  cl=rfbClientIteratorNext(i);
1219  if(clPrev->sock==RFB_INVALID_SOCKET) {
1220  rfbClientConnectionGone(clPrev);
1221  result=TRUE;
1222  }
1223  }
1225 
1226  return result;
1227 }
1228 
1229 rfbBool
1230 rfbUpdateClient(rfbClientPtr cl)
1231 {
1232  struct timeval tv;
1233  rfbBool result=FALSE;
1234  rfbScreenInfoPtr screen = cl->screen;
1235 
1236  if (cl->sock != RFB_INVALID_SOCKET && !cl->onHold && FB_UPDATE_PENDING(cl) &&
1237  !sraRgnEmpty(cl->requestedRegion)) {
1238  result=TRUE;
1239  if(screen->deferUpdateTime == 0) {
1240  rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
1241  } else if(cl->startDeferring.tv_usec == 0) {
1242  gettimeofday(&cl->startDeferring,NULL);
1243  if(cl->startDeferring.tv_usec == 0)
1244  cl->startDeferring.tv_usec++;
1245  } else {
1246  gettimeofday(&tv,NULL);
1247  if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
1248  || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
1249  +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
1250  > screen->deferUpdateTime) {
1251  cl->startDeferring.tv_usec = 0;
1252  rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
1253  }
1254  }
1255  }
1256 
1257  if (!cl->viewOnly && cl->lastPtrX >= 0) {
1258  if(cl->startPtrDeferring.tv_usec == 0) {
1259  gettimeofday(&cl->startPtrDeferring,NULL);
1260  if(cl->startPtrDeferring.tv_usec == 0)
1261  cl->startPtrDeferring.tv_usec++;
1262  } else {
1263  struct timeval tv;
1264  gettimeofday(&tv,NULL);
1265  if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */
1266  || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000
1267  +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000)
1268  > cl->screen->deferPtrUpdateTime) {
1269  cl->startPtrDeferring.tv_usec = 0;
1270  cl->screen->ptrAddEvent(cl->lastPtrButtons,
1271  cl->lastPtrX,
1272  cl->lastPtrY, cl);
1273  cl->lastPtrX = -1;
1274  }
1275  }
1276  }
1277 
1278  return result;
1279 }
1280 
1281 rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo) {
1282  return screenInfo->socketState!=RFB_SOCKET_SHUTDOWN || screenInfo->clientHead!=NULL;
1283 }
1284 
1285 void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground)
1286 {
1287  if(runInBackground) {
1288 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
1289  pthread_t listener_thread;
1290 
1291  screen->backgroundLoop = TRUE;
1292 
1293  pthread_create(&listener_thread, NULL, listenerRun, screen);
1294  return;
1295 #elif defined(LIBVNCSERVER_HAVE_WIN32THREADS)
1296  screen->backgroundLoop = TRUE;
1297  _beginthread(listenerRun, 0, screen);
1298  return;
1299 #else
1300  rfbErr("Can't run in background, because I don't have PThreads!\n");
1301  return;
1302 #endif
1303  }
1304 
1305  if(usec<0)
1306  usec=screen->deferUpdateTime*1000;
1307 
1308  while(rfbIsActive(screen))
1309  rfbProcessEvents(screen,usec);
1310 }
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen, sraRegionPtr copyRegion, int dx, int dy)
Definition: main.c:280
int x1
Definition: rfbregion.h:12
rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension *extension, void *data)
Definition: main.c:164
#define CHALLENGESIZE
Definition: rfbproto.h:1522
int x
Definition: SDLvncviewer.c:34
int rfbCheckFds(rfbScreenInfoPtr rfbScreen, long usec)
Definition: sockets.c:344
sraRegion * sraRgnCreateRect(int x1, int y1, int x2, int y2)
Definition: rfbregion.c:520
rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
Definition: rfbserver.c:167
sraRegion * sraRgnCreateRgn(const sraRegion *src)
Definition: rfbregion.c:540
#define FREE_IF(x)
void rfbMarkRectAsModified(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2)
Definition: main.c:429
rfbLogProc rfbErr
Definition: main.c:264
void rfbDoCopyRegion(rfbScreenInfoPtr screen, sraRegionPtr copyRegion, int dx, int dy)
Definition: main.c:369
void rfbInitServer(rfbScreenInfoPtr screen)
Definition: main.c:1135
#define TRUE
Definition: rfbproto.h:112
struct _rfbProtocolExtension * next
Definition: rfb.h:183
uint16_t redMax
Definition: rfbproto.h:173
#define UNLOCK(mutex)
Definition: threading.h:83
struct sraRegion * sraRegionPtr
Definition: rfb.h:381
void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen)
Definition: httpd.c:130
int8_t rfbBool
Definition: rfbproto.h:108
#define RFB_INVALID_SOCKET
Definition: rfbproto.h:106
sraRectangleIterator * sraRgnGetReverseIterator(sraRegion *s, rfbBool reverseX, rfbBool reverseY)
Definition: rfbregion.c:715
char mask
Definition: SDLvncviewer.c:19
int x2
Definition: rfbregion.h:14
rfbBool sraRgnIteratorNext(sraRectangleIterator *i, sraRect *r)
Definition: rfbregion.c:741
void rfbZlibCleanup(rfbScreenInfoPtr screen)
Definition: zlib.c:63
#define height
Definition: vncev.c:19
#define INIT_MUTEX(mutex)
Definition: threading.h:85
Protocol extension handling.
Definition: rfb.h:161
uint8_t blueShift
Definition: rfbproto.h:195
uint8_t greenShift
Definition: rfbproto.h:193
void rfbIncrClientRef(rfbClientPtr cl)
Definition: rfbserver.c:139
uint32_t rfbKeySym
Definition: rfbproto.h:115
#define rfbProtocolMajorVersion
Definition: rfbproto.h:246
#define FB_UPDATE_PENDING(cl)
This macro is used to test whether there is a framebuffer update needing to be sent to the client...
Definition: rfb.h:690
void rfbMarkRegionAsModified(rfbScreenInfoPtr screen, sraRegionPtr modRegion)
Definition: main.c:412
Per-screen (framebuffer) structure.
Definition: rfb.h:198
void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen)
Definition: sockets.c:297
#define TSIGNAL(cond)
Definition: threading.h:87
void(* rfbLogProc)(const char *format,...)
Definition: rfb.h:991
char * rfbDecryptPasswdFromFile(char *fname)
rfbBool rfbProcessArguments(rfbScreenInfoPtr rfbScreen, int *argc, char *argv[])
Definition: cargs.c:81
void rfbClientListInit(rfbScreenInfoPtr rfbScreen)
Definition: rfbserver.c:154
rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo)
Definition: main.c:1281
rfbBool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion)
Definition: rfbserver.c:2828
void sraRgnMakeEmpty(sraRegion *rgn)
Definition: rfbregion.c:550
void rfbDoCopyRect(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2, int dx, int dy)
Definition: main.c:398
rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator)
Definition: rfbserver.c:208
void rfbReleaseExtensionIterator()
Definition: main.c:159
rfbProtocolExtension * extension
Definition: rfb.h:187
uint8_t bitsPerPixel
Definition: rfbproto.h:156
void rfbRegisterProtocolExtension(rfbProtocolExtension *extension)
Definition: main.c:71
uint8_t depth
Definition: rfbproto.h:158
int y2
Definition: rfbregion.h:15
int y1
Definition: rfbregion.h:13
void rfbScreenCleanup(rfbScreenInfoPtr screen)
Definition: main.c:1097
void rfbScheduleCopyRect(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2, int dx, int dy)
Definition: main.c:405
int y
Definition: SDLvncviewer.c:34
uint8_t trueColour
Definition: rfbproto.h:166
void rfbStartOnHoldClient(rfbClientPtr cl)
Definition: main.c:655
char rfbEndianTest
Definition: main.c:55
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2)
Definition: scale.c:258
void sraRgnReleaseIterator(sraRectangleIterator *i)
Definition: rfbregion.c:781
void rfbLogPerror(const char *str)
Definition: main.c:266
void rfbShutdownServer(rfbScreenInfoPtr screen, rfbBool disconnectClients)
Definition: main.c:1145
rfbClientIteratorPtr rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen)
Definition: rfbserver.c:180
#define MUTEX(mutex)
Definition: threading.h:84
void rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)
Definition: httpd.c:93
rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension *extension)
Definition: main.c:185
void sraRgnDestroy(sraRegion *rgn)
Definition: rfbregion.c:545
struct sraRegion sraRegion
Definition: rfbregion.h:18
#define LOCK(mutex)
Definition: threading.h:82
void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer, int width, int height, int bitsPerSample, int samplesPerPixel, int bytesPerPixel)
Definition: main.c:1029
#define WAIT(cond, mutex)
Definition: threading.h:88
rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src)
Definition: rfbregion.c:557
void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground)
Definition: main.c:1285
#define rfbExtDesktopSize_ResizeProhibited
Definition: rfbproto.h:1178
uint8_t redShift
Definition: rfbproto.h:181
void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
Definition: httpd.c:156
void sraRgnOffset(sraRegion *dst, int dx, int dy)
Definition: rfbregion.c:572
void rfbRefuseOnHoldClient(rfbClientPtr cl)
Definition: main.c:678
void rfbDoNothingWithClient(rfbClientPtr cl)
Definition: main.c:808
rfbBool rfbCheckPasswordByList(rfbClientPtr cl, const char *response, int len)
to check against plain passwords
Definition: main.c:786
rfbLogProc rfbLog
Definition: main.c:263
void rfbLogEnable(int enabled)
Definition: main.c:226
void rfbFreeCursor(rfbCursorPtr cursor)
Definition: cursor.c:367
void sraRgnOr(sraRegion *dst, const sraRegion *src)
Definition: rfbregion.c:562
Definition: rfb.h:896
uint16_t blueMax
Definition: rfbproto.h:179
uint16_t greenMax
Definition: rfbproto.h:177
rfbProtocolExtension * rfbGetExtensionIterator()
Definition: main.c:148
rfbBool rfbSetTranslateFunction(rfbClientPtr cl)
Definition: translate.c:245
void rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
Definition: rfbserver.c:234
struct _rfbExtensionData * next
Definition: rfb.h:189
void rfbProcessClientMessage(rfbClientPtr cl)
Definition: rfbserver.c:645
#define TINI_MUTEX(mutex)
Definition: threading.h:86
rfbBool rfbProcessEvents(rfbScreenInfoPtr screen, long usec)
Definition: main.c:1199
uint8_t bigEndian
Definition: rfbproto.h:160
void rfbTightCleanup(rfbScreenInfoPtr screen)
Definition: tight.c:155
#define FALSE
Definition: rfbproto.h:110
rfbBool rfbSendFileTransferChunk(rfbClientPtr cl)
Definition: rfbserver.c:1516
rfbBool webSocketsHasDataInBuffer(rfbClientPtr cl)
Definition: websockets.c:451
rfbBool rfbUpdateClient(rfbClientPtr cl)
Definition: main.c:1230
rfbClientPtr rfbClientIteratorHead(rfbClientIteratorPtr i)
Definition: rfbserver.c:193
rfbNewClientAction
Definition: rfb.h:91
rfbScreenInfoPtr rfbGetScreen(int *argc, char **argv, int width, int height, int bitsPerSample, int samplesPerPixel, int bytesPerPixel)
Definition: main.c:889
void * rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension *extension)
Definition: main.c:206
#define width
Definition: vncev.c:18
void rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
cursor handling for the pointer
Definition: main.c:690
void rfbUnregisterProtocolExtension(rfbProtocolExtension *extension)
Definition: main.c:110
#define rfbProtocolMinorVersion
Definition: rfbproto.h:247
void rfbInitSockets(rfbScreenInfoPtr rfbScreen)
Definition: sockets.c:159
rfbBool sraRgnEmpty(const sraRegion *rgn)
Definition: rfbregion.c:682
rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen, rfbSocket sock)
Definition: rfbserver.c:520
void rfbEncryptBytes(unsigned char *bytes, char *passwd)
void rfbClientConnectionGone(rfbClientPtr cl)
Definition: rfbserver.c:539
void rfbDecrClientRef(rfbClientPtr cl)
Definition: rfbserver.c:140
void rfbCloseClient(rfbClientPtr cl)
Definition: sockets.c:546
void * data
Definition: rfb.h:188