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