From bc2dbef0afc08229f836c19cf816261ebfd46f53 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 4 Oct 2019 23:59:29 +0200 Subject: socketpair: an implemention for Windows and more Curl_socketpair() is designed to be used and work everywhere if there's no native version or the native version isn't good enough. Closes #4466 --- lib/socketpair.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 lib/socketpair.c (limited to 'lib/socketpair.c') diff --git a/lib/socketpair.c b/lib/socketpair.c new file mode 100644 index 000000000..5dd9f27e9 --- /dev/null +++ b/lib/socketpair.c @@ -0,0 +1,112 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "socketpair.h" + +#ifndef HAVE_SOCKETPAIR +#ifdef WIN32 +/* + * This is a socketpair() implementation for Windows. + */ +#include +#include +#include +#include +#include +#else +#ifdef HAVE_NETDB_H +#include +#endif +#endif /* !WIN32 */ + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +int Curl_socketpair(int domain, int type, int protocol, + curl_socket_t socks[2]) +{ + union { + struct sockaddr_in inaddr; + struct sockaddr addr; + } a; + curl_socket_t listener; + curl_socklen_t addrlen = sizeof(a.inaddr); + int reuse = 1; + char data[2][12]; + ssize_t dlen; + (void)domain; + (void)type; + (void)protocol; + + listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(listener == CURL_SOCKET_BAD) + return -1; + + memset(&a, 0, sizeof(a)); + a.inaddr.sin_family = AF_INET; + a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + a.inaddr.sin_port = 0; + + socks[0] = socks[1] = CURL_SOCKET_BAD; + + if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, + (char *)&reuse, (curl_socklen_t)sizeof(reuse)) == -1) + goto error; + if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1) + goto error; + if(getsockname(listener, &a.addr, &addrlen) == -1) + goto error; + if(listen(listener, 1) == -1) + goto error; + socks[0] = socket(AF_INET, SOCK_STREAM, 0); + if(socks[0] == CURL_SOCKET_BAD) + goto error; + if(connect(socks[0], &a.addr, sizeof(a.inaddr)) == -1) + goto error; + socks[1] = accept(listener, NULL, NULL); + if(socks[1] == CURL_SOCKET_BAD) + goto error; + + sclose(listener); + + /* verify that nothing else connected */ + msnprintf(data[0], sizeof(data[0]), "%p", socks); + dlen = strlen(data[0]); + if(swrite(socks[0], data[0], dlen) != dlen) + goto error; + if(sread(socks[1], data[1], sizeof(data[1])) != dlen) + goto error; + if(memcmp(data[0], data[1], dlen)) + goto error; + return 0; + + error: + sclose(listener); + sclose(socks[0]); + sclose(socks[1]); + return -1; +} + +#endif /* ! HAVE_SOCKETPAIR */ -- cgit v1.2.3