2 * FreeRDP: A Remote Desktop Protocol client.
5 * Copyright 2011 Vic Lee
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
24 #include <freerdp/utils/print.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
31 #include <arpa/inet.h>
32 #include <netinet/in.h>
35 #define close(_fd) closesocket(_fd)
40 static boolean freerdp_listener_open(freerdp_listener* instance, const char* bind_address, uint16 port)
42 rdpListener* listener = (rdpListener*)instance->listener;
46 struct addrinfo hints = { 0 };
56 hints.ai_family = AF_UNSPEC;
57 hints.ai_socktype = SOCK_STREAM;
58 if (bind_address == NULL)
59 hints.ai_flags = AI_PASSIVE;
61 snprintf(servname, sizeof(servname), "%d", port);
62 status = getaddrinfo(bind_address, servname, &hints, &res);
65 perror("getaddrinfo");
69 for (ai = res; ai && listener->num_sockfds < 5; ai = ai->ai_next)
71 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
74 sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
83 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1)
87 fcntl(sockfd, F_SETFL, O_NONBLOCK);
90 ioctlsocket(sockfd, FIONBIO, &arg);
93 status = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
101 status = listen(sockfd, 10);
109 listener->sockfds[listener->num_sockfds++] = sockfd;
111 if (ai->ai_family == AF_INET)
112 sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr);
114 sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr);
116 printf("Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname);
121 return (listener->num_sockfds > 0 ? true : false);
124 static void freerdp_listener_close(freerdp_listener* instance)
128 rdpListener* listener = (rdpListener*)instance->listener;
130 for (i = 0; i < listener->num_sockfds; i++)
132 close(listener->sockfds[i]);
134 listener->num_sockfds = 0;
137 static boolean freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount)
139 rdpListener* listener = (rdpListener*)instance->listener;
142 if (listener->num_sockfds < 1)
145 for (i = 0; i < listener->num_sockfds; i++)
147 rfds[*rcount] = (void*)(long)(listener->sockfds[i]);
154 static boolean freerdp_listener_check_fds(freerdp_listener* instance)
156 rdpListener* listener = (rdpListener*)instance->listener;
157 struct sockaddr_storage peer_addr;
158 socklen_t peer_addr_size;
161 freerdp_peer* client;
164 if (listener->num_sockfds < 1)
167 for (i = 0; i < listener->num_sockfds; i++)
169 peer_addr_size = sizeof(peer_addr);
170 peer_sockfd = accept(listener->sockfds[i], (struct sockaddr *)&peer_addr, &peer_addr_size);
172 if (peer_sockfd == -1)
175 int wsa_error = WSAGetLastError();
177 /* No data available */
178 if (wsa_error == WSAEWOULDBLOCK)
181 if (errno == EAGAIN || errno == EWOULDBLOCK)
188 client = freerdp_peer_new(peer_sockfd);
190 if (peer_addr.ss_family == AF_INET)
191 sin_addr = &(((struct sockaddr_in*)&peer_addr)->sin_addr);
193 sin_addr = &(((struct sockaddr_in6*)&peer_addr)->sin6_addr);
194 inet_ntop(peer_addr.ss_family, sin_addr, client->hostname, sizeof(client->hostname));
196 IFCALL(instance->PeerAccepted, instance, client);
202 freerdp_listener* freerdp_listener_new(void)
204 freerdp_listener* instance;
205 rdpListener* listener;
207 instance = xnew(freerdp_listener);
208 instance->Open = freerdp_listener_open;
209 instance->GetFileDescriptor = freerdp_listener_get_fds;
210 instance->CheckFileDescriptor = freerdp_listener_check_fds;
211 instance->Close = freerdp_listener_close;
213 listener = xnew(rdpListener);
214 listener->instance = instance;
216 instance->listener = (void*)listener;
221 void freerdp_listener_free(freerdp_listener* instance)
223 rdpListener* listener;
225 listener = (rdpListener*)instance->listener;