00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifdef __STRICT_ANSI__
00014 #define _BSD_SOURCE
00015 #endif
00016 #include <rfb/rfb.h>
00017 #include <rfb/rfbregion.h>
00018 #include "private.h"
00019
00020 #include <stdarg.h>
00021 #include <errno.h>
00022
00023 #ifndef false
00024 #define false 0
00025 #define true -1
00026 #endif
00027
00028 #ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
00029 #include <sys/types.h>
00030 #endif
00031
00032 #ifndef WIN32
00033 #include <sys/socket.h>
00034 #include <netinet/in.h>
00035 #include <unistd.h>
00036 #endif
00037
00038 #include <signal.h>
00039 #include <time.h>
00040
00041 static int extMutex_initialized = 0;
00042 static int logMutex_initialized = 0;
00043 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
00044 static MUTEX(logMutex);
00045 static MUTEX(extMutex);
00046 #endif
00047
00048 static int rfbEnableLogging=1;
00049
00050 #ifdef LIBVNCSERVER_WORDS_BIGENDIAN
00051 char rfbEndianTest = (1==0);
00052 #else
00053 char rfbEndianTest = (1==1);
00054 #endif
00055
00056
00057
00058
00059
00060 static rfbProtocolExtension* rfbExtensionHead = NULL;
00061
00062
00063
00064
00065
00066
00067
00068 void
00069 rfbRegisterProtocolExtension(rfbProtocolExtension* extension)
00070 {
00071 rfbProtocolExtension *head = rfbExtensionHead, *next = NULL;
00072
00073 if(extension == NULL)
00074 return;
00075
00076 next = extension->next;
00077
00078 if (! extMutex_initialized) {
00079 INIT_MUTEX(extMutex);
00080 extMutex_initialized = 1;
00081 }
00082
00083 LOCK(extMutex);
00084
00085 while(head != NULL) {
00086 if(head == extension) {
00087 UNLOCK(extMutex);
00088 rfbRegisterProtocolExtension(next);
00089 return;
00090 }
00091
00092 head = head->next;
00093 }
00094
00095 extension->next = rfbExtensionHead;
00096 rfbExtensionHead = extension;
00097
00098 UNLOCK(extMutex);
00099 rfbRegisterProtocolExtension(next);
00100 }
00101
00102
00103
00104
00105
00106
00107 void
00108 rfbUnregisterProtocolExtension(rfbProtocolExtension* extension)
00109 {
00110
00111 rfbProtocolExtension *cur = NULL, *pre = NULL;
00112
00113 if(extension == NULL)
00114 return;
00115
00116 if (! extMutex_initialized) {
00117 INIT_MUTEX(extMutex);
00118 extMutex_initialized = 1;
00119 }
00120
00121 LOCK(extMutex);
00122
00123 if(rfbExtensionHead == extension) {
00124 rfbExtensionHead = rfbExtensionHead->next;
00125 UNLOCK(extMutex);
00126 rfbUnregisterProtocolExtension(extension->next);
00127 return;
00128 }
00129
00130 cur = pre = rfbExtensionHead;
00131
00132 while(cur) {
00133 if(cur == extension) {
00134 pre->next = cur->next;
00135 break;
00136 }
00137 pre = cur;
00138 cur = cur->next;
00139 }
00140
00141 UNLOCK(extMutex);
00142
00143 rfbUnregisterProtocolExtension(extension->next);
00144 }
00145
00146 rfbProtocolExtension* rfbGetExtensionIterator()
00147 {
00148 if (! extMutex_initialized) {
00149 INIT_MUTEX(extMutex);
00150 extMutex_initialized = 1;
00151 }
00152
00153 LOCK(extMutex);
00154 return rfbExtensionHead;
00155 }
00156
00157 void rfbReleaseExtensionIterator()
00158 {
00159 UNLOCK(extMutex);
00160 }
00161
00162 rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension,
00163 void* data)
00164 {
00165 rfbExtensionData* extData;
00166
00167
00168 for(extData = cl->extensions; extData; extData = extData->next)
00169 if(extData->extension == extension)
00170 return FALSE;
00171
00172 extData = calloc(sizeof(rfbExtensionData),1);
00173 extData->extension = extension;
00174 extData->data = data;
00175 extData->next = cl->extensions;
00176 cl->extensions = extData;
00177
00178 return TRUE;
00179 }
00180
00181 rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension)
00182 {
00183 rfbExtensionData* extData;
00184 rfbExtensionData* prevData = NULL;
00185
00186 for(extData = cl->extensions; extData; extData = extData->next) {
00187 if(extData->extension == extension) {
00188 if(extData->data)
00189 free(extData->data);
00190 if(prevData == NULL)
00191 cl->extensions = extData->next;
00192 else
00193 prevData->next = extData->next;
00194 return TRUE;
00195 }
00196 prevData = extData;
00197 }
00198
00199 return FALSE;
00200 }
00201
00202 void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension)
00203 {
00204 rfbExtensionData* data = cl->extensions;
00205
00206 while(data && data->extension != extension)
00207 data = data->next;
00208
00209 if(data == NULL) {
00210 rfbLog("Extension is not enabled !\n");
00211
00212 return NULL;
00213 }
00214
00215 return data->data;
00216 }
00217
00218
00219
00220
00221
00222 void rfbLogEnable(int enabled) {
00223 rfbEnableLogging=enabled;
00224 }
00225
00226
00227
00228
00229
00230 static void
00231 rfbDefaultLog(const char *format, ...)
00232 {
00233 va_list args;
00234 char buf[256];
00235 time_t log_clock;
00236
00237 if(!rfbEnableLogging)
00238 return;
00239
00240 if (! logMutex_initialized) {
00241 INIT_MUTEX(logMutex);
00242 logMutex_initialized = 1;
00243 }
00244
00245 LOCK(logMutex);
00246 va_start(args, format);
00247
00248 time(&log_clock);
00249 strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
00250 fprintf(stderr, "%s", buf);
00251
00252 vfprintf(stderr, format, args);
00253 fflush(stderr);
00254
00255 va_end(args);
00256 UNLOCK(logMutex);
00257 }
00258
00259 rfbLogProc rfbLog=rfbDefaultLog;
00260 rfbLogProc rfbErr=rfbDefaultLog;
00261
00262 void rfbLogPerror(const char *str)
00263 {
00264 rfbErr("%s: %s\n", str, strerror(errno));
00265 }
00266
00267 void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
00268 {
00269 rfbClientIteratorPtr iterator;
00270 rfbClientPtr cl;
00271
00272 iterator=rfbGetClientIterator(rfbScreen);
00273 while((cl=rfbClientIteratorNext(iterator))) {
00274 LOCK(cl->updateMutex);
00275 if(cl->useCopyRect) {
00276 sraRegionPtr modifiedRegionBackup;
00277 if(!sraRgnEmpty(cl->copyRegion)) {
00278 if(cl->copyDX!=dx || cl->copyDY!=dy) {
00279
00280
00281
00282 sraRgnOr(cl->modifiedRegion,cl->copyRegion);
00283 sraRgnMakeEmpty(cl->copyRegion);
00284 } else {
00285
00286
00287 modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
00288 sraRgnOffset(modifiedRegionBackup,-dx,-dy);
00289 sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
00290 sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
00291 sraRgnDestroy(modifiedRegionBackup);
00292 }
00293 }
00294
00295 sraRgnOr(cl->copyRegion,copyRegion);
00296 cl->copyDX = dx;
00297 cl->copyDY = dy;
00298
00299
00300
00301
00302 modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
00303 sraRgnOffset(modifiedRegionBackup,dx,dy);
00304 sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
00305 sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
00306 sraRgnDestroy(modifiedRegionBackup);
00307
00308 if(!cl->enableCursorShapeUpdates) {
00309
00310
00311
00312
00313
00314 sraRegionPtr cursorRegion;
00315 int x = cl->cursorX - cl->screen->cursor->xhot;
00316 int y = cl->cursorY - cl->screen->cursor->yhot;
00317 int w = cl->screen->cursor->width;
00318 int h = cl->screen->cursor->height;
00319
00320 cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
00321 sraRgnAnd(cursorRegion, cl->copyRegion);
00322 if(!sraRgnEmpty(cursorRegion)) {
00323
00324
00325
00326
00327 sraRgnOr(cl->modifiedRegion, cursorRegion);
00328 }
00329 sraRgnDestroy(cursorRegion);
00330
00331 cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
00332
00333 sraRgnOffset(cursorRegion, dx, dy);
00334 sraRgnAnd(cursorRegion, cl->copyRegion);
00335 if(!sraRgnEmpty(cursorRegion)) {
00336
00337
00338
00339
00340
00341 sraRgnOr(cl->modifiedRegion, cursorRegion);
00342 }
00343 sraRgnDestroy(cursorRegion);
00344 }
00345
00346 } else {
00347 sraRgnOr(cl->modifiedRegion,copyRegion);
00348 }
00349 TSIGNAL(cl->updateCond);
00350 UNLOCK(cl->updateMutex);
00351 }
00352
00353 rfbReleaseClientIterator(iterator);
00354 }
00355
00356 void rfbDoCopyRegion(rfbScreenInfoPtr screen,sraRegionPtr copyRegion,int dx,int dy)
00357 {
00358 sraRectangleIterator* i;
00359 sraRect rect;
00360 int j,widthInBytes,bpp=screen->serverFormat.bitsPerPixel/8,
00361 rowstride=screen->paddedWidthInBytes;
00362 char *in,*out;
00363
00364
00365 i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0);
00366 while(sraRgnIteratorNext(i,&rect)) {
00367 widthInBytes = (rect.x2-rect.x1)*bpp;
00368 out = screen->frameBuffer+rect.x1*bpp+rect.y1*rowstride;
00369 in = screen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride;
00370 if(dy<0)
00371 for(j=rect.y1;j<rect.y2;j++,out+=rowstride,in+=rowstride)
00372 memmove(out,in,widthInBytes);
00373 else {
00374 out += rowstride*(rect.y2-rect.y1-1);
00375 in += rowstride*(rect.y2-rect.y1-1);
00376 for(j=rect.y2-1;j>=rect.y1;j--,out-=rowstride,in-=rowstride)
00377 memmove(out,in,widthInBytes);
00378 }
00379 }
00380 sraRgnReleaseIterator(i);
00381
00382 rfbScheduleCopyRegion(screen,copyRegion,dx,dy);
00383 }
00384
00385 void rfbDoCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy)
00386 {
00387 sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
00388 rfbDoCopyRegion(screen,region,dx,dy);
00389 sraRgnDestroy(region);
00390 }
00391
00392 void rfbScheduleCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy)
00393 {
00394 sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
00395 rfbScheduleCopyRegion(screen,region,dx,dy);
00396 sraRgnDestroy(region);
00397 }
00398
00399 void rfbMarkRegionAsModified(rfbScreenInfoPtr screen,sraRegionPtr modRegion)
00400 {
00401 rfbClientIteratorPtr iterator;
00402 rfbClientPtr cl;
00403
00404 iterator=rfbGetClientIterator(screen);
00405 while((cl=rfbClientIteratorNext(iterator))) {
00406 LOCK(cl->updateMutex);
00407 sraRgnOr(cl->modifiedRegion,modRegion);
00408 TSIGNAL(cl->updateCond);
00409 UNLOCK(cl->updateMutex);
00410 }
00411
00412 rfbReleaseClientIterator(iterator);
00413 }
00414
00415 void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
00416 void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2)
00417 {
00418 sraRegionPtr region;
00419 int i;
00420
00421 if(x1>x2) { i=x1; x1=x2; x2=i; }
00422 if(x1<0) x1=0;
00423 if(x2>screen->width) x2=screen->width;
00424 if(x1==x2) return;
00425
00426 if(y1>y2) { i=y1; y1=y2; y2=i; }
00427 if(y1<0) y1=0;
00428 if(y2>screen->height) y2=screen->height;
00429 if(y1==y2) return;
00430
00431
00432 rfbScaledScreenUpdate(screen,x1,y1,x2,y2);
00433
00434 region = sraRgnCreateRect(x1,y1,x2,y2);
00435 rfbMarkRegionAsModified(screen,region);
00436 sraRgnDestroy(region);
00437 }
00438
00439 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
00440 #include <unistd.h>
00441
00442 static void *
00443 clientOutput(void *data)
00444 {
00445 rfbClientPtr cl = (rfbClientPtr)data;
00446 rfbBool haveUpdate;
00447 sraRegion* updateRegion;
00448
00449 while (1) {
00450 haveUpdate = false;
00451 while (!haveUpdate) {
00452 if (cl->sock == -1) {
00453
00454 return NULL;
00455 }
00456 if (cl->state != RFB_NORMAL || cl->onHold) {
00457
00458 usleep(cl->screen->deferUpdateTime * 1000);
00459 continue;
00460 }
00461
00462 LOCK(cl->updateMutex);
00463
00464 if (sraRgnEmpty(cl->requestedRegion)) {
00465 ;
00466 } else {
00467 haveUpdate = FB_UPDATE_PENDING(cl);
00468 if(!haveUpdate) {
00469 updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
00470 haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion);
00471 sraRgnDestroy(updateRegion);
00472 }
00473 }
00474
00475 if (!haveUpdate) {
00476 WAIT(cl->updateCond, cl->updateMutex);
00477 }
00478
00479 UNLOCK(cl->updateMutex);
00480 }
00481
00482
00483
00484 usleep(cl->screen->deferUpdateTime * 1000);
00485
00486
00487
00488
00489
00490 LOCK(cl->updateMutex);
00491 updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
00492 UNLOCK(cl->updateMutex);
00493
00494
00495 rfbIncrClientRef(cl);
00496 LOCK(cl->sendMutex);
00497 rfbSendFramebufferUpdate(cl, updateRegion);
00498 UNLOCK(cl->sendMutex);
00499 rfbDecrClientRef(cl);
00500
00501 sraRgnDestroy(updateRegion);
00502 }
00503
00504
00505 return NULL;
00506 }
00507
00508 static void *
00509 clientInput(void *data)
00510 {
00511 rfbClientPtr cl = (rfbClientPtr)data;
00512 pthread_t output_thread;
00513 pthread_create(&output_thread, NULL, clientOutput, (void *)cl);
00514
00515 while (1) {
00516 fd_set rfds, wfds, efds;
00517 struct timeval tv;
00518 int n;
00519
00520 if (cl->sock == -1) {
00521
00522 break;
00523 }
00524
00525 FD_ZERO(&rfds);
00526 FD_SET(cl->sock, &rfds);
00527 FD_ZERO(&efds);
00528 FD_SET(cl->sock, &efds);
00529
00530
00531 FD_ZERO(&wfds);
00532 if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
00533 FD_SET(cl->sock, &wfds);
00534
00535 tv.tv_sec = 60;
00536 tv.tv_usec = 0;
00537 n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv);
00538 if (n < 0) {
00539 rfbLogPerror("ReadExact: select");
00540 break;
00541 }
00542 if (n == 0)
00543 {
00544 rfbSendFileTransferChunk(cl);
00545 continue;
00546 }
00547
00548
00549 if (FD_ISSET(cl->sock, &wfds))
00550 rfbSendFileTransferChunk(cl);
00551
00552 if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds))
00553 rfbProcessClientMessage(cl);
00554 }
00555
00556
00557 LOCK(cl->updateMutex);
00558 TSIGNAL(cl->updateCond);
00559 UNLOCK(cl->updateMutex);
00560 IF_PTHREADS(pthread_join(output_thread, NULL));
00561
00562 rfbClientConnectionGone(cl);
00563
00564 return NULL;
00565 }
00566
00567 static void*
00568 listenerRun(void *data)
00569 {
00570 rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data;
00571 int client_fd;
00572 struct sockaddr_storage peer;
00573 rfbClientPtr cl = NULL;
00574 socklen_t len;
00575 fd_set listen_fds;
00576
00577
00578
00579 while (1) {
00580 client_fd = -1;
00581 FD_ZERO(&listen_fds);
00582 if(screen->listenSock >= 0)
00583 FD_SET(screen->listenSock, &listen_fds);
00584 if(screen->listen6Sock >= 0)
00585 FD_SET(screen->listen6Sock, &listen_fds);
00586
00587 if (select(screen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) {
00588 rfbLogPerror("listenerRun: error in select");
00589 return NULL;
00590 }
00591
00592
00593 len = sizeof (peer);
00594 if (FD_ISSET(screen->listenSock, &listen_fds))
00595 client_fd = accept(screen->listenSock, (struct sockaddr*)&peer, &len);
00596 else if (FD_ISSET(screen->listen6Sock, &listen_fds))
00597 client_fd = accept(screen->listen6Sock, (struct sockaddr*)&peer, &len);
00598
00599 if(client_fd >= 0)
00600 cl = rfbNewClient(screen,client_fd);
00601 if (cl && !cl->onHold )
00602 rfbStartOnHoldClient(cl);
00603 }
00604 return(NULL);
00605 }
00606
00607 void
00608 rfbStartOnHoldClient(rfbClientPtr cl)
00609 {
00610 pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl);
00611 }
00612
00613 #else
00614
00615 void
00616 rfbStartOnHoldClient(rfbClientPtr cl)
00617 {
00618 cl->onHold = FALSE;
00619 }
00620
00621 #endif
00622
00623 void
00624 rfbRefuseOnHoldClient(rfbClientPtr cl)
00625 {
00626 rfbCloseClient(cl);
00627 rfbClientConnectionGone(cl);
00628 }
00629
00630 static void
00631 rfbDefaultKbdAddEvent(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
00632 {
00633 }
00634
00635 void
00636 rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
00637 {
00638 rfbClientIteratorPtr iterator;
00639 rfbClientPtr other_client;
00640 rfbScreenInfoPtr s = cl->screen;
00641
00642 if (x != s->cursorX || y != s->cursorY) {
00643 LOCK(s->cursorMutex);
00644 s->cursorX = x;
00645 s->cursorY = y;
00646 UNLOCK(s->cursorMutex);
00647
00648
00649 if (cl->enableCursorPosUpdates)
00650 cl->cursorWasMoved = FALSE;
00651
00652
00653 iterator = rfbGetClientIterator(s);
00654 while ((other_client = rfbClientIteratorNext(iterator)) != NULL) {
00655 if (other_client != cl && other_client->enableCursorPosUpdates) {
00656 other_client->cursorWasMoved = TRUE;
00657 }
00658 }
00659 rfbReleaseClientIterator(iterator);
00660 }
00661 }
00662
00663 static void rfbDefaultSetXCutText(char* text, int len, rfbClientPtr cl)
00664 {
00665 }
00666
00667
00668
00669 #if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI)
00670 static rfbCursor myCursor =
00671 {
00672 FALSE, FALSE, FALSE, FALSE,
00673 (unsigned char*)"\000\102\044\030\044\102\000",
00674 (unsigned char*)"\347\347\176\074\176\347\347",
00675 8, 7, 3, 3,
00676 0, 0, 0,
00677 0xffff, 0xffff, 0xffff,
00678 NULL
00679 };
00680 #else
00681 static rfbCursor myCursor =
00682 {
00683 cleanup: FALSE,
00684 cleanupSource: FALSE,
00685 cleanupMask: FALSE,
00686 cleanupRichSource: FALSE,
00687 source: "\000\102\044\030\044\102\000",
00688 mask: "\347\347\176\074\176\347\347",
00689 width: 8, height: 7, xhot: 3, yhot: 3,
00690 foreRed: 0, foreGreen: 0, foreBlue: 0,
00691 backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
00692 richSource: NULL
00693 };
00694 #endif
00695
00696 static rfbCursorPtr rfbDefaultGetCursorPtr(rfbClientPtr cl)
00697 {
00698 return(cl->screen->cursor);
00699 }
00700
00701
00702 static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
00703 {
00704 int i;
00705 char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData);
00706
00707 if(!passwd) {
00708 rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData);
00709 return(FALSE);
00710 }
00711
00712 rfbEncryptBytes(cl->authChallenge, passwd);
00713
00714
00715 for (i = strlen(passwd); i >= 0; i--) {
00716 passwd[i] = '\0';
00717 }
00718
00719 free(passwd);
00720
00721 if (memcmp(cl->authChallenge, response, len) != 0) {
00722 rfbErr("authProcessClientMessage: authentication failed from %s\n",
00723 cl->host);
00724 return(FALSE);
00725 }
00726
00727 return(TRUE);
00728 }
00729
00730
00731
00732 rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len)
00733 {
00734 char **passwds;
00735 int i=0;
00736
00737 for(passwds=(char**)cl->screen->authPasswdData;*passwds;passwds++,i++) {
00738 uint8_t auth_tmp[CHALLENGESIZE];
00739 memcpy((char *)auth_tmp, (char *)cl->authChallenge, CHALLENGESIZE);
00740 rfbEncryptBytes(auth_tmp, *passwds);
00741
00742 if (memcmp(auth_tmp, response, len) == 0) {
00743 if(i>=cl->screen->authPasswdFirstViewOnly)
00744 cl->viewOnly=TRUE;
00745 return(TRUE);
00746 }
00747 }
00748
00749 rfbErr("authProcessClientMessage: authentication failed from %s\n",
00750 cl->host);
00751 return(FALSE);
00752 }
00753
00754 void rfbDoNothingWithClient(rfbClientPtr cl)
00755 {
00756 }
00757
00758 static enum rfbNewClientAction rfbDefaultNewClientHook(rfbClientPtr cl)
00759 {
00760 return RFB_CLIENT_ACCEPT;
00761 }
00762
00763
00764
00765
00766
00767
00768 static void rfbInitServerFormat(rfbScreenInfoPtr screen, int bitsPerSample)
00769 {
00770 rfbPixelFormat* format=&screen->serverFormat;
00771
00772 format->bitsPerPixel = screen->bitsPerPixel;
00773 format->depth = screen->depth;
00774 format->bigEndian = rfbEndianTest?FALSE:TRUE;
00775 format->trueColour = TRUE;
00776 screen->colourMap.count = 0;
00777 screen->colourMap.is16 = 0;
00778 screen->colourMap.data.bytes = NULL;
00779
00780 if (format->bitsPerPixel == 8) {
00781 format->redMax = 7;
00782 format->greenMax = 7;
00783 format->blueMax = 3;
00784 format->redShift = 0;
00785 format->greenShift = 3;
00786 format->blueShift = 6;
00787 } else {
00788 format->redMax = (1 << bitsPerSample) - 1;
00789 format->greenMax = (1 << bitsPerSample) - 1;
00790 format->blueMax = (1 << bitsPerSample) - 1;
00791 if(rfbEndianTest) {
00792 format->redShift = 0;
00793 format->greenShift = bitsPerSample;
00794 format->blueShift = bitsPerSample * 2;
00795 } else {
00796 if(format->bitsPerPixel==8*3) {
00797 format->redShift = bitsPerSample*2;
00798 format->greenShift = bitsPerSample*1;
00799 format->blueShift = 0;
00800 } else {
00801 format->redShift = bitsPerSample*3;
00802 format->greenShift = bitsPerSample*2;
00803 format->blueShift = bitsPerSample;
00804 }
00805 }
00806 }
00807 }
00808
00809 rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
00810 int width,int height,int bitsPerSample,int samplesPerPixel,
00811 int bytesPerPixel)
00812 {
00813 rfbScreenInfoPtr screen=calloc(sizeof(rfbScreenInfo),1);
00814
00815 if (! logMutex_initialized) {
00816 INIT_MUTEX(logMutex);
00817 logMutex_initialized = 1;
00818 }
00819
00820
00821 if(width&3)
00822 rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
00823
00824 screen->autoPort=FALSE;
00825 screen->clientHead=NULL;
00826 screen->pointerClient=NULL;
00827 screen->port=5900;
00828 screen->ipv6port=5900;
00829 screen->socketState=RFB_SOCKET_INIT;
00830
00831 screen->inetdInitDone = FALSE;
00832 screen->inetdSock=-1;
00833
00834 screen->udpSock=-1;
00835 screen->udpSockConnected=FALSE;
00836 screen->udpPort=0;
00837 screen->udpClient=NULL;
00838
00839 screen->maxFd=0;
00840 screen->listenSock=-1;
00841 screen->listen6Sock=-1;
00842
00843 screen->httpInitDone=FALSE;
00844 screen->httpEnableProxyConnect=FALSE;
00845 screen->httpPort=0;
00846 screen->http6Port=0;
00847 screen->httpDir=NULL;
00848 screen->httpListenSock=-1;
00849 screen->httpListen6Sock=-1;
00850 screen->httpSock=-1;
00851
00852 screen->desktopName = "LibVNCServer";
00853 screen->alwaysShared = FALSE;
00854 screen->neverShared = FALSE;
00855 screen->dontDisconnect = FALSE;
00856 screen->authPasswdData = NULL;
00857 screen->authPasswdFirstViewOnly = 1;
00858
00859 screen->width = width;
00860 screen->height = height;
00861 screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
00862
00863 screen->passwordCheck = rfbDefaultPasswordCheck;
00864
00865 screen->ignoreSIGPIPE = TRUE;
00866
00867
00868 screen->progressiveSliceHeight = 0;
00869
00870 screen->listenInterface = htonl(INADDR_ANY);
00871
00872 screen->deferUpdateTime=5;
00873 screen->maxRectsPerUpdate=50;
00874
00875 screen->handleEventsEagerly = FALSE;
00876
00877 screen->protocolMajorVersion = rfbProtocolMajorVersion;
00878 screen->protocolMinorVersion = rfbProtocolMinorVersion;
00879
00880 screen->permitFileTransfer = FALSE;
00881
00882 if(!rfbProcessArguments(screen,argc,argv)) {
00883 free(screen);
00884 return NULL;
00885 }
00886
00887 #ifdef WIN32
00888 {
00889 DWORD dummy=255;
00890 GetComputerName(screen->thisHost,&dummy);
00891 }
00892 #else
00893 gethostname(screen->thisHost, 255);
00894 #endif
00895
00896 screen->paddedWidthInBytes = width*bytesPerPixel;
00897
00898
00899
00900 rfbInitServerFormat(screen, bitsPerSample);
00901
00902
00903
00904 screen->cursorX=screen->cursorY=screen->underCursorBufferLen=0;
00905 screen->underCursorBuffer=NULL;
00906 screen->dontConvertRichCursorToXCursor = FALSE;
00907 screen->cursor = &myCursor;
00908 INIT_MUTEX(screen->cursorMutex);
00909
00910 IF_PTHREADS(screen->backgroundLoop = FALSE);
00911
00912
00913
00914 screen->kbdAddEvent = rfbDefaultKbdAddEvent;
00915 screen->kbdReleaseAllKeys = rfbDoNothingWithClient;
00916 screen->ptrAddEvent = rfbDefaultPtrAddEvent;
00917 screen->setXCutText = rfbDefaultSetXCutText;
00918 screen->getCursorPtr = rfbDefaultGetCursorPtr;
00919 screen->setTranslateFunction = rfbSetTranslateFunction;
00920 screen->newClientHook = rfbDefaultNewClientHook;
00921 screen->displayHook = NULL;
00922 screen->displayFinishedHook = NULL;
00923 screen->getKeyboardLedStateHook = NULL;
00924 screen->xvpHook = NULL;
00925
00926
00927 rfbClientListInit(screen);
00928
00929 return(screen);
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer,
00941 int width, int height,
00942 int bitsPerSample, int samplesPerPixel,
00943 int bytesPerPixel)
00944 {
00945 rfbPixelFormat old_format;
00946 rfbBool format_changed = FALSE;
00947 rfbClientIteratorPtr iterator;
00948 rfbClientPtr cl;
00949
00950
00951
00952 old_format = screen->serverFormat;
00953
00954 if (width & 3)
00955 rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width);
00956
00957 screen->width = width;
00958 screen->height = height;
00959 screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
00960 screen->paddedWidthInBytes = width*bytesPerPixel;
00961
00962 rfbInitServerFormat(screen, bitsPerSample);
00963
00964 if (memcmp(&screen->serverFormat, &old_format,
00965 sizeof(rfbPixelFormat)) != 0) {
00966 format_changed = TRUE;
00967 }
00968
00969 screen->frameBuffer = framebuffer;
00970
00971
00972
00973 if (screen->cursorX >= width)
00974 screen->cursorX = width - 1;
00975 if (screen->cursorY >= height)
00976 screen->cursorY = height - 1;
00977
00978
00979 iterator = rfbGetClientIterator(screen);
00980 while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
00981
00982
00983
00984 if (format_changed)
00985 screen->setTranslateFunction(cl);
00986
00987
00988
00989
00990 LOCK(cl->updateMutex);
00991 sraRgnDestroy(cl->modifiedRegion);
00992 cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
00993 sraRgnMakeEmpty(cl->copyRegion);
00994 cl->copyDX = 0;
00995 cl->copyDY = 0;
00996
00997 if (cl->useNewFBSize)
00998 cl->newFBSizePending = TRUE;
00999
01000 TSIGNAL(cl->updateCond);
01001 UNLOCK(cl->updateMutex);
01002 }
01003 rfbReleaseClientIterator(iterator);
01004 }
01005
01006
01007
01008 void rfbScreenCleanup(rfbScreenInfoPtr screen)
01009 {
01010 rfbClientIteratorPtr i=rfbGetClientIterator(screen);
01011 rfbClientPtr cl,cl1=rfbClientIteratorNext(i);
01012 while(cl1) {
01013 cl=rfbClientIteratorNext(i);
01014 rfbClientConnectionGone(cl1);
01015 cl1=cl;
01016 }
01017 rfbReleaseClientIterator(i);
01018
01019 #define FREE_IF(x) if(screen->x) free(screen->x)
01020 FREE_IF(colourMap.data.bytes);
01021 FREE_IF(underCursorBuffer);
01022 TINI_MUTEX(screen->cursorMutex);
01023 if(screen->cursor && screen->cursor->cleanup)
01024 rfbFreeCursor(screen->cursor);
01025
01026 #ifdef LIBVNCSERVER_HAVE_LIBZ
01027 rfbZlibCleanup(screen);
01028 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
01029 rfbTightCleanup(screen);
01030 #endif
01031
01032
01033 while (screen->scaledScreenNext!=NULL)
01034 {
01035 rfbScreenInfoPtr ptr;
01036 ptr = screen->scaledScreenNext;
01037 screen->scaledScreenNext = ptr->scaledScreenNext;
01038 free(ptr->frameBuffer);
01039 free(ptr);
01040 }
01041
01042 #endif
01043 free(screen);
01044 }
01045
01046 void rfbInitServer(rfbScreenInfoPtr screen)
01047 {
01048 #ifdef WIN32
01049 WSADATA trash;
01050 WSAStartup(MAKEWORD(2,2),&trash);
01051 #endif
01052 rfbInitSockets(screen);
01053 rfbHttpInitSockets(screen);
01054 #ifndef __MINGW32__
01055 if(screen->ignoreSIGPIPE)
01056 signal(SIGPIPE,SIG_IGN);
01057 #endif
01058 }
01059
01060 void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) {
01061 if(disconnectClients) {
01062 rfbClientPtr cl;
01063 rfbClientIteratorPtr iter = rfbGetClientIterator(screen);
01064 while( (cl = rfbClientIteratorNext(iter)) )
01065 if (cl->sock > -1)
01066
01067 rfbCloseClient(cl);
01068 rfbReleaseClientIterator(iter);
01069 }
01070
01071 rfbShutdownSockets(screen);
01072 rfbHttpShutdownSockets(screen);
01073 }
01074
01075 #ifndef LIBVNCSERVER_HAVE_GETTIMEOFDAY
01076 #include <fcntl.h>
01077 #include <conio.h>
01078 #include <sys/timeb.h>
01079
01080 void gettimeofday(struct timeval* tv,char* dummy)
01081 {
01082 SYSTEMTIME t;
01083 GetSystemTime(&t);
01084 tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond;
01085 tv->tv_usec=t.wMilliseconds*1000;
01086 }
01087 #endif
01088
01089 rfbBool
01090 rfbProcessEvents(rfbScreenInfoPtr screen,long usec)
01091 {
01092 rfbClientIteratorPtr i;
01093 rfbClientPtr cl,clPrev;
01094 rfbBool result=FALSE;
01095 extern rfbClientIteratorPtr
01096 rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen);
01097
01098 if(usec<0)
01099 usec=screen->deferUpdateTime*1000;
01100
01101 rfbCheckFds(screen,usec);
01102 rfbHttpCheckFds(screen);
01103
01104 i = rfbGetClientIteratorWithClosed(screen);
01105 cl=rfbClientIteratorHead(i);
01106 while(cl) {
01107 result = rfbUpdateClient(cl);
01108 clPrev=cl;
01109 cl=rfbClientIteratorNext(i);
01110 if(clPrev->sock==-1) {
01111 rfbClientConnectionGone(clPrev);
01112 result=TRUE;
01113 }
01114 }
01115 rfbReleaseClientIterator(i);
01116
01117 return result;
01118 }
01119
01120 rfbBool
01121 rfbUpdateClient(rfbClientPtr cl)
01122 {
01123 struct timeval tv;
01124 rfbBool result=FALSE;
01125 rfbScreenInfoPtr screen = cl->screen;
01126
01127 if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) &&
01128 !sraRgnEmpty(cl->requestedRegion)) {
01129 result=TRUE;
01130 if(screen->deferUpdateTime == 0) {
01131 rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
01132 } else if(cl->startDeferring.tv_usec == 0) {
01133 gettimeofday(&cl->startDeferring,NULL);
01134 if(cl->startDeferring.tv_usec == 0)
01135 cl->startDeferring.tv_usec++;
01136 } else {
01137 gettimeofday(&tv,NULL);
01138 if(tv.tv_sec < cl->startDeferring.tv_sec
01139 || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
01140 +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
01141 > screen->deferUpdateTime) {
01142 cl->startDeferring.tv_usec = 0;
01143 rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
01144 }
01145 }
01146 }
01147
01148 if (!cl->viewOnly && cl->lastPtrX >= 0) {
01149 if(cl->startPtrDeferring.tv_usec == 0) {
01150 gettimeofday(&cl->startPtrDeferring,NULL);
01151 if(cl->startPtrDeferring.tv_usec == 0)
01152 cl->startPtrDeferring.tv_usec++;
01153 } else {
01154 struct timeval tv;
01155 gettimeofday(&tv,NULL);
01156 if(tv.tv_sec < cl->startPtrDeferring.tv_sec
01157 || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000
01158 +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000)
01159 > cl->screen->deferPtrUpdateTime) {
01160 cl->startPtrDeferring.tv_usec = 0;
01161 cl->screen->ptrAddEvent(cl->lastPtrButtons,
01162 cl->lastPtrX,
01163 cl->lastPtrY, cl);
01164 cl->lastPtrX = -1;
01165 }
01166 }
01167 }
01168
01169 return result;
01170 }
01171
01172 rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo) {
01173 return screenInfo->socketState!=RFB_SOCKET_SHUTDOWN || screenInfo->clientHead!=NULL;
01174 }
01175
01176 void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground)
01177 {
01178 if(runInBackground) {
01179 #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
01180 pthread_t listener_thread;
01181
01182 screen->backgroundLoop = TRUE;
01183
01184 pthread_create(&listener_thread, NULL, listenerRun, screen);
01185 return;
01186 #else
01187 rfbErr("Can't run in background, because I don't have PThreads!\n");
01188 return;
01189 #endif
01190 }
01191
01192 if(usec<0)
01193 usec=screen->deferUpdateTime*1000;
01194
01195 while(rfbIsActive(screen))
01196 rfbProcessEvents(screen,usec);
01197 }