]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/hw/vnc/sockets.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / hw / vnc / sockets.c
1 /*
2  * sockets.c - deal with TCP sockets.
3  *
4  * This code should be independent of any changes in the RFB protocol.  It just
5  * deals with the X server scheduling stuff, calling rfbNewClientConnection and
6  * rfbProcessClientMessage to actually deal with the protocol.  If a socket
7  * needs to be closed for any reason then rfbCloseSock should be called, and
8  * this in turn will call rfbClientConnectionGone.  To make an active
9  * connection out, call rfbConnect - note that this does _not_ call
10  * rfbNewClientConnection.
11  *
12  * This file is divided into two types of function.  Those beginning with
13  * "rfb" are specific to sockets using the RFB protocol.  Those without the
14  * "rfb" prefix are more general socket routines (which are used by the http
15  * code).
16  *
17  * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN
18  * not EWOULDBLOCK.
19  */
20
21 /*
22  *  Copyright (C) 2002 RealVNC Ltd.
23  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
24  *
25  *  This is free software; you can redistribute it and/or modify
26  *  it under the terms of the GNU General Public License as published by
27  *  the Free Software Foundation; either version 2 of the License, or
28  *  (at your option) any later version.
29  *
30  *  This software is distributed in the hope that it will be useful,
31  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
32  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33  *  GNU General Public License for more details.
34  *
35  *  You should have received a copy of the GNU General Public License
36  *  along with this software; if not, write to the Free Software
37  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
38  *  USA.
39  */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/time.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <netinet/tcp.h>
49 #include <arpa/inet.h>
50 #include <netdb.h>
51 #include <fcntl.h>
52 #include <errno.h>
53
54 #include "rfb.h"
55
56
57 int rfbMaxClientWait = 20000;   /* time (ms) after which we decide client has
58                                    gone away - needed to stop us hanging */
59
60 int rfbPort = 0;
61 int rfbListenSock = -1;
62 Bool rfbLocalhostOnly = FALSE;
63
64 static fd_set allFds;
65 static int maxFd = 0;
66
67
68 /*
69  * rfbInitSockets sets up the TCP sockets to listen for RFB
70  * connections.  It does nothing if called again.
71  */
72
73 void
74 rfbInitSockets()
75 {
76     static Bool done = FALSE;
77
78     if (done)
79         return;
80
81     done = TRUE;
82
83     if (inetdSock != -1) {
84         const int one = 1;
85
86         if (fcntl(inetdSock, F_SETFL, O_NONBLOCK) < 0) {
87             rfbLogPerror("fcntl");
88             exit(1);
89         }
90
91         if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY,
92                        (char *)&one, sizeof(one)) < 0) {
93             rfbLogPerror("setsockopt");
94             exit(1);
95         }
96
97         AddEnabledDevice(inetdSock);
98         FD_ZERO(&allFds);
99         FD_SET(inetdSock, &allFds);
100         maxFd = inetdSock;
101         return;
102     }
103
104     if (rfbPort == 0) {
105         rfbPort = 5900 + atoi(display);
106     }
107
108     rfbLog("Listening for VNC connections on TCP port %d\n", rfbPort);
109
110     if ((rfbListenSock = ListenOnTCPPort(rfbPort)) < 0) {
111         rfbLogPerror("ListenOnTCPPort");
112         exit(1);
113     }
114
115     AddEnabledDevice(rfbListenSock);
116
117     FD_ZERO(&allFds);
118     FD_SET(rfbListenSock, &allFds);
119     maxFd = rfbListenSock;
120 }
121
122
123 /*
124  * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
125  * socket(s).  If there is input to process, the appropriate function in the
126  * RFB server code will be called (rfbNewClientConnection,
127  * rfbProcessClientMessage, etc).
128  */
129
130 void
131 rfbCheckFds()
132 {
133     int nfds;
134     fd_set fds;
135     struct timeval tv;
136     struct sockaddr_in addr;
137     unsigned int addrlen = sizeof(addr);
138     const int one = 1;
139     int sock;
140     static Bool inetdInitDone = FALSE;
141
142     if (!inetdInitDone && inetdSock != -1) {
143         rfbNewClientConnection(inetdSock); 
144         inetdInitDone = TRUE;
145     }
146
147     memcpy((char *)&fds, (char *)&allFds, sizeof(fd_set));
148     tv.tv_sec = 0;
149     tv.tv_usec = 0;
150     nfds = select(maxFd + 1, &fds, NULL, NULL, &tv);
151     if (nfds == 0) {
152         return;
153     }
154     if (nfds < 0) {
155         rfbLogPerror("rfbCheckFds: select");
156         return;
157     }
158
159     if (rfbListenSock != -1 && FD_ISSET(rfbListenSock, &fds)) {
160
161         if ((sock = accept(rfbListenSock,
162                            (struct sockaddr *)&addr, &addrlen)) < 0) {
163             rfbLogPerror("rfbCheckFds: accept");
164             return;
165         }
166
167         if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
168             rfbLogPerror("rfbCheckFds: fcntl");
169             close(sock);
170             return;
171         }
172
173         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
174                        (char *)&one, sizeof(one)) < 0) {
175             rfbLogPerror("rfbCheckFds: setsockopt");
176             close(sock);
177             return;
178         }
179
180         fprintf(stderr,"\n");
181         rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
182
183         AddEnabledDevice(sock);
184         FD_SET(sock, &allFds);
185         maxFd = max(sock,maxFd);
186
187         rfbNewClientConnection(sock);
188
189         FD_CLR(rfbListenSock, &fds);
190         if (--nfds == 0)
191             return;
192     }
193
194     for (sock = 0; sock <= maxFd; sock++) {
195         if (FD_ISSET(sock, &fds) && FD_ISSET(sock, &allFds)) {
196             rfbProcessClientMessage(sock);
197         }
198     }
199 }
200
201
202 void
203 rfbCloseSock(sock)
204     int sock;
205 {
206     close(sock);
207     RemoveEnabledDevice(sock);
208     FD_CLR(sock, &allFds);
209     rfbClientConnectionGone(sock);
210     if (sock == inetdSock)
211         GiveUp(0);
212 }
213
214
215 /*
216  * rfbWaitForClient can be called to wait for the RFB client to send us a
217  * message.  When one is received it is processed by calling
218  * rfbProcessClientMessage().
219  */
220
221 void
222 rfbWaitForClient(sock)
223     int sock;
224 {
225     int n;
226     fd_set fds;
227     struct timeval tv;
228
229     FD_ZERO(&fds);
230     FD_SET(sock, &fds);
231     tv.tv_sec = rfbMaxClientWait / 1000;
232     tv.tv_usec = (rfbMaxClientWait % 1000) * 1000;
233     n = select(sock+1, &fds, NULL, NULL, &tv);
234     if (n < 0) {
235         rfbLogPerror("rfbWaitForClient: select");
236         exit(1);
237     }
238     if (n == 0) {
239         rfbCloseSock(sock);
240         return;
241     }
242
243     rfbProcessClientMessage(sock);
244 }
245
246
247 /*
248  * rfbConnect is called to make a connection out to a given TCP address.
249  */
250
251 int
252 rfbConnect(host, port)
253     char *host;
254     int port;
255 {
256     int sock;
257     int one = 1;
258
259     fprintf(stderr,"\n");
260     rfbLog("Making connection to client on host %s port %d\n",
261            host,port);
262
263     if ((sock = ConnectToTcpAddr(host, port)) < 0) {
264         rfbLogPerror("connection failed");
265         return -1;
266     }
267
268     if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
269         rfbLogPerror("fcntl failed");
270         close(sock);
271         return -1;
272     }
273
274     if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
275                    (char *)&one, sizeof(one)) < 0) {
276         rfbLogPerror("setsockopt failed");
277         close(sock);
278         return -1;
279     }
280
281     AddEnabledDevice(sock);
282     FD_SET(sock, &allFds);
283     maxFd = max(sock,maxFd);
284
285     return sock;
286 }
287
288
289
290
291 /*
292  * ReadExact reads an exact number of bytes on a TCP socket.  Returns 1 if
293  * those bytes have been read, 0 if the other end has closed, or -1 if an error
294  * occurred (errno is set to ETIMEDOUT if it timed out).
295  */
296
297 int
298 ReadExact(sock, buf, len)
299     int sock;
300     char *buf;
301     int len;
302 {
303     int n;
304     fd_set fds;
305     struct timeval tv;
306
307     while (len > 0) {
308         n = read(sock, buf, len);
309
310         if (n > 0) {
311
312             buf += n;
313             len -= n;
314
315         } else if (n == 0) {
316
317             return 0;
318
319         } else {
320             if (errno != EWOULDBLOCK && errno != EAGAIN) {
321                 return n;
322             }
323
324             FD_ZERO(&fds);
325             FD_SET(sock, &fds);
326             tv.tv_sec = rfbMaxClientWait / 1000;
327             tv.tv_usec = (rfbMaxClientWait % 1000) * 1000;
328             n = select(sock+1, &fds, NULL, NULL, &tv);
329             if (n < 0) {
330                 rfbLogPerror("ReadExact: select");
331                 return n;
332             }
333             if (n == 0) {
334                 errno = ETIMEDOUT;
335                 return -1;
336             }
337         }
338     }
339     return 1;
340 }
341
342
343
344 /*
345  * WriteExact writes an exact number of bytes on a TCP socket.  Returns 1 if
346  * those bytes have been written, or -1 if an error occurred (errno is set to
347  * ETIMEDOUT if it timed out).
348  */
349
350 int
351 WriteExact(sock, buf, len)
352     int sock;
353     char *buf;
354     int len;
355 {
356     int n;
357     fd_set fds;
358     struct timeval tv;
359     int totalTimeWaited = 0;
360
361
362     while (len > 0) {
363         n = write(sock, buf, len);
364
365         if (n > 0) {
366
367             buf += n;
368             len -= n;
369
370         } else if (n == 0) {
371
372             rfbLog("WriteExact: write returned 0?\n");
373             exit(1);
374
375         } else {
376             if (errno != EWOULDBLOCK && errno != EAGAIN) {
377                 return n;
378             }
379
380             /* Retry every 5 seconds until we exceed rfbMaxClientWait.  We
381                need to do this because select doesn't necessarily return
382                immediately when the other end has gone away */
383
384             FD_ZERO(&fds);
385             FD_SET(sock, &fds);
386             tv.tv_sec = 5;
387             tv.tv_usec = 0;
388             n = select(sock+1, NULL, &fds, NULL, &tv);
389             if (n < 0) {
390                 rfbLogPerror("WriteExact: select");
391                 return n;
392             }
393             if (n == 0) {
394                 totalTimeWaited += 5000;
395                 if (totalTimeWaited >= rfbMaxClientWait) {
396                     errno = ETIMEDOUT;
397                     return -1;
398                 }
399             } else {
400                 totalTimeWaited = 0;
401             }
402         }
403     }
404     return 1;
405 }
406
407
408 int
409 ListenOnTCPPort(port)
410     int port;
411 {
412     int sock;
413     int one = 1;
414 #ifdef AF_INET6
415     int ipv = 4;
416     struct sockaddr_in6 addr6;
417 #endif
418     struct sockaddr_in addr;
419
420     memset(&addr, 0, sizeof(addr));
421 #ifdef AF_INET6
422     ipv = 6;
423     addr6.sin6_family = AF_INET6;
424     addr6.sin6_port = htons(port);
425     if (rfbLocalhostOnly)
426         addr6.sin6_addr = in6addr_loopback;
427     else
428         addr6.sin6_addr = in6addr_any;
429
430     /* Don't fail if an IPv6 socket cannot be established, but fall back to
431        IPv4 */
432     if ((sock = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
433     {
434         ipv = 4;
435 #endif
436         addr.sin_family = AF_INET;
437         addr.sin_port = htons(port);
438         if (rfbLocalhostOnly)
439             addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
440         else
441             addr.sin_addr.s_addr = htonl(INADDR_ANY);
442
443         if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
444             return -1;
445         }
446 #ifdef AF_INET6
447     }
448 #endif
449     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
450                    (char *)&one, sizeof(one)) < 0) {
451         close(sock);
452         return -1;
453     }
454 #ifdef AF_INET6
455     if (ipv == 6) {
456       if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {
457         close(sock);
458         return -1;
459       }
460     }
461     else if (ipv == 4) {
462 #endif
463       if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
464         close(sock);
465         return -1;
466       }      
467 #ifdef AF_INET6
468     }
469 #endif
470     if (listen(sock, 5) < 0) {
471         close(sock);
472         return -1;
473     }
474
475     return sock;
476 }
477
478
479 int
480 ConnectToTcpAddr(host, port)
481     char *host;
482     int port;
483 {
484     struct hostent *hp;
485     int sock;
486     struct sockaddr_in addr;
487
488     addr.sin_family = AF_INET;
489     addr.sin_port = htons(port);
490
491     if ((addr.sin_addr.s_addr = inet_addr(host)) == -1)
492     {
493         if (!(hp = gethostbyname(host))) {
494             errno = EINVAL;
495             return -1;
496         }
497         addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
498     }
499
500     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
501         return -1;
502     }
503
504     if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
505         close(sock);
506         return -1;
507     }
508
509     return sock;
510 }