Set opcode correctly for binary frames.
[libvncserver.git] / libvncclient / listen.c
blobc91ad6e899e17db58ab9f8db463d6226ca7d2f38
1 /*
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,
18 * USA.
22 * listen.c - listen for incoming connections
25 #ifdef __STRICT_ANSI__
26 #define _BSD_SOURCE
27 #endif
28 #include <unistd.h>
29 #include <sys/types.h>
30 #ifdef __MINGW32__
31 #define close closesocket
32 #include <winsock2.h>
33 #undef max
34 #else
35 #include <sys/wait.h>
36 #include <sys/utsname.h>
37 #endif
38 #include <sys/time.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.
46 void
47 listenForIncomingConnections(rfbClient* client)
49 #ifdef __MINGW32__
50 /* FIXME */
51 rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
52 return;
53 #else
54 int listenSocket, listen6Socket = -1;
55 fd_set fds;
57 client->listenSpecified = TRUE;
59 listenSocket = ListenAtTcpPortAndAddress(client->listenPort, client->listenAddress);
61 if ((listenSocket < 0))
62 return;
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)
76 return;
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);
83 #endif
85 while (TRUE) {
86 int r;
87 /* reap any zombies */
88 int status, pid;
89 while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);
91 /* TODO: callback for discard any events (like X11 events) */
93 FD_ZERO(&fds);
95 if(listenSocket >= 0)
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);
102 if (r > 0) {
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)
109 return;
110 if (!SetNonBlocking(client->sock))
111 return;
113 /* Now fork off a new process to deal with it... */
115 switch (fork()) {
117 case -1:
118 rfbClientErr("fork\n");
119 return;
121 case 0:
122 /* child - return to caller */
123 close(listenSocket);
124 close(listen6Socket);
125 return;
127 default:
128 /* parent - go round and listen again */
129 close(client->sock);
130 break;
134 #endif
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)
150 fd_set fds;
151 struct timeval to;
152 int r;
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)
164 return -1;
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)
179 return -1;
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);
186 #endif
188 FD_ZERO(&fds);
190 if(client->listenSock >= 0)
191 FD_SET(client->listenSock, &fds);
192 if(client->listen6Sock >= 0)
193 FD_SET(client->listen6Sock, &fds);
195 if (timeout < 0)
196 r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, NULL);
197 else
198 r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, &to);
200 if (r > 0)
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)
208 return -1;
209 if (!SetNonBlocking(client->sock))
210 return -1;
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;
220 return r;
223 /* r is now either 0 (timeout) or -1 (error) */
224 return r;