aboutsummaryrefslogtreecommitdiff
path: root/src/platform/w32functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/w32functions.c')
-rw-r--r--src/platform/w32functions.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/platform/w32functions.c b/src/platform/w32functions.c
index a0b35dec..34c5d73d 100644
--- a/src/platform/w32functions.c
+++ b/src/platform/w32functions.c
@@ -541,3 +541,80 @@ void MHD_W32_set_last_winsock_error_(int errnum)
541 break; 541 break;
542 } 542 }
543} 543}
544
545/**
546 * Create pair of mutually connected TCP/IP sockets on loopback address
547 * @param sockets_pair array to receive resulted sockets
548 * @return zero on success, -1 otherwise
549 */
550int MHD_W32_pair_of_sockets_(SOCKET sockets_pair[2])
551{
552 int i;
553 if (!sockets_pair)
554 {
555 errno = EINVAL;
556 return -1;
557 }
558
559#define PAIRMAXTRYIES 800
560 for (i = 0; i < PAIRMAXTRYIES; i++)
561 {
562 struct sockaddr_in listen_addr;
563 SOCKET listen_s;
564 static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
565 int addr_len = c_addinlen;
566 int opt = 1;
567
568 listen_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
569 if (INVALID_SOCKET == listen_s)
570 break; /* can't create even single socket */
571
572 listen_addr.sin_family = AF_INET;
573 listen_addr.sin_port = htons(0);
574 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
575 if (0 == bind(listen_s, (struct sockaddr*) &listen_addr, c_addinlen)
576 && 0 == listen(listen_s, 1)
577 && 0 == getsockname(listen_s, (struct sockaddr*) &listen_addr,
578 &addr_len))
579 {
580 SOCKET client_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
581 if (INVALID_SOCKET != client_s)
582 {
583 if (0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt)
584 && (0 == connect(client_s, (struct sockaddr*) &listen_addr, c_addinlen)
585 || WSAGetLastError() == WSAEWOULDBLOCK))
586 {
587 struct sockaddr_in accepted_from_addr;
588 addr_len = c_addinlen;
589 SOCKET server_s = accept(listen_s,
590 (struct sockaddr*) &accepted_from_addr, &addr_len);
591 if (INVALID_SOCKET != server_s)
592 {
593 struct sockaddr_in client_addr;
594 addr_len = c_addinlen;
595 opt = 0;
596 if (0 == getsockname(client_s, (struct sockaddr*) &client_addr, &addr_len)
597 && accepted_from_addr.sin_family == client_addr.sin_family
598 && accepted_from_addr.sin_port == client_addr.sin_port
599 && accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr
600 && 0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt)
601 && 0 == ioctlsocket(server_s, FIONBIO, (u_long*) &opt))
602 {
603 closesocket(listen_s);
604 sockets_pair[0] = client_s;
605 sockets_pair[1] = server_s;
606 return 0;
607 }
608 closesocket(server_s);
609 }
610 }
611 closesocket(client_s);
612 }
613 }
614 closesocket(listen_s);
615 }
616
617 sockets_pair[0] = INVALID_SOCKET;
618 sockets_pair[1] = INVALID_SOCKET;
619 return -1;
620}