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 #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
ReadFromRFBServer(rfbClient * client,char * out,unsigned int n)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
WriteToRFBServer(rfbClient * client,char * buf,int n)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 
initSockets()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
ConnectClientToTcpAddr(unsigned int host,int port)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
ConnectClientToTcpAddr6(const char * hostname,int port)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
ConnectClientToUnixSock(const char * sockFile)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
FindFreeTcpPort(void)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
ListenAtTcpPort(int port)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
ListenAtTcpPortAndAddress(int port,const char * address)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
AcceptTcpConnection(int listenSock)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
SetNonBlocking(int sock)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