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