VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/socket.cpp@ 43618

Last change on this file since 43618 was 43363, checked in by vboxsync, 12 years ago

Haiku Additions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 58.1 KB
Line 
1/* $Id: socket.cpp 43363 2012-09-20 09:56:07Z vboxsync $ */
2/** @file
3 * IPRT - Network Sockets.
4 */
5
6/*
7 * Copyright (C) 2006-2012 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#ifdef RT_OS_WINDOWS
32# include <winsock2.h>
33# include <ws2tcpip.h>
34#else /* !RT_OS_WINDOWS */
35# include <errno.h>
36# include <sys/select.h>
37# include <sys/stat.h>
38# include <sys/socket.h>
39# include <netinet/in.h>
40# include <netinet/tcp.h>
41# include <arpa/inet.h>
42# ifdef IPRT_WITH_TCPIP_V6
43# include <netinet6/in6.h>
44# endif
45# include <sys/un.h>
46# include <netdb.h>
47# include <unistd.h>
48# include <fcntl.h>
49# include <sys/uio.h>
50#endif /* !RT_OS_WINDOWS */
51#include <limits.h>
52
53#include "internal/iprt.h"
54#include <iprt/socket.h>
55
56#include <iprt/alloca.h>
57#include <iprt/asm.h>
58#include <iprt/assert.h>
59#include <iprt/ctype.h>
60#include <iprt/err.h>
61#include <iprt/mempool.h>
62#include <iprt/poll.h>
63#include <iprt/string.h>
64#include <iprt/thread.h>
65#include <iprt/time.h>
66#include <iprt/mem.h>
67#include <iprt/sg.h>
68#include <iprt/log.h>
69
70#include "internal/magics.h"
71#include "internal/socket.h"
72#include "internal/string.h"
73
74
75/*******************************************************************************
76* Defined Constants And Macros *
77*******************************************************************************/
78/* non-standard linux stuff (it seems). */
79#ifndef MSG_NOSIGNAL
80# define MSG_NOSIGNAL 0
81#endif
82
83/* Windows has different names for SHUT_XXX. */
84#ifndef SHUT_RDWR
85# ifdef SD_BOTH
86# define SHUT_RDWR SD_BOTH
87# else
88# define SHUT_RDWR 2
89# endif
90#endif
91#ifndef SHUT_WR
92# ifdef SD_SEND
93# define SHUT_WR SD_SEND
94# else
95# define SHUT_WR 1
96# endif
97#endif
98#ifndef SHUT_RD
99# ifdef SD_RECEIVE
100# define SHUT_RD SD_RECEIVE
101# else
102# define SHUT_RD 0
103# endif
104#endif
105
106/* fixup backlevel OSes. */
107#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
108# define socklen_t int
109#endif
110
111/** How many pending connection. */
112#define RTTCP_SERVER_BACKLOG 10
113
114
115/*******************************************************************************
116* Structures and Typedefs *
117*******************************************************************************/
118/**
119 * Socket handle data.
120 *
121 * This is mainly required for implementing RTPollSet on Windows.
122 */
123typedef struct RTSOCKETINT
124{
125 /** Magic number (RTSOCKET_MAGIC). */
126 uint32_t u32Magic;
127 /** Exclusive user count.
128 * This is used to prevent two threads from accessing the handle concurrently.
129 * It can be higher than 1 if this handle is reference multiple times in a
130 * polling set (Windows). */
131 uint32_t volatile cUsers;
132 /** The native socket handle. */
133 RTSOCKETNATIVE hNative;
134 /** Indicates whether the handle has been closed or not. */
135 bool volatile fClosed;
136 /** Indicates whether the socket is operating in blocking or non-blocking mode
137 * currently. */
138 bool fBlocking;
139#ifdef RT_OS_WINDOWS
140 /** The event semaphore we've associated with the socket handle.
141 * This is WSA_INVALID_EVENT if not done. */
142 WSAEVENT hEvent;
143 /** The pollset currently polling this socket. This is NIL if no one is
144 * polling. */
145 RTPOLLSET hPollSet;
146 /** The events we're polling for. */
147 uint32_t fPollEvts;
148 /** The events we're currently subscribing to with WSAEventSelect.
149 * This is ZERO if we're currently not subscribing to anything. */
150 uint32_t fSubscribedEvts;
151 /** Saved events which are only posted once. */
152 uint32_t fEventsSaved;
153#endif /* RT_OS_WINDOWS */
154} RTSOCKETINT;
155
156
157/**
158 * Address union used internally for things like getpeername and getsockname.
159 */
160typedef union RTSOCKADDRUNION
161{
162 struct sockaddr Addr;
163 struct sockaddr_in IPv4;
164#ifdef IPRT_WITH_TCPIP_V6
165 struct sockaddr_in6 IPv6;
166#endif
167} RTSOCKADDRUNION;
168
169
170/**
171 * Get the last error as an iprt status code.
172 *
173 * @returns IPRT status code.
174 */
175DECLINLINE(int) rtSocketError(void)
176{
177#ifdef RT_OS_WINDOWS
178 return RTErrConvertFromWin32(WSAGetLastError());
179#else
180 return RTErrConvertFromErrno(errno);
181#endif
182}
183
184
185/**
186 * Resets the last error.
187 */
188DECLINLINE(void) rtSocketErrorReset(void)
189{
190#ifdef RT_OS_WINDOWS
191 WSASetLastError(0);
192#else
193 errno = 0;
194#endif
195}
196
197
198/**
199 * Get the last resolver error as an iprt status code.
200 *
201 * @returns iprt status code.
202 */
203int rtSocketResolverError(void)
204{
205#ifdef RT_OS_WINDOWS
206 return RTErrConvertFromWin32(WSAGetLastError());
207#else
208 switch (h_errno)
209 {
210 case HOST_NOT_FOUND:
211 return VERR_NET_HOST_NOT_FOUND;
212 case NO_DATA:
213 return VERR_NET_ADDRESS_NOT_AVAILABLE;
214 case NO_RECOVERY:
215 return VERR_IO_GEN_FAILURE;
216 case TRY_AGAIN:
217 return VERR_TRY_AGAIN;
218
219 default:
220 return VERR_UNRESOLVED_ERROR;
221 }
222#endif
223}
224
225
226/**
227 * Converts from a native socket address to a generic IPRT network address.
228 *
229 * @returns IPRT status code.
230 * @param pSrc The source address.
231 * @param cbSrc The size of the source address.
232 * @param pAddr Where to return the generic IPRT network
233 * address.
234 */
235static int rtSocketNetAddrFromAddr(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr)
236{
237 /*
238 * Convert the address.
239 */
240 if ( cbSrc == sizeof(struct sockaddr_in)
241 && pSrc->Addr.sa_family == AF_INET)
242 {
243 RT_ZERO(*pAddr);
244 pAddr->enmType = RTNETADDRTYPE_IPV4;
245 pAddr->uPort = RT_N2H_U16(pSrc->IPv4.sin_port);
246 pAddr->uAddr.IPv4.u = pSrc->IPv4.sin_addr.s_addr;
247 }
248#ifdef IPRT_WITH_TCPIP_V6
249 else if ( cbSrc == sizeof(struct sockaddr_in6)
250 && pSrc->Addr.sa_family == AF_INET6)
251 {
252 RT_ZERO(*pAddr);
253 pAddr->enmType = RTNETADDRTYPE_IPV6;
254 pAddr->uPort = RT_N2H_U16(pSrc->IPv6.sin6_port);
255 pAddr->uAddr.IPv6.au32[0] = pSrc->IPv6.sin6_addr.s6_addr32[0];
256 pAddr->uAddr.IPv6.au32[1] = pSrc->IPv6.sin6_addr.s6_addr32[1];
257 pAddr->uAddr.IPv6.au32[2] = pSrc->IPv6.sin6_addr.s6_addr32[2];
258 pAddr->uAddr.IPv6.au32[3] = pSrc->IPv6.sin6_addr.s6_addr32[3];
259 }
260#endif
261 else
262 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
263 return VINF_SUCCESS;
264}
265
266
267/**
268 * Converts from a generic IPRT network address to a native socket address.
269 *
270 * @returns IPRT status code.
271 * @param pAddr Pointer to the generic IPRT network address.
272 * @param pDst The source address.
273 * @param cbSrc The size of the source address.
274 * @param pcbAddr Where to store the size of the returned address.
275 * Optional
276 */
277static int rtSocketAddrFromNetAddr(PCRTNETADDR pAddr, RTSOCKADDRUNION *pDst, size_t cbDst, int *pcbAddr)
278{
279 RT_BZERO(pDst, cbDst);
280 if ( pAddr->enmType == RTNETADDRTYPE_IPV4
281 && cbDst >= sizeof(struct sockaddr_in))
282 {
283 pDst->Addr.sa_family = AF_INET;
284 pDst->IPv4.sin_port = RT_H2N_U16(pAddr->uPort);
285 pDst->IPv4.sin_addr.s_addr = pAddr->uAddr.IPv4.u;
286 if (pcbAddr)
287 *pcbAddr = sizeof(pDst->IPv4);
288 }
289#ifdef IPRT_WITH_TCPIP_V6
290 else if ( pAddr->enmType == RTNETADDRTYPE_IPV6
291 && cbDst >= sizeof(struct sockaddr_in6))
292 {
293 pDst->Addr.sa_family = AF_INET6;
294 pDst->IPv6.sin6_port = RT_H2N_U16(pAddr->uPort);
295 pSrc->IPv6.sin6_addr.s6_addr32[0] = pAddr->uAddr.IPv6.au32[0];
296 pSrc->IPv6.sin6_addr.s6_addr32[1] = pAddr->uAddr.IPv6.au32[1];
297 pSrc->IPv6.sin6_addr.s6_addr32[2] = pAddr->uAddr.IPv6.au32[2];
298 pSrc->IPv6.sin6_addr.s6_addr32[3] = pAddr->uAddr.IPv6.au32[3];
299 if (pcbAddr)
300 *pcbAddr = sizeof(pDst->IPv6);
301 }
302#endif
303 else
304 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
305 return VINF_SUCCESS;
306}
307
308
309/**
310 * Tries to lock the socket for exclusive usage by the calling thread.
311 *
312 * Call rtSocketUnlock() to unlock.
313 *
314 * @returns @c true if locked, @c false if not.
315 * @param pThis The socket structure.
316 */
317DECLINLINE(bool) rtSocketTryLock(RTSOCKETINT *pThis)
318{
319 return ASMAtomicCmpXchgU32(&pThis->cUsers, 1, 0);
320}
321
322
323/**
324 * Unlocks the socket.
325 *
326 * @param pThis The socket structure.
327 */
328DECLINLINE(void) rtSocketUnlock(RTSOCKETINT *pThis)
329{
330 ASMAtomicCmpXchgU32(&pThis->cUsers, 0, 1);
331}
332
333
334/**
335 * The slow path of rtSocketSwitchBlockingMode that does the actual switching.
336 *
337 * @returns IPRT status code.
338 * @param pThis The socket structure.
339 * @param fBlocking The desired mode of operation.
340 * @remarks Do not call directly.
341 */
342static int rtSocketSwitchBlockingModeSlow(RTSOCKETINT *pThis, bool fBlocking)
343{
344#ifdef RT_OS_WINDOWS
345 u_long uBlocking = fBlocking ? 0 : 1;
346 if (ioctlsocket(pThis->hNative, FIONBIO, &uBlocking))
347 return rtSocketError();
348
349#else
350 int fFlags = fcntl(pThis->hNative, F_GETFL, 0);
351 if (fFlags == -1)
352 return rtSocketError();
353
354 if (fBlocking)
355 fFlags &= ~O_NONBLOCK;
356 else
357 fFlags |= O_NONBLOCK;
358 if (fcntl(pThis->hNative, F_SETFL, fFlags) == -1)
359 return rtSocketError();
360#endif
361
362 pThis->fBlocking = fBlocking;
363 return VINF_SUCCESS;
364}
365
366
367/**
368 * Switches the socket to the desired blocking mode if necessary.
369 *
370 * The socket must be locked.
371 *
372 * @returns IPRT status code.
373 * @param pThis The socket structure.
374 * @param fBlocking The desired mode of operation.
375 */
376DECLINLINE(int) rtSocketSwitchBlockingMode(RTSOCKETINT *pThis, bool fBlocking)
377{
378 if (pThis->fBlocking != fBlocking)
379 return rtSocketSwitchBlockingModeSlow(pThis, fBlocking);
380 return VINF_SUCCESS;
381}
382
383
384/**
385 * Creates an IPRT socket handle for a native one.
386 *
387 * @returns IPRT status code.
388 * @param ppSocket Where to return the IPRT socket handle.
389 * @param hNative The native handle.
390 */
391int rtSocketCreateForNative(RTSOCKETINT **ppSocket, RTSOCKETNATIVE hNative)
392{
393 RTSOCKETINT *pThis = (RTSOCKETINT *)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pThis));
394 if (!pThis)
395 return VERR_NO_MEMORY;
396 pThis->u32Magic = RTSOCKET_MAGIC;
397 pThis->cUsers = 0;
398 pThis->hNative = hNative;
399 pThis->fClosed = false;
400 pThis->fBlocking = true;
401#ifdef RT_OS_WINDOWS
402 pThis->hEvent = WSA_INVALID_EVENT;
403 pThis->hPollSet = NIL_RTPOLLSET;
404 pThis->fPollEvts = 0;
405 pThis->fSubscribedEvts = 0;
406#endif
407 *ppSocket = pThis;
408 return VINF_SUCCESS;
409}
410
411
412RTDECL(int) RTSocketFromNative(PRTSOCKET phSocket, RTHCINTPTR uNative)
413{
414 AssertReturn(uNative != NIL_RTSOCKETNATIVE, VERR_INVALID_PARAMETER);
415#ifndef RT_OS_WINDOWS
416 AssertReturn(uNative >= 0, VERR_INVALID_PARAMETER);
417#endif
418 AssertPtrReturn(phSocket, VERR_INVALID_POINTER);
419 return rtSocketCreateForNative(phSocket, uNative);
420}
421
422
423/**
424 * Wrapper around socket().
425 *
426 * @returns IPRT status code.
427 * @param phSocket Where to store the handle to the socket on
428 * success.
429 * @param iDomain The protocol family (PF_XXX).
430 * @param iType The socket type (SOCK_XXX).
431 * @param iProtocol Socket parameter, usually 0.
432 */
433int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
434{
435 /*
436 * Create the socket.
437 */
438 RTSOCKETNATIVE hNative = socket(iDomain, iType, iProtocol);
439 if (hNative == NIL_RTSOCKETNATIVE)
440 return rtSocketError();
441
442 /*
443 * Wrap it.
444 */
445 int rc = rtSocketCreateForNative(phSocket, hNative);
446 if (RT_FAILURE(rc))
447 {
448#ifdef RT_OS_WINDOWS
449 closesocket(hNative);
450#else
451 close(hNative);
452#endif
453 }
454 return rc;
455}
456
457
458RTDECL(uint32_t) RTSocketRetain(RTSOCKET hSocket)
459{
460 RTSOCKETINT *pThis = hSocket;
461 AssertPtrReturn(pThis, UINT32_MAX);
462 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
463 return RTMemPoolRetain(pThis);
464}
465
466
467/**
468 * Worker for RTSocketRelease and RTSocketClose.
469 *
470 * @returns IPRT status code.
471 * @param pThis The socket handle instance data.
472 * @param fDestroy Whether we're reaching ref count zero.
473 */
474static int rtSocketCloseIt(RTSOCKETINT *pThis, bool fDestroy)
475{
476 /*
477 * Invalidate the handle structure on destroy.
478 */
479 if (fDestroy)
480 {
481 Assert(ASMAtomicReadU32(&pThis->u32Magic) == RTSOCKET_MAGIC);
482 ASMAtomicWriteU32(&pThis->u32Magic, RTSOCKET_MAGIC_DEAD);
483 }
484
485 int rc = VINF_SUCCESS;
486 if (ASMAtomicCmpXchgBool(&pThis->fClosed, true, false))
487 {
488 /*
489 * Close the native handle.
490 */
491 RTSOCKETNATIVE hNative = pThis->hNative;
492 if (hNative != NIL_RTSOCKETNATIVE)
493 {
494 pThis->hNative = NIL_RTSOCKETNATIVE;
495
496#ifdef RT_OS_WINDOWS
497 if (closesocket(hNative))
498#else
499 if (close(hNative))
500#endif
501 {
502 rc = rtSocketError();
503#ifdef RT_OS_WINDOWS
504 AssertMsgFailed(("\"%s\": closesocket(%p) -> %Rrc\n", (uintptr_t)hNative, rc));
505#else
506 AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", hNative, rc));
507#endif
508 }
509 }
510
511#ifdef RT_OS_WINDOWS
512 /*
513 * Close the event.
514 */
515 WSAEVENT hEvent = pThis->hEvent;
516 if (hEvent == WSA_INVALID_EVENT)
517 {
518 pThis->hEvent = WSA_INVALID_EVENT;
519 WSACloseEvent(hEvent);
520 }
521#endif
522 }
523
524 return rc;
525}
526
527
528RTDECL(uint32_t) RTSocketRelease(RTSOCKET hSocket)
529{
530 RTSOCKETINT *pThis = hSocket;
531 if (pThis == NIL_RTSOCKET)
532 return 0;
533 AssertPtrReturn(pThis, UINT32_MAX);
534 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
535
536 /* get the refcount without killing it... */
537 uint32_t cRefs = RTMemPoolRefCount(pThis);
538 AssertReturn(cRefs != UINT32_MAX, UINT32_MAX);
539 if (cRefs == 1)
540 rtSocketCloseIt(pThis, true);
541
542 return RTMemPoolRelease(RTMEMPOOL_DEFAULT, pThis);
543}
544
545
546RTDECL(int) RTSocketClose(RTSOCKET hSocket)
547{
548 RTSOCKETINT *pThis = hSocket;
549 if (pThis == NIL_RTSOCKET)
550 return VINF_SUCCESS;
551 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
552 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
553
554 uint32_t cRefs = RTMemPoolRefCount(pThis);
555 AssertReturn(cRefs != UINT32_MAX, UINT32_MAX);
556
557 int rc = rtSocketCloseIt(pThis, cRefs == 1);
558
559 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pThis);
560 return rc;
561}
562
563
564RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket)
565{
566 RTSOCKETINT *pThis = hSocket;
567 AssertPtrReturn(pThis, RTHCUINTPTR_MAX);
568 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, RTHCUINTPTR_MAX);
569 return (RTHCUINTPTR)pThis->hNative;
570}
571
572
573RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
574{
575 RTSOCKETINT *pThis = hSocket;
576 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
577 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
578 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
579
580 int rc = VINF_SUCCESS;
581#ifdef RT_OS_WINDOWS
582 if (!SetHandleInformation((HANDLE)pThis->hNative, HANDLE_FLAG_INHERIT, fInheritable ? HANDLE_FLAG_INHERIT : 0))
583 rc = RTErrConvertFromWin32(GetLastError());
584#else
585 if (fcntl(pThis->hNative, F_SETFD, fInheritable ? 0 : FD_CLOEXEC) < 0)
586 rc = RTErrConvertFromErrno(errno);
587#endif
588
589 return rc;
590}
591
592
593static bool rtSocketIsIPv4Numerical(const char *pszAddress, PRTNETADDRIPV4 pAddr)
594{
595
596 /* Empty address resolves to the INADDR_ANY address (good for bind). */
597 if (!pszAddress || !*pszAddress)
598 {
599 pAddr->u = INADDR_ANY;
600 return true;
601 }
602
603 /* Four quads? */
604 char *psz = (char *)pszAddress;
605 for (int i = 0; i < 4; i++)
606 {
607 uint8_t u8;
608 int rc = RTStrToUInt8Ex(psz, &psz, 0, &u8);
609 if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS)
610 return false;
611 if (*psz != (i < 3 ? '.' : '\0'))
612 return false;
613 psz++;
614
615 pAddr->au8[i] = u8; /* big endian */
616 }
617
618 return true;
619}
620
621RTDECL(int) RTSocketParseInetAddress(const char *pszAddress, unsigned uPort, PRTNETADDR pAddr)
622{
623 int rc;
624
625 /*
626 * Validate input.
627 */
628 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
629 AssertPtrNullReturn(pszAddress, VERR_INVALID_POINTER);
630
631#ifdef RT_OS_WINDOWS
632 /*
633 * Initialize WinSock and check version.
634 */
635 WORD wVersionRequested = MAKEWORD(1, 1);
636 WSADATA wsaData;
637 rc = WSAStartup(wVersionRequested, &wsaData);
638 if (wsaData.wVersion != wVersionRequested)
639 {
640 AssertMsgFailed(("Wrong winsock version\n"));
641 return VERR_NOT_SUPPORTED;
642 }
643#endif
644
645 /*
646 * Resolve the address. Pretty crude at the moment, but we have to make
647 * sure to not ask the NT 4 gethostbyname about an IPv4 address as it may
648 * give a wrong answer.
649 */
650 /** @todo this only supports IPv4, and IPv6 support needs to be added.
651 * It probably needs to be converted to getaddrinfo(). */
652 RTNETADDRIPV4 IPv4Quad;
653 if (rtSocketIsIPv4Numerical(pszAddress, &IPv4Quad))
654 {
655 Log3(("rtSocketIsIPv4Numerical: %#x (%RTnaipv4)\n", pszAddress, IPv4Quad.u, IPv4Quad));
656 RT_ZERO(*pAddr);
657 pAddr->enmType = RTNETADDRTYPE_IPV4;
658 pAddr->uPort = uPort;
659 pAddr->uAddr.IPv4 = IPv4Quad;
660 return VINF_SUCCESS;
661 }
662
663 struct hostent *pHostEnt;
664 pHostEnt = gethostbyname(pszAddress);
665 if (!pHostEnt)
666 {
667 rc = rtSocketResolverError();
668 AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
669 return rc;
670 }
671
672 if (pHostEnt->h_addrtype == AF_INET)
673 {
674 RT_ZERO(*pAddr);
675 pAddr->enmType = RTNETADDRTYPE_IPV4;
676 pAddr->uPort = uPort;
677 pAddr->uAddr.IPv4.u = ((struct in_addr *)pHostEnt->h_addr)->s_addr;
678 Log3(("gethostbyname: %s -> %#x (%RTnaipv4)\n", pszAddress, pAddr->uAddr.IPv4.u, pAddr->uAddr.IPv4));
679 }
680 else
681 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
682
683 return VINF_SUCCESS;
684}
685
686
687/*
688 * New function to allow both ipv4 and ipv6 addresses to be resolved.
689 * Breaks compatibility with windows before 2000.
690 */
691RTDECL(int) RTSocketQueryAddressStr(const char *pszHost, char *pszResult, size_t *pcbResult, PRTNETADDRTYPE penmAddrType)
692{
693 AssertPtrReturn(pszHost, VERR_INVALID_POINTER);
694 AssertPtrReturn(pcbResult, VERR_INVALID_POINTER);
695 AssertPtrNullReturn(penmAddrType, VERR_INVALID_POINTER);
696 AssertPtrNullReturn(pszResult, VERR_INVALID_POINTER);
697
698#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) /** @todo dynamically resolve the APIs not present in NT4! */
699 return VERR_NOT_SUPPORTED;
700
701#else
702 int rc;
703 if (*pcbResult < 16)
704 return VERR_NET_ADDRESS_NOT_AVAILABLE;
705
706 /* Setup the hint. */
707 struct addrinfo grHints;
708 RT_ZERO(grHints);
709 grHints.ai_socktype = 0;
710 grHints.ai_flags = 0;
711 grHints.ai_protocol = 0;
712 grHints.ai_family = AF_UNSPEC;
713 if (penmAddrType)
714 {
715 switch (*penmAddrType)
716 {
717 case RTNETADDRTYPE_INVALID:
718 /*grHints.ai_family = AF_UNSPEC;*/
719 break;
720 case RTNETADDRTYPE_IPV4:
721 grHints.ai_family = AF_INET;
722 break;
723 case RTNETADDRTYPE_IPV6:
724 grHints.ai_family = AF_INET6;
725 break;
726 default:
727 AssertFailedReturn(VERR_INVALID_PARAMETER);
728 }
729 }
730
731# ifdef RT_OS_WINDOWS
732 /*
733 * Winsock2 init
734 */
735 /** @todo someone should check if we really need 2, 2 here */
736 WORD wVersionRequested = MAKEWORD(2, 2);
737 WSADATA wsaData;
738 rc = WSAStartup(wVersionRequested, &wsaData);
739 if (wsaData.wVersion != wVersionRequested)
740 {
741 AssertMsgFailed(("Wrong winsock version\n"));
742 return VERR_NOT_SUPPORTED;
743 }
744# endif
745
746 /** @todo r=bird: getaddrinfo and freeaddrinfo breaks the additions on NT4. */
747 struct addrinfo *pgrResults = NULL;
748 rc = getaddrinfo(pszHost, "", &grHints, &pgrResults);
749 if (rc != 0)
750 return VERR_NET_ADDRESS_NOT_AVAILABLE;
751
752 // return data
753 // on multiple matches return only the first one
754
755 if (!pgrResults)
756 return VERR_NET_ADDRESS_NOT_AVAILABLE;
757
758 struct addrinfo const *pgrResult = pgrResults->ai_next;
759 if (!pgrResult)
760 {
761 freeaddrinfo(pgrResults);
762 return VERR_NET_ADDRESS_NOT_AVAILABLE;
763 }
764
765 uint8_t const *pbDummy;
766 RTNETADDRTYPE enmAddrType = RTNETADDRTYPE_INVALID;
767 size_t cchIpAddress;
768 char szIpAddress[48];
769 if (pgrResult->ai_family == AF_INET)
770 {
771 struct sockaddr_in const *pgrSa = (struct sockaddr_in const *)pgrResult->ai_addr;
772 pbDummy = (uint8_t const *)&pgrSa->sin_addr;
773 cchIpAddress = RTStrPrintf(szIpAddress, sizeof(szIpAddress), "%u.%u.%u.%u",
774 pbDummy[0], pbDummy[1], pbDummy[2], pbDummy[3]);
775 Assert(cchIpAddress >= 7 && cchIpAddress < sizeof(szIpAddress) - 1);
776 enmAddrType = RTNETADDRTYPE_IPV4;
777 rc = VINF_SUCCESS;
778 }
779 else if (pgrResult->ai_family == AF_INET6)
780 {
781 struct sockaddr_in6 const *pgrSa6 = (struct sockaddr_in6 const *)pgrResult->ai_addr;
782 pbDummy = (uint8_t const *) &pgrSa6->sin6_addr;
783 char szTmp[32+1];
784 size_t cchTmp = RTStrPrintf(szTmp, sizeof(szTmp),
785 "%02x%02x%02x%02x"
786 "%02x%02x%02x%02x"
787 "%02x%02x%02x%02x"
788 "%02x%02x%02x%02x",
789 pbDummy[0], pbDummy[1], pbDummy[2], pbDummy[3],
790 pbDummy[4], pbDummy[5], pbDummy[6], pbDummy[7],
791 pbDummy[8], pbDummy[9], pbDummy[10], pbDummy[11],
792 pbDummy[12], pbDummy[13], pbDummy[14], pbDummy[15]);
793 Assert(cchTmp == 32);
794 rc = rtStrToIpAddr6Str(szTmp, szIpAddress, sizeof(szIpAddress), NULL, 0, true);
795 if (RT_SUCCESS(rc))
796 cchIpAddress = strlen(szIpAddress);
797 else
798 {
799 szIpAddress[0] = '\0';
800 cchIpAddress = 0;
801 }
802 enmAddrType = RTNETADDRTYPE_IPV6;
803 }
804 else
805 {
806 rc = VERR_NET_ADDRESS_NOT_AVAILABLE;
807 szIpAddress[0] = '\0';
808 cchIpAddress = 0;
809 }
810 freeaddrinfo(pgrResults);
811
812 /*
813 * Copy out the result.
814 */
815 size_t const cbResult = *pcbResult;
816 *pcbResult = cchIpAddress + 1;
817 if (cchIpAddress < cbResult)
818 memcpy(pszResult, szIpAddress, cchIpAddress + 1);
819 else
820 {
821 RT_BZERO(pszResult, cbResult);
822 if (RT_SUCCESS(rc))
823 rc = VERR_BUFFER_OVERFLOW;
824 }
825 if (penmAddrType && RT_SUCCESS(rc))
826 *penmAddrType = enmAddrType;
827 return rc;
828#endif /* !RT_OS_OS2 */
829}
830
831
832RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
833{
834 /*
835 * Validate input.
836 */
837 RTSOCKETINT *pThis = hSocket;
838 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
839 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
840 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
841 AssertPtr(pvBuffer);
842 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
843
844 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
845 if (RT_FAILURE(rc))
846 return rc;
847
848 /*
849 * Read loop.
850 * If pcbRead is NULL we have to fill the entire buffer!
851 */
852 size_t cbRead = 0;
853 size_t cbToRead = cbBuffer;
854 for (;;)
855 {
856 rtSocketErrorReset();
857#ifdef RT_OS_WINDOWS
858 int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
859#else
860 size_t cbNow = cbToRead;
861#endif
862 ssize_t cbBytesRead = recv(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
863 if (cbBytesRead <= 0)
864 {
865 rc = rtSocketError();
866 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
867 if (RT_SUCCESS_NP(rc))
868 {
869 if (!pcbRead)
870 rc = VERR_NET_SHUTDOWN;
871 else
872 {
873 *pcbRead = 0;
874 rc = VINF_SUCCESS;
875 }
876 }
877 break;
878 }
879 if (pcbRead)
880 {
881 /* return partial data */
882 *pcbRead = cbBytesRead;
883 break;
884 }
885
886 /* read more? */
887 cbRead += cbBytesRead;
888 if (cbRead == cbBuffer)
889 break;
890
891 /* next */
892 cbToRead = cbBuffer - cbRead;
893 }
894
895 rtSocketUnlock(pThis);
896 return rc;
897}
898
899
900RTDECL(int) RTSocketReadFrom(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr)
901{
902 /*
903 * Validate input.
904 */
905 RTSOCKETINT *pThis = hSocket;
906 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
907 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
908 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
909 AssertPtr(pvBuffer);
910 AssertPtr(pcbRead);
911 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
912
913 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
914 if (RT_FAILURE(rc))
915 return rc;
916
917 /*
918 * Read data.
919 */
920 size_t cbRead = 0;
921 size_t cbToRead = cbBuffer;
922 rtSocketErrorReset();
923 RTSOCKADDRUNION u;
924#ifdef RT_OS_WINDOWS
925 int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
926 int cbAddr = sizeof(u);
927#else
928 size_t cbNow = cbToRead;
929 socklen_t cbAddr = sizeof(u);
930#endif
931 ssize_t cbBytesRead = recvfrom(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL, &u.Addr, &cbAddr);
932 if (cbBytesRead <= 0)
933 {
934 rc = rtSocketError();
935 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
936 if (RT_SUCCESS_NP(rc))
937 {
938 *pcbRead = 0;
939 rc = VINF_SUCCESS;
940 }
941 }
942 else
943 {
944 if (pSrcAddr)
945 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pSrcAddr);
946 *pcbRead = cbBytesRead;
947 }
948
949 rtSocketUnlock(pThis);
950 return rc;
951}
952
953
954RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
955{
956 /*
957 * Validate input.
958 */
959 RTSOCKETINT *pThis = hSocket;
960 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
961 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
962 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
963
964 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
965 if (RT_FAILURE(rc))
966 return rc;
967
968 /*
969 * Try write all at once.
970 */
971#ifdef RT_OS_WINDOWS
972 int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
973#else
974 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
975#endif
976 ssize_t cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
977 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
978 rc = VINF_SUCCESS;
979 else if (cbWritten < 0)
980 rc = rtSocketError();
981 else
982 {
983 /*
984 * Unfinished business, write the remainder of the request. Must ignore
985 * VERR_INTERRUPTED here if we've managed to send something.
986 */
987 size_t cbSentSoFar = 0;
988 for (;;)
989 {
990 /* advance */
991 cbBuffer -= (size_t)cbWritten;
992 if (!cbBuffer)
993 break;
994 cbSentSoFar += (size_t)cbWritten;
995 pvBuffer = (char const *)pvBuffer + cbWritten;
996
997 /* send */
998#ifdef RT_OS_WINDOWS
999 cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
1000#else
1001 cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1002#endif
1003 cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1004 if (cbWritten >= 0)
1005 AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtSocketError()=%d\n",
1006 cbWritten, cbBuffer, rtSocketError()));
1007 else
1008 {
1009 rc = rtSocketError();
1010 if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
1011 break;
1012 cbWritten = 0;
1013 rc = VINF_SUCCESS;
1014 }
1015 }
1016 }
1017
1018 rtSocketUnlock(pThis);
1019 return rc;
1020}
1021
1022
1023RTDECL(int) RTSocketWriteTo(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pAddr)
1024{
1025 /*
1026 * Validate input.
1027 */
1028 RTSOCKETINT *pThis = hSocket;
1029 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1030 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1031
1032 /* no locking since UDP reads may be done concurrently to writes, and
1033 * this is the normal use case of this code. */
1034
1035 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
1036 if (RT_FAILURE(rc))
1037 return rc;
1038
1039 /* Figure out destination address. */
1040 struct sockaddr *pSA = NULL;
1041#ifdef RT_OS_WINDOWS
1042 int cbSA = 0;
1043#else
1044 socklen_t cbSA = 0;
1045#endif
1046 RTSOCKADDRUNION u;
1047 if (pAddr)
1048 {
1049 rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), NULL);
1050 if (RT_FAILURE(rc))
1051 return rc;
1052 pSA = &u.Addr;
1053 cbSA = sizeof(u);
1054 }
1055
1056 /*
1057 * Must write all at once, otherwise it is a failure.
1058 */
1059#ifdef RT_OS_WINDOWS
1060 int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
1061#else
1062 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1063#endif
1064 ssize_t cbWritten = sendto(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL, pSA, cbSA);
1065 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
1066 rc = VINF_SUCCESS;
1067 else if (cbWritten < 0)
1068 rc = rtSocketError();
1069 else
1070 rc = VERR_TOO_MUCH_DATA;
1071
1072 rtSocketUnlock(pThis);
1073 return rc;
1074}
1075
1076
1077RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf)
1078{
1079 /*
1080 * Validate input.
1081 */
1082 RTSOCKETINT *pThis = hSocket;
1083 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1084 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1085 AssertPtrReturn(pSgBuf, VERR_INVALID_PARAMETER);
1086 AssertReturn(pSgBuf->cSegs > 0, VERR_INVALID_PARAMETER);
1087 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1088
1089 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
1090 if (RT_FAILURE(rc))
1091 return rc;
1092
1093 /*
1094 * Construct message descriptor (translate pSgBuf) and send it.
1095 */
1096 rc = VERR_NO_TMP_MEMORY;
1097#ifdef RT_OS_WINDOWS
1098 AssertCompileSize(WSABUF, sizeof(RTSGSEG));
1099 AssertCompileMemberSize(WSABUF, buf, RT_SIZEOFMEMB(RTSGSEG, pvSeg));
1100
1101 LPWSABUF paMsg = (LPWSABUF)RTMemTmpAllocZ(pSgBuf->cSegs * sizeof(WSABUF));
1102 if (paMsg)
1103 {
1104 for (unsigned i = 0; i < pSgBuf->cSegs; i++)
1105 {
1106 paMsg[i].buf = (char *)pSgBuf->paSegs[i].pvSeg;
1107 paMsg[i].len = (u_long)pSgBuf->paSegs[i].cbSeg;
1108 }
1109
1110 DWORD dwSent;
1111 int hrc = WSASend(pThis->hNative, paMsg, pSgBuf->cSegs, &dwSent,
1112 MSG_NOSIGNAL, NULL, NULL);
1113 if (!hrc)
1114 rc = VINF_SUCCESS;
1115/** @todo check for incomplete writes */
1116 else
1117 rc = rtSocketError();
1118
1119 RTMemTmpFree(paMsg);
1120 }
1121
1122#else /* !RT_OS_WINDOWS */
1123 AssertCompileSize(struct iovec, sizeof(RTSGSEG));
1124 AssertCompileMemberSize(struct iovec, iov_base, RT_SIZEOFMEMB(RTSGSEG, pvSeg));
1125 AssertCompileMemberSize(struct iovec, iov_len, RT_SIZEOFMEMB(RTSGSEG, cbSeg));
1126
1127 struct iovec *paMsg = (struct iovec *)RTMemTmpAllocZ(pSgBuf->cSegs * sizeof(struct iovec));
1128 if (paMsg)
1129 {
1130 for (unsigned i = 0; i < pSgBuf->cSegs; i++)
1131 {
1132 paMsg[i].iov_base = pSgBuf->paSegs[i].pvSeg;
1133 paMsg[i].iov_len = pSgBuf->paSegs[i].cbSeg;
1134 }
1135
1136 struct msghdr msgHdr;
1137 RT_ZERO(msgHdr);
1138 msgHdr.msg_iov = paMsg;
1139 msgHdr.msg_iovlen = pSgBuf->cSegs;
1140 ssize_t cbWritten = sendmsg(pThis->hNative, &msgHdr, MSG_NOSIGNAL);
1141 if (RT_LIKELY(cbWritten >= 0))
1142 rc = VINF_SUCCESS;
1143/** @todo check for incomplete writes */
1144 else
1145 rc = rtSocketError();
1146
1147 RTMemTmpFree(paMsg);
1148 }
1149#endif /* !RT_OS_WINDOWS */
1150
1151 rtSocketUnlock(pThis);
1152 return rc;
1153}
1154
1155
1156RTDECL(int) RTSocketSgWriteL(RTSOCKET hSocket, size_t cSegs, ...)
1157{
1158 va_list va;
1159 va_start(va, cSegs);
1160 int rc = RTSocketSgWriteLV(hSocket, cSegs, va);
1161 va_end(va);
1162 return rc;
1163}
1164
1165
1166RTDECL(int) RTSocketSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va)
1167{
1168 /*
1169 * Set up a S/G segment array + buffer on the stack and pass it
1170 * on to RTSocketSgWrite.
1171 */
1172 Assert(cSegs <= 16);
1173 PRTSGSEG paSegs = (PRTSGSEG)alloca(cSegs * sizeof(RTSGSEG));
1174 AssertReturn(paSegs, VERR_NO_TMP_MEMORY);
1175 for (size_t i = 0; i < cSegs; i++)
1176 {
1177 paSegs[i].pvSeg = va_arg(va, void *);
1178 paSegs[i].cbSeg = va_arg(va, size_t);
1179 }
1180
1181 RTSGBUF SgBuf;
1182 RTSgBufInit(&SgBuf, paSegs, cSegs);
1183 return RTSocketSgWrite(hSocket, &SgBuf);
1184}
1185
1186
1187RTDECL(int) RTSocketReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
1188{
1189 /*
1190 * Validate input.
1191 */
1192 RTSOCKETINT *pThis = hSocket;
1193 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1194 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1195 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
1196 AssertPtr(pvBuffer);
1197 AssertPtrReturn(pcbRead, VERR_INVALID_PARAMETER);
1198 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1199
1200 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1201 if (RT_FAILURE(rc))
1202 return rc;
1203
1204 rtSocketErrorReset();
1205#ifdef RT_OS_WINDOWS
1206 int cbNow = cbBuffer >= INT_MAX/2 ? INT_MAX/2 : (int)cbBuffer;
1207
1208 int cbRead = recv(pThis->hNative, (char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1209 if (cbRead >= 0)
1210 {
1211 *pcbRead = cbRead;
1212 rc = VINF_SUCCESS;
1213 }
1214 else
1215 rc = rtSocketError();
1216
1217 if (rc == VERR_TRY_AGAIN)
1218 rc = VINF_TRY_AGAIN;
1219#else
1220 ssize_t cbRead = recv(pThis->hNative, pvBuffer, cbBuffer, MSG_NOSIGNAL);
1221 if (cbRead >= 0)
1222 *pcbRead = cbRead;
1223 else if (errno == EAGAIN)
1224 {
1225 *pcbRead = 0;
1226 rc = VINF_TRY_AGAIN;
1227 }
1228 else
1229 rc = rtSocketError();
1230#endif
1231
1232 rtSocketUnlock(pThis);
1233 return rc;
1234}
1235
1236
1237RTDECL(int) RTSocketWriteNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)
1238{
1239 /*
1240 * Validate input.
1241 */
1242 RTSOCKETINT *pThis = hSocket;
1243 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1244 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1245 AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER);
1246 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1247
1248 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1249 if (RT_FAILURE(rc))
1250 return rc;
1251
1252 rtSocketErrorReset();
1253#ifdef RT_OS_WINDOWS
1254 int cbNow = RT_MIN((int)cbBuffer, INT_MAX/2);
1255
1256 int cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1257
1258 if (cbWritten >= 0)
1259 {
1260 *pcbWritten = cbWritten;
1261 rc = VINF_SUCCESS;
1262 }
1263 else
1264 rc = rtSocketError();
1265
1266 if (rc == VERR_TRY_AGAIN)
1267 rc = VINF_TRY_AGAIN;
1268#else
1269 ssize_t cbWritten = send(pThis->hNative, pvBuffer, cbBuffer, MSG_NOSIGNAL);
1270 if (cbWritten >= 0)
1271 *pcbWritten = cbWritten;
1272 else if (errno == EAGAIN)
1273 {
1274 *pcbWritten = 0;
1275 rc = VINF_TRY_AGAIN;
1276 }
1277 else
1278 rc = rtSocketError();
1279#endif
1280
1281 rtSocketUnlock(pThis);
1282 return rc;
1283}
1284
1285
1286RTDECL(int) RTSocketSgWriteNB(RTSOCKET hSocket, PCRTSGBUF pSgBuf, size_t *pcbWritten)
1287{
1288 /*
1289 * Validate input.
1290 */
1291 RTSOCKETINT *pThis = hSocket;
1292 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1293 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1294 AssertPtrReturn(pSgBuf, VERR_INVALID_PARAMETER);
1295 AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER);
1296 AssertReturn(pSgBuf->cSegs > 0, VERR_INVALID_PARAMETER);
1297 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1298
1299 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1300 if (RT_FAILURE(rc))
1301 return rc;
1302
1303 unsigned cSegsToSend = 0;
1304 rc = VERR_NO_TMP_MEMORY;
1305#ifdef RT_OS_WINDOWS
1306 LPWSABUF paMsg = NULL;
1307
1308 RTSgBufMapToNative(paMsg, pSgBuf, WSABUF, buf, char *, len, u_long, cSegsToSend);
1309 if (paMsg)
1310 {
1311 DWORD dwSent = 0;
1312 int hrc = WSASend(pThis->hNative, paMsg, cSegsToSend, &dwSent,
1313 MSG_NOSIGNAL, NULL, NULL);
1314 if (!hrc)
1315 rc = VINF_SUCCESS;
1316 else
1317 rc = rtSocketError();
1318
1319 *pcbWritten = dwSent;
1320
1321 RTMemTmpFree(paMsg);
1322 }
1323
1324#else /* !RT_OS_WINDOWS */
1325 struct iovec *paMsg = NULL;
1326
1327 RTSgBufMapToNative(paMsg, pSgBuf, struct iovec, iov_base, void *, iov_len, size_t, cSegsToSend);
1328 if (paMsg)
1329 {
1330 struct msghdr msgHdr;
1331 RT_ZERO(msgHdr);
1332 msgHdr.msg_iov = paMsg;
1333 msgHdr.msg_iovlen = cSegsToSend;
1334 ssize_t cbWritten = sendmsg(pThis->hNative, &msgHdr, MSG_NOSIGNAL);
1335 if (RT_LIKELY(cbWritten >= 0))
1336 {
1337 rc = VINF_SUCCESS;
1338 *pcbWritten = cbWritten;
1339 }
1340 else
1341 rc = rtSocketError();
1342
1343 RTMemTmpFree(paMsg);
1344 }
1345#endif /* !RT_OS_WINDOWS */
1346
1347 rtSocketUnlock(pThis);
1348 return rc;
1349}
1350
1351
1352RTDECL(int) RTSocketSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...)
1353{
1354 va_list va;
1355 va_start(va, pcbWritten);
1356 int rc = RTSocketSgWriteLVNB(hSocket, cSegs, pcbWritten, va);
1357 va_end(va);
1358 return rc;
1359}
1360
1361
1362RTDECL(int) RTSocketSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va)
1363{
1364 /*
1365 * Set up a S/G segment array + buffer on the stack and pass it
1366 * on to RTSocketSgWrite.
1367 */
1368 Assert(cSegs <= 16);
1369 PRTSGSEG paSegs = (PRTSGSEG)alloca(cSegs * sizeof(RTSGSEG));
1370 AssertReturn(paSegs, VERR_NO_TMP_MEMORY);
1371 for (size_t i = 0; i < cSegs; i++)
1372 {
1373 paSegs[i].pvSeg = va_arg(va, void *);
1374 paSegs[i].cbSeg = va_arg(va, size_t);
1375 }
1376
1377 RTSGBUF SgBuf;
1378 RTSgBufInit(&SgBuf, paSegs, cSegs);
1379 return RTSocketSgWriteNB(hSocket, &SgBuf, pcbWritten);
1380}
1381
1382
1383RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
1384{
1385 /*
1386 * Validate input.
1387 */
1388 RTSOCKETINT *pThis = hSocket;
1389 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1390 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1391 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1392 int const fdMax = (int)pThis->hNative + 1;
1393 AssertReturn(fdMax - 1 == pThis->hNative, VERR_INTERNAL_ERROR_5);
1394
1395 /*
1396 * Set up the file descriptor sets and do the select.
1397 */
1398 fd_set fdsetR;
1399 FD_ZERO(&fdsetR);
1400 FD_SET(pThis->hNative, &fdsetR);
1401
1402 fd_set fdsetE = fdsetR;
1403
1404 int rc;
1405 if (cMillies == RT_INDEFINITE_WAIT)
1406 rc = select(fdMax, &fdsetR, NULL, &fdsetE, NULL);
1407 else
1408 {
1409 struct timeval timeout;
1410 timeout.tv_sec = cMillies / 1000;
1411 timeout.tv_usec = (cMillies % 1000) * 1000;
1412 rc = select(fdMax, &fdsetR, NULL, &fdsetE, &timeout);
1413 }
1414 if (rc > 0)
1415 rc = VINF_SUCCESS;
1416 else if (rc == 0)
1417 rc = VERR_TIMEOUT;
1418 else
1419 rc = rtSocketError();
1420
1421 return rc;
1422}
1423
1424
1425RTDECL(int) RTSocketSelectOneEx(RTSOCKET hSocket, uint32_t fEvents, uint32_t *pfEvents,
1426 RTMSINTERVAL cMillies)
1427{
1428 /*
1429 * Validate input.
1430 */
1431 RTSOCKETINT *pThis = hSocket;
1432 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1433 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1434 AssertPtrReturn(pfEvents, VERR_INVALID_PARAMETER);
1435 AssertReturn(!(fEvents & ~RTSOCKET_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
1436 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1437 int const fdMax = (int)pThis->hNative + 1;
1438 AssertReturn(fdMax - 1 == pThis->hNative, VERR_INTERNAL_ERROR_5);
1439
1440 *pfEvents = 0;
1441
1442 /*
1443 * Set up the file descriptor sets and do the select.
1444 */
1445 fd_set fdsetR;
1446 fd_set fdsetW;
1447 fd_set fdsetE;
1448 FD_ZERO(&fdsetR);
1449 FD_ZERO(&fdsetW);
1450 FD_ZERO(&fdsetE);
1451
1452 if (fEvents & RTSOCKET_EVT_READ)
1453 FD_SET(pThis->hNative, &fdsetR);
1454 if (fEvents & RTSOCKET_EVT_WRITE)
1455 FD_SET(pThis->hNative, &fdsetW);
1456 if (fEvents & RTSOCKET_EVT_ERROR)
1457 FD_SET(pThis->hNative, &fdsetE);
1458
1459 int rc;
1460 if (cMillies == RT_INDEFINITE_WAIT)
1461 rc = select(fdMax, &fdsetR, &fdsetW, &fdsetE, NULL);
1462 else
1463 {
1464 struct timeval timeout;
1465 timeout.tv_sec = cMillies / 1000;
1466 timeout.tv_usec = (cMillies % 1000) * 1000;
1467 rc = select(fdMax, &fdsetR, &fdsetW, &fdsetE, &timeout);
1468 }
1469 if (rc > 0)
1470 {
1471 if (FD_ISSET(pThis->hNative, &fdsetR))
1472 *pfEvents |= RTSOCKET_EVT_READ;
1473 if (FD_ISSET(pThis->hNative, &fdsetW))
1474 *pfEvents |= RTSOCKET_EVT_WRITE;
1475 if (FD_ISSET(pThis->hNative, &fdsetE))
1476 *pfEvents |= RTSOCKET_EVT_ERROR;
1477
1478 rc = VINF_SUCCESS;
1479 }
1480 else if (rc == 0)
1481 rc = VERR_TIMEOUT;
1482 else
1483 rc = rtSocketError();
1484
1485 return rc;
1486}
1487
1488
1489RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
1490{
1491 /*
1492 * Validate input, don't lock it because we might want to interrupt a call
1493 * active on a different thread.
1494 */
1495 RTSOCKETINT *pThis = hSocket;
1496 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1497 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1498 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1499 AssertReturn(fRead || fWrite, VERR_INVALID_PARAMETER);
1500
1501 /*
1502 * Do the job.
1503 */
1504 int rc = VINF_SUCCESS;
1505 int fHow;
1506 if (fRead && fWrite)
1507 fHow = SHUT_RDWR;
1508 else if (fRead)
1509 fHow = SHUT_RD;
1510 else
1511 fHow = SHUT_WR;
1512 if (shutdown(pThis->hNative, fHow) == -1)
1513 rc = rtSocketError();
1514
1515 return rc;
1516}
1517
1518
1519RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
1520{
1521 /*
1522 * Validate input.
1523 */
1524 RTSOCKETINT *pThis = hSocket;
1525 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1526 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1527 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1528
1529 /*
1530 * Get the address and convert it.
1531 */
1532 int rc;
1533 RTSOCKADDRUNION u;
1534#ifdef RT_OS_WINDOWS
1535 int cbAddr = sizeof(u);
1536#else
1537 socklen_t cbAddr = sizeof(u);
1538#endif
1539 RT_ZERO(u);
1540 if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0)
1541 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pAddr);
1542 else
1543 rc = rtSocketError();
1544
1545 return rc;
1546}
1547
1548
1549RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
1550{
1551 /*
1552 * Validate input.
1553 */
1554 RTSOCKETINT *pThis = hSocket;
1555 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1556 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1557 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1558
1559 /*
1560 * Get the address and convert it.
1561 */
1562 int rc;
1563 RTSOCKADDRUNION u;
1564#ifdef RT_OS_WINDOWS
1565 int cbAddr = sizeof(u);
1566#else
1567 socklen_t cbAddr = sizeof(u);
1568#endif
1569 RT_ZERO(u);
1570 if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0)
1571 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pAddr);
1572 else
1573 rc = rtSocketError();
1574
1575 return rc;
1576}
1577
1578
1579
1580/**
1581 * Wrapper around bind.
1582 *
1583 * @returns IPRT status code.
1584 * @param hSocket The socket handle.
1585 * @param pAddr The address to bind to.
1586 */
1587int rtSocketBind(RTSOCKET hSocket, PCRTNETADDR pAddr)
1588{
1589 /*
1590 * Validate input.
1591 */
1592 RTSOCKETINT *pThis = hSocket;
1593 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1594 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1595 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1596
1597 RTSOCKADDRUNION u;
1598 int cbAddr;
1599 int rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), &cbAddr);
1600 if (RT_SUCCESS(rc))
1601 {
1602 if (bind(pThis->hNative, &u.Addr, cbAddr) != 0)
1603 rc = rtSocketError();
1604 }
1605
1606 rtSocketUnlock(pThis);
1607 return rc;
1608}
1609
1610
1611/**
1612 * Wrapper around listen.
1613 *
1614 * @returns IPRT status code.
1615 * @param hSocket The socket handle.
1616 * @param cMaxPending The max number of pending connections.
1617 */
1618int rtSocketListen(RTSOCKET hSocket, int cMaxPending)
1619{
1620 /*
1621 * Validate input.
1622 */
1623 RTSOCKETINT *pThis = hSocket;
1624 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1625 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1626 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1627
1628 int rc = VINF_SUCCESS;
1629 if (listen(pThis->hNative, cMaxPending) != 0)
1630 rc = rtSocketError();
1631
1632 rtSocketUnlock(pThis);
1633 return rc;
1634}
1635
1636
1637/**
1638 * Wrapper around accept.
1639 *
1640 * @returns IPRT status code.
1641 * @param hSocket The socket handle.
1642 * @param phClient Where to return the client socket handle on
1643 * success.
1644 * @param pAddr Where to return the client address.
1645 * @param pcbAddr On input this gives the size buffer size of what
1646 * @a pAddr point to. On return this contains the
1647 * size of what's stored at @a pAddr.
1648 */
1649int rtSocketAccept(RTSOCKET hSocket, PRTSOCKET phClient, struct sockaddr *pAddr, size_t *pcbAddr)
1650{
1651 /*
1652 * Validate input.
1653 * Only lock the socket temporarily while we get the native handle, so that
1654 * we can safely shutdown and destroy the socket from a different thread.
1655 */
1656 RTSOCKETINT *pThis = hSocket;
1657 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1658 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1659 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1660
1661 /*
1662 * Call accept().
1663 */
1664 rtSocketErrorReset();
1665 int rc = VINF_SUCCESS;
1666#ifdef RT_OS_WINDOWS
1667 int cbAddr = (int)*pcbAddr;
1668#else
1669 socklen_t cbAddr = *pcbAddr;
1670#endif
1671 RTSOCKETNATIVE hNativeClient = accept(pThis->hNative, pAddr, &cbAddr);
1672 if (hNativeClient != NIL_RTSOCKETNATIVE)
1673 {
1674 *pcbAddr = cbAddr;
1675
1676 /*
1677 * Wrap the client socket.
1678 */
1679 rc = rtSocketCreateForNative(phClient, hNativeClient);
1680 if (RT_FAILURE(rc))
1681 {
1682#ifdef RT_OS_WINDOWS
1683 closesocket(hNativeClient);
1684#else
1685 close(hNativeClient);
1686#endif
1687 }
1688 }
1689 else
1690 rc = rtSocketError();
1691
1692 rtSocketUnlock(pThis);
1693 return rc;
1694}
1695
1696
1697/**
1698 * Wrapper around connect.
1699 *
1700 * @returns IPRT status code.
1701 * @param hSocket The socket handle.
1702 * @param pAddr The socket address to connect to.
1703 */
1704int rtSocketConnect(RTSOCKET hSocket, PCRTNETADDR pAddr)
1705{
1706 /*
1707 * Validate input.
1708 */
1709 RTSOCKETINT *pThis = hSocket;
1710 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1711 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1712 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1713
1714 RTSOCKADDRUNION u;
1715 int cbAddr;
1716 int rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), &cbAddr);
1717 if (RT_SUCCESS(rc))
1718 {
1719 if (connect(pThis->hNative, &u.Addr, cbAddr) != 0)
1720 rc = rtSocketError();
1721 }
1722
1723 rtSocketUnlock(pThis);
1724 return rc;
1725}
1726
1727
1728/**
1729 * Wrapper around setsockopt.
1730 *
1731 * @returns IPRT status code.
1732 * @param hSocket The socket handle.
1733 * @param iLevel The protocol level, e.g. IPPORTO_TCP.
1734 * @param iOption The option, e.g. TCP_NODELAY.
1735 * @param pvValue The value buffer.
1736 * @param cbValue The size of the value pointed to by pvValue.
1737 */
1738int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValue, int cbValue)
1739{
1740 /*
1741 * Validate input.
1742 */
1743 RTSOCKETINT *pThis = hSocket;
1744 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1745 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1746 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1747
1748 int rc = VINF_SUCCESS;
1749 if (setsockopt(pThis->hNative, iLevel, iOption, (const char *)pvValue, cbValue) != 0)
1750 rc = rtSocketError();
1751
1752 rtSocketUnlock(pThis);
1753 return rc;
1754}
1755
1756#ifdef RT_OS_WINDOWS
1757
1758/**
1759 * Internal RTPollSetAdd helper that returns the handle that should be added to
1760 * the pollset.
1761 *
1762 * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
1763 * @param hSocket The socket handle.
1764 * @param fEvents The events we're polling for.
1765 * @param ph where to put the primary handle.
1766 */
1767int rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PHANDLE ph)
1768{
1769 RTSOCKETINT *pThis = hSocket;
1770 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1771 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1772 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1773
1774 int rc = VINF_SUCCESS;
1775 if (pThis->hEvent != WSA_INVALID_EVENT)
1776 *ph = pThis->hEvent;
1777 else
1778 {
1779 *ph = pThis->hEvent = WSACreateEvent();
1780 if (pThis->hEvent == WSA_INVALID_EVENT)
1781 rc = rtSocketError();
1782 }
1783
1784 rtSocketUnlock(pThis);
1785 return rc;
1786}
1787
1788
1789/**
1790 * Undos the harm done by WSAEventSelect.
1791 *
1792 * @returns IPRT status code.
1793 * @param pThis The socket handle.
1794 */
1795static int rtSocketPollClearEventAndRestoreBlocking(RTSOCKETINT *pThis)
1796{
1797 int rc = VINF_SUCCESS;
1798 if (pThis->fSubscribedEvts)
1799 {
1800 if (WSAEventSelect(pThis->hNative, WSA_INVALID_EVENT, 0) == 0)
1801 {
1802 pThis->fSubscribedEvts = 0;
1803
1804 /*
1805 * Switch back to blocking mode if that was the state before the
1806 * operation.
1807 */
1808 if (pThis->fBlocking)
1809 {
1810 u_long fNonBlocking = 0;
1811 int rc2 = ioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking);
1812 if (rc2 != 0)
1813 {
1814 rc = rtSocketError();
1815 AssertMsgFailed(("%Rrc; rc2=%d\n", rc, rc2));
1816 }
1817 }
1818 }
1819 else
1820 {
1821 rc = rtSocketError();
1822 AssertMsgFailed(("%Rrc\n", rc));
1823 }
1824 }
1825 return rc;
1826}
1827
1828
1829/**
1830 * Updates the mask of events we're subscribing to.
1831 *
1832 * @returns IPRT status code.
1833 * @param pThis The socket handle.
1834 * @param fEvents The events we want to subscribe to.
1835 */
1836static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
1837{
1838 LONG fNetworkEvents = 0;
1839 if (fEvents & RTPOLL_EVT_READ)
1840 fNetworkEvents |= FD_READ;
1841 if (fEvents & RTPOLL_EVT_WRITE)
1842 fNetworkEvents |= FD_WRITE;
1843 if (fEvents & RTPOLL_EVT_ERROR)
1844 fNetworkEvents |= FD_CLOSE;
1845 LogFlowFunc(("fNetworkEvents=%#x\n", fNetworkEvents));
1846 if (WSAEventSelect(pThis->hNative, pThis->hEvent, fNetworkEvents) == 0)
1847 {
1848 pThis->fSubscribedEvts = fEvents;
1849 return VINF_SUCCESS;
1850 }
1851
1852 int rc = rtSocketError();
1853 AssertMsgFailed(("fNetworkEvents=%#x rc=%Rrc\n", fNetworkEvents, rtSocketError()));
1854 return rc;
1855}
1856
1857
1858/**
1859 * Checks for pending events.
1860 *
1861 * @returns Event mask or 0.
1862 * @param pThis The socket handle.
1863 * @param fEvents The desired events.
1864 */
1865static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
1866{
1867 int rc = VINF_SUCCESS;
1868 uint32_t fRetEvents = 0;
1869
1870 LogFlowFunc(("pThis=%#p fEvents=%#x\n", pThis, fEvents));
1871
1872 /* Make sure WSAEnumNetworkEvents returns what we want. */
1873 if ((pThis->fSubscribedEvts & fEvents) != fEvents)
1874 rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents);
1875
1876 /* Get the event mask, ASSUMES that WSAEnumNetworkEvents doesn't clear stuff. */
1877 WSANETWORKEVENTS NetEvts;
1878 RT_ZERO(NetEvts);
1879 if (WSAEnumNetworkEvents(pThis->hNative, pThis->hEvent, &NetEvts) == 0)
1880 {
1881 if ( (NetEvts.lNetworkEvents & FD_READ)
1882 && (fEvents & RTPOLL_EVT_READ)
1883 && NetEvts.iErrorCode[FD_READ_BIT] == 0)
1884 fRetEvents |= RTPOLL_EVT_READ;
1885
1886 if ( (NetEvts.lNetworkEvents & FD_WRITE)
1887 && (fEvents & RTPOLL_EVT_WRITE)
1888 && NetEvts.iErrorCode[FD_WRITE_BIT] == 0)
1889 fRetEvents |= RTPOLL_EVT_WRITE;
1890
1891 if (fEvents & RTPOLL_EVT_ERROR)
1892 {
1893 if (NetEvts.lNetworkEvents & FD_CLOSE)
1894 fRetEvents |= RTPOLL_EVT_ERROR;
1895 else
1896 for (uint32_t i = 0; i < FD_MAX_EVENTS; i++)
1897 if ( (NetEvts.lNetworkEvents & (1L << i))
1898 && NetEvts.iErrorCode[i] != 0)
1899 fRetEvents |= RTPOLL_EVT_ERROR;
1900 }
1901 }
1902 else
1903 rc = rtSocketError();
1904
1905 /* Fall back on select if we hit an error above. */
1906 if (RT_FAILURE(rc))
1907 {
1908 /** @todo */
1909 }
1910
1911 LogFlowFunc(("fRetEvents=%#x\n", fRetEvents));
1912 return fRetEvents;
1913}
1914
1915
1916/**
1917 * Internal RTPoll helper that polls the socket handle and, if @a fNoWait is
1918 * clear, starts whatever actions we've got running during the poll call.
1919 *
1920 * @returns 0 if no pending events, actions initiated if @a fNoWait is clear.
1921 * Event mask (in @a fEvents) and no actions if the handle is ready
1922 * already.
1923 * UINT32_MAX (asserted) if the socket handle is busy in I/O or a
1924 * different poll set.
1925 *
1926 * @param hSocket The socket handle.
1927 * @param hPollSet The poll set handle (for access checks).
1928 * @param fEvents The events we're polling for.
1929 * @param fFinalEntry Set if this is the final entry for this handle
1930 * in this poll set. This can be used for dealing
1931 * with duplicate entries.
1932 * @param fNoWait Set if it's a zero-wait poll call. Clear if
1933 * we'll wait for an event to occur.
1934 *
1935 * @remarks There is a potential race wrt duplicate handles when @a fNoWait is
1936 * @c true, we don't currently care about that oddity...
1937 */
1938uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
1939{
1940 RTSOCKETINT *pThis = hSocket;
1941 AssertPtrReturn(pThis, UINT32_MAX);
1942 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
1943 if (rtSocketTryLock(pThis))
1944 pThis->hPollSet = hPollSet;
1945 else
1946 {
1947 AssertReturn(pThis->hPollSet == hPollSet, UINT32_MAX);
1948 ASMAtomicIncU32(&pThis->cUsers);
1949 }
1950
1951 /* (rtSocketPollCheck will reset the event object). */
1952 uint32_t fRetEvents = pThis->fEventsSaved;
1953 pThis->fEventsSaved = 0; /* Reset */
1954 fRetEvents |= rtSocketPollCheck(pThis, fEvents);
1955
1956 if ( !fRetEvents
1957 && !fNoWait)
1958 {
1959 pThis->fPollEvts |= fEvents;
1960 if ( fFinalEntry
1961 && pThis->fSubscribedEvts != pThis->fPollEvts)
1962 {
1963 int rc = rtSocketPollUpdateEvents(pThis, pThis->fPollEvts);
1964 if (RT_FAILURE(rc))
1965 {
1966 pThis->fPollEvts = 0;
1967 fRetEvents = UINT32_MAX;
1968 }
1969 }
1970 }
1971
1972 if (fRetEvents || fNoWait)
1973 {
1974 if (pThis->cUsers == 1)
1975 {
1976 rtSocketPollClearEventAndRestoreBlocking(pThis);
1977 pThis->hPollSet = NIL_RTPOLLSET;
1978 }
1979 ASMAtomicDecU32(&pThis->cUsers);
1980 }
1981
1982 return fRetEvents;
1983}
1984
1985
1986/**
1987 * Called after a WaitForMultipleObjects returned in order to check for pending
1988 * events and stop whatever actions that rtSocketPollStart() initiated.
1989 *
1990 * @returns Event mask or 0.
1991 *
1992 * @param hSocket The socket handle.
1993 * @param fEvents The events we're polling for.
1994 * @param fFinalEntry Set if this is the final entry for this handle
1995 * in this poll set. This can be used for dealing
1996 * with duplicate entries. Only keep in mind that
1997 * this method is called in reverse order, so the
1998 * first call will have this set (when the entire
1999 * set was processed).
2000 * @param fHarvestEvents Set if we should check for pending events.
2001 */
2002uint32_t rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry, bool fHarvestEvents)
2003{
2004 RTSOCKETINT *pThis = hSocket;
2005 AssertPtrReturn(pThis, 0);
2006 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, 0);
2007 Assert(pThis->cUsers > 0);
2008 Assert(pThis->hPollSet != NIL_RTPOLLSET);
2009
2010 /* Harvest events and clear the event mask for the next round of polling. */
2011 uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
2012 pThis->fPollEvts = 0;
2013
2014 /*
2015 * Save the write event if required.
2016 * It is only posted once and might get lost if the another source in the
2017 * pollset with a higher priority has pending events.
2018 */
2019 if ( !fHarvestEvents
2020 && fRetEvents)
2021 {
2022 pThis->fEventsSaved = fRetEvents;
2023 fRetEvents = 0;
2024 }
2025
2026 /* Make the socket blocking again and unlock the handle. */
2027 if (pThis->cUsers == 1)
2028 {
2029 rtSocketPollClearEventAndRestoreBlocking(pThis);
2030 pThis->hPollSet = NIL_RTPOLLSET;
2031 }
2032 ASMAtomicDecU32(&pThis->cUsers);
2033 return fRetEvents;
2034}
2035
2036#endif /* RT_OS_WINDOWS */
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