summaryrefslogtreecommitdiff
path: root/src/microhttpd/mhd_itc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/mhd_itc.c')
-rw-r--r--src/microhttpd/mhd_itc.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/microhttpd/mhd_itc.c b/src/microhttpd/mhd_itc.c
new file mode 100644
index 00000000..cd0e5371
--- /dev/null
+++ b/src/microhttpd/mhd_itc.c
@@ -0,0 +1,108 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2016 Karlson2k (Evgeny Grin)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file microhttpd/mhd_sockets.c
+ * @brief Implementation of inter-thread communication functions
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_itc.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+/**
+ * Create pair of mutually connected TCP/IP sockets on loopback address
+ * @param sockets_pair array to receive resulted sockets
+ * @return zero on success, -1 otherwise
+ */
+int MHD_W32_pair_of_sockets_(SOCKET sockets_pair[2])
+{
+ int i;
+ if (!sockets_pair)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+#define PAIRMAXTRYIES 800
+ for (i = 0; i < PAIRMAXTRYIES; i++)
+ {
+ struct sockaddr_in listen_addr;
+ SOCKET listen_s;
+ static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */
+ int addr_len = c_addinlen;
+ int opt = 1;
+
+ listen_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (INVALID_SOCKET == listen_s)
+ break; /* can't create even single socket */
+
+ listen_addr.sin_family = AF_INET;
+ listen_addr.sin_port = htons(0);
+ listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ if (0 == bind(listen_s, (struct sockaddr*) &listen_addr, c_addinlen)
+ && 0 == listen(listen_s, 1)
+ && 0 == getsockname(listen_s, (struct sockaddr*) &listen_addr,
+ &addr_len))
+ {
+ SOCKET client_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (INVALID_SOCKET != client_s)
+ {
+ if (0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt)
+ && (0 == connect(client_s, (struct sockaddr*) &listen_addr, c_addinlen)
+ || WSAGetLastError() == WSAEWOULDBLOCK))
+ {
+ struct sockaddr_in accepted_from_addr;
+ SOCKET server_s;
+ addr_len = c_addinlen;
+ server_s = accept(listen_s,
+ (struct sockaddr*) &accepted_from_addr, &addr_len);
+ if (INVALID_SOCKET != server_s)
+ {
+ struct sockaddr_in client_addr;
+ addr_len = c_addinlen;
+ opt = 0;
+ if (0 == getsockname(client_s, (struct sockaddr*) &client_addr, &addr_len)
+ && accepted_from_addr.sin_family == client_addr.sin_family
+ && accepted_from_addr.sin_port == client_addr.sin_port
+ && accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr
+ && 0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt)
+ && 0 == ioctlsocket(server_s, FIONBIO, (u_long*) &opt))
+ {
+ closesocket(listen_s);
+ sockets_pair[0] = client_s;
+ sockets_pair[1] = server_s;
+ return 0;
+ }
+ closesocket(server_s);
+ }
+ }
+ closesocket(client_s);
+ }
+ }
+ closesocket(listen_s);
+ }
+
+ sockets_pair[0] = INVALID_SOCKET;
+ sockets_pair[1] = INVALID_SOCKET;
+ return -1;
+}
+
+#endif /* _WIN32 && ! __CYGWIN__ */