VirtualBox

source: vbox/trunk/src/libs/curl-8.0.1/lib/socketpair.c@ 99874

Last change on this file since 99874 was 99344, checked in by vboxsync, 2 years ago

curl-8.0.1: Applied and adjusted our curl changes to 7.87.0 bugref:10417

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25#include "curl_setup.h"
26#include "socketpair.h"
27
28#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
29#ifdef WIN32
30/*
31 * This is a socketpair() implementation for Windows.
32 */
33#include <string.h>
34#include <winsock2.h>
35#include <ws2tcpip.h>
36#include <windows.h>
37#include <io.h>
38#else
39#ifdef HAVE_NETDB_H
40#include <netdb.h>
41#endif
42#ifdef HAVE_NETINET_IN_H
43#include <netinet/in.h> /* IPPROTO_TCP */
44#endif
45#ifdef HAVE_ARPA_INET_H
46#include <arpa/inet.h>
47#endif
48#ifndef INADDR_LOOPBACK
49#define INADDR_LOOPBACK 0x7f000001
50#endif /* !INADDR_LOOPBACK */
51#endif /* !WIN32 */
52
53#include "nonblock.h" /* for curlx_nonblock */
54#include "timeval.h" /* needed before select.h */
55#include "select.h" /* for Curl_poll */
56
57/* The last 3 #include files should be in this order */
58#include "curl_printf.h"
59#include "curl_memory.h"
60#include "memdebug.h"
61
62int Curl_socketpair(int domain, int type, int protocol,
63 curl_socket_t socks[2])
64{
65 union {
66 struct sockaddr_in inaddr;
67 struct sockaddr addr;
68 } a;
69 curl_socket_t listener;
70 curl_socklen_t addrlen = sizeof(a.inaddr);
71 int reuse = 1;
72 struct pollfd pfd[1];
73 (void)domain;
74 (void)type;
75 (void)protocol;
76
77 listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
78 if(listener == CURL_SOCKET_BAD)
79 return -1;
80
81 memset(&a, 0, sizeof(a));
82 a.inaddr.sin_family = AF_INET;
83 a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
84 a.inaddr.sin_port = 0;
85
86 socks[0] = socks[1] = CURL_SOCKET_BAD;
87
88#if defined(WIN32) || defined(__CYGWIN__)
89 /* don't set SO_REUSEADDR on Windows */
90 (void)reuse;
91#ifdef SO_EXCLUSIVEADDRUSE
92 {
93 int exclusive = 1;
94 if(setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
95 (char *)&exclusive, (curl_socklen_t)sizeof(exclusive)) == -1)
96 goto error;
97 }
98#endif
99#else
100 if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
101 (char *)&reuse, (curl_socklen_t)sizeof(reuse)) == -1)
102 goto error;
103#endif
104 if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1)
105 goto error;
106 if(getsockname(listener, &a.addr, &addrlen) == -1 ||
107 addrlen < (int)sizeof(a.inaddr))
108 goto error;
109 if(listen(listener, 1) == -1)
110 goto error;
111 socks[0] = socket(AF_INET, SOCK_STREAM, 0);
112 if(socks[0] == CURL_SOCKET_BAD)
113 goto error;
114 if(connect(socks[0], &a.addr, sizeof(a.inaddr)) == -1)
115 goto error;
116
117 /* use non-blocking accept to make sure we don't block forever */
118 if(curlx_nonblock(listener, TRUE) < 0)
119 goto error;
120 pfd[0].fd = listener;
121 pfd[0].events = POLLIN;
122 pfd[0].revents = 0;
123 (void)Curl_poll(pfd, 1, 1000); /* one second */
124 socks[1] = accept(listener, NULL, NULL);
125 if(socks[1] == CURL_SOCKET_BAD)
126 goto error;
127 else {
128 struct curltime check;
129 struct curltime start = Curl_now();
130 char *p = (char *)&check;
131 size_t s = sizeof(check);
132
133 /* write data to the socket */
134 swrite(socks[0], &start, sizeof(start));
135 /* verify that we read the correct data */
136 do {
137 ssize_t nread;
138
139 pfd[0].fd = socks[1];
140 pfd[0].events = POLLIN;
141 pfd[0].revents = 0;
142 (void)Curl_poll(pfd, 1, 1000); /* one second */
143
144 nread = sread(socks[1], p, s);
145 if(nread == -1) {
146 int sockerr = SOCKERRNO;
147 /* Don't block forever */
148 if(Curl_timediff(Curl_now(), start) > (60 * 1000))
149 goto error;
150 if(
151#ifdef WSAEWOULDBLOCK
152 /* This is how Windows does it */
153 (WSAEWOULDBLOCK == sockerr)
154#else
155 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it
156 returned due to its inability to send off data without
157 blocking. We therefore treat both error codes the same here */
158 (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) ||
159 (EINTR == sockerr) || (EINPROGRESS == sockerr)
160#endif
161 ) {
162 continue;
163 }
164 goto error;
165 }
166 s -= nread;
167 if(s) {
168 p += nread;
169 continue;
170 }
171 if(memcmp(&start, &check, sizeof(check)))
172 goto error;
173 break;
174 } while(1);
175 }
176
177 sclose(listener);
178 return 0;
179
180 error:
181 sclose(listener);
182 sclose(socks[0]);
183 sclose(socks[1]);
184 return -1;
185}
186
187#endif /* ! HAVE_SOCKETPAIR */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette