xref: /aosp_15_r20/external/deqp/framework/delibs/deutil/deSocket.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Utility Library
3*35238bceSAndroid Build Coastguard Worker  * ----------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Socket abstraction.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "deSocket.h"
25*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
26*35238bceSAndroid Build Coastguard Worker #include "deMutex.h"
27*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
28*35238bceSAndroid Build Coastguard Worker 
29*35238bceSAndroid Build Coastguard Worker #if (DE_OS == DE_OS_WIN32)
30*35238bceSAndroid Build Coastguard Worker #define DE_USE_WINSOCK
31*35238bceSAndroid Build Coastguard Worker #elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || \
32*35238bceSAndroid Build Coastguard Worker     (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
33*35238bceSAndroid Build Coastguard Worker #define DE_USE_BERKELEY_SOCKETS
34*35238bceSAndroid Build Coastguard Worker #else
35*35238bceSAndroid Build Coastguard Worker #error Implement deSocket for your OS.
36*35238bceSAndroid Build Coastguard Worker #endif
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker /* Common utilities. */
39*35238bceSAndroid Build Coastguard Worker 
deGetSocketResultName(deSocketResult result)40*35238bceSAndroid Build Coastguard Worker const char *deGetSocketResultName(deSocketResult result)
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker     switch (result)
43*35238bceSAndroid Build Coastguard Worker     {
44*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETRESULT_SUCCESS:
45*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETRESULT_SUCCESS";
46*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETRESULT_WOULD_BLOCK:
47*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETRESULT_WOULD_BLOCK";
48*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETRESULT_CONNECTION_CLOSED:
49*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETRESULT_CONNECTION_CLOSED";
50*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETRESULT_CONNECTION_TERMINATED:
51*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETRESULT_CONNECTION_TERMINATED";
52*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETRESULT_ERROR:
53*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETRESULT_ERROR";
54*35238bceSAndroid Build Coastguard Worker     default:
55*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
56*35238bceSAndroid Build Coastguard Worker     }
57*35238bceSAndroid Build Coastguard Worker }
58*35238bceSAndroid Build Coastguard Worker 
deGetSocketFamilyName(deSocketFamily family)59*35238bceSAndroid Build Coastguard Worker const char *deGetSocketFamilyName(deSocketFamily family)
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker     switch (family)
62*35238bceSAndroid Build Coastguard Worker     {
63*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETFAMILY_INET4:
64*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETFAMILY_INET4";
65*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETFAMILY_INET6:
66*35238bceSAndroid Build Coastguard Worker         return "DE_SOCKETFAMILY_INET6";
67*35238bceSAndroid Build Coastguard Worker     default:
68*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
69*35238bceSAndroid Build Coastguard Worker     }
70*35238bceSAndroid Build Coastguard Worker }
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK) || defined(DE_USE_BERKELEY_SOCKETS)
73*35238bceSAndroid Build Coastguard Worker 
74*35238bceSAndroid Build Coastguard Worker /* Common deSocketAddress implementation. */
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker struct deSocketAddress_s
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker     char *host;
79*35238bceSAndroid Build Coastguard Worker     int port;
80*35238bceSAndroid Build Coastguard Worker     deSocketFamily family;
81*35238bceSAndroid Build Coastguard Worker     deSocketType type;
82*35238bceSAndroid Build Coastguard Worker     deSocketProtocol protocol;
83*35238bceSAndroid Build Coastguard Worker };
84*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_create(void)85*35238bceSAndroid Build Coastguard Worker deSocketAddress *deSocketAddress_create(void)
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker     deSocketAddress *addr = (deSocketAddress *)deCalloc(sizeof(deSocketAddress));
88*35238bceSAndroid Build Coastguard Worker     if (!addr)
89*35238bceSAndroid Build Coastguard Worker         return addr;
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker     /* Sane defaults. */
92*35238bceSAndroid Build Coastguard Worker     addr->family   = DE_SOCKETFAMILY_INET4;
93*35238bceSAndroid Build Coastguard Worker     addr->type     = DE_SOCKETTYPE_STREAM;
94*35238bceSAndroid Build Coastguard Worker     addr->protocol = DE_SOCKETPROTOCOL_TCP;
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker     return addr;
97*35238bceSAndroid Build Coastguard Worker }
98*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_setFamily(deSocketAddress * address,deSocketFamily family)99*35238bceSAndroid Build Coastguard Worker bool deSocketAddress_setFamily(deSocketAddress *address, deSocketFamily family)
100*35238bceSAndroid Build Coastguard Worker {
101*35238bceSAndroid Build Coastguard Worker     address->family = family;
102*35238bceSAndroid Build Coastguard Worker     return true;
103*35238bceSAndroid Build Coastguard Worker }
104*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_getFamily(const deSocketAddress * address)105*35238bceSAndroid Build Coastguard Worker deSocketFamily deSocketAddress_getFamily(const deSocketAddress *address)
106*35238bceSAndroid Build Coastguard Worker {
107*35238bceSAndroid Build Coastguard Worker     return address->family;
108*35238bceSAndroid Build Coastguard Worker }
109*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_destroy(deSocketAddress * address)110*35238bceSAndroid Build Coastguard Worker void deSocketAddress_destroy(deSocketAddress *address)
111*35238bceSAndroid Build Coastguard Worker {
112*35238bceSAndroid Build Coastguard Worker     deFree(address->host);
113*35238bceSAndroid Build Coastguard Worker     deFree(address);
114*35238bceSAndroid Build Coastguard Worker }
115*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_setPort(deSocketAddress * address,int port)116*35238bceSAndroid Build Coastguard Worker bool deSocketAddress_setPort(deSocketAddress *address, int port)
117*35238bceSAndroid Build Coastguard Worker {
118*35238bceSAndroid Build Coastguard Worker     address->port = port;
119*35238bceSAndroid Build Coastguard Worker     return true;
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_getPort(const deSocketAddress * address)122*35238bceSAndroid Build Coastguard Worker int deSocketAddress_getPort(const deSocketAddress *address)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker     return address->port;
125*35238bceSAndroid Build Coastguard Worker }
126*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_setHost(deSocketAddress * address,const char * host)127*35238bceSAndroid Build Coastguard Worker bool deSocketAddress_setHost(deSocketAddress *address, const char *host)
128*35238bceSAndroid Build Coastguard Worker {
129*35238bceSAndroid Build Coastguard Worker     if (address->host)
130*35238bceSAndroid Build Coastguard Worker     {
131*35238bceSAndroid Build Coastguard Worker         deFree(address->host);
132*35238bceSAndroid Build Coastguard Worker         address->host = DE_NULL;
133*35238bceSAndroid Build Coastguard Worker     }
134*35238bceSAndroid Build Coastguard Worker 
135*35238bceSAndroid Build Coastguard Worker     address->host = deStrdup(host);
136*35238bceSAndroid Build Coastguard Worker     return address->host != DE_NULL;
137*35238bceSAndroid Build Coastguard Worker }
138*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_getHost(const deSocketAddress * address)139*35238bceSAndroid Build Coastguard Worker const char *deSocketAddress_getHost(const deSocketAddress *address)
140*35238bceSAndroid Build Coastguard Worker {
141*35238bceSAndroid Build Coastguard Worker     return address->host;
142*35238bceSAndroid Build Coastguard Worker }
143*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_setType(deSocketAddress * address,deSocketType type)144*35238bceSAndroid Build Coastguard Worker bool deSocketAddress_setType(deSocketAddress *address, deSocketType type)
145*35238bceSAndroid Build Coastguard Worker {
146*35238bceSAndroid Build Coastguard Worker     address->type = type;
147*35238bceSAndroid Build Coastguard Worker     return true;
148*35238bceSAndroid Build Coastguard Worker }
149*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_getType(const deSocketAddress * address)150*35238bceSAndroid Build Coastguard Worker deSocketType deSocketAddress_getType(const deSocketAddress *address)
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker     return address->type;
153*35238bceSAndroid Build Coastguard Worker }
154*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_setProtocol(deSocketAddress * address,deSocketProtocol protocol)155*35238bceSAndroid Build Coastguard Worker bool deSocketAddress_setProtocol(deSocketAddress *address, deSocketProtocol protocol)
156*35238bceSAndroid Build Coastguard Worker {
157*35238bceSAndroid Build Coastguard Worker     address->protocol = protocol;
158*35238bceSAndroid Build Coastguard Worker     return true;
159*35238bceSAndroid Build Coastguard Worker }
160*35238bceSAndroid Build Coastguard Worker 
deSocketAddress_getProtocol(const deSocketAddress * address)161*35238bceSAndroid Build Coastguard Worker deSocketProtocol deSocketAddress_getProtocol(const deSocketAddress *address)
162*35238bceSAndroid Build Coastguard Worker {
163*35238bceSAndroid Build Coastguard Worker     return address->protocol;
164*35238bceSAndroid Build Coastguard Worker }
165*35238bceSAndroid Build Coastguard Worker 
166*35238bceSAndroid Build Coastguard Worker #endif
167*35238bceSAndroid Build Coastguard Worker 
168*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker /* WinSock spesific. */
171*35238bceSAndroid Build Coastguard Worker #include <winsock2.h>
172*35238bceSAndroid Build Coastguard Worker #include <ws2tcpip.h>
173*35238bceSAndroid Build Coastguard Worker #include <windef.h>
174*35238bceSAndroid Build Coastguard Worker 
initWinsock(void)175*35238bceSAndroid Build Coastguard Worker static bool initWinsock(void)
176*35238bceSAndroid Build Coastguard Worker {
177*35238bceSAndroid Build Coastguard Worker     WSADATA wsaData;
178*35238bceSAndroid Build Coastguard Worker     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
179*35238bceSAndroid Build Coastguard Worker         return false;
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker     return true;
182*35238bceSAndroid Build Coastguard Worker }
183*35238bceSAndroid Build Coastguard Worker 
184*35238bceSAndroid Build Coastguard Worker #elif defined(DE_USE_BERKELEY_SOCKETS)
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker /* Berkeley Socket includes. */
187*35238bceSAndroid Build Coastguard Worker #include <sys/socket.h>
188*35238bceSAndroid Build Coastguard Worker #include <netinet/in.h>
189*35238bceSAndroid Build Coastguard Worker #include <netinet/tcp.h>
190*35238bceSAndroid Build Coastguard Worker #include <arpa/inet.h>
191*35238bceSAndroid Build Coastguard Worker #include <netdb.h>
192*35238bceSAndroid Build Coastguard Worker #include <unistd.h>
193*35238bceSAndroid Build Coastguard Worker #include <fcntl.h>
194*35238bceSAndroid Build Coastguard Worker #include <errno.h>
195*35238bceSAndroid Build Coastguard Worker 
196*35238bceSAndroid Build Coastguard Worker #endif
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker /* Socket type. */
199*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
200*35238bceSAndroid Build Coastguard Worker /* \note SOCKET is unsigned type! */
201*35238bceSAndroid Build Coastguard Worker typedef SOCKET deSocketHandle;
202*35238bceSAndroid Build Coastguard Worker typedef int NativeSocklen;
203*35238bceSAndroid Build Coastguard Worker typedef int NativeSize;
204*35238bceSAndroid Build Coastguard Worker #define DE_INVALID_SOCKET_HANDLE INVALID_SOCKET
205*35238bceSAndroid Build Coastguard Worker #else
206*35238bceSAndroid Build Coastguard Worker typedef int deSocketHandle;
207*35238bceSAndroid Build Coastguard Worker typedef socklen_t NativeSocklen;
208*35238bceSAndroid Build Coastguard Worker typedef size_t NativeSize;
209*35238bceSAndroid Build Coastguard Worker #define DE_INVALID_SOCKET_HANDLE (-1)
210*35238bceSAndroid Build Coastguard Worker #endif
211*35238bceSAndroid Build Coastguard Worker 
deSocketHandleIsValid(deSocketHandle handle)212*35238bceSAndroid Build Coastguard Worker DE_INLINE bool deSocketHandleIsValid(deSocketHandle handle)
213*35238bceSAndroid Build Coastguard Worker {
214*35238bceSAndroid Build Coastguard Worker     return handle != DE_INVALID_SOCKET_HANDLE;
215*35238bceSAndroid Build Coastguard Worker }
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK) || defined(DE_USE_BERKELEY_SOCKETS)
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker /* Shared berkeley and winsock implementation. */
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker struct deSocket_s
222*35238bceSAndroid Build Coastguard Worker {
223*35238bceSAndroid Build Coastguard Worker     deSocketHandle handle;
224*35238bceSAndroid Build Coastguard Worker 
225*35238bceSAndroid Build Coastguard Worker     deMutex stateLock;
226*35238bceSAndroid Build Coastguard Worker     volatile deSocketState state;
227*35238bceSAndroid Build Coastguard Worker     volatile uint32_t openChannels;
228*35238bceSAndroid Build Coastguard Worker };
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker /* Common socket functions. */
231*35238bceSAndroid Build Coastguard Worker 
deHostToNetworkOrder16(uint16_t v)232*35238bceSAndroid Build Coastguard Worker static uint16_t deHostToNetworkOrder16(uint16_t v)
233*35238bceSAndroid Build Coastguard Worker {
234*35238bceSAndroid Build Coastguard Worker #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
235*35238bceSAndroid Build Coastguard Worker     return deReverseBytes16(v);
236*35238bceSAndroid Build Coastguard Worker #else
237*35238bceSAndroid Build Coastguard Worker     return v;
238*35238bceSAndroid Build Coastguard Worker #endif
239*35238bceSAndroid Build Coastguard Worker }
240*35238bceSAndroid Build Coastguard Worker 
deNetworkToHostOrder16(uint16_t v)241*35238bceSAndroid Build Coastguard Worker static uint16_t deNetworkToHostOrder16(uint16_t v)
242*35238bceSAndroid Build Coastguard Worker {
243*35238bceSAndroid Build Coastguard Worker #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
244*35238bceSAndroid Build Coastguard Worker     return deReverseBytes16(v);
245*35238bceSAndroid Build Coastguard Worker #else
246*35238bceSAndroid Build Coastguard Worker     return v;
247*35238bceSAndroid Build Coastguard Worker #endif
248*35238bceSAndroid Build Coastguard Worker }
249*35238bceSAndroid Build Coastguard Worker 
250*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(sizeof(((struct sockaddr_in *)DE_NULL)->sin_port) == sizeof(uint16_t));
251*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(sizeof(((struct sockaddr_in6 *)DE_NULL)->sin6_port) == sizeof(uint16_t));
252*35238bceSAndroid Build Coastguard Worker 
deSocketFamilyToBsdFamily(deSocketFamily family)253*35238bceSAndroid Build Coastguard Worker static int deSocketFamilyToBsdFamily(deSocketFamily family)
254*35238bceSAndroid Build Coastguard Worker {
255*35238bceSAndroid Build Coastguard Worker     switch (family)
256*35238bceSAndroid Build Coastguard Worker     {
257*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETFAMILY_INET4:
258*35238bceSAndroid Build Coastguard Worker         return AF_INET;
259*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETFAMILY_INET6:
260*35238bceSAndroid Build Coastguard Worker         return AF_INET6;
261*35238bceSAndroid Build Coastguard Worker     default:
262*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
263*35238bceSAndroid Build Coastguard Worker         return 0;
264*35238bceSAndroid Build Coastguard Worker     }
265*35238bceSAndroid Build Coastguard Worker }
266*35238bceSAndroid Build Coastguard Worker 
deSocketTypeToBsdType(deSocketType type)267*35238bceSAndroid Build Coastguard Worker static int deSocketTypeToBsdType(deSocketType type)
268*35238bceSAndroid Build Coastguard Worker {
269*35238bceSAndroid Build Coastguard Worker     switch (type)
270*35238bceSAndroid Build Coastguard Worker     {
271*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETTYPE_STREAM:
272*35238bceSAndroid Build Coastguard Worker         return SOCK_STREAM;
273*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETTYPE_DATAGRAM:
274*35238bceSAndroid Build Coastguard Worker         return SOCK_DGRAM;
275*35238bceSAndroid Build Coastguard Worker     default:
276*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
277*35238bceSAndroid Build Coastguard Worker         return 0;
278*35238bceSAndroid Build Coastguard Worker     }
279*35238bceSAndroid Build Coastguard Worker }
280*35238bceSAndroid Build Coastguard Worker 
deSocketProtocolToBsdProtocol(deSocketProtocol protocol)281*35238bceSAndroid Build Coastguard Worker static int deSocketProtocolToBsdProtocol(deSocketProtocol protocol)
282*35238bceSAndroid Build Coastguard Worker {
283*35238bceSAndroid Build Coastguard Worker     switch (protocol)
284*35238bceSAndroid Build Coastguard Worker     {
285*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETPROTOCOL_TCP:
286*35238bceSAndroid Build Coastguard Worker         return IPPROTO_TCP;
287*35238bceSAndroid Build Coastguard Worker     case DE_SOCKETPROTOCOL_UDP:
288*35238bceSAndroid Build Coastguard Worker         return IPPROTO_UDP;
289*35238bceSAndroid Build Coastguard Worker     default:
290*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
291*35238bceSAndroid Build Coastguard Worker         return 0;
292*35238bceSAndroid Build Coastguard Worker     }
293*35238bceSAndroid Build Coastguard Worker }
294*35238bceSAndroid Build Coastguard Worker 
deSocketAddressToBsdAddress(const deSocketAddress * address,size_t bsdAddrBufSize,struct sockaddr * bsdAddr,NativeSocklen * bsdAddrLen)295*35238bceSAndroid Build Coastguard Worker static bool deSocketAddressToBsdAddress(const deSocketAddress *address, size_t bsdAddrBufSize, struct sockaddr *bsdAddr,
296*35238bceSAndroid Build Coastguard Worker                                         NativeSocklen *bsdAddrLen)
297*35238bceSAndroid Build Coastguard Worker {
298*35238bceSAndroid Build Coastguard Worker     deMemset(bsdAddr, 0, bsdAddrBufSize);
299*35238bceSAndroid Build Coastguard Worker 
300*35238bceSAndroid Build Coastguard Worker     /* Resolve host. */
301*35238bceSAndroid Build Coastguard Worker     if (address->host != DE_NULL)
302*35238bceSAndroid Build Coastguard Worker     {
303*35238bceSAndroid Build Coastguard Worker         struct addrinfo *result = DE_NULL;
304*35238bceSAndroid Build Coastguard Worker         struct addrinfo hints;
305*35238bceSAndroid Build Coastguard Worker 
306*35238bceSAndroid Build Coastguard Worker         deMemset(&hints, 0, sizeof(hints));
307*35238bceSAndroid Build Coastguard Worker         hints.ai_family   = deSocketFamilyToBsdFamily(address->family);
308*35238bceSAndroid Build Coastguard Worker         hints.ai_socktype = deSocketTypeToBsdType(address->type);
309*35238bceSAndroid Build Coastguard Worker         hints.ai_protocol = deSocketProtocolToBsdProtocol(address->protocol);
310*35238bceSAndroid Build Coastguard Worker 
311*35238bceSAndroid Build Coastguard Worker         if (getaddrinfo(address->host, DE_NULL, &hints, &result) != 0 || !result)
312*35238bceSAndroid Build Coastguard Worker         {
313*35238bceSAndroid Build Coastguard Worker             if (result)
314*35238bceSAndroid Build Coastguard Worker                 freeaddrinfo(result);
315*35238bceSAndroid Build Coastguard Worker             return false;
316*35238bceSAndroid Build Coastguard Worker         }
317*35238bceSAndroid Build Coastguard Worker 
318*35238bceSAndroid Build Coastguard Worker         /* \note Always uses first address. */
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker         if (bsdAddrBufSize < (size_t)result->ai_addrlen)
321*35238bceSAndroid Build Coastguard Worker         {
322*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Too small bsdAddr buffer");
323*35238bceSAndroid Build Coastguard Worker             freeaddrinfo(result);
324*35238bceSAndroid Build Coastguard Worker             return false;
325*35238bceSAndroid Build Coastguard Worker         }
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker         *bsdAddrLen = (NativeSocklen)result->ai_addrlen;
328*35238bceSAndroid Build Coastguard Worker 
329*35238bceSAndroid Build Coastguard Worker         deMemcpy(bsdAddr, result->ai_addr, (size_t)result->ai_addrlen);
330*35238bceSAndroid Build Coastguard Worker         freeaddrinfo(result);
331*35238bceSAndroid Build Coastguard Worker 
332*35238bceSAndroid Build Coastguard Worker         /* Add port. */
333*35238bceSAndroid Build Coastguard Worker         if (bsdAddr->sa_family == AF_INET)
334*35238bceSAndroid Build Coastguard Worker         {
335*35238bceSAndroid Build Coastguard Worker             if (*bsdAddrLen < (NativeSocklen)sizeof(struct sockaddr_in))
336*35238bceSAndroid Build Coastguard Worker                 return false;
337*35238bceSAndroid Build Coastguard Worker             ((struct sockaddr_in *)bsdAddr)->sin_port = deHostToNetworkOrder16((uint16_t)address->port);
338*35238bceSAndroid Build Coastguard Worker         }
339*35238bceSAndroid Build Coastguard Worker         else if (bsdAddr->sa_family == AF_INET6)
340*35238bceSAndroid Build Coastguard Worker         {
341*35238bceSAndroid Build Coastguard Worker             if (*bsdAddrLen < (NativeSocklen)sizeof(struct sockaddr_in6))
342*35238bceSAndroid Build Coastguard Worker                 return false;
343*35238bceSAndroid Build Coastguard Worker             ((struct sockaddr_in6 *)bsdAddr)->sin6_port = deHostToNetworkOrder16((uint16_t)address->port);
344*35238bceSAndroid Build Coastguard Worker         }
345*35238bceSAndroid Build Coastguard Worker         else
346*35238bceSAndroid Build Coastguard Worker             return false;
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker         return true;
349*35238bceSAndroid Build Coastguard Worker     }
350*35238bceSAndroid Build Coastguard Worker     else if (address->family == DE_SOCKETFAMILY_INET4)
351*35238bceSAndroid Build Coastguard Worker     {
352*35238bceSAndroid Build Coastguard Worker         struct sockaddr_in *addr4 = (struct sockaddr_in *)bsdAddr;
353*35238bceSAndroid Build Coastguard Worker 
354*35238bceSAndroid Build Coastguard Worker         if (bsdAddrBufSize < sizeof(struct sockaddr_in))
355*35238bceSAndroid Build Coastguard Worker         {
356*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Too small bsdAddr buffer");
357*35238bceSAndroid Build Coastguard Worker             return false;
358*35238bceSAndroid Build Coastguard Worker         }
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker         addr4->sin_port        = deHostToNetworkOrder16((uint16_t)address->port);
361*35238bceSAndroid Build Coastguard Worker         addr4->sin_family      = AF_INET;
362*35238bceSAndroid Build Coastguard Worker         addr4->sin_addr.s_addr = INADDR_ANY;
363*35238bceSAndroid Build Coastguard Worker 
364*35238bceSAndroid Build Coastguard Worker         *bsdAddrLen = (NativeSocklen)sizeof(struct sockaddr_in);
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker         return true;
367*35238bceSAndroid Build Coastguard Worker     }
368*35238bceSAndroid Build Coastguard Worker     else if (address->family == DE_SOCKETFAMILY_INET6)
369*35238bceSAndroid Build Coastguard Worker     {
370*35238bceSAndroid Build Coastguard Worker         struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)bsdAddr;
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker         if (bsdAddrBufSize < sizeof(struct sockaddr_in6))
373*35238bceSAndroid Build Coastguard Worker         {
374*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Too small bsdAddr buffer");
375*35238bceSAndroid Build Coastguard Worker             return false;
376*35238bceSAndroid Build Coastguard Worker         }
377*35238bceSAndroid Build Coastguard Worker 
378*35238bceSAndroid Build Coastguard Worker         addr6->sin6_port   = deHostToNetworkOrder16((uint16_t)address->port);
379*35238bceSAndroid Build Coastguard Worker         addr6->sin6_family = AF_INET6;
380*35238bceSAndroid Build Coastguard Worker 
381*35238bceSAndroid Build Coastguard Worker         *bsdAddrLen = (NativeSocklen)sizeof(struct sockaddr_in6);
382*35238bceSAndroid Build Coastguard Worker 
383*35238bceSAndroid Build Coastguard Worker         return true;
384*35238bceSAndroid Build Coastguard Worker     }
385*35238bceSAndroid Build Coastguard Worker     else
386*35238bceSAndroid Build Coastguard Worker         return false;
387*35238bceSAndroid Build Coastguard Worker }
388*35238bceSAndroid Build Coastguard Worker 
deBsdAddressToSocketAddress(deSocketAddress * address,const struct sockaddr * bsdAddr,int addrLen)389*35238bceSAndroid Build Coastguard Worker void deBsdAddressToSocketAddress(deSocketAddress *address, const struct sockaddr *bsdAddr, int addrLen)
390*35238bceSAndroid Build Coastguard Worker {
391*35238bceSAndroid Build Coastguard Worker     /* Decode client address info. */
392*35238bceSAndroid Build Coastguard Worker     if (bsdAddr->sa_family == AF_INET)
393*35238bceSAndroid Build Coastguard Worker     {
394*35238bceSAndroid Build Coastguard Worker         const struct sockaddr_in *addr4 = (const struct sockaddr_in *)bsdAddr;
395*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(addrLen >= (int)sizeof(struct sockaddr_in));
396*35238bceSAndroid Build Coastguard Worker         DE_UNREF(addrLen);
397*35238bceSAndroid Build Coastguard Worker 
398*35238bceSAndroid Build Coastguard Worker         deSocketAddress_setFamily(address, DE_SOCKETFAMILY_INET4);
399*35238bceSAndroid Build Coastguard Worker         deSocketAddress_setPort(address, (int)deNetworkToHostOrder16((uint16_t)addr4->sin_port));
400*35238bceSAndroid Build Coastguard Worker 
401*35238bceSAndroid Build Coastguard Worker         {
402*35238bceSAndroid Build Coastguard Worker             char buf[16]; /* Max valid address takes 3*4 + 3 = 15 chars */
403*35238bceSAndroid Build Coastguard Worker             inet_ntop(AF_INET, (void *)&addr4->sin_addr, buf, sizeof(buf));
404*35238bceSAndroid Build Coastguard Worker             deSocketAddress_setHost(address, buf);
405*35238bceSAndroid Build Coastguard Worker         }
406*35238bceSAndroid Build Coastguard Worker     }
407*35238bceSAndroid Build Coastguard Worker     else if (bsdAddr->sa_family == AF_INET6)
408*35238bceSAndroid Build Coastguard Worker     {
409*35238bceSAndroid Build Coastguard Worker         const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)bsdAddr;
410*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(addrLen >= (int)sizeof(struct sockaddr_in6));
411*35238bceSAndroid Build Coastguard Worker         DE_UNREF(addrLen);
412*35238bceSAndroid Build Coastguard Worker 
413*35238bceSAndroid Build Coastguard Worker         deSocketAddress_setFamily(address, DE_SOCKETFAMILY_INET6);
414*35238bceSAndroid Build Coastguard Worker         deSocketAddress_setPort(address, (int)deNetworkToHostOrder16((uint16_t)addr6->sin6_port));
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker         {
417*35238bceSAndroid Build Coastguard Worker             char buf[40]; /* Max valid address takes 8*4 + 7 = 39 chars */
418*35238bceSAndroid Build Coastguard Worker             inet_ntop(AF_INET6, (void *)&addr6->sin6_addr, buf, sizeof(buf));
419*35238bceSAndroid Build Coastguard Worker             deSocketAddress_setHost(address, buf);
420*35238bceSAndroid Build Coastguard Worker         }
421*35238bceSAndroid Build Coastguard Worker     }
422*35238bceSAndroid Build Coastguard Worker     else
423*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
424*35238bceSAndroid Build Coastguard Worker }
425*35238bceSAndroid Build Coastguard Worker 
deSocket_create(void)426*35238bceSAndroid Build Coastguard Worker deSocket *deSocket_create(void)
427*35238bceSAndroid Build Coastguard Worker {
428*35238bceSAndroid Build Coastguard Worker     deSocket *sock = (deSocket *)deCalloc(sizeof(deSocket));
429*35238bceSAndroid Build Coastguard Worker     if (!sock)
430*35238bceSAndroid Build Coastguard Worker         return sock;
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
433*35238bceSAndroid Build Coastguard Worker     /* Make sure WSA is up. */
434*35238bceSAndroid Build Coastguard Worker     if (!initWinsock())
435*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
436*35238bceSAndroid Build Coastguard Worker #endif
437*35238bceSAndroid Build Coastguard Worker 
438*35238bceSAndroid Build Coastguard Worker     sock->stateLock = deMutex_create(0);
439*35238bceSAndroid Build Coastguard Worker     sock->handle    = DE_INVALID_SOCKET_HANDLE;
440*35238bceSAndroid Build Coastguard Worker     sock->state     = DE_SOCKETSTATE_CLOSED;
441*35238bceSAndroid Build Coastguard Worker 
442*35238bceSAndroid Build Coastguard Worker     return sock;
443*35238bceSAndroid Build Coastguard Worker }
444*35238bceSAndroid Build Coastguard Worker 
deSocket_destroy(deSocket * sock)445*35238bceSAndroid Build Coastguard Worker void deSocket_destroy(deSocket *sock)
446*35238bceSAndroid Build Coastguard Worker {
447*35238bceSAndroid Build Coastguard Worker     if (sock->state != DE_SOCKETSTATE_CLOSED)
448*35238bceSAndroid Build Coastguard Worker         deSocket_close(sock);
449*35238bceSAndroid Build Coastguard Worker 
450*35238bceSAndroid Build Coastguard Worker     deMutex_destroy(sock->stateLock);
451*35238bceSAndroid Build Coastguard Worker     deFree(sock);
452*35238bceSAndroid Build Coastguard Worker }
453*35238bceSAndroid Build Coastguard Worker 
deSocket_getState(const deSocket * sock)454*35238bceSAndroid Build Coastguard Worker deSocketState deSocket_getState(const deSocket *sock)
455*35238bceSAndroid Build Coastguard Worker {
456*35238bceSAndroid Build Coastguard Worker     return sock->state;
457*35238bceSAndroid Build Coastguard Worker }
458*35238bceSAndroid Build Coastguard Worker 
deSocket_getOpenChannels(const deSocket * sock)459*35238bceSAndroid Build Coastguard Worker uint32_t deSocket_getOpenChannels(const deSocket *sock)
460*35238bceSAndroid Build Coastguard Worker {
461*35238bceSAndroid Build Coastguard Worker     return sock->openChannels;
462*35238bceSAndroid Build Coastguard Worker }
463*35238bceSAndroid Build Coastguard Worker 
deSocket_setFlags(deSocket * sock,uint32_t flags)464*35238bceSAndroid Build Coastguard Worker bool deSocket_setFlags(deSocket *sock, uint32_t flags)
465*35238bceSAndroid Build Coastguard Worker {
466*35238bceSAndroid Build Coastguard Worker     deSocketHandle fd = sock->handle;
467*35238bceSAndroid Build Coastguard Worker 
468*35238bceSAndroid Build Coastguard Worker     if (sock->state == DE_SOCKETSTATE_CLOSED)
469*35238bceSAndroid Build Coastguard Worker         return false;
470*35238bceSAndroid Build Coastguard Worker 
471*35238bceSAndroid Build Coastguard Worker     /* Keepalive. */
472*35238bceSAndroid Build Coastguard Worker     {
473*35238bceSAndroid Build Coastguard Worker         int mode = (flags & DE_SOCKET_KEEPALIVE) ? 1 : 0;
474*35238bceSAndroid Build Coastguard Worker         if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&mode, sizeof(mode)) != 0)
475*35238bceSAndroid Build Coastguard Worker             return false;
476*35238bceSAndroid Build Coastguard Worker     }
477*35238bceSAndroid Build Coastguard Worker 
478*35238bceSAndroid Build Coastguard Worker     /* Nodelay. */
479*35238bceSAndroid Build Coastguard Worker     {
480*35238bceSAndroid Build Coastguard Worker         int mode = (flags & DE_SOCKET_NODELAY) ? 1 : 0;
481*35238bceSAndroid Build Coastguard Worker         if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&mode, sizeof(mode)) != 0)
482*35238bceSAndroid Build Coastguard Worker             return false;
483*35238bceSAndroid Build Coastguard Worker     }
484*35238bceSAndroid Build Coastguard Worker 
485*35238bceSAndroid Build Coastguard Worker     /* Non-blocking. */
486*35238bceSAndroid Build Coastguard Worker     {
487*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
488*35238bceSAndroid Build Coastguard Worker         u_long mode = (flags & DE_SOCKET_NONBLOCKING) ? 1 : 0;
489*35238bceSAndroid Build Coastguard Worker         if (ioctlsocket(fd, FIONBIO, &mode) != 0)
490*35238bceSAndroid Build Coastguard Worker             return false;
491*35238bceSAndroid Build Coastguard Worker #else
492*35238bceSAndroid Build Coastguard Worker         int oldFlags = fcntl(fd, F_GETFL, 0);
493*35238bceSAndroid Build Coastguard Worker         int newFlags = (flags & DE_SOCKET_NONBLOCKING) ? (oldFlags | O_NONBLOCK) : (oldFlags & ~O_NONBLOCK);
494*35238bceSAndroid Build Coastguard Worker         if (fcntl(fd, F_SETFL, newFlags) != 0)
495*35238bceSAndroid Build Coastguard Worker             return false;
496*35238bceSAndroid Build Coastguard Worker #endif
497*35238bceSAndroid Build Coastguard Worker     }
498*35238bceSAndroid Build Coastguard Worker 
499*35238bceSAndroid Build Coastguard Worker     /* Close on exec. */
500*35238bceSAndroid Build Coastguard Worker     {
501*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_BERKELEY_SOCKETS)
502*35238bceSAndroid Build Coastguard Worker         int oldFlags = fcntl(fd, F_GETFD, 0);
503*35238bceSAndroid Build Coastguard Worker         int newFlags = (flags & DE_SOCKET_CLOSE_ON_EXEC) ? (oldFlags | FD_CLOEXEC) : (oldFlags & ~FD_CLOEXEC);
504*35238bceSAndroid Build Coastguard Worker         if (fcntl(fd, F_SETFD, newFlags) != 0)
505*35238bceSAndroid Build Coastguard Worker             return false;
506*35238bceSAndroid Build Coastguard Worker #endif
507*35238bceSAndroid Build Coastguard Worker     }
508*35238bceSAndroid Build Coastguard Worker 
509*35238bceSAndroid Build Coastguard Worker     return true;
510*35238bceSAndroid Build Coastguard Worker }
511*35238bceSAndroid Build Coastguard Worker 
deSocket_listen(deSocket * sock,const deSocketAddress * address)512*35238bceSAndroid Build Coastguard Worker bool deSocket_listen(deSocket *sock, const deSocketAddress *address)
513*35238bceSAndroid Build Coastguard Worker {
514*35238bceSAndroid Build Coastguard Worker     const int backlogSize = 4;
515*35238bceSAndroid Build Coastguard Worker     uint8_t bsdAddrBuf[sizeof(struct sockaddr_in6)];
516*35238bceSAndroid Build Coastguard Worker     struct sockaddr *bsdAddr = (struct sockaddr *)&bsdAddrBuf[0];
517*35238bceSAndroid Build Coastguard Worker     NativeSocklen bsdAddrLen;
518*35238bceSAndroid Build Coastguard Worker 
519*35238bceSAndroid Build Coastguard Worker     if (sock->state != DE_SOCKETSTATE_CLOSED)
520*35238bceSAndroid Build Coastguard Worker         return false;
521*35238bceSAndroid Build Coastguard Worker 
522*35238bceSAndroid Build Coastguard Worker     /* Resolve address. */
523*35238bceSAndroid Build Coastguard Worker     if (!deSocketAddressToBsdAddress(address, sizeof(bsdAddrBuf), bsdAddr, &bsdAddrLen))
524*35238bceSAndroid Build Coastguard Worker         return false;
525*35238bceSAndroid Build Coastguard Worker 
526*35238bceSAndroid Build Coastguard Worker     /* Create socket. */
527*35238bceSAndroid Build Coastguard Worker     sock->handle = socket(bsdAddr->sa_family, deSocketTypeToBsdType(address->type),
528*35238bceSAndroid Build Coastguard Worker                           deSocketProtocolToBsdProtocol(address->protocol));
529*35238bceSAndroid Build Coastguard Worker     if (!deSocketHandleIsValid(sock->handle))
530*35238bceSAndroid Build Coastguard Worker         return false;
531*35238bceSAndroid Build Coastguard Worker 
532*35238bceSAndroid Build Coastguard Worker     sock->state = DE_SOCKETSTATE_DISCONNECTED;
533*35238bceSAndroid Build Coastguard Worker 
534*35238bceSAndroid Build Coastguard Worker     /* Allow re-using address. */
535*35238bceSAndroid Build Coastguard Worker     {
536*35238bceSAndroid Build Coastguard Worker         int reuseVal = 1;
537*35238bceSAndroid Build Coastguard Worker         setsockopt(sock->handle, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseVal, (int)sizeof(reuseVal));
538*35238bceSAndroid Build Coastguard Worker     }
539*35238bceSAndroid Build Coastguard Worker 
540*35238bceSAndroid Build Coastguard Worker     /* Bind to address. */
541*35238bceSAndroid Build Coastguard Worker     if (bind(sock->handle, bsdAddr, (NativeSocklen)bsdAddrLen) != 0)
542*35238bceSAndroid Build Coastguard Worker     {
543*35238bceSAndroid Build Coastguard Worker         deSocket_close(sock);
544*35238bceSAndroid Build Coastguard Worker         return false;
545*35238bceSAndroid Build Coastguard Worker     }
546*35238bceSAndroid Build Coastguard Worker 
547*35238bceSAndroid Build Coastguard Worker     /* Start listening. */
548*35238bceSAndroid Build Coastguard Worker     if (listen(sock->handle, backlogSize) != 0)
549*35238bceSAndroid Build Coastguard Worker     {
550*35238bceSAndroid Build Coastguard Worker         deSocket_close(sock);
551*35238bceSAndroid Build Coastguard Worker         return false;
552*35238bceSAndroid Build Coastguard Worker     }
553*35238bceSAndroid Build Coastguard Worker 
554*35238bceSAndroid Build Coastguard Worker     sock->state = DE_SOCKETSTATE_LISTENING;
555*35238bceSAndroid Build Coastguard Worker 
556*35238bceSAndroid Build Coastguard Worker     return true;
557*35238bceSAndroid Build Coastguard Worker }
558*35238bceSAndroid Build Coastguard Worker 
deSocket_accept(deSocket * sock,deSocketAddress * clientAddress)559*35238bceSAndroid Build Coastguard Worker deSocket *deSocket_accept(deSocket *sock, deSocketAddress *clientAddress)
560*35238bceSAndroid Build Coastguard Worker {
561*35238bceSAndroid Build Coastguard Worker     deSocketHandle newFd = DE_INVALID_SOCKET_HANDLE;
562*35238bceSAndroid Build Coastguard Worker     deSocket *newSock    = DE_NULL;
563*35238bceSAndroid Build Coastguard Worker     uint8_t bsdAddrBuf[sizeof(struct sockaddr_in6)];
564*35238bceSAndroid Build Coastguard Worker     struct sockaddr *bsdAddr = (struct sockaddr *)&bsdAddrBuf[0];
565*35238bceSAndroid Build Coastguard Worker     NativeSocklen bsdAddrLen = (NativeSocklen)sizeof(bsdAddrBuf);
566*35238bceSAndroid Build Coastguard Worker 
567*35238bceSAndroid Build Coastguard Worker     deMemset(bsdAddr, 0, (size_t)bsdAddrLen);
568*35238bceSAndroid Build Coastguard Worker 
569*35238bceSAndroid Build Coastguard Worker     newFd = accept(sock->handle, bsdAddr, &bsdAddrLen);
570*35238bceSAndroid Build Coastguard Worker     if (!deSocketHandleIsValid(newFd))
571*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
572*35238bceSAndroid Build Coastguard Worker 
573*35238bceSAndroid Build Coastguard Worker     newSock = (deSocket *)deCalloc(sizeof(deSocket));
574*35238bceSAndroid Build Coastguard Worker     if (!newSock)
575*35238bceSAndroid Build Coastguard Worker     {
576*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
577*35238bceSAndroid Build Coastguard Worker         closesocket(newFd);
578*35238bceSAndroid Build Coastguard Worker #else
579*35238bceSAndroid Build Coastguard Worker         close(newFd);
580*35238bceSAndroid Build Coastguard Worker #endif
581*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
582*35238bceSAndroid Build Coastguard Worker     }
583*35238bceSAndroid Build Coastguard Worker 
584*35238bceSAndroid Build Coastguard Worker     newSock->stateLock    = deMutex_create(0);
585*35238bceSAndroid Build Coastguard Worker     newSock->handle       = newFd;
586*35238bceSAndroid Build Coastguard Worker     newSock->state        = DE_SOCKETSTATE_CONNECTED;
587*35238bceSAndroid Build Coastguard Worker     newSock->openChannels = DE_SOCKETCHANNEL_BOTH;
588*35238bceSAndroid Build Coastguard Worker 
589*35238bceSAndroid Build Coastguard Worker     if (clientAddress)
590*35238bceSAndroid Build Coastguard Worker         deBsdAddressToSocketAddress(clientAddress, bsdAddr, (int)bsdAddrLen);
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker     return newSock;
593*35238bceSAndroid Build Coastguard Worker }
594*35238bceSAndroid Build Coastguard Worker 
deSocket_connect(deSocket * sock,const deSocketAddress * address)595*35238bceSAndroid Build Coastguard Worker bool deSocket_connect(deSocket *sock, const deSocketAddress *address)
596*35238bceSAndroid Build Coastguard Worker {
597*35238bceSAndroid Build Coastguard Worker     uint8_t bsdAddrBuf[sizeof(struct sockaddr_in6)];
598*35238bceSAndroid Build Coastguard Worker     struct sockaddr *bsdAddr = (struct sockaddr *)&bsdAddrBuf[0];
599*35238bceSAndroid Build Coastguard Worker     NativeSocklen bsdAddrLen;
600*35238bceSAndroid Build Coastguard Worker 
601*35238bceSAndroid Build Coastguard Worker     /* Resolve address. */
602*35238bceSAndroid Build Coastguard Worker     if (!deSocketAddressToBsdAddress(address, sizeof(bsdAddrBuf), bsdAddr, &bsdAddrLen))
603*35238bceSAndroid Build Coastguard Worker         return false;
604*35238bceSAndroid Build Coastguard Worker 
605*35238bceSAndroid Build Coastguard Worker     /* Create socket. */
606*35238bceSAndroid Build Coastguard Worker     sock->handle = socket(bsdAddr->sa_family, deSocketTypeToBsdType(address->type),
607*35238bceSAndroid Build Coastguard Worker                           deSocketProtocolToBsdProtocol(address->protocol));
608*35238bceSAndroid Build Coastguard Worker     if (!deSocketHandleIsValid(sock->handle))
609*35238bceSAndroid Build Coastguard Worker         return false;
610*35238bceSAndroid Build Coastguard Worker 
611*35238bceSAndroid Build Coastguard Worker     /* Connect. */
612*35238bceSAndroid Build Coastguard Worker     if (connect(sock->handle, bsdAddr, bsdAddrLen) != 0)
613*35238bceSAndroid Build Coastguard Worker     {
614*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
615*35238bceSAndroid Build Coastguard Worker         closesocket(sock->handle);
616*35238bceSAndroid Build Coastguard Worker #else
617*35238bceSAndroid Build Coastguard Worker         close(sock->handle);
618*35238bceSAndroid Build Coastguard Worker #endif
619*35238bceSAndroid Build Coastguard Worker         sock->handle = DE_INVALID_SOCKET_HANDLE;
620*35238bceSAndroid Build Coastguard Worker         return false;
621*35238bceSAndroid Build Coastguard Worker     }
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker     sock->state        = DE_SOCKETSTATE_CONNECTED;
624*35238bceSAndroid Build Coastguard Worker     sock->openChannels = DE_SOCKETCHANNEL_BOTH;
625*35238bceSAndroid Build Coastguard Worker 
626*35238bceSAndroid Build Coastguard Worker     return true;
627*35238bceSAndroid Build Coastguard Worker }
628*35238bceSAndroid Build Coastguard Worker 
deSocket_shutdown(deSocket * sock,uint32_t channels)629*35238bceSAndroid Build Coastguard Worker bool deSocket_shutdown(deSocket *sock, uint32_t channels)
630*35238bceSAndroid Build Coastguard Worker {
631*35238bceSAndroid Build Coastguard Worker     uint32_t closedChannels = 0;
632*35238bceSAndroid Build Coastguard Worker 
633*35238bceSAndroid Build Coastguard Worker     deMutex_lock(sock->stateLock);
634*35238bceSAndroid Build Coastguard Worker 
635*35238bceSAndroid Build Coastguard Worker     if (sock->state == DE_SOCKETSTATE_DISCONNECTED || sock->state == DE_SOCKETSTATE_CLOSED)
636*35238bceSAndroid Build Coastguard Worker     {
637*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(sock->stateLock);
638*35238bceSAndroid Build Coastguard Worker         return false;
639*35238bceSAndroid Build Coastguard Worker     }
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(channels != 0 && (channels & ~(uint32_t)DE_SOCKETCHANNEL_BOTH) == 0);
642*35238bceSAndroid Build Coastguard Worker 
643*35238bceSAndroid Build Coastguard Worker     /* Don't attempt to close already closed channels on partially open socket. */
644*35238bceSAndroid Build Coastguard Worker     channels &= sock->openChannels;
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker     if (channels == 0)
647*35238bceSAndroid Build Coastguard Worker     {
648*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(sock->stateLock);
649*35238bceSAndroid Build Coastguard Worker         return false;
650*35238bceSAndroid Build Coastguard Worker     }
651*35238bceSAndroid Build Coastguard Worker 
652*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
653*35238bceSAndroid Build Coastguard Worker     {
654*35238bceSAndroid Build Coastguard Worker         int how = 0;
655*35238bceSAndroid Build Coastguard Worker 
656*35238bceSAndroid Build Coastguard Worker         if ((channels & DE_SOCKETCHANNEL_BOTH) == DE_SOCKETCHANNEL_BOTH)
657*35238bceSAndroid Build Coastguard Worker             how = SD_BOTH;
658*35238bceSAndroid Build Coastguard Worker         else if (channels & DE_SOCKETCHANNEL_SEND)
659*35238bceSAndroid Build Coastguard Worker             how = SD_SEND;
660*35238bceSAndroid Build Coastguard Worker         else if (channels & DE_SOCKETCHANNEL_RECEIVE)
661*35238bceSAndroid Build Coastguard Worker             how = SD_RECEIVE;
662*35238bceSAndroid Build Coastguard Worker 
663*35238bceSAndroid Build Coastguard Worker         if (shutdown(sock->handle, how) == 0)
664*35238bceSAndroid Build Coastguard Worker             closedChannels = channels;
665*35238bceSAndroid Build Coastguard Worker         else
666*35238bceSAndroid Build Coastguard Worker         {
667*35238bceSAndroid Build Coastguard Worker             int err = WSAGetLastError();
668*35238bceSAndroid Build Coastguard Worker 
669*35238bceSAndroid Build Coastguard Worker             /* \note Due to asynchronous behavior certain errors are perfectly ok. */
670*35238bceSAndroid Build Coastguard Worker             if (err == WSAECONNABORTED || err == WSAECONNRESET || err == WSAENOTCONN)
671*35238bceSAndroid Build Coastguard Worker                 closedChannels = DE_SOCKETCHANNEL_BOTH;
672*35238bceSAndroid Build Coastguard Worker             else
673*35238bceSAndroid Build Coastguard Worker             {
674*35238bceSAndroid Build Coastguard Worker                 deMutex_unlock(sock->stateLock);
675*35238bceSAndroid Build Coastguard Worker                 return false;
676*35238bceSAndroid Build Coastguard Worker             }
677*35238bceSAndroid Build Coastguard Worker         }
678*35238bceSAndroid Build Coastguard Worker     }
679*35238bceSAndroid Build Coastguard Worker #else
680*35238bceSAndroid Build Coastguard Worker     {
681*35238bceSAndroid Build Coastguard Worker         int how = 0;
682*35238bceSAndroid Build Coastguard Worker 
683*35238bceSAndroid Build Coastguard Worker         if ((channels & DE_SOCKETCHANNEL_BOTH) == DE_SOCKETCHANNEL_BOTH)
684*35238bceSAndroid Build Coastguard Worker             how = SHUT_RDWR;
685*35238bceSAndroid Build Coastguard Worker         else if (channels & DE_SOCKETCHANNEL_SEND)
686*35238bceSAndroid Build Coastguard Worker             how = SHUT_WR;
687*35238bceSAndroid Build Coastguard Worker         else if (channels & DE_SOCKETCHANNEL_RECEIVE)
688*35238bceSAndroid Build Coastguard Worker             how = SHUT_RD;
689*35238bceSAndroid Build Coastguard Worker 
690*35238bceSAndroid Build Coastguard Worker         if (shutdown(sock->handle, how) == 0)
691*35238bceSAndroid Build Coastguard Worker             closedChannels = channels;
692*35238bceSAndroid Build Coastguard Worker         else
693*35238bceSAndroid Build Coastguard Worker         {
694*35238bceSAndroid Build Coastguard Worker             if (errno == ENOTCONN)
695*35238bceSAndroid Build Coastguard Worker                 closedChannels = DE_SOCKETCHANNEL_BOTH;
696*35238bceSAndroid Build Coastguard Worker             else
697*35238bceSAndroid Build Coastguard Worker             {
698*35238bceSAndroid Build Coastguard Worker                 deMutex_unlock(sock->stateLock);
699*35238bceSAndroid Build Coastguard Worker                 return false;
700*35238bceSAndroid Build Coastguard Worker             }
701*35238bceSAndroid Build Coastguard Worker         }
702*35238bceSAndroid Build Coastguard Worker     }
703*35238bceSAndroid Build Coastguard Worker #endif
704*35238bceSAndroid Build Coastguard Worker 
705*35238bceSAndroid Build Coastguard Worker     sock->openChannels &= ~closedChannels;
706*35238bceSAndroid Build Coastguard Worker     if (sock->openChannels == 0)
707*35238bceSAndroid Build Coastguard Worker         sock->state = DE_SOCKETSTATE_DISCONNECTED;
708*35238bceSAndroid Build Coastguard Worker 
709*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(sock->stateLock);
710*35238bceSAndroid Build Coastguard Worker     return true;
711*35238bceSAndroid Build Coastguard Worker }
712*35238bceSAndroid Build Coastguard Worker 
deSocket_close(deSocket * sock)713*35238bceSAndroid Build Coastguard Worker bool deSocket_close(deSocket *sock)
714*35238bceSAndroid Build Coastguard Worker {
715*35238bceSAndroid Build Coastguard Worker     deMutex_lock(sock->stateLock);
716*35238bceSAndroid Build Coastguard Worker 
717*35238bceSAndroid Build Coastguard Worker     if (sock->state == DE_SOCKETSTATE_CLOSED)
718*35238bceSAndroid Build Coastguard Worker     {
719*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(sock->stateLock);
720*35238bceSAndroid Build Coastguard Worker         return false;
721*35238bceSAndroid Build Coastguard Worker     }
722*35238bceSAndroid Build Coastguard Worker 
723*35238bceSAndroid Build Coastguard Worker #if !defined(DE_USE_WINSOCK)
724*35238bceSAndroid Build Coastguard Worker     if (sock->state == DE_SOCKETSTATE_LISTENING)
725*35238bceSAndroid Build Coastguard Worker     {
726*35238bceSAndroid Build Coastguard Worker         /* There can be a thread blockin in accept(). Release it by calling shutdown. */
727*35238bceSAndroid Build Coastguard Worker         shutdown(sock->handle, SHUT_RDWR);
728*35238bceSAndroid Build Coastguard Worker     }
729*35238bceSAndroid Build Coastguard Worker #endif
730*35238bceSAndroid Build Coastguard Worker 
731*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
732*35238bceSAndroid Build Coastguard Worker     if (closesocket(sock->handle) != 0)
733*35238bceSAndroid Build Coastguard Worker         return false;
734*35238bceSAndroid Build Coastguard Worker #else
735*35238bceSAndroid Build Coastguard Worker     if (close(sock->handle) != 0)
736*35238bceSAndroid Build Coastguard Worker         return false;
737*35238bceSAndroid Build Coastguard Worker #endif
738*35238bceSAndroid Build Coastguard Worker     sock->state        = DE_SOCKETSTATE_CLOSED;
739*35238bceSAndroid Build Coastguard Worker     sock->handle       = DE_INVALID_SOCKET_HANDLE;
740*35238bceSAndroid Build Coastguard Worker     sock->openChannels = 0;
741*35238bceSAndroid Build Coastguard Worker 
742*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(sock->stateLock);
743*35238bceSAndroid Build Coastguard Worker     return true;
744*35238bceSAndroid Build Coastguard Worker }
745*35238bceSAndroid Build Coastguard Worker 
mapSendRecvResult(int numBytes)746*35238bceSAndroid Build Coastguard Worker static deSocketResult mapSendRecvResult(int numBytes)
747*35238bceSAndroid Build Coastguard Worker {
748*35238bceSAndroid Build Coastguard Worker     if (numBytes > 0)
749*35238bceSAndroid Build Coastguard Worker         return DE_SOCKETRESULT_SUCCESS;
750*35238bceSAndroid Build Coastguard Worker     else if (numBytes == 0)
751*35238bceSAndroid Build Coastguard Worker         return DE_SOCKETRESULT_CONNECTION_CLOSED;
752*35238bceSAndroid Build Coastguard Worker     else
753*35238bceSAndroid Build Coastguard Worker     {
754*35238bceSAndroid Build Coastguard Worker         /* Other errors. */
755*35238bceSAndroid Build Coastguard Worker #if defined(DE_USE_WINSOCK)
756*35238bceSAndroid Build Coastguard Worker         int error = WSAGetLastError();
757*35238bceSAndroid Build Coastguard Worker         switch (error)
758*35238bceSAndroid Build Coastguard Worker         {
759*35238bceSAndroid Build Coastguard Worker         case WSAEWOULDBLOCK:
760*35238bceSAndroid Build Coastguard Worker             return DE_SOCKETRESULT_WOULD_BLOCK;
761*35238bceSAndroid Build Coastguard Worker         case WSAENETDOWN:
762*35238bceSAndroid Build Coastguard Worker         case WSAENETRESET:
763*35238bceSAndroid Build Coastguard Worker         case WSAECONNABORTED:
764*35238bceSAndroid Build Coastguard Worker         case WSAECONNRESET:
765*35238bceSAndroid Build Coastguard Worker             return DE_SOCKETRESULT_CONNECTION_TERMINATED;
766*35238bceSAndroid Build Coastguard Worker         default:
767*35238bceSAndroid Build Coastguard Worker             return DE_SOCKETRESULT_ERROR;
768*35238bceSAndroid Build Coastguard Worker         }
769*35238bceSAndroid Build Coastguard Worker #else
770*35238bceSAndroid Build Coastguard Worker         switch (errno)
771*35238bceSAndroid Build Coastguard Worker         {
772*35238bceSAndroid Build Coastguard Worker         case EAGAIN:
773*35238bceSAndroid Build Coastguard Worker             return DE_SOCKETRESULT_WOULD_BLOCK;
774*35238bceSAndroid Build Coastguard Worker         case ECONNABORTED:
775*35238bceSAndroid Build Coastguard Worker         case ECONNRESET:
776*35238bceSAndroid Build Coastguard Worker             return DE_SOCKETRESULT_CONNECTION_TERMINATED;
777*35238bceSAndroid Build Coastguard Worker         default:
778*35238bceSAndroid Build Coastguard Worker             return DE_SOCKETRESULT_ERROR;
779*35238bceSAndroid Build Coastguard Worker         }
780*35238bceSAndroid Build Coastguard Worker #endif
781*35238bceSAndroid Build Coastguard Worker     }
782*35238bceSAndroid Build Coastguard Worker }
783*35238bceSAndroid Build Coastguard Worker 
deSocket_setChannelsClosed(deSocket * sock,uint32_t channels)784*35238bceSAndroid Build Coastguard Worker DE_INLINE void deSocket_setChannelsClosed(deSocket *sock, uint32_t channels)
785*35238bceSAndroid Build Coastguard Worker {
786*35238bceSAndroid Build Coastguard Worker     deMutex_lock(sock->stateLock);
787*35238bceSAndroid Build Coastguard Worker 
788*35238bceSAndroid Build Coastguard Worker     sock->openChannels &= ~channels;
789*35238bceSAndroid Build Coastguard Worker     if (sock->openChannels == 0)
790*35238bceSAndroid Build Coastguard Worker         sock->state = DE_SOCKETSTATE_DISCONNECTED;
791*35238bceSAndroid Build Coastguard Worker 
792*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(sock->stateLock);
793*35238bceSAndroid Build Coastguard Worker }
794*35238bceSAndroid Build Coastguard Worker 
deSocket_send(deSocket * sock,const void * buf,size_t bufSize,size_t * numSentPtr)795*35238bceSAndroid Build Coastguard Worker deSocketResult deSocket_send(deSocket *sock, const void *buf, size_t bufSize, size_t *numSentPtr)
796*35238bceSAndroid Build Coastguard Worker {
797*35238bceSAndroid Build Coastguard Worker     int numSent           = (int)send(sock->handle, (const char *)buf, (NativeSize)bufSize, 0);
798*35238bceSAndroid Build Coastguard Worker     deSocketResult result = mapSendRecvResult(numSent);
799*35238bceSAndroid Build Coastguard Worker 
800*35238bceSAndroid Build Coastguard Worker     if (numSentPtr)
801*35238bceSAndroid Build Coastguard Worker         *numSentPtr = (numSent > 0) ? ((size_t)numSent) : (0);
802*35238bceSAndroid Build Coastguard Worker 
803*35238bceSAndroid Build Coastguard Worker     /* Update state. */
804*35238bceSAndroid Build Coastguard Worker     if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
805*35238bceSAndroid Build Coastguard Worker         deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_SEND);
806*35238bceSAndroid Build Coastguard Worker     else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
807*35238bceSAndroid Build Coastguard Worker         deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_BOTH);
808*35238bceSAndroid Build Coastguard Worker 
809*35238bceSAndroid Build Coastguard Worker     return result;
810*35238bceSAndroid Build Coastguard Worker }
811*35238bceSAndroid Build Coastguard Worker 
deSocket_receive(deSocket * sock,void * buf,size_t bufSize,size_t * numReceivedPtr)812*35238bceSAndroid Build Coastguard Worker deSocketResult deSocket_receive(deSocket *sock, void *buf, size_t bufSize, size_t *numReceivedPtr)
813*35238bceSAndroid Build Coastguard Worker {
814*35238bceSAndroid Build Coastguard Worker     int numRecv           = (int)recv(sock->handle, (char *)buf, (NativeSize)bufSize, 0);
815*35238bceSAndroid Build Coastguard Worker     deSocketResult result = mapSendRecvResult(numRecv);
816*35238bceSAndroid Build Coastguard Worker 
817*35238bceSAndroid Build Coastguard Worker     if (numReceivedPtr)
818*35238bceSAndroid Build Coastguard Worker         *numReceivedPtr = (numRecv > 0) ? ((size_t)numRecv) : (0);
819*35238bceSAndroid Build Coastguard Worker 
820*35238bceSAndroid Build Coastguard Worker     /* Update state. */
821*35238bceSAndroid Build Coastguard Worker     if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
822*35238bceSAndroid Build Coastguard Worker         deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_RECEIVE);
823*35238bceSAndroid Build Coastguard Worker     else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
824*35238bceSAndroid Build Coastguard Worker         deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_BOTH);
825*35238bceSAndroid Build Coastguard Worker 
826*35238bceSAndroid Build Coastguard Worker     return result;
827*35238bceSAndroid Build Coastguard Worker }
828*35238bceSAndroid Build Coastguard Worker 
829*35238bceSAndroid Build Coastguard Worker #endif
830