Home | History | Annotate | Download | only in libvncclient
      1 /*
      2  *  Copyright (C) 2011-2012 Christian Beier <dontmind (at) freeshell.org>
      3  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
      4  *
      5  *  This is free software; you can redistribute it and/or modify
      6  *  it under the terms of the GNU General Public License as published by
      7  *  the Free Software Foundation; either version 2 of the License, or
      8  *  (at your option) any later version.
      9  *
     10  *  This software is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  *  GNU General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU General Public License
     16  *  along with this software; if not, write to the Free Software
     17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
     18  *  USA.
     19  */
     20 
     21 /*
     22  * sockets.c - functions to deal with sockets.
     23  */
     24 
     25 #ifdef __STRICT_ANSI__
     26 #define _BSD_SOURCE
     27 #endif
     28 #include <unistd.h>
     29 #include <errno.h>
     30 #include <fcntl.h>
     31 #include <assert.h>
     32 #include <rfb/rfbclient.h>
     33 #ifdef WIN32
     34 #undef SOCKET
     35 #include <winsock2.h>
     36 #define EWOULDBLOCK WSAEWOULDBLOCK
     37 #define close closesocket
     38 #define read(sock,buf,len) recv(sock,buf,len,0)
     39 #define write(sock,buf,len) send(sock,buf,len,0)
     40 #define socklen_t int
     41 #ifdef LIBVNCSERVER_HAVE_WS2TCPIP_H
     42 #undef socklen_t
     43 #include <ws2tcpip.h>
     44 #endif
     45 #else
     46 #include <sys/socket.h>
     47 #include <netinet/in.h>
     48 #include <sys/un.h>
     49 #include <netinet/tcp.h>
     50 #include <arpa/inet.h>
     51 #include <netdb.h>
     52 #endif
     53 #include "tls.h"
     54 
     55 void PrintInHex(char *buf, int len);
     56 
     57 rfbBool errorMessageOnReadFailure = TRUE;
     58 
     59 /*
     60  * ReadFromRFBServer is called whenever we want to read some data from the RFB
     61  * server.  It is non-trivial for two reasons:
     62  *
     63  * 1. For efficiency it performs some intelligent buffering, avoiding invoking
     64  *    the read() system call too often.  For small chunks of data, it simply
     65  *    copies the data out of an internal buffer.  For large amounts of data it
     66  *    reads directly into the buffer provided by the caller.
     67  *
     68  * 2. Whenever read() would block, it invokes the Xt event dispatching
     69  *    mechanism to process X events.  In fact, this is the only place these
     70  *    events are processed, as there is no XtAppMainLoop in the program.
     71  */
     72 
     73 rfbBool
     74 ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
     75 {
     76 #undef DEBUG_READ_EXACT
     77 #ifdef DEBUG_READ_EXACT
     78 	char* oout=out;
     79 	int nn=n;
     80 	rfbClientLog("ReadFromRFBServer %d bytes\n",n);
     81 #endif
     82   if (client->serverPort==-1) {
     83     /* vncrec playing */
     84     rfbVNCRec* rec = client->vncRec;
     85     struct timeval tv;
     86 
     87     if (rec->readTimestamp) {
     88       rec->readTimestamp = FALSE;
     89       if (!fread(&tv,sizeof(struct timeval),1,rec->file))
     90         return FALSE;
     91 
     92       tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec);
     93       tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec);
     94 
     95       if (rec->tv.tv_sec!=0 && !rec->doNotSleep) {
     96         struct timeval diff;
     97         diff.tv_sec = tv.tv_sec - rec->tv.tv_sec;
     98         diff.tv_usec = tv.tv_usec - rec->tv.tv_usec;
     99         if(diff.tv_usec<0) {
    100 	  diff.tv_sec--;
    101 	  diff.tv_usec+=1000000;
    102         }
    103 #ifndef __MINGW32__
    104         sleep (diff.tv_sec);
    105         usleep (diff.tv_usec);
    106 #else
    107 	Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000);
    108 #endif
    109       }
    110 
    111       rec->tv=tv;
    112     }
    113 
    114     return (fread(out,1,n,rec->file)<0?FALSE:TRUE);
    115   }
    116 
    117   if (n <= client->buffered) {
    118     memcpy(out, client->bufoutptr, n);
    119     client->bufoutptr += n;
    120     client->buffered -= n;
    121 #ifdef DEBUG_READ_EXACT
    122     goto hexdump;
    123 #endif
    124     return TRUE;
    125   }
    126 
    127   memcpy(out, client->bufoutptr, client->buffered);
    128 
    129   out += client->buffered;
    130   n -= client->buffered;
    131 
    132   client->bufoutptr = client->buf;
    133   client->buffered = 0;
    134 
    135   if (n <= RFB_BUF_SIZE) {
    136 
    137     while (client->buffered < n) {
    138       int i;
    139       if (client->tlsSession) {
    140         i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered);
    141       } else {
    142         i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered);
    143       }
    144       if (i <= 0) {
    145 	if (i < 0) {
    146 #ifdef WIN32
    147 	  errno=WSAGetLastError();
    148 #endif
    149 	  if (errno == EWOULDBLOCK || errno == EAGAIN) {
    150 	    /* TODO:
    151 	       ProcessXtEvents();
    152 	    */
    153 	    WaitForMessage(client, 100000);
    154 	    i = 0;
    155 	  } else {
    156 	    rfbClientErr("read (%d: %s)\n",errno,strerror(errno));
    157 	    return FALSE;
    158 	  }
    159 	} else {
    160 	  if (errorMessageOnReadFailure) {
    161 	    rfbClientLog("VNC server closed connection\n");
    162 	  }
    163 	  return FALSE;
    164 	}
    165       }
    166       client->buffered += i;
    167     }
    168 
    169     memcpy(out, client->bufoutptr, n);
    170     client->bufoutptr += n;
    171     client->buffered -= n;
    172 
    173   } else {
    174 
    175     while (n > 0) {
    176       int i;
    177       if (client->tlsSession) {
    178         i = ReadFromTLS(client, out, n);
    179       } else {
    180         i = read(client->sock, out, n);
    181       }
    182 
    183       if (i <= 0) {
    184 	if (i < 0) {
    185 #ifdef WIN32
    186 	  errno=WSAGetLastError();
    187 #endif
    188 	  if (errno == EWOULDBLOCK || errno == EAGAIN) {
    189 	    /* TODO:
    190 	       ProcessXtEvents();
    191 	    */
    192 	    WaitForMessage(client, 100000);
    193 	    i = 0;
    194 	  } else {
    195 	    rfbClientErr("read (%s)\n",strerror(errno));
    196 	    return FALSE;
    197 	  }
    198 	} else {
    199 	  if (errorMessageOnReadFailure) {
    200 	    rfbClientLog("VNC server closed connection\n");
    201 	  }
    202 	  return FALSE;
    203 	}
    204       }
    205       out += i;
    206       n -= i;
    207     }
    208   }
    209 
    210 #ifdef DEBUG_READ_EXACT
    211 hexdump:
    212   { int ii;
    213     for(ii=0;ii<nn;ii++)
    214       fprintf(stderr,"%02x ",(unsigned char)oout[ii]);
    215     fprintf(stderr,"\n");
    216   }
    217 #endif
    218 
    219   return TRUE;
    220 }
    221 
    222 
    223 /*
    224  * Write an exact number of bytes, and don't return until you've sent them.
    225  */
    226 
    227 rfbBool
    228 WriteToRFBServer(rfbClient* client, char *buf, int n)
    229 {
    230   fd_set fds;
    231   int i = 0;
    232   int j;
    233 
    234   if (client->serverPort==-1)
    235     return TRUE; /* vncrec playing */
    236 
    237   if (client->tlsSession) {
    238     /* WriteToTLS() will guarantee either everything is written, or error/eof returns */
    239     i = WriteToTLS(client, buf, n);
    240     if (i <= 0) return FALSE;
    241 
    242     return TRUE;
    243   }
    244 
    245   while (i < n) {
    246     j = write(client->sock, buf + i, (n - i));
    247     if (j <= 0) {
    248       if (j < 0) {
    249 #ifdef WIN32
    250 	 errno=WSAGetLastError();
    251 #endif
    252 	if (errno == EWOULDBLOCK ||
    253 #ifdef LIBVNCSERVER_ENOENT_WORKAROUND
    254 		errno == ENOENT ||
    255 #endif
    256 		errno == EAGAIN) {
    257 	  FD_ZERO(&fds);
    258 	  FD_SET(client->sock,&fds);
    259 
    260 	  if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) {
    261 	    rfbClientErr("select\n");
    262 	    return FALSE;
    263 	  }
    264 	  j = 0;
    265 	} else {
    266 	  rfbClientErr("write\n");
    267 	  return FALSE;
    268 	}
    269       } else {
    270 	rfbClientLog("write failed\n");
    271 	return FALSE;
    272       }
    273     }
    274     i += j;
    275   }
    276   return TRUE;
    277 }
    278 
    279 
    280 
    281 static int initSockets() {
    282 #ifdef WIN32
    283   WSADATA trash;
    284   static rfbBool WSAinitted=FALSE;
    285   if(!WSAinitted) {
    286     int i=WSAStartup(MAKEWORD(2,0),&trash);
    287     if(i!=0) {
    288       rfbClientErr("Couldn't init Windows Sockets\n");
    289       return 0;
    290     }
    291     WSAinitted=TRUE;
    292   }
    293 #endif
    294   return 1;
    295 }
    296 
    297 /*
    298  * ConnectToTcpAddr connects to the given TCP port.
    299  */
    300 
    301 int
    302 ConnectClientToTcpAddr(unsigned int host, int port)
    303 {
    304   int sock;
    305   struct sockaddr_in addr;
    306   int one = 1;
    307 
    308   if (!initSockets())
    309 	  return -1;
    310 
    311   addr.sin_family = AF_INET;
    312   addr.sin_port = htons(port);
    313   addr.sin_addr.s_addr = host;
    314 
    315   sock = socket(AF_INET, SOCK_STREAM, 0);
    316   if (sock < 0) {
    317 #ifdef WIN32
    318     errno=WSAGetLastError();
    319 #endif
    320     rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno));
    321     return -1;
    322   }
    323 
    324   if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    325     rfbClientErr("ConnectToTcpAddr: connect\n");
    326     close(sock);
    327     return -1;
    328   }
    329 
    330   if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
    331 		 (char *)&one, sizeof(one)) < 0) {
    332     rfbClientErr("ConnectToTcpAddr: setsockopt\n");
    333     close(sock);
    334     return -1;
    335   }
    336 
    337   return sock;
    338 }
    339 
    340 int
    341 ConnectClientToTcpAddr6(const char *hostname, int port)
    342 {
    343 #ifdef LIBVNCSERVER_IPv6
    344   int sock;
    345   int n;
    346   struct addrinfo hints, *res, *ressave;
    347   char port_s[10];
    348   int one = 1;
    349 
    350   if (!initSockets())
    351 	  return -1;
    352 
    353   snprintf(port_s, 10, "%d", port);
    354   memset(&hints, 0, sizeof(struct addrinfo));
    355   hints.ai_family = AF_UNSPEC;
    356   hints.ai_socktype = SOCK_STREAM;
    357   if ((n = getaddrinfo(hostname, port_s, &hints, &res)))
    358   {
    359     rfbClientErr("ConnectClientToTcpAddr6: getaddrinfo (%s)\n", gai_strerror(n));
    360     return -1;
    361   }
    362 
    363   ressave = res;
    364   sock = -1;
    365   while (res)
    366   {
    367     sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    368     if (sock >= 0)
    369     {
    370       if (connect(sock, res->ai_addr, res->ai_addrlen) == 0)
    371         break;
    372       close(sock);
    373       sock = -1;
    374     }
    375     res = res->ai_next;
    376   }
    377   freeaddrinfo(ressave);
    378 
    379   if (sock == -1)
    380   {
    381     rfbClientErr("ConnectClientToTcpAddr6: connect\n");
    382     return -1;
    383   }
    384 
    385   if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
    386 		 (char *)&one, sizeof(one)) < 0) {
    387     rfbClientErr("ConnectToTcpAddr: setsockopt\n");
    388     close(sock);
    389     return -1;
    390   }
    391 
    392   return sock;
    393 
    394 #else
    395 
    396   rfbClientErr("ConnectClientToTcpAddr6: IPv6 disabled\n");
    397   return -1;
    398 
    399 #endif
    400 }
    401 
    402 int
    403 ConnectClientToUnixSock(const char *sockFile)
    404 {
    405 #ifdef WIN32
    406   rfbClientErr("Windows doesn't support UNIX sockets\n");
    407   return -1;
    408 #else
    409   int sock;
    410   struct sockaddr_un addr;
    411   addr.sun_family = AF_UNIX;
    412   strcpy(addr.sun_path, sockFile);
    413 
    414   sock = socket(AF_UNIX, SOCK_STREAM, 0);
    415   if (sock < 0) {
    416     rfbClientErr("ConnectToUnixSock: socket (%s)\n",strerror(errno));
    417     return -1;
    418   }
    419 
    420   if (connect(sock, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) < 0) {
    421     rfbClientErr("ConnectToUnixSock: connect\n");
    422     close(sock);
    423     return -1;
    424   }
    425 
    426   return sock;
    427 #endif
    428 }
    429 
    430 
    431 
    432 /*
    433  * FindFreeTcpPort tries to find unused TCP port in the range
    434  * (TUNNEL_PORT_OFFSET, TUNNEL_PORT_OFFSET + 99]. Returns 0 on failure.
    435  */
    436 
    437 int
    438 FindFreeTcpPort(void)
    439 {
    440   int sock, port;
    441   struct sockaddr_in addr;
    442 
    443   addr.sin_family = AF_INET;
    444   addr.sin_addr.s_addr = htonl(INADDR_ANY);
    445 
    446   if (!initSockets())
    447     return -1;
    448 
    449   sock = socket(AF_INET, SOCK_STREAM, 0);
    450   if (sock < 0) {
    451     rfbClientErr(": FindFreeTcpPort: socket\n");
    452     return 0;
    453   }
    454 
    455   for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) {
    456     addr.sin_port = htons((unsigned short)port);
    457     if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
    458       close(sock);
    459       return port;
    460     }
    461   }
    462 
    463   close(sock);
    464   return 0;
    465 }
    466 
    467 
    468 /*
    469  * ListenAtTcpPort starts listening at the given TCP port.
    470  */
    471 
    472 int
    473 ListenAtTcpPort(int port)
    474 {
    475   return ListenAtTcpPortAndAddress(port, NULL);
    476 }
    477 
    478 
    479 
    480 /*
    481  * ListenAtTcpPortAndAddress starts listening at the given TCP port on
    482  * the given IP address
    483  */
    484 
    485 int
    486 ListenAtTcpPortAndAddress(int port, const char *address)
    487 {
    488   int sock;
    489   int one = 1;
    490 #ifndef LIBVNCSERVER_IPv6
    491   struct sockaddr_in addr;
    492 
    493   addr.sin_family = AF_INET;
    494   addr.sin_port = htons(port);
    495   if (address) {
    496     addr.sin_addr.s_addr = inet_addr(address);
    497   } else {
    498     addr.sin_addr.s_addr = htonl(INADDR_ANY);
    499   }
    500 
    501   if (!initSockets())
    502     return -1;
    503 
    504   sock = socket(AF_INET, SOCK_STREAM, 0);
    505   if (sock < 0) {
    506     rfbClientErr("ListenAtTcpPort: socket\n");
    507     return -1;
    508   }
    509 
    510   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
    511 		 (const char *)&one, sizeof(one)) < 0) {
    512     rfbClientErr("ListenAtTcpPort: setsockopt\n");
    513     close(sock);
    514     return -1;
    515   }
    516 
    517   if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    518     rfbClientErr("ListenAtTcpPort: bind\n");
    519     close(sock);
    520     return -1;
    521   }
    522 
    523 #else
    524   int rv;
    525   struct addrinfo hints, *servinfo, *p;
    526   char port_str[8];
    527 
    528   snprintf(port_str, 8, "%d", port);
    529 
    530   memset(&hints, 0, sizeof(hints));
    531   hints.ai_family = AF_UNSPEC;
    532   hints.ai_socktype = SOCK_STREAM;
    533   hints.ai_flags = AI_PASSIVE; /* fill in wildcard address if address == NULL */
    534 
    535   if (!initSockets())
    536     return -1;
    537 
    538   if ((rv = getaddrinfo(address, port_str, &hints, &servinfo)) != 0) {
    539     rfbClientErr("ListenAtTcpPortAndAddress: error in getaddrinfo: %s\n", gai_strerror(rv));
    540     return -1;
    541   }
    542 
    543   /* loop through all the results and bind to the first we can */
    544   for(p = servinfo; p != NULL; p = p->ai_next) {
    545     if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
    546       continue;
    547     }
    548 
    549 #ifdef IPV6_V6ONLY
    550     /* we have seperate IPv4 and IPv6 sockets since some OS's do not support dual binding */
    551     if (p->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
    552       rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt IPV6_V6ONLY: %s\n", strerror(errno));
    553       close(sock);
    554       freeaddrinfo(servinfo);
    555       return -1;
    556     }
    557 #endif
    558 
    559     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
    560       rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt SO_REUSEADDR: %s\n", strerror(errno));
    561       close(sock);
    562       freeaddrinfo(servinfo);
    563       return -1;
    564     }
    565 
    566     if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
    567       close(sock);
    568       continue;
    569     }
    570 
    571     break;
    572   }
    573 
    574   if (p == NULL)  {
    575     rfbClientErr("ListenAtTcpPortAndAddress: error in bind: %s\n", strerror(errno));
    576     return -1;
    577   }
    578 
    579   /* all done with this structure now */
    580   freeaddrinfo(servinfo);
    581 #endif
    582 
    583   if (listen(sock, 5) < 0) {
    584     rfbClientErr("ListenAtTcpPort: listen\n");
    585     close(sock);
    586     return -1;
    587   }
    588 
    589   return sock;
    590 }
    591 
    592 
    593 /*
    594  * AcceptTcpConnection accepts a TCP connection.
    595  */
    596 
    597 int
    598 AcceptTcpConnection(int listenSock)
    599 {
    600   int sock;
    601   struct sockaddr_in addr;
    602   socklen_t addrlen = sizeof(addr);
    603   int one = 1;
    604 
    605   sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen);
    606   if (sock < 0) {
    607     rfbClientErr("AcceptTcpConnection: accept\n");
    608     return -1;
    609   }
    610 
    611   if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
    612 		 (char *)&one, sizeof(one)) < 0) {
    613     rfbClientErr("AcceptTcpConnection: setsockopt\n");
    614     close(sock);
    615     return -1;
    616   }
    617 
    618   return sock;
    619 }
    620 
    621 
    622 /*
    623  * SetNonBlocking sets a socket into non-blocking mode.
    624  */
    625 
    626 rfbBool
    627 SetNonBlocking(int sock)
    628 {
    629 #ifdef WIN32
    630   unsigned long block=1;
    631   if(ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR) {
    632     errno=WSAGetLastError();
    633 #else
    634   int flags = fcntl(sock, F_GETFL);
    635   if(flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
    636 #endif
    637     rfbClientErr("Setting socket to non-blocking failed: %s\n",strerror(errno));
    638     return FALSE;
    639   }
    640   return TRUE;
    641 }
    642 
    643 
    644 
    645 /*
    646  * SetDSCP sets a socket's IP QoS parameters aka Differentiated Services Code Point field
    647  */
    648 
    649 rfbBool
    650 SetDSCP(int sock, int dscp)
    651 {
    652 #ifdef WIN32
    653   rfbClientErr("Setting of QoS IP DSCP not implemented for Windows\n");
    654   return TRUE;
    655 #else
    656   int level, cmd;
    657   struct sockaddr addr;
    658   socklen_t addrlen = sizeof(addr);
    659 
    660   if(getsockname(sock, &addr, &addrlen) != 0) {
    661     rfbClientErr("Setting socket QoS failed while getting socket address: %s\n",strerror(errno));
    662     return FALSE;
    663   }
    664 
    665   switch(addr.sa_family)
    666     {
    667 #if defined LIBVNCSERVER_IPv6 && defined IPV6_TCLASS
    668     case AF_INET6:
    669       level = IPPROTO_IPV6;
    670       cmd = IPV6_TCLASS;
    671       break;
    672 #endif
    673     case AF_INET:
    674       level = IPPROTO_IP;
    675       cmd = IP_TOS;
    676       break;
    677     default:
    678       rfbClientErr("Setting socket QoS failed: Not bound to IP address");
    679       return FALSE;
    680     }
    681 
    682   if(setsockopt(sock, level, cmd, (void*)&dscp, sizeof(dscp)) != 0) {
    683     rfbClientErr("Setting socket QoS failed: %s\n", strerror(errno));
    684     return FALSE;
    685   }
    686 
    687   return TRUE;
    688 #endif
    689 }
    690 
    691 
    692 
    693 /*
    694  * StringToIPAddr - convert a host string to an IP address.
    695  */
    696 
    697 rfbBool
    698 StringToIPAddr(const char *str, unsigned int *addr)
    699 {
    700   struct hostent *hp;
    701 
    702   if (strcmp(str,"") == 0) {
    703     *addr = htonl(INADDR_LOOPBACK); /* local */
    704     return TRUE;
    705   }
    706 
    707   *addr = inet_addr(str);
    708 
    709   if (*addr != -1)
    710     return TRUE;
    711 
    712   if (!initSockets())
    713 	  return -1;
    714 
    715   hp = gethostbyname(str);
    716 
    717   if (hp) {
    718     *addr = *(unsigned int *)hp->h_addr;
    719     return TRUE;
    720   }
    721 
    722   return FALSE;
    723 }
    724 
    725 
    726 /*
    727  * Test if the other end of a socket is on the same machine.
    728  */
    729 
    730 rfbBool
    731 SameMachine(int sock)
    732 {
    733   struct sockaddr_in peeraddr, myaddr;
    734   socklen_t addrlen = sizeof(struct sockaddr_in);
    735 
    736   getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen);
    737   getsockname(sock, (struct sockaddr *)&myaddr, &addrlen);
    738 
    739   return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr);
    740 }
    741 
    742 
    743 /*
    744  * Print out the contents of a packet for debugging.
    745  */
    746 
    747 void
    748 PrintInHex(char *buf, int len)
    749 {
    750   int i, j;
    751   char c, str[17];
    752 
    753   str[16] = 0;
    754 
    755   rfbClientLog("ReadExact: ");
    756 
    757   for (i = 0; i < len; i++)
    758     {
    759       if ((i % 16 == 0) && (i != 0)) {
    760 	rfbClientLog("           ");
    761       }
    762       c = buf[i];
    763       str[i % 16] = (((c > 31) && (c < 127)) ? c : '.');
    764       rfbClientLog("%02x ",(unsigned char)c);
    765       if ((i % 4) == 3)
    766 	rfbClientLog(" ");
    767       if ((i % 16) == 15)
    768 	{
    769 	  rfbClientLog("%s\n",str);
    770 	}
    771     }
    772   if ((i % 16) != 0)
    773     {
    774       for (j = i % 16; j < 16; j++)
    775 	{
    776 	  rfbClientLog("   ");
    777 	  if ((j % 4) == 3) rfbClientLog(" ");
    778 	}
    779       str[i % 16] = 0;
    780       rfbClientLog("%s\n",str);
    781     }
    782 
    783   fflush(stderr);
    784 }
    785 
    786 int WaitForMessage(rfbClient* client,unsigned int usecs)
    787 {
    788   fd_set fds;
    789   struct timeval timeout;
    790   int num;
    791 
    792   if (client->serverPort==-1)
    793     /* playing back vncrec file */
    794     return 1;
    795 
    796   timeout.tv_sec=(usecs/1000000);
    797   timeout.tv_usec=(usecs%1000000);
    798 
    799   FD_ZERO(&fds);
    800   FD_SET(client->sock,&fds);
    801 
    802   num=select(client->sock+1, &fds, NULL, NULL, &timeout);
    803   if(num<0) {
    804 #ifdef WIN32
    805     errno=WSAGetLastError();
    806 #endif
    807     rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno));
    808   }
    809 
    810   return num;
    811 }
    812 
    813 
    814