diff options
author | Daniel Stenberg <daniel@haxx.se> | 2019-10-04 23:59:29 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2019-10-10 11:04:38 +0200 |
commit | bc2dbef0afc08229f836c19cf816261ebfd46f53 (patch) | |
tree | ae037083ba53646e058b64bca7042e5bcede7e23 /lib | |
parent | 41c69f473eac2a9bd25c27748b33676ba0ce4086 (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.inc | 4 | ||||
-rw-r--r-- | lib/socketpair.c | 112 | ||||
-rw-r--r-- | lib/socketpair.h | 36 |
3 files changed, 150 insertions, 2 deletions
diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 3e3a385c5..72ef428ee 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -61,7 +61,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ curl_multibyte.c hostcheck.c conncache.c dotdot.c \ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ - doh.c urlapi.c curl_get_line.c altsvc.c + doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ @@ -82,7 +82,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ - curl_get_line.h altsvc.h quic.h + curl_get_line.h altsvc.h quic.h socketpair.h LIB_RCFILES = libcurl.rc 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, <daniel@haxx.se>, 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 <string.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#include <windows.h> +#include <io.h> +#else +#ifdef HAVE_NETDB_H +#include <netdb.h> +#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 */ diff --git a/lib/socketpair.h b/lib/socketpair.h new file mode 100644 index 000000000..be9fb24f9 --- /dev/null +++ b/lib/socketpair.h @@ -0,0 +1,36 @@ +#ifndef HEADER_CURL_SOCKETPAIR_H +#define HEADER_CURL_SOCKETPAIR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, 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" +#ifndef HAVE_SOCKETPAIR +int Curl_socketpair(int domain, int type, int protocol, + curl_socket_t socks[2]); +#else +#define Curl_socketpair(a,b,c,d) socketpair(a,b,c,d) +#endif + +/* Defined here to allow specific build configs to disable it completely */ +#define USE_SOCKETPAIR 1 + +#endif /* HEADER_CURL_SOCKETPAIR_H */ |