aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/mhd_sockets.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/mhd_sockets.c')
-rw-r--r--src/microhttpd/mhd_sockets.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/microhttpd/mhd_sockets.c b/src/microhttpd/mhd_sockets.c
index 64b45f9c..1023017f 100644
--- a/src/microhttpd/mhd_sockets.c
+++ b/src/microhttpd/mhd_sockets.c
@@ -238,6 +238,86 @@ const char* MHD_W32_strerror_winsock_(int err)
238} 238}
239 239
240 240
241/**
242 * Create pair of mutually connected TCP/IP sockets on loopback address
243 * @param sockets_pair array to receive resulted sockets
244 * @return non-zero if succeeded, zero otherwise
245 */
246int MHD_W32_socket_pair_(SOCKET sockets_pair[2])
247{
248 int i;
249 if (!sockets_pair)
250 {
251 WSASetLastError(WSAEFAULT);
252 return 0;
253 }
254
255#define PAIRMAXTRYIES 800
256 for (i = 0; i < PAIRMAXTRYIES; i++)
257 {
258 struct sockaddr_in listen_addr;
259 SOCKET listen_s;
260 static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
261 int addr_len = c_addinlen;
262 int opt = 1;
263
264 listen_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
265 if (INVALID_SOCKET == listen_s)
266 break; /* can't create even single socket */
267
268 listen_addr.sin_family = AF_INET;
269 listen_addr.sin_port = 0; /* same as htons(0) */
270 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
271 if (0 == bind(listen_s, (struct sockaddr*) &listen_addr, c_addinlen)
272 && 0 == listen(listen_s, 1)
273 && 0 == getsockname(listen_s, (struct sockaddr*) &listen_addr,
274 &addr_len))
275 {
276 SOCKET client_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
277 if (INVALID_SOCKET != client_s)
278 {
279 if (0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt)
280 && (0 == connect(client_s, (struct sockaddr*) &listen_addr, c_addinlen)
281 || WSAGetLastError() == WSAEWOULDBLOCK))
282 {
283 struct sockaddr_in accepted_from_addr;
284 SOCKET server_s;
285 addr_len = c_addinlen;
286 server_s = accept(listen_s,
287 (struct sockaddr*) &accepted_from_addr, &addr_len);
288 if (INVALID_SOCKET != server_s)
289 {
290 struct sockaddr_in client_addr;
291 addr_len = c_addinlen;
292 opt = 0;
293 if (0 == getsockname(client_s, (struct sockaddr*) &client_addr, &addr_len)
294 && accepted_from_addr.sin_family == client_addr.sin_family
295 && accepted_from_addr.sin_port == client_addr.sin_port
296 && accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr
297 && 0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt)
298 && 0 == ioctlsocket(server_s, FIONBIO, (u_long*) &opt))
299 {
300 closesocket(listen_s);
301 sockets_pair[0] = client_s;
302 sockets_pair[1] = server_s;
303 return !0;
304 }
305 closesocket(server_s);
306 }
307 }
308 closesocket(client_s);
309 }
310 }
311 closesocket(listen_s);
312 }
313
314 sockets_pair[0] = INVALID_SOCKET;
315 sockets_pair[1] = INVALID_SOCKET;
316 WSASetLastError(WSAECONNREFUSED);
317
318 return 0;
319}
320
241#endif /* MHD_WINSOCK_SOCKETS */ 321#endif /* MHD_WINSOCK_SOCKETS */
242 322
243 323