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