2 * Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
3 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
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.
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.
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,
22 * listen.c - listen for incoming connections
25 #ifdef __STRICT_ANSI__
29 #include <sys/types.h>
31 #define close closesocket
36 #include <sys/utsname.h>
39 #include <rfb/rfbclient.h>
42 * listenForIncomingConnections() - listen for incoming connections from
43 * servers, and fork a new process to deal with each connection.
47 listenForIncomingConnections(rfbClient
* client
)
51 rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
54 int listenSocket
, listen6Socket
= -1;
57 client
->listenSpecified
= TRUE
;
59 listenSocket
= ListenAtTcpPortAndAddress(client
->listenPort
, client
->listenAddress
);
61 if ((listenSocket
< 0))
64 rfbClientLog("%s -listen: Listening on port %d\n",
65 client
->programName
,client
->listenPort
);
66 rfbClientLog("%s -listen: Command line errors are not reported until "
67 "a connection comes in.\n", client
->programName
);
69 #ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
70 /* only do IPv6 listen of listen6Port is set */
71 if (client
->listen6Port
> 0)
73 listen6Socket
= ListenAtTcpPortAndAddress(client
->listen6Port
, client
->listen6Address
);
75 if (listen6Socket
< 0)
78 rfbClientLog("%s -listen: Listening on IPV6 port %d\n",
79 client
->programName
,client
->listenPort
);
80 rfbClientLog("%s -listen: Command line errors are not reported until "
81 "a connection comes in.\n", client
->programName
);
87 /* reap any zombies */
89 while ((pid
= wait3(&status
, WNOHANG
, (struct rusage
*)0))>0);
91 /* TODO: callback for discard any events (like X11 events) */
96 FD_SET(listenSocket
, &fds
);
97 if(listen6Socket
>= 0)
98 FD_SET(listen6Socket
, &fds
);
100 r
= select(max(listenSocket
, listen6Socket
)+1, &fds
, NULL
, NULL
, NULL
);
103 if (FD_ISSET(listenSocket
, &fds
))
104 client
->sock
= AcceptTcpConnection(client
->listenSock
);
105 else if (FD_ISSET(listen6Socket
, &fds
))
106 client
->sock
= AcceptTcpConnection(client
->listen6Sock
);
108 if (client
->sock
< 0)
110 if (!SetNonBlocking(client
->sock
))
113 /* Now fork off a new process to deal with it... */
118 rfbClientErr("fork\n");
122 /* child - return to caller */
124 close(listen6Socket
);
128 /* parent - go round and listen again */
140 * listenForIncomingConnectionsNoFork() - listen for incoming connections
141 * from servers, but DON'T fork, instead just wait timeout microseconds.
142 * If timeout is negative, block indefinitly.
143 * Returns 1 on success (there was an incoming connection on the listen socket
144 * and we accepted it successfully), -1 on error, 0 on timeout.
148 listenForIncomingConnectionsNoFork(rfbClient
* client
, int timeout
)
154 to
.tv_sec
= timeout
/ 1000000;
155 to
.tv_usec
= timeout
% 1000000;
157 client
->listenSpecified
= TRUE
;
159 if (client
->listenSock
< 0)
161 client
->listenSock
= ListenAtTcpPortAndAddress(client
->listenPort
, client
->listenAddress
);
163 if (client
->listenSock
< 0)
166 rfbClientLog("%s -listennofork: Listening on port %d\n",
167 client
->programName
,client
->listenPort
);
168 rfbClientLog("%s -listennofork: Command line errors are not reported until "
169 "a connection comes in.\n", client
->programName
);
172 #ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
173 /* only do IPv6 listen of listen6Port is set */
174 if (client
->listen6Port
> 0 && client
->listen6Sock
< 0)
176 client
->listen6Sock
= ListenAtTcpPortAndAddress(client
->listen6Port
, client
->listen6Address
);
178 if (client
->listen6Sock
< 0)
181 rfbClientLog("%s -listennofork: Listening on IPV6 port %d\n",
182 client
->programName
,client
->listenPort
);
183 rfbClientLog("%s -listennofork: Command line errors are not reported until "
184 "a connection comes in.\n", client
->programName
);
190 if(client
->listenSock
>= 0)
191 FD_SET(client
->listenSock
, &fds
);
192 if(client
->listen6Sock
>= 0)
193 FD_SET(client
->listen6Sock
, &fds
);
196 r
= select(max(client
->listenSock
, client
->listen6Sock
) +1, &fds
, NULL
, NULL
, NULL
);
198 r
= select(max(client
->listenSock
, client
->listen6Sock
) +1, &fds
, NULL
, NULL
, &to
);
202 if (FD_ISSET(client
->listenSock
, &fds
))
203 client
->sock
= AcceptTcpConnection(client
->listenSock
);
204 else if (FD_ISSET(client
->listen6Sock
, &fds
))
205 client
->sock
= AcceptTcpConnection(client
->listen6Sock
);
207 if (client
->sock
< 0)
209 if (!SetNonBlocking(client
->sock
))
212 if(client
->listenSock
>= 0) {
213 close(client
->listenSock
);
214 client
->listenSock
= -1;
216 if(client
->listen6Sock
>= 0) {
217 close(client
->listen6Sock
);
218 client
->listen6Sock
= -1;
223 /* r is now either 0 (timeout) or -1 (error) */