PageRenderTime 48ms CodeModel.GetById 13ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 0ms

/apps/desktop/libvncserver/sockets.c

http://ftk.googlecode.com/
C | 707 lines | 528 code | 108 blank | 71 comment | 124 complexity | 53a9b6f0b37e0396e20fa77c3e0ee8a7 MD5 | raw file
  1/*
  2 * sockets.c - deal with TCP & UDP 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 rfbCloseClient 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) 2005 Rohit Kumar, Johannes E. Schindelin
 23 *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
 24 *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.  
 25 *  All Rights Reserved.
 26 *
 27 *  This is free software; you can redistribute it and/or modify
 28 *  it under the terms of the GNU General Public License as published by
 29 *  the Free Software Foundation; either version 2 of the License, or
 30 *  (at your option) any later version.
 31 *
 32 *  This software is distributed in the hope that it will be useful,
 33 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 34 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 35 *  GNU General Public License for more details.
 36 *
 37 *  You should have received a copy of the GNU General Public License
 38 *  along with this software; if not, write to the Free Software
 39 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 40 *  USA.
 41 */
 42
 43#include <rfb/rfb.h>
 44
 45#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
 46#include <sys/types.h>
 47#endif
 48
 49#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H
 50#include <sys/time.h>
 51#endif
 52#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
 53#include <sys/socket.h>
 54#endif
 55#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
 56#include <netinet/in.h>
 57#include <netinet/tcp.h>
 58#include <netdb.h>
 59#include <arpa/inet.h>
 60#endif
 61#ifdef LIBVNCSERVER_HAVE_UNISTD_H
 62#include <unistd.h>
 63#endif
 64
 65#if defined(__linux__) && defined(NEED_TIMEVAL)
 66struct timeval 
 67{
 68   long int tv_sec,tv_usec;
 69}
 70;
 71#endif
 72
 73#ifdef LIBVNCSERVER_HAVE_FCNTL_H
 74#include <fcntl.h>
 75#endif
 76
 77#include <errno.h>
 78
 79#ifdef USE_LIBWRAP
 80#include <syslog.h>
 81#include <tcpd.h>
 82int allow_severity=LOG_INFO;
 83int deny_severity=LOG_WARNING;
 84#endif
 85
 86#if defined(WIN32)
 87#ifndef __MINGW32__
 88#pragma warning (disable: 4018 4761)
 89#endif
 90#define read(sock,buf,len) recv(sock,buf,len,0)
 91#define EWOULDBLOCK WSAEWOULDBLOCK
 92#define ETIMEDOUT WSAETIMEDOUT
 93#define write(sock,buf,len) send(sock,buf,len,0)
 94#else
 95#define closesocket close
 96#endif
 97
 98int rfbMaxClientWait = 20000;   /* time (ms) after which we decide client has
 99                                   gone away - needed to stop us hanging */
