VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/RTWinSocketPair.cpp@ 69387

Last change on this file since 69387 was 68766, checked in by vboxsync, 7 years ago

NAT/Net: Make windows socket pair non-blocking.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: RTWinSocketPair.cpp 68766 2017-09-14 16:28:07Z vboxsync $ */
2/** @file
3 * NAT Network - socketpair(2) emulation for winsock.
4 */
5
6/*
7 * Copyright (C) 2013-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/asm.h>
19#include <iprt/assert.h>
20#include <iprt/cdefs.h>
21#include <iprt/err.h>
22
23#include <VBox/err.h>
24
25#include <iprt/win/winsock2.h>
26#include <iprt/win/windows.h>
27
28#include <stdio.h>
29#include <iprt/log.h>
30
31extern "C" int RTWinSocketPair(int domain, int type, int protocol, SOCKET socket_vector[2])
32{
33 LogFlowFunc(("ENTER: domain:%d, type:%d, protocol:%d, socket_vector:%p\n",
34 domain, type, protocol, socket_vector));
35 switch (domain)
36 {
37 case AF_INET:
38 break;
39 case AF_INET6: /* I dobt we really need it. */
40 default:
41 AssertMsgFailedReturn(("Unsuported domain:%d\n", domain),
42 VERR_INVALID_PARAMETER);
43 }
44
45 switch(type)
46 {
47 case SOCK_STREAM:
48 case SOCK_DGRAM:
49 break;
50 default:
51 AssertMsgFailedReturn(("Unsuported type:%d\n", type),
52 VERR_INVALID_PARAMETER);
53 }
54
55 AssertPtrReturn(socket_vector, VERR_INVALID_PARAMETER);
56 if (!socket_vector)
57 return VERR_INVALID_PARAMETER;
58
59 socket_vector[0] = socket_vector[1] = INVALID_SOCKET;
60
61 SOCKET listener = INVALID_SOCKET;
62
63 union {
64 struct sockaddr_in in_addr;
65 struct sockaddr addr;
66 } sa[2];
67
68 int cb = sizeof(sa);
69 memset(&sa, 0, cb);
70
71 sa[0].in_addr.sin_family = domain;
72 sa[0].in_addr.sin_addr.s_addr = RT_H2N_U32(INADDR_LOOPBACK);
73 sa[0].in_addr.sin_port = 0;
74 cb = sizeof(sa[0]);
75
76 if (type == SOCK_STREAM)
77 {
78 listener = WSASocket(domain, type, protocol, 0, NULL, 0);
79
80 if (listener == INVALID_SOCKET)
81 {
82 return VERR_INTERNAL_ERROR;
83 }
84
85 int reuse = 1;
86 cb = sizeof(int);
87 int rc = setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, cb);
88
89 if (rc)
90 {
91 goto close_socket;
92 }
93
94 cb = sizeof(sa[0]);
95 rc = bind(listener, &sa[0].addr, cb);
96 if(rc)
97 {
98 goto close_socket;
99 }
100
101 memset(&sa[0], 0, cb);
102 rc = getsockname(listener, &sa[0].addr, &cb);
103 if (rc)
104 {
105 goto close_socket;
106 }
107
108 rc = listen(listener, 1);
109 if (rc)
110 {
111 goto close_socket;
112 }
113
114 socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0);
115 if (socket_vector[0] == INVALID_SOCKET)
116 {
117 goto close_socket;
118 }
119
120 rc = connect(socket_vector[0], &sa[0].addr, cb);
121 if (rc)
122 goto close_socket;
123
124
125 socket_vector[1] = accept(listener, NULL, NULL);
126 if (socket_vector[1] == INVALID_SOCKET)
127 {
128 goto close_socket;
129 }
130
131 closesocket(listener);
132 }
133 else
134 {
135 socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0);
136
137 cb = sizeof(sa[0]);
138 int rc = bind(socket_vector[0], &sa[0].addr, cb);
139 Assert(rc != SOCKET_ERROR);
140 if (rc == SOCKET_ERROR)
141 {
142 goto close_socket;
143 }
144
145 sa[1].in_addr.sin_family = domain;
146 sa[1].in_addr.sin_addr.s_addr = RT_H2N_U32(INADDR_LOOPBACK);
147 sa[1].in_addr.sin_port = 0;
148
149 socket_vector[1] = WSASocket(domain, type, protocol, 0, NULL, 0);
150 rc = bind(socket_vector[1], &sa[1].addr, cb);
151 Assert(rc != SOCKET_ERROR);
152 if (rc == SOCKET_ERROR)
153 {
154 goto close_socket;
155 }
156
157 {
158 u_long mode = 0;
159 rc = ioctlsocket(socket_vector[0], FIONBIO, &mode);
160 AssertMsgReturn(rc != SOCKET_ERROR,
161 ("ioctl error: %d\n", WSAGetLastError()),
162 VERR_INTERNAL_ERROR);
163
164 rc = ioctlsocket(socket_vector[1], FIONBIO, &mode);
165 AssertMsgReturn(rc != SOCKET_ERROR,
166 ("ioctl error: %d\n", WSAGetLastError()),
167 VERR_INTERNAL_ERROR);
168 }
169
170 memset(&sa, 0, 2 * cb);
171 rc = getsockname(socket_vector[0], &sa[0].addr, &cb);
172 Assert(rc != SOCKET_ERROR);
173 if (rc == SOCKET_ERROR)
174 {
175 goto close_socket;
176 }
177
178 rc = getsockname(socket_vector[1], &sa[1].addr, &cb);
179 Assert(rc != SOCKET_ERROR);
180 if (rc == SOCKET_ERROR)
181 {
182 goto close_socket;
183 }
184
185 rc = connect(socket_vector[0], &sa[1].addr, cb);
186 Assert(rc != SOCKET_ERROR);
187 if (rc == SOCKET_ERROR)
188 {
189 goto close_socket;
190 }
191
192 rc = connect(socket_vector[1], &sa[0].addr, cb);
193 Assert(rc != SOCKET_ERROR);
194 if (rc == SOCKET_ERROR)
195 {
196 goto close_socket;
197 }
198 }
199
200 for (int i = 0; i < 2; ++i) {
201 SOCKET s = socket_vector[i];
202 u_long mode = 1;
203
204 int status = ioctlsocket(s, FIONBIO, &mode);
205 if (status == SOCKET_ERROR) {
206 LogRel(("FIONBIO: %R[sockerr]\n", WSAGetLastError()));
207 }
208 }
209
210 LogFlowFuncLeaveRC(VINF_SUCCESS);
211 return VINF_SUCCESS;
212
213close_socket:
214 if (listener != INVALID_SOCKET)
215 closesocket(listener);
216
217 if (socket_vector[0] != INVALID_SOCKET)
218 closesocket(socket_vector[0]);
219
220 if (socket_vector[1] != INVALID_SOCKET)
221 closesocket(socket_vector[1]);
222
223 LogFlowFuncLeaveRC(VERR_INTERNAL_ERROR);
224 return VERR_INTERNAL_ERROR;
225}
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