VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/socketpair.c@ 105284

Last change on this file since 105284 was 104083, checked in by vboxsync, 11 months ago

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <[email protected]>, 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#include "urldata.h"
28#include "rand.h"
29
30#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
31#ifdef _WIN32
32/*
33 * This is a socketpair() implementation for Windows.
34 */
35#include <string.h>
36#include <io.h>
37#else
38#ifdef HAVE_NETDB_H
39#include <netdb.h>
40#endif
41#ifdef HAVE_NETINET_IN_H
42#include <netinet/in.h> /* IPPROTO_TCP */
43#endif
44#ifdef HAVE_ARPA_INET_H
45#include <arpa/inet.h>
46#endif
47#ifndef INADDR_LOOPBACK
48#define INADDR_LOOPBACK 0x7f000001
49#endif /* !INADDR_LOOPBACK */
50#endif /* !_WIN32 */
51
52#include "nonblock.h" /* for curlx_nonblock */
53#include "timeval.h" /* needed before select.h */
54#include "select.h" /* for Curl_poll */
55
56/* The last 3 #include files should be in this order */
57#include "curl_printf.h"
58#include "curl_memory.h"
59#include "memdebug.h"
60
61int Curl_socketpair(int domain, int type, int protocol,
62 curl_socket_t socks[2])
63{
64 union {
65 struct sockaddr_in inaddr;
66 struct sockaddr addr;
67 } a;
68 curl_socket_t listener;
69 curl_socklen_t addrlen = sizeof(a.inaddr);
70 int reuse = 1;
71 struct pollfd pfd[1];
72 (void)domain;
73 (void)type;
74 (void)protocol;
75
76 listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
77 if(listener == CURL_SOCKET_BAD)
78 return -1;
79
80 memset(&a, 0, sizeof(a));
81 a.inaddr.sin_family = AF_INET;
82 a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
83 a.inaddr.sin_port = 0;
84
85 socks[0] = socks[1] = CURL_SOCKET_BAD;
86
87#if defined(_WIN32) || defined(__CYGWIN__)
88 /* don't set SO_REUSEADDR on Windows */
89 (void)reuse;
90#ifdef SO_EXCLUSIVEADDRUSE
91 {
92 int exclusive = 1;
93 if(setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
94 (char *)&exclusive, (curl_socklen_t)sizeof(exclusive)) == -1)
95 goto error;
96 }
97#endif
98#else
99 if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
100 (char *)&reuse, (curl_socklen_t)sizeof(reuse)) == -1)
101 goto error;
102#endif
103 if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1)
104 goto error;
105 if(getsockname(listener, &a.addr, &addrlen) == -1 ||
106 addrlen < (int)sizeof(a.inaddr))
107 goto error;
108 if(listen(listener, 1) == -1)
109 goto error;
110 socks[0] = socket(AF_INET, SOCK_STREAM, 0);
111 if(socks[0] == CURL_SOCKET_BAD)
112 goto error;
113 if(connect(socks[0], &a.addr, sizeof(a.inaddr)) == -1)
114 goto error;
115
116 /* use non-blocking accept to make sure we don't block forever */
117 if(curlx_nonblock(listener, TRUE) < 0)
118 goto error;
119 pfd[0].fd = listener;
120 pfd[0].events = POLLIN;
121 pfd[0].revents = 0;
122 (void)Curl_poll(pfd, 1, 1000); /* one second */
123 socks[1] = accept(listener, NULL, NULL);
124 if(socks[1] == CURL_SOCKET_BAD)
125 goto error;
126 else {
127 struct curltime start = Curl_now();
128 char rnd[9];
129 char check[sizeof(rnd)];
130 char *p = &check[0];
131 size_t s = sizeof(check);
132
133 if(Curl_rand(NULL, (unsigned char *)rnd, sizeof(rnd)))
134 goto error;
135
136 /* write data to the socket */
137 swrite(socks[0], rnd, sizeof(rnd));
138 /* verify that we read the correct data */
139 do {
140 ssize_t nread;
141
142 pfd[0].fd = socks[1];
143 pfd[0].events = POLLIN;
144 pfd[0].revents = 0;
145 (void)Curl_poll(pfd, 1, 1000); /* one second */
146
147 nread = sread(socks[1], p, s);
148 if(nread == -1) {
149 int sockerr = SOCKERRNO;
150 /* Don't block forever */
151 if(Curl_timediff(Curl_now(), start) > (60 * 1000))
152 goto error;
153 if(
154#ifdef WSAEWOULDBLOCK
155 /* This is how Windows does it */
156 (WSAEWOULDBLOCK == sockerr)
157#else
158 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it
159 returned due to its inability to send off data without
160 blocking. We therefore treat both error codes the same here */
161 (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) ||
162 (EINTR == sockerr) || (EINPROGRESS == sockerr)
163#endif
164 ) {
165 continue;
166 }
167 goto error;
168 }
169 s -= nread;
170 if(s) {
171 p += nread;
172 continue;
173 }
174 if(memcmp(rnd, check, sizeof(check)))
175 goto error;
176 break;
177 } while(1);
178 }
179
180 sclose(listener);
181 return 0;
182
183error:
184 sclose(listener);
185 sclose(socks[0]);
186 sclose(socks[1]);
187 return -1;
188}
189
190#endif /* ! HAVE_SOCKETPAIR */
Note: See TracBrowser for help on using the repository browser.

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