100
101/*
102 * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB
103 * connections.  It does nothing if called again.
104 */
105
106void
107rfbInitSockets(rfbScreenInfoPtr rfbScreen)
108{
109    in_addr_t iface = rfbScreen->listenInterface;
110
111    if (rfbScreen->socketState!=RFB_SOCKET_INIT)
112	return;
113
114    rfbScreen->socketState = RFB_SOCKET_READY;
115
116    if (rfbScreen->inetdSock != -1) {
117	const int one = 1;
118
119#ifndef WIN32
120	if (fcntl(rfbScreen->inetdSock, F_SETFL, O_NONBLOCK) < 0) {
121	    rfbLogPerror("fcntl");
122	    return;
123	}
124#endif
125
126	if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY,
127		       (char *)&one, sizeof(one)) < 0) {
128	    rfbLogPerror("setsockopt");
129	    return;
130	}
131
132    	FD_ZERO(&(rfbScreen->allFds));
133    	FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds));
134    	rfbScreen->maxFd = rfbScreen->inetdSock;
135	return;
136    }
137
138    if(rfbScreen->autoPort) {
139        int i;
140        rfbLog("Autoprobing TCP port \n");
141        for (i = 5900; i < 6000; i++) {
142            if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) {
143		rfbScreen->port = i;
144		break;
145	    }
146        }
147
148        if (i >= 6000) {
149	    rfbLogPerror("Failure autoprobing");
150	    return;
151        }
152
153        rfbLog("Autoprobing selected port %d\n", rfbScreen->port);
154        FD_ZERO(&(rfbScreen->allFds));
155        FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
156        rfbScreen->maxFd = rfbScreen->listenSock;
157    }
158    else if(rfbScreen->port>0) {
159      rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);
160
161      if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) {
162	rfbLogPerror("ListenOnTCPPort");
163	return;
164      }
165
166      FD_ZERO(&(rfbScreen->allFds));
167      FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
168      rfbScreen->maxFd = rfbScreen->listenSock;
169    }
170
171    if (rfbScreen->udpPort != 0) {
172	rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort);
173
174	if ((rfbScreen->udpSock = rfbListenOnUDPPort(rfbScreen->udpPort, iface)) < 0) {
175	    rfbLogPerror("ListenOnUDPPort");
176	    return;
177	}
178	FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
179	rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
180    }
181}
182
183void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen)
184{
185    if (rfbScreen->socketState!=RFB_SOCKET_READY)
186	return;
187
188    rfbScreen->socketState = RFB_SOCKET_SHUTDOWN;
189
190    if(rfbScreen->inetdSock>-1) {
191	closesocket(rfbScreen->inetdSock);
192	FD_CLR(rfbScreen->inetdSock,&rfbScreen->allFds);
193	rfbScreen->inetdSock=-1;
194    }
195
196    if(rfbScreen->listenSock>-1) {
197	closesocket(rfbScreen->listenSock);
198	FD_CLR(rfbScreen->listenSock,&rfbScreen->allFds);
199	rfbScreen->listenSock=-1;
200    }
201
202    if(rfbScreen->udpSock>-1) {
203	closesocket(rfbScreen->udpSock);
204	FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds);
205	rfbScreen->udpSock=-1;
206    }
207}
208
209/*
210 * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
211 * socket(s).  If there is input to process, the appropriate function in the
212 * RFB server code will be called (rfbNewClientConnection,
213 * rfbProcessClientMessage, etc).
214 */
215
216int
217rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
218{
219    int nfds;
220    fd_set fds;
221    struct timeval tv;
222    struct sockaddr_in addr;
223    socklen_t addrlen = sizeof(addr);
224    char buf[6];
225    const int one = 1;
226    int sock;
227    rfbClientIteratorPtr i;
228    rfbClientPtr cl;
229    int result = 0;
230
231    if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
232	rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); 
233	rfbScreen->inetdInitDone = TRUE;
234    }
235
236    do {
237	memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
238	tv.tv_sec = 0;
239	tv.tv_usec = usec;
240	nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
241	if (nfds == 0) {
242	    /* timed out, check for async events */
243            i = rfbGetClientIterator(rfbScreen);
244            while((cl = rfbClientIteratorNext(i))) {
245                if (cl->onHold)
246                    continue;
247                if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
248                    rfbSendFileTransferChunk(cl);
249            }
250            rfbReleaseClientIterator(i);
251	    return result;
252	}
253
254	if (nfds < 0) {
255#ifdef WIN32
256	    errno = WSAGetLastError();
257#endif
258	    if (errno != EINTR)
259		rfbLogPerror("rfbCheckFds: select");
260	    return -1;
261	}
262
263	result += nfds;
264
265	if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) {
266
267	    if ((sock = accept(rfbScreen->listenSock,
268			    (struct sockaddr *)&addr, &addrlen)) < 0) {
269		rfbLogPerror("rfbCheckFds: accept");
270		return -1;
271	    }
272
273#ifndef WIN32
274	    if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
275		rfbLogPerror("rfbCheckFds: fcntl");
276		closesocket(sock);
277		return -1;
278	    }
279#endif
280
281	    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
282			(char *)&one, sizeof(one)) < 0) {
283		rfbLogPerror("rfbCheckFds: setsockopt");
284		closesocket(sock);
285		return -1;
286	    }
287
288#ifdef USE_LIBWRAP
289	    if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
290			STRING_UNKNOWN)) {
291		rfbLog("Rejected connection from client %s\n",
292			inet_ntoa(addr.sin_addr));
293		closesocket(sock);
294		return -1;
295	    }
296#endif
297
298	    rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
299
300	    rfbNewClient(rfbScreen,sock);
301
302	    FD_CLR(rfbScreen->listenSock, &fds);
303	    if (--nfds == 0)
304		return result;
305	}
306
307	if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
308	    if(!rfbScreen->udpClient)
309		rfbNewUDPClient(rfbScreen);
310	    if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK,
311			(struct sockaddr *)&addr, &addrlen) < 0) {
312		rfbLogPerror("rfbCheckFds: UDP: recvfrom");
313		rfbDisconnectUDPSock(rfbScreen);
314		rfbScreen->udpSockConnected = FALSE;
315	    } else {
316		if (!rfbScreen->udpSockConnected ||
317			(memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0))
318		{
319		    /* new remote end */
320		    rfbLog("rfbCheckFds: UDP: got connection\n");
321
322		    memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen);
323		    rfbScreen->udpSockConnected = TRUE;
324
325		    if (connect(rfbScreen->udpSock,
326				(struct sockaddr *)&addr, addrlen) < 0) {
327			rfbLogPerror("rfbCheckFds: UDP: connect");
328			rfbDisconnectUDPSock(rfbScreen);
329			return -1;
330		    }
331
332		    rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
333		}
334
335		rfbProcessUDPInput(rfbScreen);
336	    }
337
338	    FD_CLR(rfbScreen->udpSock, &fds);
339	    if (--nfds == 0)
340		return result;
341	}
342
343	i = rfbGetClientIterator(rfbScreen);
344	while((cl = rfbClientIteratorNext(i))) {
345
346	    if (cl->onHold)
347		continue;
348
349            if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
350            {
351                if (FD_ISSET(cl->sock, &fds))
352                    rfbProcessClientMessage(cl);
353                else
354                    rfbSendFileTransferChunk(cl);
355            }
356	}
357	rfbReleaseClientIterator(i);
358    } while(rfbScreen->handleEventsEagerly);
359    return result;
360}
361
362
363void
364rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen)
365{
366  rfbScreen->udpSockConnected = FALSE;
367}
368
369
370
371void
372rfbCloseClient(rfbClientPtr cl)
373{
374    rfbExtensionData* extension;
375
376    for(extension=cl->extensions; extension; extension=extension->next)
377	if(extension->extension->close)
378	    extension->extension->close(cl, extension->data);
379
380    LOCK(cl->updateMutex);
381#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
382    if (cl->sock != -1)
383#endif
384      {
385	FD_CLR(cl->sock,&(cl->screen->allFds));
386	if(cl->sock==cl->screen->maxFd)
387	  while(cl->screen->maxFd>0
388		&& !FD_ISSET(cl->screen->maxFd,&(cl->screen->allFds)))
389	    cl->screen->maxFd--;
390#ifndef __MINGW32__
391	shutdown(cl->sock,SHUT_RDWR);
392#endif
393	closesocket(cl->sock);
394	cl->sock = -1;
395      }
396    TSIGNAL(cl->updateCond);
397    UNLOCK(cl->updateMutex);
398}
399
400
401/*
402 * rfbConnect is called to make a connection out to a given TCP address.
403 */
404
405int
406rfbConnect(rfbScreenInfoPtr rfbScreen,
407           char *host,
408           int port)
409{
410    int sock;
411    int one = 1;
412
413    rfbLog("Making connection to client on host %s port %d\n",
414	   host,port);
415
416    if ((sock = rfbConnectToTcpAddr(host, port)) < 0) {
417	rfbLogPerror("connection failed");
418	return -1;
419    }
420
421#ifndef WIN32
422    if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
423	rfbLogPerror("fcntl failed");
424	closesocket(sock);
425	return -1;
426    }
427#endif
428
429    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
430		   (char *)&one, sizeof(one)) < 0) {
431	rfbLogPerror("setsockopt failed");
432	closesocket(sock);
433	return -1;
434    }
435
436    /* AddEnabledDevice(sock); */
437    FD_SET(sock, &rfbScreen->allFds);
438    rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
439
440    return sock;
441}
442
443/*
444 * ReadExact reads an exact number of bytes from a client.  Returns 1 if
445 * those bytes have been read, 0 if the other end has closed, or -1 if an error
446 * occurred (errno is set to ETIMEDOUT if it timed out).
447 */
448
449int
450rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
451{
452    int sock = cl->sock;
453    int n;
454    fd_set fds;
455    struct timeval tv;
456
457    while (len > 0) {
458        n = read(sock, buf, len);
459
460        if (n > 0) {
461
462            buf += n;
463            len -= n;
464
465        } else if (n == 0) {
466
467            return 0;
468
469        } else {
470#ifdef WIN32
471	    errno = WSAGetLastError();
472#endif
473	    if (errno == EINTR)
474		continue;
475
476#ifdef LIBVNCSERVER_ENOENT_WORKAROUND
477	    if (errno != ENOENT)
478#endif
479            if (errno != EWOULDBLOCK && errno != EAGAIN) {
480                return n;
481            }
482
483            FD_ZERO(&fds);
484            FD_SET(sock, &fds);
485            tv.tv_sec = timeout / 1000;
486            tv.tv_usec = (timeout % 1000) * 1000;
487            n = select(sock+1, &fds, NULL, &fds, &tv);
488            if (n < 0) {
489                rfbLogPerror("ReadExact: select");
490                return n;
491            }
492            if (n == 0) {
493                errno = ETIMEDOUT;
494                return -1;
495            }
496        }
497    }
498#undef DEBUG_READ_EXACT
499#ifdef DEBUG_READ_EXACT
500    rfbLog("ReadExact %d bytes\n",len);
501    for(n=0;n<len;n++)
502	    fprintf(stderr,"%02x ",(unsigned char)buf[n]);
503    fprintf(stderr,"\n");
504#endif
505
506    return 1;
507}
508
509int rfbReadExact(rfbClientPtr cl,char* buf,int len)
510{
511  return(rfbReadExactTimeout(cl,buf,len,rfbMaxClientWait));
512}
513
514/*
515 * WriteExact writes an exact number of bytes to a client.  Returns 1 if
516 * those bytes have been written, or -1 if an error occurred (errno is set to
517 * ETIMEDOUT if it timed out).
518 */
519
520int
521rfbWriteExact(rfbClientPtr cl,
522              const char *buf,
523              int len)
524{
525    int sock = cl->sock;
526    int n;
527    fd_set fds;
528    struct timeval tv;
529    int totalTimeWaited = 0;
530
531#undef DEBUG_WRITE_EXACT
532#ifdef DEBUG_WRITE_EXACT
533    rfbLog("WriteExact %d bytes\n",len);
534    for(n=0;n<len;n++)
535	    fprintf(stderr,"%02x ",(unsigned char)buf[n]);
536    fprintf(stderr,"\n");
537#endif
538
539    LOCK(cl->outputMutex);
540    while (len > 0) {
541        n = write(sock, buf, len);
542
543        if (n > 0) {
544
545            buf += n;
546            len -= n;
547
548        } else if (n == 0) {
549
550            rfbErr("WriteExact: write returned 0?\n");
551            return 0;
552
553        } else {
554#ifdef WIN32
555			errno = WSAGetLastError();
556#endif
557	    if (errno == EINTR)
558		continue;
559
560            if (errno != EWOULDBLOCK && errno != EAGAIN) {
561	        UNLOCK(cl->outputMutex);
562                return n;
563            }
564
565            /* Retry every 5 seconds until we exceed rfbMaxClientWait.  We
566               need to do this because select doesn't necessarily return
567               immediately when the other end has gone away */
568
569            FD_ZERO(&fds);
570            FD_SET(sock, &fds);
571            tv.tv_sec = 5;
572            tv.tv_usec = 0;
573            n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv);
574	    if (n < 0) {
575       	        if(errno==EINTR)
576		    continue;
577                rfbLogPerror("WriteExact: select");
578                UNLOCK(cl->outputMutex);
579                return n;
580            }
581            if (n == 0) {
582                totalTimeWaited += 5000;
583                if (totalTimeWaited >= rfbMaxClientWait) {
584                    errno = ETIMEDOUT;
585                    UNLOCK(cl->outputMutex);
586                    return -1;
587                }
588            } else {
589                totalTimeWaited = 0;
590            }
591        }
592    }
593    UNLOCK(cl->outputMutex);
594    return 1;
595}
596
597/* currently private, called by rfbProcessArguments() */
598int
599rfbStringToAddr(char *str, in_addr_t *addr)  {
600    if (str == NULL || *str == '\0' || strcmp(str, "any") == 0) {
601        *addr = htonl(INADDR_ANY);
602    } else if (strcmp(str, "localhost") == 0) {
603        *addr = htonl(INADDR_LOOPBACK);
604    } else {
605        struct hostent *hp;
606        if ((*addr = inet_addr(str)) == htonl(INADDR_NONE)) {
607            if (!(hp = gethostbyname(str))) {
608                return 0;
609            }
610            *addr = *(unsigned long *)hp->h_addr;
611        }
612    }
613    return 1;
614}
615
616int
617rfbListenOnTCPPort(int port,
618                   in_addr_t iface)
619{
620    struct sockaddr_in addr;
621    int sock;
622    int one = 1;
623
624    memset(&addr, 0, sizeof(addr));
625    addr.sin_family = AF_INET;
626    addr.sin_port = htons(port);
627    addr.sin_addr.s_addr = iface;
628
629    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
630	return -1;
631    }
632    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
633		   (char *)&one, sizeof(one)) < 0) {
634	closesocket(sock);
635	return -1;
636    }
637    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
638	closesocket(sock);
639	return -1;
640    }
641    if (listen(sock, 5) < 0) {
642	closesocket(sock);
643	return -1;
644    }
645
646    return sock;
647}
648
649int
650rfbConnectToTcpAddr(char *host,
651                    int port)
652{
653    struct hostent *hp;
654    int sock;
655    struct sockaddr_in addr;
656
657    memset(&addr, 0, sizeof(addr));
658    addr.sin_family = AF_INET;
659    addr.sin_port = htons(port);
660
661    if ((addr.sin_addr.s_addr = inet_addr(host)) == htonl(INADDR_NONE))
662    {
663	if (!(hp = gethostbyname(host))) {
664	    errno = EINVAL;
665	    return -1;
666	}
667	addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
668    }
669
670    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
671	return -1;
672    }
673
674    if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
675	closesocket(sock);
676	return -1;
677    }
678
679    return sock;
680}
681
682int
683rfbListenOnUDPPort(int port,
684                   in_addr_t iface)
685{
686    struct sockaddr_in addr;
687    int sock;
688    int one = 1;
689
690    memset(&addr, 0, sizeof(addr));
691    addr.sin_family = AF_INET;
692    addr.sin_port = htons(port);
693    addr.sin_addr.s_addr = iface;
694
695    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
696	return -1;
697    }
698    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
699		   (char *)&one, sizeof(one)) < 0) {
700	return -1;
701    }
702    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
703	return -1;
704    }
705
706    return sock;
707}