/apps/desktop/libvncserver/main.c

http://ftk.googlecode.com/ · C · 1151 lines · 842 code · 204 blank · 105 comment · 152 complexity · 13788b5cb9073aae7feab0dcb7ed5b6f MD5 · raw 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. #ifdef __STRICT_ANSI__
  13. #define _BSD_SOURCE
  14. #endif
  15. #include <rfb/rfb.h>
  16. #include <rfb/rfbregion.h>
  17. #include "private.h"
  18. #include <stdarg.h>
  19. #include <errno.h>
  20. #ifndef false
  21. #define false 0
  22. #define true -1
  23. #endif
  24. #ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
  25. #include <sys/types.h>
  26. #endif
  27. #ifndef WIN32
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <unistd.h>
  31. #endif
  32. #include <signal.h>
  33. #include <time.h>
  34. static int extMutex_initialized = 0;
  35. static int logMutex_initialized = 0;
  36. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  37. static MUTEX(logMutex);
  38. static MUTEX(extMutex);
  39. #endif
  40. static int rfbEnableLogging=1;
  41. #ifdef LIBVNCSERVER_WORDS_BIGENDIAN
  42. char rfbEndianTest = (1==0);
  43. #else
  44. char rfbEndianTest = (1==1);
  45. #endif
  46. /*
  47. * Protocol extensions
  48. */
  49. static rfbProtocolExtension* rfbExtensionHead = NULL;
  50. /*
  51. * This method registers a list of new extensions.
  52. * It avoids same extension getting registered multiple times.
  53. * The order is not preserved if multiple extensions are
  54. * registered at one-go.
  55. */
  56. void
  57. rfbRegisterProtocolExtension(rfbProtocolExtension* extension)
  58. {
  59. rfbProtocolExtension *head = rfbExtensionHead, *next = NULL;
  60. if(extension == NULL)
  61. return;
  62. next = extension->next;
  63. if (! extMutex_initialized) {
  64. INIT_MUTEX(extMutex);
  65. extMutex_initialized = 1;
  66. }
  67. LOCK(extMutex);
  68. while(head != NULL) {
  69. if(head == extension) {
  70. UNLOCK(extMutex);
  71. rfbRegisterProtocolExtension(next);
  72. return;
  73. }
  74. head = head->next;
  75. }
  76. extension->next = rfbExtensionHead;
  77. rfbExtensionHead = extension;
  78. UNLOCK(extMutex);
  79. rfbRegisterProtocolExtension(next);
  80. }
  81. /*
  82. * This method unregisters a list of extensions.
  83. * These extensions won't be available for any new
  84. * client connection.
  85. */
  86. void
  87. rfbUnregisterProtocolExtension(rfbProtocolExtension* extension)
  88. {
  89. rfbProtocolExtension *cur = NULL, *pre = NULL;
  90. if(extension == NULL)
  91. return;
  92. if (! extMutex_initialized) {
  93. INIT_MUTEX(extMutex);
  94. extMutex_initialized = 1;
  95. }
  96. LOCK(extMutex);
  97. if(rfbExtensionHead == extension) {
  98. rfbExtensionHead = rfbExtensionHead->next;
  99. UNLOCK(extMutex);
  100. rfbUnregisterProtocolExtension(extension->next);
  101. return;
  102. }
  103. cur = pre = rfbExtensionHead;
  104. while(cur) {
  105. if(cur == extension) {
  106. pre->next = cur->next;
  107. break;
  108. }
  109. pre = cur;
  110. cur = cur->next;
  111. }
  112. UNLOCK(extMutex);
  113. rfbUnregisterProtocolExtension(extension->next);
  114. }
  115. rfbProtocolExtension* rfbGetExtensionIterator()
  116. {
  117. LOCK(extMutex);
  118. return rfbExtensionHead;
  119. }
  120. void rfbReleaseExtensionIterator()
  121. {
  122. UNLOCK(extMutex);
  123. }
  124. rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension,
  125. void* data)
  126. {
  127. rfbExtensionData* extData;
  128. /* make sure extension is not yet enabled. */
  129. for(extData = cl->extensions; extData; extData = extData->next)
  130. if(extData->extension == extension)
  131. return FALSE;
  132. extData = calloc(sizeof(rfbExtensionData),1);
  133. extData->extension = extension;
  134. extData->data = data;
  135. extData->next = cl->extensions;
  136. cl->extensions = extData;
  137. return TRUE;
  138. }
  139. rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension)
  140. {
  141. rfbExtensionData* extData;
  142. rfbExtensionData* prevData = NULL;
  143. for(extData = cl->extensions; extData; extData = extData->next) {
  144. if(extData->extension == extension) {
  145. if(extData->data)
  146. free(extData->data);
  147. if(prevData == NULL)
  148. cl->extensions = extData->next;
  149. else
  150. prevData->next = extData->next;
  151. return TRUE;
  152. }
  153. prevData = extData;
  154. }
  155. return FALSE;
  156. }
  157. void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension)
  158. {
  159. rfbExtensionData* data = cl->extensions;
  160. while(data && data->extension != extension)
  161. data = data->next;
  162. if(data == NULL) {
  163. rfbLog("Extension is not enabled !\n");
  164. /* rfbCloseClient(cl); */
  165. return NULL;
  166. }
  167. return data->data;
  168. }
  169. /*
  170. * Logging
  171. */
  172. void rfbLogEnable(int enabled) {
  173. rfbEnableLogging=enabled;
  174. }
  175. /*
  176. * rfbLog prints a time-stamped message to the log file (stderr).
  177. */
  178. static void
  179. rfbDefaultLog(const char *format, ...)
  180. {
  181. va_list args;
  182. char buf[256];
  183. time_t log_clock;
  184. if(!rfbEnableLogging)
  185. return;
  186. if (! logMutex_initialized) {
  187. INIT_MUTEX(logMutex);
  188. logMutex_initialized = 1;
  189. }
  190. LOCK(logMutex);
  191. va_start(args, format);
  192. time(&log_clock);
  193. strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
  194. fprintf(stderr, "%s", buf);
  195. vfprintf(stderr, format, args);
  196. fflush(stderr);
  197. va_end(args);
  198. UNLOCK(logMutex);
  199. }
  200. rfbLogProc rfbLog=rfbDefaultLog;
  201. rfbLogProc rfbErr=rfbDefaultLog;
  202. void rfbLogPerror(const char *str)
  203. {
  204. rfbErr("%s: %s\n", str, strerror(errno));
  205. }
  206. void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
  207. {
  208. rfbClientIteratorPtr iterator;
  209. rfbClientPtr cl;
  210. iterator=rfbGetClientIterator(rfbScreen);
  211. while((cl=rfbClientIteratorNext(iterator))) {
  212. LOCK(cl->updateMutex);
  213. if(cl->useCopyRect) {
  214. sraRegionPtr modifiedRegionBackup;
  215. if(!sraRgnEmpty(cl->copyRegion)) {
  216. if(cl->copyDX!=dx || cl->copyDY!=dy) {
  217. /* if a copyRegion was not yet executed, treat it as a
  218. * modifiedRegion. The idea: in this case it could be
  219. * source of the new copyRect or modified anyway. */
  220. sraRgnOr(cl->modifiedRegion,cl->copyRegion);
  221. sraRgnMakeEmpty(cl->copyRegion);
  222. } else {
  223. /* we have to set the intersection of the source of the copy
  224. * and the old copy to modified. */
  225. modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
  226. sraRgnOffset(modifiedRegionBackup,-dx,-dy);
  227. sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
  228. sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
  229. sraRgnDestroy(modifiedRegionBackup);
  230. }
  231. }
  232. sraRgnOr(cl->copyRegion,copyRegion);
  233. cl->copyDX = dx;
  234. cl->copyDY = dy;
  235. /* if there were modified regions, which are now copied,
  236. * mark them as modified, because the source of these can be overlapped
  237. * either by new modified or now copied regions. */
  238. modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
  239. sraRgnOffset(modifiedRegionBackup,dx,dy);
  240. sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
  241. sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
  242. sraRgnDestroy(modifiedRegionBackup);
  243. if(!cl->enableCursorShapeUpdates) {
  244. /*
  245. * n.b. (dx, dy) is the vector pointing in the direction the
  246. * copyrect displacement will take place. copyRegion is the
  247. * destination rectangle (say), not the source rectangle.
  248. */
  249. sraRegionPtr cursorRegion;
  250. int x = cl->cursorX - cl->screen->cursor->xhot;
  251. int y = cl->cursorY - cl->screen->cursor->yhot;
  252. int w = cl->screen->cursor->width;
  253. int h = cl->screen->cursor->height;
  254. cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
  255. sraRgnAnd(cursorRegion, cl->copyRegion);
  256. if(!sraRgnEmpty(cursorRegion)) {
  257. /*
  258. * current cursor rect overlaps with the copy region *dest*,
  259. * mark it as modified since we won't copy-rect stuff to it.
  260. */
  261. sraRgnOr(cl->modifiedRegion, cursorRegion);
  262. }
  263. sraRgnDestroy(cursorRegion);
  264. cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
  265. /* displace it to check for overlap with copy region source: */
  266. sraRgnOffset(cursorRegion, dx, dy);
  267. sraRgnAnd(cursorRegion, cl->copyRegion);
  268. if(!sraRgnEmpty(cursorRegion)) {
  269. /*
  270. * current cursor rect overlaps with the copy region *source*,
  271. * mark the *displaced* cursorRegion as modified since we
  272. * won't copyrect stuff to it.
  273. */
  274. sraRgnOr(cl->modifiedRegion, cursorRegion);
  275. }
  276. sraRgnDestroy(cursorRegion);
  277. }
  278. } else {
  279. sraRgnOr(cl->modifiedRegion,copyRegion);
  280. }
  281. TSIGNAL(cl->updateCond);
  282. UNLOCK(cl->updateMutex);
  283. }
  284. rfbReleaseClientIterator(iterator);
  285. }
  286. void rfbDoCopyRegion(rfbScreenInfoPtr screen,sraRegionPtr copyRegion,int dx,int dy)
  287. {
  288. sraRectangleIterator* i;
  289. sraRect rect;
  290. int j,widthInBytes,bpp=screen->serverFormat.bitsPerPixel/8,
  291. rowstride=screen->paddedWidthInBytes;
  292. char *in,*out;
  293. /* copy it, really */
  294. i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0);
  295. while(sraRgnIteratorNext(i,&rect)) {
  296. widthInBytes = (rect.x2-rect.x1)*bpp;
  297. out = screen->frameBuffer+rect.x1*bpp+rect.y1*rowstride;
  298. in = screen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride;
  299. if(dy<0)
  300. for(j=rect.y1;j<rect.y2;j++,out+=rowstride,in+=rowstride)
  301. memmove(out,in,widthInBytes);
  302. else {
  303. out += rowstride*(rect.y2-rect.y1-1);
  304. in += rowstride*(rect.y2-rect.y1-1);
  305. for(j=rect.y2-1;j>=rect.y1;j--,out-=rowstride,in-=rowstride)
  306. memmove(out,in,widthInBytes);
  307. }
  308. }
  309. sraRgnReleaseIterator(i);
  310. rfbScheduleCopyRegion(screen,copyRegion,dx,dy);
  311. }
  312. void rfbDoCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy)
  313. {
  314. sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
  315. rfbDoCopyRegion(screen,region,dx,dy);
  316. sraRgnDestroy(region);
  317. }
  318. void rfbScheduleCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy)
  319. {
  320. sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
  321. rfbScheduleCopyRegion(screen,region,dx,dy);
  322. sraRgnDestroy(region);
  323. }
  324. void rfbMarkRegionAsModified(rfbScreenInfoPtr screen,sraRegionPtr modRegion)
  325. {
  326. rfbClientIteratorPtr iterator;
  327. rfbClientPtr cl;
  328. iterator=rfbGetClientIterator(screen);
  329. while((cl=rfbClientIteratorNext(iterator))) {
  330. LOCK(cl->updateMutex);
  331. sraRgnOr(cl->modifiedRegion,modRegion);
  332. TSIGNAL(cl->updateCond);
  333. UNLOCK(cl->updateMutex);
  334. }
  335. rfbReleaseClientIterator(iterator);
  336. }
  337. void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
  338. void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2)
  339. {
  340. sraRegionPtr region;
  341. int i;
  342. if(x1>x2) { i=x1; x1=x2; x2=i; }
  343. if(x1<0) x1=0;
  344. if(x2>screen->width) x2=screen->width;
  345. if(x1==x2) return;
  346. if(y1>y2) { i=y1; y1=y2; y2=i; }
  347. if(y1<0) y1=0;
  348. if(y2>screen->height) y2=screen->height;
  349. if(y1==y2) return;
  350. /* update scaled copies for this rectangle */
  351. rfbScaledScreenUpdate(screen,x1,y1,x2,y2);
  352. region = sraRgnCreateRect(x1,y1,x2,y2);
  353. rfbMarkRegionAsModified(screen,region);
  354. sraRgnDestroy(region);
  355. }
  356. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  357. #include <unistd.h>
  358. static void *
  359. clientOutput(void *data)
  360. {
  361. rfbClientPtr cl = (rfbClientPtr)data;
  362. rfbBool haveUpdate;
  363. sraRegion* updateRegion;
  364. while (1) {
  365. haveUpdate = false;
  366. while (!haveUpdate) {
  367. if (cl->sock == -1) {
  368. /* Client has disconnected. */
  369. return NULL;
  370. }
  371. LOCK(cl->updateMutex);
  372. haveUpdate = FB_UPDATE_PENDING(cl);
  373. if(!haveUpdate) {
  374. updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
  375. haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion);
  376. sraRgnDestroy(updateRegion);
  377. }
  378. if (!haveUpdate) {
  379. WAIT(cl->updateCond, cl->updateMutex);
  380. }
  381. UNLOCK(cl->updateMutex);
  382. }
  383. /* OK, now, to save bandwidth, wait a little while for more
  384. updates to come along. */
  385. usleep(cl->screen->deferUpdateTime * 1000);
  386. /* Now, get the region we're going to update, and remove
  387. it from cl->modifiedRegion _before_ we send the update.
  388. That way, if anything that overlaps the region we're sending
  389. is updated, we'll be sure to do another update later. */
  390. LOCK(cl->updateMutex);
  391. updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
  392. UNLOCK(cl->updateMutex);
  393. /* Now actually send the update. */
  394. rfbIncrClientRef(cl);
  395. rfbSendFramebufferUpdate(cl, updateRegion);
  396. rfbDecrClientRef(cl);
  397. sraRgnDestroy(updateRegion);
  398. }
  399. /* Not reached. */
  400. return NULL;
  401. }
  402. static void *
  403. clientInput(void *data)
  404. {
  405. rfbClientPtr cl = (rfbClientPtr)data;
  406. pthread_t output_thread;
  407. pthread_create(&output_thread, NULL, clientOutput, (void *)cl);
  408. while (1) {
  409. fd_set rfds, wfds, efds;
  410. struct timeval tv;
  411. int n;
  412. FD_ZERO(&rfds);
  413. FD_SET(cl->sock, &rfds);
  414. FD_ZERO(&efds);
  415. FD_SET(cl->sock, &efds);
  416. /* Are we transferring a file in the background? */
  417. FD_ZERO(&wfds);
  418. if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
  419. FD_SET(cl->sock, &wfds);
  420. tv.tv_sec = 60; /* 1 minute */
  421. tv.tv_usec = 0;
  422. n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv);
  423. if (n < 0) {
  424. rfbLogPerror("ReadExact: select");
  425. break;
  426. }
  427. if (n == 0) /* timeout */
  428. {
  429. rfbSendFileTransferChunk(cl);
  430. continue;
  431. }
  432. /* We have some space on the transmit queue, send some data */
  433. if (FD_ISSET(cl->sock, &wfds))
  434. rfbSendFileTransferChunk(cl);
  435. if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds))
  436. rfbProcessClientMessage(cl);
  437. if (cl->sock == -1) {
  438. /* Client has disconnected. */
  439. break;
  440. }
  441. }
  442. /* Get rid of the output thread. */
  443. LOCK(cl->updateMutex);
  444. TSIGNAL(cl->updateCond);
  445. UNLOCK(cl->updateMutex);
  446. IF_PTHREADS(pthread_join(output_thread, NULL));
  447. rfbClientConnectionGone(cl);
  448. return NULL;
  449. }
  450. static void*
  451. listenerRun(void *data)
  452. {
  453. rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data;
  454. int client_fd;
  455. struct sockaddr_in peer;
  456. rfbClientPtr cl;
  457. socklen_t len;
  458. len = sizeof(peer);
  459. /* TODO: this thread wont die by restarting the server */
  460. /* TODO: HTTP is not handled */
  461. while ((client_fd = accept(screen->listenSock,
  462. (struct sockaddr*)&peer, &len)) >= 0) {
  463. cl = rfbNewClient(screen,client_fd);
  464. len = sizeof(peer);
  465. if (cl && !cl->onHold )
  466. rfbStartOnHoldClient(cl);
  467. }
  468. return(NULL);
  469. }
  470. void
  471. rfbStartOnHoldClient(rfbClientPtr cl)
  472. {
  473. pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl);
  474. }
  475. #else
  476. void
  477. rfbStartOnHoldClient(rfbClientPtr cl)
  478. {
  479. cl->onHold = FALSE;
  480. }
  481. #endif
  482. void
  483. rfbRefuseOnHoldClient(rfbClientPtr cl)
  484. {
  485. rfbCloseClient(cl);
  486. rfbClientConnectionGone(cl);
  487. }
  488. static void
  489. rfbDefaultKbdAddEvent(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
  490. {
  491. }
  492. void
  493. rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
  494. {
  495. rfbClientIteratorPtr iterator;
  496. rfbClientPtr other_client;
  497. rfbScreenInfoPtr s = cl->screen;
  498. if (x != s->cursorX || y != s->cursorY) {
  499. LOCK(s->cursorMutex);
  500. s->cursorX = x;
  501. s->cursorY = y;
  502. UNLOCK(s->cursorMutex);
  503. /* The cursor was moved by this client, so don't send CursorPos. */
  504. if (cl->enableCursorPosUpdates)
  505. cl->cursorWasMoved = FALSE;
  506. /* But inform all remaining clients about this cursor movement. */
  507. iterator = rfbGetClientIterator(s);
  508. while ((other_client = rfbClientIteratorNext(iterator)) != NULL) {
  509. if (other_client != cl && other_client->enableCursorPosUpdates) {
  510. other_client->cursorWasMoved = TRUE;
  511. }
  512. }
  513. rfbReleaseClientIterator(iterator);
  514. }
  515. }
  516. static void rfbDefaultSetXCutText(char* text, int len, rfbClientPtr cl)
  517. {
  518. }
  519. /* TODO: add a nice VNC or RFB cursor */
  520. #if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI)
  521. static rfbCursor myCursor =
  522. {
  523. FALSE, FALSE, FALSE, FALSE,
  524. (unsigned char*)"\000\102\044\030\044\102\000",
  525. (unsigned char*)"\347\347\176\074\176\347\347",
  526. 8, 7, 3, 3,
  527. 0, 0, 0,
  528. 0xffff, 0xffff, 0xffff,
  529. NULL
  530. };
  531. #else
  532. static rfbCursor myCursor =
  533. {
  534. cleanup: FALSE,
  535. cleanupSource: FALSE,
  536. cleanupMask: FALSE,
  537. cleanupRichSource: FALSE,
  538. source: "\000\102\044\030\044\102\000",
  539. mask: "\347\347\176\074\176\347\347",
  540. width: 8, height: 7, xhot: 3, yhot: 3,
  541. foreRed: 0, foreGreen: 0, foreBlue: 0,
  542. backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
  543. richSource: NULL
  544. };
  545. #endif
  546. static rfbCursorPtr rfbDefaultGetCursorPtr(rfbClientPtr cl)
  547. {
  548. return(cl->screen->cursor);
  549. }
  550. /* response is cl->authChallenge vncEncrypted with passwd */
  551. static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
  552. {
  553. int i;
  554. char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData);
  555. if(!passwd) {
  556. rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData);
  557. return(FALSE);
  558. }
  559. rfbEncryptBytes(cl->authChallenge, passwd);
  560. /* Lose the password from memory */
  561. for (i = strlen(passwd); i >= 0; i--) {
  562. passwd[i] = '\0';
  563. }
  564. free(passwd);
  565. if (memcmp(cl->authChallenge, response, len) != 0) {
  566. rfbErr("authProcessClientMessage: authentication failed from %s\n",
  567. cl->host);
  568. return(FALSE);
  569. }
  570. return(TRUE);
  571. }
  572. /* for this method, authPasswdData is really a pointer to an array
  573. of char*'s, where the last pointer is 0. */
  574. rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len)
  575. {
  576. char **passwds;
  577. int i=0;
  578. for(passwds=(char**)cl->screen->authPasswdData;*passwds;passwds++,i++) {
  579. uint8_t auth_tmp[CHALLENGESIZE];
  580. memcpy((char *)auth_tmp, (char *)cl->authChallenge, CHALLENGESIZE);
  581. rfbEncryptBytes(auth_tmp, *passwds);
  582. if (memcmp(auth_tmp, response, len) == 0) {
  583. if(i>=cl->screen->authPasswdFirstViewOnly)
  584. cl->viewOnly=TRUE;
  585. return(TRUE);
  586. }
  587. }
  588. rfbErr("authProcessClientMessage: authentication failed from %s\n",
  589. cl->host);
  590. return(FALSE);
  591. }
  592. void rfbDoNothingWithClient(rfbClientPtr cl)
  593. {
  594. }
  595. static enum rfbNewClientAction rfbDefaultNewClientHook(rfbClientPtr cl)
  596. {
  597. return RFB_CLIENT_ACCEPT;
  598. }
  599. /*
  600. * Update server's pixel format in screenInfo structure. This
  601. * function is called from rfbGetScreen() and rfbNewFramebuffer().
  602. */
  603. static void rfbInitServerFormat(rfbScreenInfoPtr screen, int bitsPerSample)
  604. {
  605. rfbPixelFormat* format=&screen->serverFormat;
  606. format->bitsPerPixel = screen->bitsPerPixel;
  607. format->depth = screen->depth;
  608. format->bigEndian = rfbEndianTest?FALSE:TRUE;
  609. format->trueColour = TRUE;
  610. screen->colourMap.count = 0;
  611. screen->colourMap.is16 = 0;
  612. screen->colourMap.data.bytes = NULL;
  613. if (format->bitsPerPixel == 8) {
  614. format->redMax = 7;
  615. format->greenMax = 7;
  616. format->blueMax = 3;
  617. format->redShift = 0;
  618. format->greenShift = 3;
  619. format->blueShift = 6;
  620. } else {
  621. format->redMax = (1 << bitsPerSample) - 1;
  622. format->greenMax = (1 << bitsPerSample) - 1;
  623. format->blueMax = (1 << bitsPerSample) - 1;
  624. if(rfbEndianTest) {
  625. format->redShift = 0;
  626. format->greenShift = bitsPerSample;
  627. format->blueShift = bitsPerSample * 2;
  628. } else {
  629. if(format->bitsPerPixel==8*3) {
  630. format->redShift = bitsPerSample*2;
  631. format->greenShift = bitsPerSample*1;
  632. format->blueShift = 0;
  633. } else {
  634. format->redShift = bitsPerSample*3;
  635. format->greenShift = bitsPerSample*2;
  636. format->blueShift = bitsPerSample;
  637. }
  638. }
  639. }
  640. }
  641. rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
  642. int width,int height,int bitsPerSample,int samplesPerPixel,
  643. int bytesPerPixel)
  644. {
  645. rfbScreenInfoPtr screen=calloc(sizeof(rfbScreenInfo),1);
  646. if (! logMutex_initialized) {
  647. INIT_MUTEX(logMutex);
  648. logMutex_initialized = 1;
  649. }
  650. if(width&3)
  651. rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
  652. screen->autoPort=FALSE;
  653. screen->clientHead=NULL;
  654. screen->pointerClient=NULL;
  655. screen->port=5900;
  656. screen->socketState=RFB_SOCKET_INIT;
  657. screen->inetdInitDone = FALSE;
  658. screen->inetdSock=-1;
  659. screen->udpSock=-1;
  660. screen->udpSockConnected=FALSE;
  661. screen->udpPort=0;
  662. screen->udpClient=NULL;
  663. screen->maxFd=0;
  664. screen->listenSock=-1;
  665. screen->httpInitDone=FALSE;
  666. screen->httpEnableProxyConnect=FALSE;
  667. screen->httpPort=0;
  668. screen->httpDir=NULL;
  669. screen->httpListenSock=-1;
  670. screen->httpSock=-1;
  671. screen->desktopName = "LibVNCServer";
  672. screen->alwaysShared = FALSE;
  673. screen->neverShared = FALSE;
  674. screen->dontDisconnect = FALSE;
  675. screen->authPasswdData = NULL;
  676. screen->authPasswdFirstViewOnly = 1;
  677. screen->width = width;
  678. screen->height = height;
  679. screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
  680. screen->passwordCheck = rfbDefaultPasswordCheck;
  681. screen->ignoreSIGPIPE = TRUE;
  682. /* disable progressive updating per default */
  683. screen->progressiveSliceHeight = 0;
  684. screen->listenInterface = htonl(INADDR_ANY);
  685. screen->deferUpdateTime=5;
  686. screen->maxRectsPerUpdate=50;
  687. screen->handleEventsEagerly = FALSE;
  688. screen->protocolMajorVersion = rfbProtocolMajorVersion;
  689. screen->protocolMinorVersion = rfbProtocolMinorVersion;
  690. screen->permitFileTransfer = FALSE;
  691. if(!rfbProcessArguments(screen,argc,argv)) {
  692. free(screen);
  693. return NULL;
  694. }
  695. #ifdef WIN32
  696. {
  697. DWORD dummy=255;
  698. GetComputerName(screen->thisHost,&dummy);
  699. }
  700. #else
  701. gethostname(screen->thisHost, 255);
  702. #endif
  703. screen->paddedWidthInBytes = width*bytesPerPixel;
  704. /* format */
  705. rfbInitServerFormat(screen, bitsPerSample);
  706. /* cursor */
  707. screen->cursorX=screen->cursorY=screen->underCursorBufferLen=0;
  708. screen->underCursorBuffer=NULL;
  709. screen->dontConvertRichCursorToXCursor = FALSE;
  710. screen->cursor = &myCursor;
  711. INIT_MUTEX(screen->cursorMutex);
  712. IF_PTHREADS(screen->backgroundLoop = FALSE);
  713. /* proc's and hook's */
  714. screen->kbdAddEvent = rfbDefaultKbdAddEvent;
  715. screen->kbdReleaseAllKeys = rfbDoNothingWithClient;
  716. screen->ptrAddEvent = rfbDefaultPtrAddEvent;
  717. screen->setXCutText = rfbDefaultSetXCutText;
  718. screen->getCursorPtr = rfbDefaultGetCursorPtr;
  719. screen->setTranslateFunction = rfbSetTranslateFunction;
  720. screen->newClientHook = rfbDefaultNewClientHook;
  721. screen->displayHook = NULL;
  722. screen->getKeyboardLedStateHook = NULL;
  723. /* initialize client list and iterator mutex */
  724. rfbClientListInit(screen);
  725. return(screen);
  726. }
  727. /*
  728. * Switch to another framebuffer (maybe of different size and color
  729. * format). Clients supporting NewFBSize pseudo-encoding will change
  730. * their local framebuffer dimensions if necessary.
  731. * NOTE: Rich cursor data should be converted to new pixel format by
  732. * the caller.
  733. */
  734. void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer,
  735. int width, int height,
  736. int bitsPerSample, int samplesPerPixel,
  737. int bytesPerPixel)
  738. {
  739. rfbPixelFormat old_format;
  740. rfbBool format_changed = FALSE;
  741. rfbClientIteratorPtr iterator;
  742. rfbClientPtr cl;
  743. /* Update information in the screenInfo structure */
  744. old_format = screen->serverFormat;
  745. if (width & 3)
  746. rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width);
  747. screen->width = width;
  748. screen->height = height;
  749. screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
  750. screen->paddedWidthInBytes = width*bytesPerPixel;
  751. rfbInitServerFormat(screen, bitsPerSample);
  752. if (memcmp(&screen->serverFormat, &old_format,
  753. sizeof(rfbPixelFormat)) != 0) {
  754. format_changed = TRUE;
  755. }
  756. screen->frameBuffer = framebuffer;
  757. /* Adjust pointer position if necessary */
  758. if (screen->cursorX >= width)
  759. screen->cursorX = width - 1;
  760. if (screen->cursorY >= height)
  761. screen->cursorY = height - 1;
  762. /* For each client: */
  763. iterator = rfbGetClientIterator(screen);
  764. while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
  765. /* Re-install color translation tables if necessary */
  766. if (format_changed)
  767. screen->setTranslateFunction(cl);
  768. /* Mark the screen contents as changed, and schedule sending
  769. NewFBSize message if supported by this client. */
  770. LOCK(cl->updateMutex);
  771. sraRgnDestroy(cl->modifiedRegion);
  772. cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
  773. sraRgnMakeEmpty(cl->copyRegion);
  774. cl->copyDX = 0;
  775. cl->copyDY = 0;
  776. if (cl->useNewFBSize)
  777. cl->newFBSizePending = TRUE;
  778. TSIGNAL(cl->updateCond);
  779. UNLOCK(cl->updateMutex);
  780. }
  781. rfbReleaseClientIterator(iterator);
  782. }
  783. /* hang up on all clients and free all reserved memory */
  784. void rfbScreenCleanup(rfbScreenInfoPtr screen)
  785. {
  786. rfbClientIteratorPtr i=rfbGetClientIterator(screen);
  787. rfbClientPtr cl,cl1=rfbClientIteratorNext(i);
  788. while(cl1) {
  789. cl=rfbClientIteratorNext(i);
  790. rfbClientConnectionGone(cl1);
  791. cl1=cl;
  792. }
  793. rfbReleaseClientIterator(i);
  794. #define FREE_IF(x) if(screen->x) free(screen->x)
  795. FREE_IF(colourMap.data.bytes);
  796. FREE_IF(underCursorBuffer);
  797. TINI_MUTEX(screen->cursorMutex);
  798. if(screen->cursor && screen->cursor->cleanup)
  799. rfbFreeCursor(screen->cursor);
  800. rfbRRECleanup(screen);
  801. rfbCoRRECleanup(screen);
  802. rfbUltraCleanup(screen);
  803. #ifdef LIBVNCSERVER_HAVE_LIBZ
  804. rfbZlibCleanup(screen);
  805. #ifdef LIBVNCSERVER_HAVE_LIBJPEG
  806. rfbTightCleanup(screen);
  807. #endif
  808. /* free all 'scaled' versions of this screen */
  809. while (screen->scaledScreenNext!=NULL)
  810. {
  811. rfbScreenInfoPtr ptr;
  812. ptr = screen->scaledScreenNext;
  813. screen->scaledScreenNext = ptr->scaledScreenNext;
  814. free(ptr->frameBuffer);
  815. free(ptr);
  816. }
  817. #endif
  818. free(screen);
  819. }
  820. void rfbInitServer(rfbScreenInfoPtr screen)
  821. {
  822. #ifdef WIN32
  823. WSADATA trash;
  824. WSAStartup(MAKEWORD(2,2),&trash);
  825. #endif
  826. rfbInitSockets(screen);
  827. rfbHttpInitSockets(screen);
  828. #ifndef __MINGW32__
  829. if(screen->ignoreSIGPIPE)
  830. signal(SIGPIPE,SIG_IGN);
  831. #endif
  832. }
  833. void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) {
  834. if(disconnectClients) {
  835. rfbClientPtr cl;
  836. rfbClientIteratorPtr iter = rfbGetClientIterator(screen);
  837. while( (cl = rfbClientIteratorNext(iter)) )
  838. if (cl->sock > -1)
  839. /* we don't care about maxfd here, because the server goes away */
  840. rfbCloseClient(cl);
  841. rfbReleaseClientIterator(iter);
  842. }
  843. rfbShutdownSockets(screen);
  844. rfbHttpShutdownSockets(screen);
  845. }
  846. #ifndef LIBVNCSERVER_HAVE_GETTIMEOFDAY
  847. #include <fcntl.h>
  848. #include <conio.h>
  849. #include <sys/timeb.h>
  850. void gettimeofday(struct timeval* tv,char* dummy)
  851. {
  852. SYSTEMTIME t;
  853. GetSystemTime(&t);
  854. tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond;
  855. tv->tv_usec=t.wMilliseconds*1000;
  856. }
  857. #endif
  858. rfbBool
  859. rfbProcessEvents(rfbScreenInfoPtr screen,long usec)
  860. {
  861. rfbClientIteratorPtr i;
  862. rfbClientPtr cl,clPrev;
  863. struct timeval tv;
  864. rfbBool result=FALSE;
  865. extern rfbClientIteratorPtr
  866. rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen);
  867. if(usec<0)
  868. usec=screen->deferUpdateTime*1000;
  869. rfbCheckFds(screen,usec);
  870. rfbHttpCheckFds(screen);
  871. #ifdef CORBA
  872. corbaCheckFds(screen);
  873. #endif
  874. i = rfbGetClientIteratorWithClosed(screen);
  875. cl=rfbClientIteratorHead(i);
  876. while(cl) {
  877. if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) &&
  878. !sraRgnEmpty(cl->requestedRegion)) {
  879. result=TRUE;
  880. if(screen->deferUpdateTime == 0) {
  881. rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
  882. } else if(cl->startDeferring.tv_usec == 0) {
  883. gettimeofday(&cl->startDeferring,NULL);
  884. if(cl->startDeferring.tv_usec == 0)
  885. cl->startDeferring.tv_usec++;
  886. } else {
  887. gettimeofday(&tv,NULL);
  888. if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
  889. || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
  890. +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
  891. > screen->deferUpdateTime) {
  892. cl->startDeferring.tv_usec = 0;
  893. rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
  894. }
  895. }
  896. }
  897. if (!cl->viewOnly && cl->lastPtrX >= 0) {
  898. if(cl->startPtrDeferring.tv_usec == 0) {
  899. gettimeofday(&cl->startPtrDeferring,NULL);
  900. if(cl->startPtrDeferring.tv_usec == 0)
  901. cl->startPtrDeferring.tv_usec++;
  902. } else {
  903. struct timeval tv;
  904. gettimeofday(&tv,NULL);
  905. if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */
  906. || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000
  907. +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000)
  908. > cl->screen->deferPtrUpdateTime) {
  909. cl->startPtrDeferring.tv_usec = 0;
  910. cl->screen->ptrAddEvent(cl->lastPtrButtons,
  911. cl->lastPtrX,
  912. cl->lastPtrY, cl);
  913. cl->lastPtrX = -1;
  914. }
  915. }
  916. }
  917. clPrev=cl;
  918. cl=rfbClientIteratorNext(i);
  919. if(clPrev->sock==-1) {
  920. rfbClientConnectionGone(clPrev);
  921. result=TRUE;
  922. }
  923. }
  924. rfbReleaseClientIterator(i);
  925. return result;
  926. }
  927. rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo) {
  928. return screenInfo->socketState!=RFB_SOCKET_SHUTDOWN || screenInfo->clientHead!=NULL;
  929. }
  930. void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground)
  931. {
  932. if(runInBackground) {
  933. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  934. pthread_t listener_thread;
  935. screen->backgroundLoop = TRUE;
  936. pthread_create(&listener_thread, NULL, listenerRun, screen);
  937. return;
  938. #else
  939. rfbErr("Can't run in background, because I don't have PThreads!\n");
  940. return;
  941. #endif
  942. }
  943. if(usec<0)
  944. usec=screen->deferUpdateTime*1000;
  945. while(rfbIsActive(screen))
  946. rfbProcessEvents(screen,usec);
  947. }