VirtualBox

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

最後變更 在這個檔案從70375是 70244,由 vboxsync 提交於 7 年 前

iprt/socket: fix a white-space-checker burn.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 74.1 KB
 
1/* $Id: socket.cpp 70244 2017-12-20 15:13:14Z vboxsync $ */
2/** @file
3 * IPRT - Network Sockets.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 <iprt/win/winsock2.h>
33# include <iprt/win/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#ifdef RT_OS_WINDOWS
74# include "win/internal-r3-win.h"
75#endif
76
77
78/*********************************************************************************************************************************
79* Defined Constants And Macros *
80*********************************************************************************************************************************/
81/* non-standard linux stuff (it seems). */
82#ifndef MSG_NOSIGNAL
83# define MSG_NOSIGNAL 0
84#endif
85
86/* Windows has different names for SHUT_XXX. */
87#ifndef SHUT_RDWR
88# ifdef SD_BOTH
89# define SHUT_RDWR SD_BOTH
90# else
91# define SHUT_RDWR 2
92# endif
93#endif
94#ifndef SHUT_WR
95# ifdef SD_SEND
96# define SHUT_WR SD_SEND
97# else
98# define SHUT_WR 1
99# endif
100#endif
101#ifndef SHUT_RD
102# ifdef SD_RECEIVE
103# define SHUT_RD SD_RECEIVE
104# else
105# define SHUT_RD 0
106# endif
107#endif
108
109/* fixup backlevel OSes. */
110#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
111# define socklen_t int
112#endif
113
114/** How many pending connection. */
115#define RTTCP_SERVER_BACKLOG 10
116
117/* Limit read and write sizes on Windows and OS/2. */
118#ifdef RT_OS_WINDOWS
119# define RTSOCKET_MAX_WRITE (INT_MAX / 2)
120# define RTSOCKET_MAX_READ (INT_MAX / 2)
121#elif defined(RT_OS_OS2)
122# define RTSOCKET_MAX_WRITE 0x10000
123# define RTSOCKET_MAX_READ 0x10000
124#endif
125
126
127/*********************************************************************************************************************************
128* Structures and Typedefs *
129*********************************************************************************************************************************/
130/**
131 * Socket handle data.
132 *
133 * This is mainly required for implementing RTPollSet on Windows.
134 */
135typedef struct RTSOCKETINT
136{
137 /** Magic number (RTSOCKET_MAGIC). */
138 uint32_t u32Magic;
139 /** Exclusive user count.
140 * This is used to prevent two threads from accessing the handle concurrently.
141 * It can be higher than 1 if this handle is reference multiple times in a
142 * polling set (Windows). */
143 uint32_t volatile cUsers;
144 /** The native socket handle. */
145 RTSOCKETNATIVE hNative;
146 /** Indicates whether the handle has been closed or not. */
147 bool volatile fClosed;
148 /** Indicates whether the socket is operating in blocking or non-blocking mode
149 * currently. */
150 bool fBlocking;
151#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
152 /** The pollset currently polling this socket. This is NIL if no one is
153 * polling. */
154 RTPOLLSET hPollSet;
155#endif
156#ifdef RT_OS_WINDOWS
157 /** The event semaphore we've associated with the socket handle.
158 * This is WSA_INVALID_EVENT if not done. */
159 WSAEVENT hEvent;
160 /** The events we're polling for. */
161 uint32_t fPollEvts;
162 /** The events we're currently subscribing to with WSAEventSelect.
163 * This is ZERO if we're currently not subscribing to anything. */
164 uint32_t fSubscribedEvts;
165 /** Saved events which are only posted once. */
166 uint32_t fEventsSaved;
167#endif /* RT_OS_WINDOWS */
168} RTSOCKETINT;
169
170
171/**
172 * Address union used internally for things like getpeername and getsockname.
173 */
174typedef union RTSOCKADDRUNION
175{
176 struct sockaddr Addr;
177 struct sockaddr_in IPv4;
178#ifdef IPRT_WITH_TCPIP_V6
179 struct sockaddr_in6 IPv6;
180#endif
181} RTSOCKADDRUNION;
182
183
184/**
185 * Get the last error as an iprt status code.
186 *
187 * @returns IPRT status code.
188 */
189DECLINLINE(int) rtSocketError(void)
190{
191#ifdef RT_OS_WINDOWS
192 if (g_pfnWSAGetLastError)
193 return RTErrConvertFromWin32(g_pfnWSAGetLastError());
194 return VERR_NET_IO_ERROR;
195#else
196 return RTErrConvertFromErrno(errno);
197#endif
198}
199
200
201/**
202 * Resets the last error.
203 */
204DECLINLINE(void) rtSocketErrorReset(void)
205{
206#ifdef RT_OS_WINDOWS
207 if (g_pfnWSASetLastError)
208 g_pfnWSASetLastError(0);
209#else
210 errno = 0;
211#endif
212}
213
214
215/**
216 * Get the last resolver error as an iprt status code.
217 *
218 * @returns iprt status code.
219 */
220DECLHIDDEN(int) rtSocketResolverError(void)
221{
222#ifdef RT_OS_WINDOWS
223 if (g_pfnWSAGetLastError)
224 return RTErrConvertFromWin32(g_pfnWSAGetLastError());
225 return VERR_UNRESOLVED_ERROR;
226#else
227 switch (h_errno)
228 {
229 case HOST_NOT_FOUND:
230 return VERR_NET_HOST_NOT_FOUND;
231 case NO_DATA:
232 return VERR_NET_ADDRESS_NOT_AVAILABLE;
233 case NO_RECOVERY:
234 return VERR_IO_GEN_FAILURE;
235 case TRY_AGAIN:
236 return VERR_TRY_AGAIN;
237
238 default:
239 AssertLogRelMsgFailed(("Unhandled error %u\n", h_errno));
240 return VERR_UNRESOLVED_ERROR;
241 }
242#endif
243}
244
245
246/**
247 * Converts from a native socket address to a generic IPRT network address.
248 *
249 * @returns IPRT status code.
250 * @param pSrc The source address.
251 * @param cbSrc The size of the source address.
252 * @param pAddr Where to return the generic IPRT network
253 * address.
254 */
255static int rtSocketNetAddrFromAddr(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr)
256{
257 /*
258 * Convert the address.
259 */
260 if ( cbSrc == sizeof(struct sockaddr_in)
261 && pSrc->Addr.sa_family == AF_INET)
262 {
263 RT_ZERO(*pAddr);
264 pAddr->enmType = RTNETADDRTYPE_IPV4;
265 pAddr->uPort = RT_N2H_U16(pSrc->IPv4.sin_port);
266 pAddr->uAddr.IPv4.u = pSrc->IPv4.sin_addr.s_addr;
267 }
268#ifdef IPRT_WITH_TCPIP_V6
269 else if ( cbSrc == sizeof(struct sockaddr_in6)
270 && pSrc->Addr.sa_family == AF_INET6)
271 {
272 RT_ZERO(*pAddr);
273 pAddr->enmType = RTNETADDRTYPE_IPV6;
274 pAddr->uPort = RT_N2H_U16(pSrc->IPv6.sin6_port);
275 pAddr->uAddr.IPv6.au32[0] = pSrc->IPv6.sin6_addr.s6_addr32[0];
276 pAddr->uAddr.IPv6.au32[1] = pSrc->IPv6.sin6_addr.s6_addr32[1];
277 pAddr->uAddr.IPv6.au32[2] = pSrc->IPv6.sin6_addr.s6_addr32[2];
278 pAddr->uAddr.IPv6.au32[3] = pSrc->IPv6.sin6_addr.s6_addr32[3];
279 }
280#endif
281 else
282 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
283 return VINF_SUCCESS;
284}
285
286
287/**
288 * Converts from a generic IPRT network address to a native socket address.
289 *
290 * @returns IPRT status code.
291 * @param pAddr Pointer to the generic IPRT network address.
292 * @param pDst The source address.
293 * @param cbDst The size of the source address.
294 * @param pcbAddr Where to store the size of the returned address.
295 * Optional
296 */
297static int rtSocketAddrFromNetAddr(PCRTNETADDR pAddr, RTSOCKADDRUNION *pDst, size_t cbDst, int *pcbAddr)
298{
299 RT_BZERO(pDst, cbDst);
300 if ( pAddr->enmType == RTNETADDRTYPE_IPV4
301 && cbDst >= sizeof(struct sockaddr_in))
302 {
303 pDst->Addr.sa_family = AF_INET;
304 pDst->IPv4.sin_port = RT_H2N_U16(pAddr->uPort);
305 pDst->IPv4.sin_addr.s_addr = pAddr->uAddr.IPv4.u;
306 if (pcbAddr)
307 *pcbAddr = sizeof(pDst->IPv4);
308 }
309#ifdef IPRT_WITH_TCPIP_V6
310 else if ( pAddr->enmType == RTNETADDRTYPE_IPV6
311 && cbDst >= sizeof(struct sockaddr_in6))
312 {
313 pDst->Addr.sa_family = AF_INET6;
314 pDst->IPv6.sin6_port = RT_H2N_U16(pAddr->uPort);
315 pSrc->IPv6.sin6_addr.s6_addr32[0] = pAddr->uAddr.IPv6.au32[0];
316 pSrc->IPv6.sin6_addr.s6_addr32[1] = pAddr->uAddr.IPv6.au32[1];
317 pSrc->IPv6.sin6_addr.s6_addr32[2] = pAddr->uAddr.IPv6.au32[2];
318 pSrc->IPv6.sin6_addr.s6_addr32[3] = pAddr->uAddr.IPv6.au32[3];
319 if (pcbAddr)
320 *pcbAddr = sizeof(pDst->IPv6);
321 }
322#endif
323 else
324 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
325 return VINF_SUCCESS;
326}
327
328
329/**
330 * Tries to lock the socket for exclusive usage by the calling thread.
331 *
332 * Call rtSocketUnlock() to unlock.
333 *
334 * @returns @c true if locked, @c false if not.
335 * @param pThis The socket structure.
336 */
337DECLINLINE(bool) rtSocketTryLock(RTSOCKETINT *pThis)
338{
339 return ASMAtomicCmpXchgU32(&pThis->cUsers, 1, 0);
340}
341
342
343/**
344 * Unlocks the socket.
345 *
346 * @param pThis The socket structure.
347 */
348DECLINLINE(void) rtSocketUnlock(RTSOCKETINT *pThis)
349{
350 ASMAtomicCmpXchgU32(&pThis->cUsers, 0, 1);
351}
352
353
354/**
355 * The slow path of rtSocketSwitchBlockingMode that does the actual switching.
356 *
357 * @returns IPRT status code.
358 * @param pThis The socket structure.
359 * @param fBlocking The desired mode of operation.
360 * @remarks Do not call directly.
361 */
362static int rtSocketSwitchBlockingModeSlow(RTSOCKETINT *pThis, bool fBlocking)
363{
364#ifdef RT_OS_WINDOWS
365 AssertReturn(g_pfnioctlsocket, VERR_NOT_SUPPORTED);
366 u_long uBlocking = fBlocking ? 0 : 1;
367 if (g_pfnioctlsocket(pThis->hNative, FIONBIO, &uBlocking))
368 return rtSocketError();
369
370#else
371 int fFlags = fcntl(pThis->hNative, F_GETFL, 0);
372 if (fFlags == -1)
373 return rtSocketError();
374
375 if (fBlocking)
376 fFlags &= ~O_NONBLOCK;
377 else
378 fFlags |= O_NONBLOCK;
379 if (fcntl(pThis->hNative, F_SETFL, fFlags) == -1)
380 return rtSocketError();
381#endif
382
383 pThis->fBlocking = fBlocking;
384 return VINF_SUCCESS;
385}
386
387
388/**
389 * Switches the socket to the desired blocking mode if necessary.
390 *
391 * The socket must be locked.
392 *
393 * @returns IPRT status code.
394 * @param pThis The socket structure.
395 * @param fBlocking The desired mode of operation.
396 */
397DECLINLINE(int) rtSocketSwitchBlockingMode(RTSOCKETINT *pThis, bool fBlocking)
398{
399 if (pThis->fBlocking != fBlocking)
400 return rtSocketSwitchBlockingModeSlow(pThis, fBlocking);
401 return VINF_SUCCESS;
402}
403
404
405/**
406 * Creates an IPRT socket handle for a native one.
407 *
408 * @returns IPRT status code.
409 * @param ppSocket Where to return the IPRT socket handle.
410 * @param hNative The native handle.
411 */
412DECLHIDDEN(int) rtSocketCreateForNative(RTSOCKETINT **ppSocket, RTSOCKETNATIVE hNative)
413{
414 RTSOCKETINT *pThis = (RTSOCKETINT *)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pThis));
415 if (!pThis)
416 return VERR_NO_MEMORY;
417 pThis->u32Magic = RTSOCKET_MAGIC;
418 pThis->cUsers = 0;
419 pThis->hNative = hNative;
420 pThis->fClosed = false;
421 pThis->fBlocking = true;
422#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
423 pThis->hPollSet = NIL_RTPOLLSET;
424#endif
425#ifdef RT_OS_WINDOWS
426 pThis->hEvent = WSA_INVALID_EVENT;
427 pThis->fPollEvts = 0;
428 pThis->fSubscribedEvts = 0;
429 pThis->fEventsSaved = 0;
430#endif
431 *ppSocket = pThis;
432 return VINF_SUCCESS;
433}
434
435
436RTDECL(int) RTSocketFromNative(PRTSOCKET phSocket, RTHCINTPTR uNative)
437{
438 AssertReturn(uNative != NIL_RTSOCKETNATIVE, VERR_INVALID_PARAMETER);
439#ifndef RT_OS_WINDOWS
440 AssertReturn(uNative >= 0, VERR_INVALID_PARAMETER);
441#endif
442 AssertPtrReturn(phSocket, VERR_INVALID_POINTER);
443 return rtSocketCreateForNative(phSocket, uNative);
444}
445
446
447/**
448 * Wrapper around socket().
449 *
450 * @returns IPRT status code.
451 * @param phSocket Where to store the handle to the socket on
452 * success.
453 * @param iDomain The protocol family (PF_XXX).
454 * @param iType The socket type (SOCK_XXX).
455 * @param iProtocol Socket parameter, usually 0.
456 */
457DECLHIDDEN(int) rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
458{
459#ifdef RT_OS_WINDOWS
460 AssertReturn(g_pfnsocket, VERR_NOT_SUPPORTED);
461 AssertReturn(g_pfnclosesocket, VERR_NOT_SUPPORTED);
462 AssertReturn(g_pfnWSAStartup, VERR_NOT_SUPPORTED);
463
464 /* Initialize WinSock. */
465 WORD const wVersionRequested = MAKEWORD(1, 1);
466 WSADATA wsaData;
467 RT_ZERO(wsaData);
468 int rcWsa = g_pfnWSAStartup(wVersionRequested, &wsaData);
469 AssertMsgReturn(wsaData.wVersion >= wVersionRequested && rcWsa == 0,
470 ("Wrong winsock version %#x rcWsa=%#x (%d)\n", wsaData.wVersion, rcWsa, rcWsa),
471 VERR_NOT_SUPPORTED);
472#endif
473
474 /*
475 * Create the socket.
476 */
477#ifdef RT_OS_WINDOWS
478 RTSOCKETNATIVE hNative = g_pfnsocket(iDomain, iType, iProtocol);
479#else
480 RTSOCKETNATIVE hNative = socket(iDomain, iType, iProtocol);
481#endif
482 if (hNative == NIL_RTSOCKETNATIVE)
483 return rtSocketError();
484
485 /*
486 * Wrap it.
487 */
488 int rc = rtSocketCreateForNative(phSocket, hNative);
489 if (RT_FAILURE(rc))
490 {
491#ifdef RT_OS_WINDOWS
492 g_pfnclosesocket(hNative);
493#else
494 close(hNative);
495#endif
496 }
497 return rc;
498}
499
500
501RTDECL(uint32_t) RTSocketRetain(RTSOCKET hSocket)
502{
503 RTSOCKETINT *pThis = hSocket;
504 AssertPtrReturn(pThis, UINT32_MAX);
505 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
506 return RTMemPoolRetain(pThis);
507}
508
509
510/**
511 * Worker for RTSocketRelease and RTSocketClose.
512 *
513 * @returns IPRT status code.
514 * @param pThis The socket handle instance data.
515 * @param fDestroy Whether we're reaching ref count zero.
516 */
517static int rtSocketCloseIt(RTSOCKETINT *pThis, bool fDestroy)
518{
519 /*
520 * Invalidate the handle structure on destroy.
521 */
522 if (fDestroy)
523 {
524 Assert(ASMAtomicReadU32(&pThis->u32Magic) == RTSOCKET_MAGIC);
525 ASMAtomicWriteU32(&pThis->u32Magic, RTSOCKET_MAGIC_DEAD);
526 }
527
528 int rc = VINF_SUCCESS;
529 if (ASMAtomicCmpXchgBool(&pThis->fClosed, true, false))
530 {
531 /*
532 * Close the native handle.
533 */
534 RTSOCKETNATIVE hNative = pThis->hNative;
535 if (hNative != NIL_RTSOCKETNATIVE)
536 {
537 pThis->hNative = NIL_RTSOCKETNATIVE;
538
539#ifdef RT_OS_WINDOWS
540 AssertReturn(g_pfnclosesocket, VERR_NOT_SUPPORTED);
541 if (g_pfnclosesocket(hNative))
542#else
543 if (close(hNative))
544#endif
545 {
546 rc = rtSocketError();
547#ifdef RT_OS_WINDOWS
548 AssertMsgFailed(("closesocket(%p) -> %Rrc\n", (uintptr_t)hNative, rc));
549#else
550 AssertMsgFailed(("close(%d) -> %Rrc\n", hNative, rc));
551#endif
552 }
553 }
554
555#ifdef RT_OS_WINDOWS
556 /*
557 * Close the event.
558 */
559 WSAEVENT hEvent = pThis->hEvent;
560 if (hEvent != WSA_INVALID_EVENT)
561 {
562 pThis->hEvent = WSA_INVALID_EVENT;
563 Assert(g_pfnWSACloseEvent);
564 if (g_pfnWSACloseEvent)
565 g_pfnWSACloseEvent(hEvent);
566 }
567#endif
568 }
569
570 return rc;
571}
572
573
574RTDECL(uint32_t) RTSocketRelease(RTSOCKET hSocket)
575{
576 RTSOCKETINT *pThis = hSocket;
577 if (pThis == NIL_RTSOCKET)
578 return 0;
579 AssertPtrReturn(pThis, UINT32_MAX);
580 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
581
582 /* get the refcount without killing it... */
583 uint32_t cRefs = RTMemPoolRefCount(pThis);
584 AssertReturn(cRefs != UINT32_MAX, UINT32_MAX);
585 if (cRefs == 1)
586 rtSocketCloseIt(pThis, true);
587
588 return RTMemPoolRelease(RTMEMPOOL_DEFAULT, pThis);
589}
590
591
592RTDECL(int) RTSocketClose(RTSOCKET hSocket)
593{
594 RTSOCKETINT *pThis = hSocket;
595 if (pThis == NIL_RTSOCKET)
596 return VINF_SUCCESS;
597 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
598 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
599
600 uint32_t cRefs = RTMemPoolRefCount(pThis);
601 AssertReturn(cRefs != UINT32_MAX, UINT32_MAX);
602
603 int rc = rtSocketCloseIt(pThis, cRefs == 1);
604
605 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pThis);
606 return rc;
607}
608
609
610RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket)
611{
612 RTSOCKETINT *pThis = hSocket;
613 AssertPtrReturn(pThis, RTHCUINTPTR_MAX);
614 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, RTHCUINTPTR_MAX);
615 return (RTHCUINTPTR)pThis->hNative;
616}
617
618
619RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
620{
621 RTSOCKETINT *pThis = hSocket;
622 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
623 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
624 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
625
626 int rc = VINF_SUCCESS;
627#ifdef RT_OS_WINDOWS
628 if (!SetHandleInformation((HANDLE)pThis->hNative, HANDLE_FLAG_INHERIT, fInheritable ? HANDLE_FLAG_INHERIT : 0))
629 rc = RTErrConvertFromWin32(GetLastError());
630#else
631 if (fcntl(pThis->hNative, F_SETFD, fInheritable ? 0 : FD_CLOEXEC) < 0)
632 rc = RTErrConvertFromErrno(errno);
633#endif
634
635 return rc;
636}
637
638
639static bool rtSocketIsIPv4Numerical(const char *pszAddress, PRTNETADDRIPV4 pAddr)
640{
641
642 /* Empty address resolves to the INADDR_ANY address (good for bind). */
643 if (!pszAddress || !*pszAddress)
644 {
645 pAddr->u = INADDR_ANY;
646 return true;
647 }
648
649 /* Four quads? */
650 char *psz = (char *)pszAddress;
651 for (int i = 0; i < 4; i++)
652 {
653 uint8_t u8;
654 int rc = RTStrToUInt8Ex(psz, &psz, 0, &u8);
655 if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS)
656 return false;
657 if (*psz != (i < 3 ? '.' : '\0'))
658 return false;
659 psz++;
660
661 pAddr->au8[i] = u8; /* big endian */
662 }
663
664 return true;
665}
666
667RTDECL(int) RTSocketParseInetAddress(const char *pszAddress, unsigned uPort, PRTNETADDR pAddr)
668{
669 int rc;
670
671 /*
672 * Validate input.
673 */
674 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
675 AssertPtrNullReturn(pszAddress, VERR_INVALID_POINTER);
676
677 /*
678 * Resolve the address. Pretty crude at the moment, but we have to make
679 * sure to not ask the NT 4 gethostbyname about an IPv4 address as it may
680 * give a wrong answer.
681 */
682 /** @todo this only supports IPv4, and IPv6 support needs to be added.
683 * It probably needs to be converted to getaddrinfo(). */
684 RTNETADDRIPV4 IPv4Quad;
685 if (rtSocketIsIPv4Numerical(pszAddress, &IPv4Quad))
686 {
687 Log3(("rtSocketIsIPv4Numerical: %s -> %#x (%RTnaipv4)\n", pszAddress, IPv4Quad.u, IPv4Quad));
688 RT_ZERO(*pAddr);
689 pAddr->enmType = RTNETADDRTYPE_IPV4;
690 pAddr->uPort = uPort;
691 pAddr->uAddr.IPv4 = IPv4Quad;
692 return VINF_SUCCESS;
693 }
694
695#ifdef RT_OS_WINDOWS
696 /* Initialize WinSock and check version before we call gethostbyname. */
697 if ( !g_pfnWSAStartup
698 || !g_pfngethostbyname)
699 return VERR_NOT_SUPPORTED;
700 WORD const wVersionRequested = MAKEWORD(1, 1);
701 WSADATA wsaData;
702 RT_ZERO(wsaData);
703 int rcWsa = g_pfnWSAStartup(wVersionRequested, &wsaData);
704 AssertMsgReturn(wsaData.wVersion >= wVersionRequested && rcWsa == 0,
705 ("Wrong winsock version %#x rcWsa=%#x (%d)\n", wsaData.wVersion, rcWsa, rcWsa),
706 VERR_NOT_SUPPORTED);
707# define gethostbyname g_pfngethostbyname
708#endif
709
710 struct hostent *pHostEnt;
711 pHostEnt = gethostbyname(pszAddress);
712 if (!pHostEnt)
713 {
714 rc = rtSocketResolverError();
715 AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
716 return rc;
717 }
718
719 if (pHostEnt->h_addrtype == AF_INET)
720 {
721 RT_ZERO(*pAddr);
722 pAddr->enmType = RTNETADDRTYPE_IPV4;
723 pAddr->uPort = uPort;
724 pAddr->uAddr.IPv4.u = ((struct in_addr *)pHostEnt->h_addr)->s_addr;
725 Log3(("gethostbyname: %s -> %#x (%RTnaipv4)\n", pszAddress, pAddr->uAddr.IPv4.u, pAddr->uAddr.IPv4));
726 }
727 else
728 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
729
730#ifdef RT_OS_WINDOWS
731# undef gethostbyname
732#endif
733 return VINF_SUCCESS;
734}
735
736
737/*
738 * New function to allow both ipv4 and ipv6 addresses to be resolved.
739 * Breaks compatibility with windows before 2000.
740 */
741RTDECL(int) RTSocketQueryAddressStr(const char *pszHost, char *pszResult, size_t *pcbResult, PRTNETADDRTYPE penmAddrType)
742{
743 AssertPtrReturn(pszHost, VERR_INVALID_POINTER);
744 AssertPtrReturn(pcbResult, VERR_INVALID_POINTER);
745 AssertPtrNullReturn(penmAddrType, VERR_INVALID_POINTER);
746 AssertPtrNullReturn(pszResult, VERR_INVALID_POINTER);
747
748#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) /** @todo dynamically resolve the APIs not present in NT4! */
749 return VERR_NOT_SUPPORTED;
750
751#else
752 int rc;
753 if (*pcbResult < 16)
754 return VERR_NET_ADDRESS_NOT_AVAILABLE;
755
756 /* Setup the hint. */
757 struct addrinfo grHints;
758 RT_ZERO(grHints);
759 grHints.ai_socktype = 0;
760 grHints.ai_flags = 0;
761 grHints.ai_protocol = 0;
762 grHints.ai_family = AF_UNSPEC;
763 if (penmAddrType)
764 {
765 switch (*penmAddrType)
766 {
767 case RTNETADDRTYPE_INVALID:
768 /*grHints.ai_family = AF_UNSPEC;*/
769 break;
770 case RTNETADDRTYPE_IPV4:
771 grHints.ai_family = AF_INET;
772 break;
773 case RTNETADDRTYPE_IPV6:
774 grHints.ai_family = AF_INET6;
775 break;
776 default:
777 AssertFailedReturn(VERR_INVALID_PARAMETER);
778 }
779 }
780
781# ifdef RT_OS_WINDOWS
782 /*
783 * Winsock2 init
784 */
785 if ( !g_pfnWSAStartup
786 || !g_pfngetaddrinfo
787 || !g_pfnfreeaddrinfo)
788 return VERR_NOT_SUPPORTED;
789 /** @todo someone should check if we really need 2, 2 here */
790 WORD const wVersionRequested = MAKEWORD(2, 2);
791 WSADATA wsaData;
792 RT_ZERO(wsaData);
793 int rcWsa = g_pfnWSAStartup(wVersionRequested, &wsaData);
794 AssertMsgReturn(wsaData.wVersion >= wVersionRequested && rcWsa == 0,
795 ("Wrong winsock version %#x rcWsa=%#x (%d)\n", wsaData.wVersion, rcWsa, rcWsa),
796 VERR_NOT_SUPPORTED);
797# define getaddrinfo g_pfngetaddrinfo
798# define freeaddrinfo g_pfnfreeaddrinfo
799# endif
800
801 /** @todo r=bird: getaddrinfo and freeaddrinfo breaks the additions on NT4. */
802 struct addrinfo *pgrResults = NULL;
803 rc = getaddrinfo(pszHost, "", &grHints, &pgrResults);
804 if (rc != 0)
805 return VERR_NET_ADDRESS_NOT_AVAILABLE;
806
807 // return data
808 // on multiple matches return only the first one
809
810 if (!pgrResults)
811 return VERR_NET_ADDRESS_NOT_AVAILABLE;
812
813 struct addrinfo const *pgrResult = pgrResults->ai_next;
814 if (!pgrResult)
815 {
816 freeaddrinfo(pgrResults);
817 return VERR_NET_ADDRESS_NOT_AVAILABLE;
818 }
819
820 RTNETADDRTYPE enmAddrType = RTNETADDRTYPE_INVALID;
821 size_t cchIpAddress;
822 char szIpAddress[48];
823 if (pgrResult->ai_family == AF_INET)
824 {
825 struct sockaddr_in const *pgrSa = (struct sockaddr_in const *)pgrResult->ai_addr;
826 cchIpAddress = RTStrPrintf(szIpAddress, sizeof(szIpAddress),
827 "%RTnaipv4", pgrSa->sin_addr.s_addr);
828 Assert(cchIpAddress >= 7 && cchIpAddress < sizeof(szIpAddress) - 1);
829 enmAddrType = RTNETADDRTYPE_IPV4;
830 rc = VINF_SUCCESS;
831 }
832 else if (pgrResult->ai_family == AF_INET6)
833 {
834 struct sockaddr_in6 const *pgrSa6 = (struct sockaddr_in6 const *)pgrResult->ai_addr;
835 cchIpAddress = RTStrPrintf(szIpAddress, sizeof(szIpAddress),
836 "%RTnaipv6", (PRTNETADDRIPV6)&pgrSa6->sin6_addr);
837 enmAddrType = RTNETADDRTYPE_IPV6;
838 rc = VINF_SUCCESS;
839 }
840 else
841 {
842 rc = VERR_NET_ADDRESS_NOT_AVAILABLE;
843 szIpAddress[0] = '\0';
844 cchIpAddress = 0;
845 }
846 freeaddrinfo(pgrResults);
847
848 /*
849 * Copy out the result.
850 */
851 size_t const cbResult = *pcbResult;
852 *pcbResult = cchIpAddress + 1;
853 if (cchIpAddress < cbResult)
854 memcpy(pszResult, szIpAddress, cchIpAddress + 1);
855 else
856 {
857 RT_BZERO(pszResult, cbResult);
858 if (RT_SUCCESS(rc))
859 rc = VERR_BUFFER_OVERFLOW;
860 }
861 if (penmAddrType && RT_SUCCESS(rc))
862 *penmAddrType = enmAddrType;
863 return rc;
864
865# ifdef RT_OS_WINDOWS
866# undef getaddrinfo
867# undef freeaddrinfo
868# endif
869#endif /* !RT_OS_OS2 */
870}
871
872
873RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
874{
875 /*
876 * Validate input.
877 */
878 RTSOCKETINT *pThis = hSocket;
879 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
880 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
881 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
882 AssertPtr(pvBuffer);
883#ifdef RT_OS_WINDOWS
884 AssertReturn(g_pfnrecv, VERR_NOT_SUPPORTED);
885# define recv g_pfnrecv
886#endif
887 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
888
889 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
890 if (RT_FAILURE(rc))
891 return rc;
892
893 /*
894 * Read loop.
895 * If pcbRead is NULL we have to fill the entire buffer!
896 */
897 size_t cbRead = 0;
898 size_t cbToRead = cbBuffer;
899 for (;;)
900 {
901 rtSocketErrorReset();
902#ifdef RTSOCKET_MAX_READ
903 int cbNow = cbToRead >= RTSOCKET_MAX_READ ? RTSOCKET_MAX_READ : (int)cbToRead;
904#else
905 size_t cbNow = cbToRead;
906#endif
907 ssize_t cbBytesRead = recv(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
908 if (cbBytesRead <= 0)
909 {
910 rc = rtSocketError();
911 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
912 if (RT_SUCCESS_NP(rc))
913 {
914 if (!pcbRead)
915 rc = VERR_NET_SHUTDOWN;
916 else
917 {
918 *pcbRead = 0;
919 rc = VINF_SUCCESS;
920 }
921 }
922 break;
923 }
924 if (pcbRead)
925 {
926 /* return partial data */
927 *pcbRead = cbBytesRead;
928 break;
929 }
930
931 /* read more? */
932 cbRead += cbBytesRead;
933 if (cbRead == cbBuffer)
934 break;
935
936 /* next */
937 cbToRead = cbBuffer - cbRead;
938 }
939
940 rtSocketUnlock(pThis);
941#ifdef RT_OS_WINDOWS
942# undef recv
943#endif
944 return rc;
945}
946
947
948RTDECL(int) RTSocketReadFrom(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr)
949{
950 /*
951 * Validate input.
952 */
953 RTSOCKETINT *pThis = hSocket;
954 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
955 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
956 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
957 AssertPtr(pvBuffer);
958 AssertPtr(pcbRead);
959#ifdef RT_OS_WINDOWS
960 AssertReturn(g_pfnrecvfrom, VERR_NOT_SUPPORTED);
961# define recvfrom g_pfnrecvfrom
962#endif
963 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
964
965 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
966 if (RT_FAILURE(rc))
967 return rc;
968
969 /*
970 * Read data.
971 */
972 size_t cbRead = 0;
973 size_t cbToRead = cbBuffer;
974 rtSocketErrorReset();
975 RTSOCKADDRUNION u;
976#ifdef RTSOCKET_MAX_READ
977 int cbNow = cbToRead >= RTSOCKET_MAX_READ ? RTSOCKET_MAX_READ : (int)cbToRead;
978 int cbAddr = sizeof(u);
979#else
980 size_t cbNow = cbToRead;
981 socklen_t cbAddr = sizeof(u);
982#endif
983 ssize_t cbBytesRead = recvfrom(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL, &u.Addr, &cbAddr);
984 if (cbBytesRead <= 0)
985 {
986 rc = rtSocketError();
987 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
988 if (RT_SUCCESS_NP(rc))
989 {
990 *pcbRead = 0;
991 rc = VINF_SUCCESS;
992 }
993 }
994 else
995 {
996 if (pSrcAddr)
997 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pSrcAddr);
998 *pcbRead = cbBytesRead;
999 }
1000
1001 rtSocketUnlock(pThis);
1002#ifdef RT_OS_WINDOWS
1003# undef recvfrom
1004#endif
1005 return rc;
1006}
1007
1008
1009RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
1010{
1011 /*
1012 * Validate input.
1013 */
1014 RTSOCKETINT *pThis = hSocket;
1015 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1016 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1017#ifdef RT_OS_WINDOWS
1018 AssertReturn(g_pfnsend, VERR_NOT_SUPPORTED);
1019# define send g_pfnsend
1020#endif
1021 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1022
1023 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
1024 if (RT_FAILURE(rc))
1025 return rc;
1026
1027 /*
1028 * Try write all at once.
1029 */
1030#ifdef RTSOCKET_MAX_WRITE
1031 int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
1032#else
1033 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1034#endif
1035 ssize_t cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1036 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
1037 rc = VINF_SUCCESS;
1038 else if (cbWritten < 0)
1039 rc = rtSocketError();
1040 else
1041 {
1042 /*
1043 * Unfinished business, write the remainder of the request. Must ignore
1044 * VERR_INTERRUPTED here if we've managed to send something.
1045 */
1046 size_t cbSentSoFar = 0;
1047 for (;;)
1048 {
1049 /* advance */
1050 cbBuffer -= (size_t)cbWritten;
1051 if (!cbBuffer)
1052 break;
1053 cbSentSoFar += (size_t)cbWritten;
1054 pvBuffer = (char const *)pvBuffer + cbWritten;
1055
1056 /* send */
1057#ifdef RTSOCKET_MAX_WRITE
1058 cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
1059#else
1060 cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1061#endif
1062 cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1063 if (cbWritten >= 0)
1064 AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtSocketError()=%d\n",
1065 cbWritten, cbBuffer, rtSocketError()));
1066 else
1067 {
1068 rc = rtSocketError();
1069 if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
1070 break;
1071 cbWritten = 0;
1072 rc = VINF_SUCCESS;
1073 }
1074 }
1075 }
1076
1077 rtSocketUnlock(pThis);
1078#ifdef RT_OS_WINDOWS
1079# undef send
1080#endif
1081 return rc;
1082}
1083
1084
1085RTDECL(int) RTSocketWriteTo(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pAddr)
1086{
1087 /*
1088 * Validate input.
1089 */
1090 RTSOCKETINT *pThis = hSocket;
1091 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1092 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1093#ifdef RT_OS_WINDOWS
1094 AssertReturn(g_pfnsendto, VERR_NOT_SUPPORTED);
1095# define sendto g_pfnsendto
1096#endif
1097
1098 /* no locking since UDP reads may be done concurrently to writes, and
1099 * this is the normal use case of this code. */
1100
1101 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
1102 if (RT_FAILURE(rc))
1103 return rc;
1104
1105 /* Figure out destination address. */
1106 struct sockaddr *pSA = NULL;
1107#ifdef RT_OS_WINDOWS
1108 int cbSA = 0;
1109#else
1110 socklen_t cbSA = 0;
1111#endif
1112 RTSOCKADDRUNION u;
1113 if (pAddr)
1114 {
1115 rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), NULL);
1116 if (RT_FAILURE(rc))
1117 return rc;
1118 pSA = &u.Addr;
1119 cbSA = sizeof(u);
1120 }
1121
1122 /*
1123 * Must write all at once, otherwise it is a failure.
1124 */
1125#ifdef RT_OS_WINDOWS
1126 int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
1127#else
1128 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1129#endif
1130 ssize_t cbWritten = sendto(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL, pSA, cbSA);
1131 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
1132 rc = VINF_SUCCESS;
1133 else if (cbWritten < 0)
1134 rc = rtSocketError();
1135 else
1136 rc = VERR_TOO_MUCH_DATA;
1137
1138 /// @todo rtSocketUnlock(pThis);
1139#ifdef RT_OS_WINDOWS
1140# undef sendto
1141#endif
1142 return rc;
1143}
1144
1145
1146RTDECL(int) RTSocketWriteToNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pAddr)
1147{
1148 /*
1149 * Validate input.
1150 */
1151 RTSOCKETINT *pThis = hSocket;
1152 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1153 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1154#ifdef RT_OS_WINDOWS
1155 AssertReturn(g_pfnsendto, VERR_NOT_SUPPORTED);
1156# define sendto g_pfnsendto
1157#endif
1158
1159 /* no locking since UDP reads may be done concurrently to writes, and
1160 * this is the normal use case of this code. */
1161
1162 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1163 if (RT_FAILURE(rc))
1164 return rc;
1165
1166 /* Figure out destination address. */
1167 struct sockaddr *pSA = NULL;
1168#ifdef RT_OS_WINDOWS
1169 int cbSA = 0;
1170#else
1171 socklen_t cbSA = 0;
1172#endif
1173 RTSOCKADDRUNION u;
1174 if (pAddr)
1175 {
1176 rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), NULL);
1177 if (RT_FAILURE(rc))
1178 return rc;
1179 pSA = &u.Addr;
1180 cbSA = sizeof(u);
1181 }
1182
1183 /*
1184 * Must write all at once, otherwise it is a failure.
1185 */
1186#ifdef RT_OS_WINDOWS
1187 int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
1188#else
1189 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1190#endif
1191 ssize_t cbWritten = sendto(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL, pSA, cbSA);
1192 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
1193 rc = VINF_SUCCESS;
1194 else if (cbWritten < 0)
1195 rc = rtSocketError();
1196 else
1197 rc = VERR_TOO_MUCH_DATA;
1198
1199 /// @todo rtSocketUnlock(pThis);
1200#ifdef RT_OS_WINDOWS
1201# undef sendto
1202#endif
1203 return rc;
1204}
1205
1206
1207RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf)
1208{
1209 /*
1210 * Validate input.
1211 */
1212 RTSOCKETINT *pThis = hSocket;
1213 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1214 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1215 AssertPtrReturn(pSgBuf, VERR_INVALID_PARAMETER);
1216 AssertReturn(pSgBuf->cSegs > 0, VERR_INVALID_PARAMETER);
1217 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1218
1219 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
1220 if (RT_FAILURE(rc))
1221 return rc;
1222
1223 /*
1224 * Construct message descriptor (translate pSgBuf) and send it.
1225 */
1226 rc = VERR_NO_TMP_MEMORY;
1227#ifdef RT_OS_WINDOWS
1228 if (g_pfnWSASend)
1229 {
1230 AssertCompileSize(WSABUF, sizeof(RTSGSEG));
1231 AssertCompileMemberSize(WSABUF, buf, RT_SIZEOFMEMB(RTSGSEG, pvSeg));
1232
1233 LPWSABUF paMsg = (LPWSABUF)RTMemTmpAllocZ(pSgBuf->cSegs * sizeof(WSABUF));
1234 if (paMsg)
1235 {
1236 for (unsigned i = 0; i < pSgBuf->cSegs; i++)
1237 {
1238 paMsg[i].buf = (char *)pSgBuf->paSegs[i].pvSeg;
1239 paMsg[i].len = (u_long)pSgBuf->paSegs[i].cbSeg;
1240 }
1241
1242 DWORD dwSent;
1243 int hrc = g_pfnWSASend(pThis->hNative, paMsg, pSgBuf->cSegs, &dwSent, MSG_NOSIGNAL, NULL, NULL);
1244 if (!hrc)
1245 rc = VINF_SUCCESS;
1246 /** @todo check for incomplete writes */
1247 else
1248 rc = rtSocketError();
1249
1250 RTMemTmpFree(paMsg);
1251 }
1252 }
1253 else if (g_pfnsend)
1254 {
1255 rc = VINF_SUCCESS;
1256 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
1257 {
1258 uint8_t const *pbSeg = (uint8_t const *)pSgBuf->paSegs[iSeg].pvSeg;
1259 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
1260 int cbNow;
1261 ssize_t cbWritten;
1262 for (;;)
1263 {
1264 cbNow = cbSeg >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbSeg;
1265 cbWritten = g_pfnsend(pThis->hNative, (const char *)pbSeg, cbNow, MSG_NOSIGNAL);
1266 if ((size_t)cbWritten >= cbSeg || cbWritten < 0)
1267 break;
1268 pbSeg += cbWritten;
1269 cbSeg -= cbWritten;
1270 }
1271 if (cbWritten < 0)
1272 {
1273 rc = rtSocketError();
1274 break;
1275 }
1276 }
1277 }
1278 else
1279 rc = VERR_NOT_SUPPORTED;
1280
1281#else /* !RT_OS_WINDOWS */
1282 AssertCompileSize(struct iovec, sizeof(RTSGSEG));
1283 AssertCompileMemberSize(struct iovec, iov_base, RT_SIZEOFMEMB(RTSGSEG, pvSeg));
1284 AssertCompileMemberSize(struct iovec, iov_len, RT_SIZEOFMEMB(RTSGSEG, cbSeg));
1285
1286 struct iovec *paMsg = (struct iovec *)RTMemTmpAllocZ(pSgBuf->cSegs * sizeof(struct iovec));
1287 if (paMsg)
1288 {
1289 for (unsigned i = 0; i < pSgBuf->cSegs; i++)
1290 {
1291 paMsg[i].iov_base = pSgBuf->paSegs[i].pvSeg;
1292 paMsg[i].iov_len = pSgBuf->paSegs[i].cbSeg;
1293 }
1294
1295 struct msghdr msgHdr;
1296 RT_ZERO(msgHdr);
1297 msgHdr.msg_iov = paMsg;
1298 msgHdr.msg_iovlen = pSgBuf->cSegs;
1299 ssize_t cbWritten = sendmsg(pThis->hNative, &msgHdr, MSG_NOSIGNAL);
1300 if (RT_LIKELY(cbWritten >= 0))
1301 rc = VINF_SUCCESS;
1302/** @todo check for incomplete writes */
1303 else
1304 rc = rtSocketError();
1305
1306 RTMemTmpFree(paMsg);
1307 }
1308#endif /* !RT_OS_WINDOWS */
1309
1310 rtSocketUnlock(pThis);
1311 return rc;
1312}
1313
1314
1315RTDECL(int) RTSocketSgWriteL(RTSOCKET hSocket, size_t cSegs, ...)
1316{
1317 va_list va;
1318 va_start(va, cSegs);
1319 int rc = RTSocketSgWriteLV(hSocket, cSegs, va);
1320 va_end(va);
1321 return rc;
1322}
1323
1324
1325RTDECL(int) RTSocketSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va)
1326{
1327 /*
1328 * Set up a S/G segment array + buffer on the stack and pass it
1329 * on to RTSocketSgWrite.
1330 */
1331 Assert(cSegs <= 16);
1332 PRTSGSEG paSegs = (PRTSGSEG)alloca(cSegs * sizeof(RTSGSEG));
1333 AssertReturn(paSegs, VERR_NO_TMP_MEMORY);
1334 for (size_t i = 0; i < cSegs; i++)
1335 {
1336 paSegs[i].pvSeg = va_arg(va, void *);
1337 paSegs[i].cbSeg = va_arg(va, size_t);
1338 }
1339
1340 RTSGBUF SgBuf;
1341 RTSgBufInit(&SgBuf, paSegs, cSegs);
1342 return RTSocketSgWrite(hSocket, &SgBuf);
1343}
1344
1345
1346RTDECL(int) RTSocketReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
1347{
1348 /*
1349 * Validate input.
1350 */
1351 RTSOCKETINT *pThis = hSocket;
1352 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1353 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1354 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
1355 AssertPtr(pvBuffer);
1356 AssertPtrReturn(pcbRead, VERR_INVALID_PARAMETER);
1357#ifdef RT_OS_WINDOWS
1358 AssertReturn(g_pfnrecv, VERR_NOT_SUPPORTED);
1359#endif
1360 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1361
1362 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1363 if (RT_FAILURE(rc))
1364 return rc;
1365
1366 rtSocketErrorReset();
1367#ifdef RTSOCKET_MAX_READ
1368 int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
1369#else
1370 size_t cbNow = cbBuffer;
1371#endif
1372
1373#ifdef RT_OS_WINDOWS
1374 int cbRead = g_pfnrecv(pThis->hNative, (char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1375 if (cbRead >= 0)
1376 {
1377 *pcbRead = cbRead;
1378 rc = VINF_SUCCESS;
1379 }
1380 else
1381 {
1382 rc = rtSocketError();
1383 if (rc == VERR_TRY_AGAIN)
1384 {
1385 *pcbRead = 0;
1386 rc = VINF_TRY_AGAIN;
1387 }
1388 }
1389
1390#else
1391 ssize_t cbRead = recv(pThis->hNative, pvBuffer, cbNow, MSG_NOSIGNAL);
1392 if (cbRead >= 0)
1393 *pcbRead = cbRead;
1394 else if ( errno == EAGAIN
1395# ifdef EWOULDBLOCK
1396# if EWOULDBLOCK != EAGAIN
1397 || errno == EWOULDBLOCK
1398# endif
1399# endif
1400 )
1401 {
1402 *pcbRead = 0;
1403 rc = VINF_TRY_AGAIN;
1404 }
1405 else
1406 rc = rtSocketError();
1407#endif
1408
1409 rtSocketUnlock(pThis);
1410 return rc;
1411}
1412
1413
1414RTDECL(int) RTSocketWriteNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)
1415{
1416 /*
1417 * Validate input.
1418 */
1419 RTSOCKETINT *pThis = hSocket;
1420 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1421 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1422 AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER);
1423#ifdef RT_OS_WINDOWS
1424 AssertReturn(g_pfnsend, VERR_NOT_SUPPORTED);
1425#endif
1426 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1427
1428 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1429 if (RT_FAILURE(rc))
1430 return rc;
1431
1432 rtSocketErrorReset();
1433#ifdef RT_OS_WINDOWS
1434# ifdef RTSOCKET_MAX_WRITE
1435 int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
1436# else
1437 size_t cbNow = cbBuffer;
1438# endif
1439 int cbWritten = g_pfnsend(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1440 if (cbWritten >= 0)
1441 {
1442 *pcbWritten = cbWritten;
1443 rc = VINF_SUCCESS;
1444 }
1445 else
1446 {
1447 rc = rtSocketError();
1448 if (rc == VERR_TRY_AGAIN)
1449 {
1450 *pcbWritten = 0;
1451 rc = VINF_TRY_AGAIN;
1452 }
1453 }
1454#else
1455 ssize_t cbWritten = send(pThis->hNative, pvBuffer, cbBuffer, MSG_NOSIGNAL);
1456 if (cbWritten >= 0)
1457 *pcbWritten = cbWritten;
1458 else if ( errno == EAGAIN
1459# ifdef EWOULDBLOCK
1460# if EWOULDBLOCK != EAGAIN
1461 || errno == EWOULDBLOCK
1462# endif
1463# endif
1464 )
1465 {
1466 *pcbWritten = 0;
1467 rc = VINF_TRY_AGAIN;
1468 }
1469 else
1470 rc = rtSocketError();
1471#endif
1472
1473 rtSocketUnlock(pThis);
1474 return rc;
1475}
1476
1477
1478RTDECL(int) RTSocketSgWriteNB(RTSOCKET hSocket, PCRTSGBUF pSgBuf, size_t *pcbWritten)
1479{
1480 /*
1481 * Validate input.
1482 */
1483 RTSOCKETINT *pThis = hSocket;
1484 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1485 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1486 AssertPtrReturn(pSgBuf, VERR_INVALID_PARAMETER);
1487 AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER);
1488 AssertReturn(pSgBuf->cSegs > 0, VERR_INVALID_PARAMETER);
1489 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1490
1491 int rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
1492 if (RT_FAILURE(rc))
1493 return rc;
1494
1495 unsigned cSegsToSend = 0;
1496 rc = VERR_NO_TMP_MEMORY;
1497#ifdef RT_OS_WINDOWS
1498 if (g_pfnWSASend)
1499 {
1500 LPWSABUF paMsg = NULL;
1501 RTSgBufMapToNative(paMsg, pSgBuf, WSABUF, buf, char *, len, u_long, cSegsToSend);
1502 if (paMsg)
1503 {
1504 DWORD dwSent = 0;
1505 int hrc = g_pfnWSASend(pThis->hNative, paMsg, cSegsToSend, &dwSent, MSG_NOSIGNAL, NULL, NULL);
1506 if (!hrc)
1507 rc = VINF_SUCCESS;
1508 else
1509 rc = rtSocketError();
1510
1511 *pcbWritten = dwSent;
1512
1513 RTMemTmpFree(paMsg);
1514 }
1515 }
1516 else if (g_pfnsend)
1517 {
1518 size_t cbWrittenTotal = 0;
1519 rc = VINF_SUCCESS;
1520 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
1521 {
1522 uint8_t const *pbSeg = (uint8_t const *)pSgBuf->paSegs[iSeg].pvSeg;
1523 size_t cbSeg = pSgBuf->paSegs[iSeg].cbSeg;
1524 int cbNow;
1525 ssize_t cbWritten;
1526 for (;;)
1527 {
1528 cbNow = cbSeg >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbSeg;
1529 cbWritten = g_pfnsend(pThis->hNative, (const char *)pbSeg, cbNow, MSG_NOSIGNAL);
1530 if ((size_t)cbWritten >= cbSeg || cbWritten < 0)
1531 break;
1532 cbWrittenTotal += cbWrittenTotal;
1533 pbSeg += cbWritten;
1534 cbSeg -= cbWritten;
1535 }
1536 if (cbWritten < 0)
1537 {
1538 rc = rtSocketError();
1539 break;
1540 }
1541 if (cbWritten != cbNow)
1542 break;
1543 }
1544 *pcbWritten = cbWrittenTotal;
1545 }
1546 else
1547 rc = VERR_NOT_SUPPORTED;
1548
1549#else /* !RT_OS_WINDOWS */
1550 struct iovec *paMsg = NULL;
1551
1552 RTSgBufMapToNative(paMsg, pSgBuf, struct iovec, iov_base, void *, iov_len, size_t, cSegsToSend);
1553 if (paMsg)
1554 {
1555 struct msghdr msgHdr;
1556 RT_ZERO(msgHdr);
1557 msgHdr.msg_iov = paMsg;
1558 msgHdr.msg_iovlen = cSegsToSend;
1559 ssize_t cbWritten = sendmsg(pThis->hNative, &msgHdr, MSG_NOSIGNAL);
1560 if (RT_LIKELY(cbWritten >= 0))
1561 {
1562 rc = VINF_SUCCESS;
1563 *pcbWritten = cbWritten;
1564 }
1565 else
1566 rc = rtSocketError();
1567
1568 RTMemTmpFree(paMsg);
1569 }
1570#endif /* !RT_OS_WINDOWS */
1571
1572 rtSocketUnlock(pThis);
1573 return rc;
1574}
1575
1576
1577RTDECL(int) RTSocketSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...)
1578{
1579 va_list va;
1580 va_start(va, pcbWritten);
1581 int rc = RTSocketSgWriteLVNB(hSocket, cSegs, pcbWritten, va);
1582 va_end(va);
1583 return rc;
1584}
1585
1586
1587RTDECL(int) RTSocketSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va)
1588{
1589 /*
1590 * Set up a S/G segment array + buffer on the stack and pass it
1591 * on to RTSocketSgWrite.
1592 */
1593 Assert(cSegs <= 16);
1594 PRTSGSEG paSegs = (PRTSGSEG)alloca(cSegs * sizeof(RTSGSEG));
1595 AssertReturn(paSegs, VERR_NO_TMP_MEMORY);
1596 for (size_t i = 0; i < cSegs; i++)
1597 {
1598 paSegs[i].pvSeg = va_arg(va, void *);
1599 paSegs[i].cbSeg = va_arg(va, size_t);
1600 }
1601
1602 RTSGBUF SgBuf;
1603 RTSgBufInit(&SgBuf, paSegs, cSegs);
1604 return RTSocketSgWriteNB(hSocket, &SgBuf, pcbWritten);
1605}
1606
1607
1608RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
1609{
1610 /*
1611 * Validate input.
1612 */
1613 RTSOCKETINT *pThis = hSocket;
1614 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1615 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1616 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1617 int const fdMax = (int)pThis->hNative + 1;
1618 AssertReturn((RTSOCKETNATIVE)(fdMax - 1) == pThis->hNative, VERR_INTERNAL_ERROR_5);
1619#ifdef RT_OS_WINDOWS
1620 AssertReturn(g_pfnselect, VERR_NOT_SUPPORTED);
1621# define select g_pfnselect
1622#endif
1623
1624 /*
1625 * Set up the file descriptor sets and do the select.
1626 */
1627 fd_set fdsetR;
1628 FD_ZERO(&fdsetR);
1629 FD_SET(pThis->hNative, &fdsetR);
1630
1631 fd_set fdsetE = fdsetR;
1632
1633 int rc;
1634 if (cMillies == RT_INDEFINITE_WAIT)
1635 rc = select(fdMax, &fdsetR, NULL, &fdsetE, NULL);
1636 else
1637 {
1638 struct timeval timeout;
1639 timeout.tv_sec = cMillies / 1000;
1640 timeout.tv_usec = (cMillies % 1000) * 1000;
1641 rc = select(fdMax, &fdsetR, NULL, &fdsetE, &timeout);
1642 }
1643 if (rc > 0)
1644 rc = VINF_SUCCESS;
1645 else if (rc == 0)
1646 rc = VERR_TIMEOUT;
1647 else
1648 rc = rtSocketError();
1649
1650#ifdef RT_OS_WINDOWS
1651# undef select
1652#endif
1653 return rc;
1654}
1655
1656
1657RTDECL(int) RTSocketSelectOneEx(RTSOCKET hSocket, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies)
1658{
1659 /*
1660 * Validate input.
1661 */
1662 RTSOCKETINT *pThis = hSocket;
1663 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1664 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1665 AssertPtrReturn(pfEvents, VERR_INVALID_PARAMETER);
1666 AssertReturn(!(fEvents & ~RTSOCKET_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
1667 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1668
1669 RTSOCKETNATIVE hNative = pThis->hNative;
1670 if (hNative == NIL_RTSOCKETNATIVE)
1671 {
1672 /* Socket is already closed? Possible we raced someone calling rtSocketCloseIt.
1673 Should we return a different status code? */
1674 *pfEvents = RTSOCKET_EVT_ERROR;
1675 return VINF_SUCCESS;
1676 }
1677
1678 int const fdMax = (int)hNative + 1;
1679 AssertReturn((RTSOCKETNATIVE)(fdMax - 1) == hNative, VERR_INTERNAL_ERROR_5);
1680#ifdef RT_OS_WINDOWS
1681 AssertReturn(g_pfnselect, VERR_NOT_SUPPORTED);
1682 AssertReturn(g_pfn__WSAFDIsSet, VERR_NOT_SUPPORTED);
1683# define select g_pfnselect
1684# define __WSAFDIsSet g_pfn__WSAFDIsSet
1685#endif
1686
1687 *pfEvents = 0;
1688
1689 /*
1690 * Set up the file descriptor sets and do the select.
1691 */
1692 fd_set fdsetR;
1693 fd_set fdsetW;
1694 fd_set fdsetE;
1695 FD_ZERO(&fdsetR);
1696 FD_ZERO(&fdsetW);
1697 FD_ZERO(&fdsetE);
1698
1699 if (fEvents & RTSOCKET_EVT_READ)
1700 FD_SET(hNative, &fdsetR);
1701 if (fEvents & RTSOCKET_EVT_WRITE)
1702 FD_SET(hNative, &fdsetW);
1703 if (fEvents & RTSOCKET_EVT_ERROR)
1704 FD_SET(hNative, &fdsetE);
1705
1706 int rc;
1707 if (cMillies == RT_INDEFINITE_WAIT)
1708 rc = select(fdMax, &fdsetR, &fdsetW, &fdsetE, NULL);
1709 else
1710 {
1711 struct timeval timeout;
1712 timeout.tv_sec = cMillies / 1000;
1713 timeout.tv_usec = (cMillies % 1000) * 1000;
1714 rc = select(fdMax, &fdsetR, &fdsetW, &fdsetE, &timeout);
1715 }
1716 if (rc > 0)
1717 {
1718 if (pThis->hNative == hNative)
1719 {
1720 if (FD_ISSET(hNative, &fdsetR))
1721 *pfEvents |= RTSOCKET_EVT_READ;
1722 if (FD_ISSET(hNative, &fdsetW))
1723 *pfEvents |= RTSOCKET_EVT_WRITE;
1724 if (FD_ISSET(hNative, &fdsetE))
1725 *pfEvents |= RTSOCKET_EVT_ERROR;
1726 rc = VINF_SUCCESS;
1727 }
1728 else
1729 {
1730 /* Socket was closed while we waited (rtSocketCloseIt). Different status code? */
1731 *pfEvents = RTSOCKET_EVT_ERROR;
1732 rc = VINF_SUCCESS;
1733 }
1734 }
1735 else if (rc == 0)
1736 rc = VERR_TIMEOUT;
1737 else
1738 rc = rtSocketError();
1739
1740#ifdef RT_OS_WINDOWS
1741# undef select
1742# undef __WSAFDIsSet
1743#endif
1744 return rc;
1745}
1746
1747
1748RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
1749{
1750 /*
1751 * Validate input, don't lock it because we might want to interrupt a call
1752 * active on a different thread.
1753 */
1754 RTSOCKETINT *pThis = hSocket;
1755 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1756 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1757 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1758 AssertReturn(fRead || fWrite, VERR_INVALID_PARAMETER);
1759#ifdef RT_OS_WINDOWS
1760 AssertReturn(g_pfnshutdown, VERR_NOT_SUPPORTED);
1761# define shutdown g_pfnshutdown
1762#endif
1763
1764 /*
1765 * Do the job.
1766 */
1767 int rc = VINF_SUCCESS;
1768 int fHow;
1769 if (fRead && fWrite)
1770 fHow = SHUT_RDWR;
1771 else if (fRead)
1772 fHow = SHUT_RD;
1773 else
1774 fHow = SHUT_WR;
1775 if (shutdown(pThis->hNative, fHow) == -1)
1776 rc = rtSocketError();
1777
1778#ifdef RT_OS_WINDOWS
1779# undef shutdown
1780#endif
1781 return rc;
1782}
1783
1784
1785RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
1786{
1787 /*
1788 * Validate input.
1789 */
1790 RTSOCKETINT *pThis = hSocket;
1791 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1792 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1793 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1794#ifdef RT_OS_WINDOWS
1795 AssertReturn(g_pfngetsockname, VERR_NOT_SUPPORTED);
1796# define getsockname g_pfngetsockname
1797#endif
1798
1799 /*
1800 * Get the address and convert it.
1801 */
1802 int rc;
1803 RTSOCKADDRUNION u;
1804#ifdef RT_OS_WINDOWS
1805 int cbAddr = sizeof(u);
1806#else
1807 socklen_t cbAddr = sizeof(u);
1808#endif
1809 RT_ZERO(u);
1810 if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0)
1811 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pAddr);
1812 else
1813 rc = rtSocketError();
1814
1815#ifdef RT_OS_WINDOWS
1816# undef getsockname
1817#endif
1818 return rc;
1819}
1820
1821
1822RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
1823{
1824 /*
1825 * Validate input.
1826 */
1827 RTSOCKETINT *pThis = hSocket;
1828 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1829 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1830 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
1831#ifdef RT_OS_WINDOWS
1832 AssertReturn(g_pfngetpeername, VERR_NOT_SUPPORTED);
1833# define getpeername g_pfngetpeername
1834#endif
1835
1836 /*
1837 * Get the address and convert it.
1838 */
1839 int rc;
1840 RTSOCKADDRUNION u;
1841#ifdef RT_OS_WINDOWS
1842 int cbAddr = sizeof(u);
1843#else
1844 socklen_t cbAddr = sizeof(u);
1845#endif
1846 RT_ZERO(u);
1847 if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0)
1848 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pAddr);
1849 else
1850 rc = rtSocketError();
1851
1852#ifdef RT_OS_WINDOWS
1853# undef getpeername
1854#endif
1855 return rc;
1856}
1857
1858
1859
1860/**
1861 * Wrapper around bind.
1862 *
1863 * @returns IPRT status code.
1864 * @param hSocket The socket handle.
1865 * @param pAddr The address to bind to.
1866 */
1867DECLHIDDEN(int) rtSocketBind(RTSOCKET hSocket, PCRTNETADDR pAddr)
1868{
1869 RTSOCKADDRUNION u;
1870 int cbAddr;
1871 int rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), &cbAddr);
1872 if (RT_SUCCESS(rc))
1873 rc = rtSocketBindRawAddr(hSocket, &u.Addr, cbAddr);
1874 return rc;
1875}
1876
1877
1878/**
1879 * Very thin wrapper around bind.
1880 *
1881 * @returns IPRT status code.
1882 * @param hSocket The socket handle.
1883 * @param pvAddr The address to bind to (struct sockaddr and
1884 * friends).
1885 * @param cbAddr The size of the address.
1886 */
1887DECLHIDDEN(int) rtSocketBindRawAddr(RTSOCKET hSocket, void const *pvAddr, size_t cbAddr)
1888{
1889 /*
1890 * Validate input.
1891 */
1892 RTSOCKETINT *pThis = hSocket;
1893 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1894 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1895 AssertPtrReturn(pvAddr, VERR_INVALID_POINTER);
1896#ifdef RT_OS_WINDOWS
1897 AssertReturn(g_pfnbind, VERR_NOT_SUPPORTED);
1898# define bind g_pfnbind
1899#endif
1900 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1901
1902 int rc;
1903 if (bind(pThis->hNative, (struct sockaddr const *)pvAddr, (int)cbAddr) == 0)
1904 rc = VINF_SUCCESS;
1905 else
1906 rc = rtSocketError();
1907
1908 rtSocketUnlock(pThis);
1909#ifdef RT_OS_WINDOWS
1910# undef bind
1911#endif
1912 return rc;
1913}
1914
1915
1916
1917/**
1918 * Wrapper around listen.
1919 *
1920 * @returns IPRT status code.
1921 * @param hSocket The socket handle.
1922 * @param cMaxPending The max number of pending connections.
1923 */
1924DECLHIDDEN(int) rtSocketListen(RTSOCKET hSocket, int cMaxPending)
1925{
1926 /*
1927 * Validate input.
1928 */
1929 RTSOCKETINT *pThis = hSocket;
1930 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1931 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1932#ifdef RT_OS_WINDOWS
1933 AssertReturn(g_pfnlisten, VERR_NOT_SUPPORTED);
1934# define listen g_pfnlisten
1935#endif
1936 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1937
1938 int rc = VINF_SUCCESS;
1939 if (listen(pThis->hNative, cMaxPending) != 0)
1940 rc = rtSocketError();
1941
1942 rtSocketUnlock(pThis);
1943#ifdef RT_OS_WINDOWS
1944# undef listen
1945#endif
1946 return rc;
1947}
1948
1949
1950/**
1951 * Wrapper around accept.
1952 *
1953 * @returns IPRT status code.
1954 * @param hSocket The socket handle.
1955 * @param phClient Where to return the client socket handle on
1956 * success.
1957 * @param pAddr Where to return the client address.
1958 * @param pcbAddr On input this gives the size buffer size of what
1959 * @a pAddr point to. On return this contains the
1960 * size of what's stored at @a pAddr.
1961 */
1962DECLHIDDEN(int) rtSocketAccept(RTSOCKET hSocket, PRTSOCKET phClient, struct sockaddr *pAddr, size_t *pcbAddr)
1963{
1964 /*
1965 * Validate input.
1966 * Only lock the socket temporarily while we get the native handle, so that
1967 * we can safely shutdown and destroy the socket from a different thread.
1968 */
1969 RTSOCKETINT *pThis = hSocket;
1970 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1971 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
1972#ifdef RT_OS_WINDOWS
1973 AssertReturn(g_pfnaccept, VERR_NOT_SUPPORTED);
1974 AssertReturn(g_pfnclosesocket, VERR_NOT_SUPPORTED);
1975# define accept g_pfnaccept
1976#endif
1977 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
1978
1979 /*
1980 * Call accept().
1981 */
1982 rtSocketErrorReset();
1983 int rc = VINF_SUCCESS;
1984#ifdef RT_OS_WINDOWS
1985 int cbAddr = (int)*pcbAddr;
1986#else
1987 socklen_t cbAddr = *pcbAddr;
1988#endif
1989 RTSOCKETNATIVE hNativeClient = accept(pThis->hNative, pAddr, &cbAddr);
1990 if (hNativeClient != NIL_RTSOCKETNATIVE)
1991 {
1992 *pcbAddr = cbAddr;
1993
1994 /*
1995 * Wrap the client socket.
1996 */
1997 rc = rtSocketCreateForNative(phClient, hNativeClient);
1998 if (RT_FAILURE(rc))
1999 {
2000#ifdef RT_OS_WINDOWS
2001 g_pfnclosesocket(hNativeClient);
2002#else
2003 close(hNativeClient);
2004#endif
2005 }
2006 }
2007 else
2008 rc = rtSocketError();
2009
2010 rtSocketUnlock(pThis);
2011#ifdef RT_OS_WINDOWS
2012# undef accept
2013#endif
2014 return rc;
2015}
2016
2017
2018/**
2019 * Wrapper around connect.
2020 *
2021 * @returns IPRT status code.
2022 * @param hSocket The socket handle.
2023 * @param pAddr The socket address to connect to.
2024 * @param cMillies Number of milliseconds to wait for the connect attempt to complete.
2025 * Use RT_INDEFINITE_WAIT to wait for ever.
2026 * Use RT_TCPCLIENTCONNECT_DEFAULT_WAIT to wait for the default time
2027 * configured on the running system.
2028 */
2029DECLHIDDEN(int) rtSocketConnect(RTSOCKET hSocket, PCRTNETADDR pAddr, RTMSINTERVAL cMillies)
2030{
2031 /*
2032 * Validate input.
2033 */
2034 RTSOCKETINT *pThis = hSocket;
2035 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2036 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
2037#ifdef RT_OS_WINDOWS
2038 AssertReturn(g_pfnconnect, VERR_NOT_SUPPORTED);
2039 AssertReturn(g_pfnselect, VERR_NOT_SUPPORTED);
2040 AssertReturn(g_pfngetsockopt, VERR_NOT_SUPPORTED);
2041# define connect g_pfnconnect
2042# define select g_pfnselect
2043# define getsockopt g_pfngetsockopt
2044#endif
2045 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
2046
2047 RTSOCKADDRUNION u;
2048 int cbAddr;
2049 int rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u), &cbAddr);
2050 if (RT_SUCCESS(rc))
2051 {
2052 if (cMillies == RT_SOCKETCONNECT_DEFAULT_WAIT)
2053 {
2054 if (connect(pThis->hNative, &u.Addr, cbAddr) != 0)
2055 rc = rtSocketError();
2056 }
2057 else
2058 {
2059 /*
2060 * Switch the socket to nonblocking mode, initiate the connect
2061 * and wait for the socket to become writable or until the timeout
2062 * expires.
2063 */
2064 rc = rtSocketSwitchBlockingMode(pThis, false /* fBlocking */);
2065 if (RT_SUCCESS(rc))
2066 {
2067 if (connect(pThis->hNative, &u.Addr, cbAddr) != 0)
2068 {
2069 rc = rtSocketError();
2070 if (rc == VERR_TRY_AGAIN || rc == VERR_NET_IN_PROGRESS)
2071 {
2072 int rcSock = 0;
2073 fd_set FdSetWriteable;
2074 struct timeval TvTimeout;
2075
2076 TvTimeout.tv_sec = cMillies / RT_MS_1SEC;
2077 TvTimeout.tv_usec = (cMillies % RT_MS_1SEC) * RT_US_1MS;
2078
2079 FD_ZERO(&FdSetWriteable);
2080 FD_SET(pThis->hNative, &FdSetWriteable);
2081 do
2082 {
2083 rcSock = select(pThis->hNative + 1, NULL, &FdSetWriteable, NULL,
2084 cMillies == RT_INDEFINITE_WAIT || cMillies >= INT_MAX
2085 ? NULL
2086 : &TvTimeout);
2087 if (rcSock > 0)
2088 {
2089 int iSockError = 0;
2090 socklen_t cbSockOpt = sizeof(iSockError);
2091 rcSock = getsockopt(pThis->hNative, SOL_SOCKET, SO_ERROR, (char *)&iSockError, &cbSockOpt);
2092 if (rcSock == 0)
2093 {
2094 if (iSockError == 0)
2095 rc = VINF_SUCCESS;
2096 else
2097 {
2098#ifdef RT_OS_WINDOWS
2099 rc = RTErrConvertFromWin32(iSockError);
2100#else
2101 rc = RTErrConvertFromErrno(iSockError);
2102#endif
2103 }
2104 }
2105 else
2106 rc = rtSocketError();
2107 }
2108 else if (rcSock == 0)
2109 rc = VERR_TIMEOUT;
2110 else
2111 rc = rtSocketError();
2112 } while (rc == VERR_INTERRUPTED);
2113 }
2114 }
2115
2116 rtSocketSwitchBlockingMode(pThis, true /* fBlocking */);
2117 }
2118 }
2119 }
2120
2121 rtSocketUnlock(pThis);
2122#ifdef RT_OS_WINDOWS
2123# undef connect
2124# undef select
2125# undef getsockopt
2126#endif
2127 return rc;
2128}
2129
2130
2131/**
2132 * Wrapper around connect, raw address, no timeout.
2133 *
2134 * @returns IPRT status code.
2135 * @param hSocket The socket handle.
2136 * @param pvAddr The raw socket address to connect to.
2137 * @param cbAddr The size of the raw address.
2138 */
2139DECLHIDDEN(int) rtSocketConnectRaw(RTSOCKET hSocket, void const *pvAddr, size_t cbAddr)
2140{
2141 /*
2142 * Validate input.
2143 */
2144 RTSOCKETINT *pThis = hSocket;
2145 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2146 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
2147#ifdef RT_OS_WINDOWS
2148 AssertReturn(g_pfnconnect, VERR_NOT_SUPPORTED);
2149# define connect g_pfnconnect
2150#endif
2151 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
2152
2153 int rc;
2154 if (connect(pThis->hNative, (const struct sockaddr *)pvAddr, (int)cbAddr) == 0)
2155 rc = VINF_SUCCESS;
2156 else
2157 rc = rtSocketError();
2158
2159 rtSocketUnlock(pThis);
2160#ifdef RT_OS_WINDOWS
2161# undef connect
2162#endif
2163 return rc;
2164}
2165
2166
2167/**
2168 * Wrapper around setsockopt.
2169 *
2170 * @returns IPRT status code.
2171 * @param hSocket The socket handle.
2172 * @param iLevel The protocol level, e.g. IPPORTO_TCP.
2173 * @param iOption The option, e.g. TCP_NODELAY.
2174 * @param pvValue The value buffer.
2175 * @param cbValue The size of the value pointed to by pvValue.
2176 */
2177DECLHIDDEN(int) rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValue, int cbValue)
2178{
2179 /*
2180 * Validate input.
2181 */
2182 RTSOCKETINT *pThis = hSocket;
2183 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2184 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
2185#ifdef RT_OS_WINDOWS
2186 AssertReturn(g_pfnsetsockopt, VERR_NOT_SUPPORTED);
2187# define setsockopt g_pfnsetsockopt
2188#endif
2189 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
2190
2191 int rc = VINF_SUCCESS;
2192 if (setsockopt(pThis->hNative, iLevel, iOption, (const char *)pvValue, cbValue) != 0)
2193 rc = rtSocketError();
2194
2195 rtSocketUnlock(pThis);
2196#ifdef RT_OS_WINDOWS
2197# undef setsockopt
2198#endif
2199 return rc;
2200}
2201
2202
2203/**
2204 * Internal RTPollSetAdd helper that returns the handle that should be added to
2205 * the pollset.
2206 *
2207 * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
2208 * @param hSocket The socket handle.
2209 * @param fEvents The events we're polling for.
2210 * @param phNative Where to put the primary handle.
2211 */
2212DECLHIDDEN(int) rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PRTHCINTPTR phNative)
2213{
2214 RTSOCKETINT *pThis = hSocket;
2215 RT_NOREF_PV(fEvents);
2216 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
2217 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
2218#ifdef RT_OS_WINDOWS
2219 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
2220
2221 int rc = VINF_SUCCESS;
2222 if (pThis->hEvent != WSA_INVALID_EVENT)
2223 *phNative = (RTHCINTPTR)pThis->hEvent;
2224 else if (g_pfnWSACreateEvent)
2225 {
2226 pThis->hEvent = g_pfnWSACreateEvent();
2227 *phNative = (RTHCINTPTR)pThis->hEvent;
2228 if (pThis->hEvent == WSA_INVALID_EVENT)
2229 rc = rtSocketError();
2230 }
2231 else
2232 rc = VERR_NOT_SUPPORTED;
2233
2234 rtSocketUnlock(pThis);
2235 return rc;
2236
2237#else /* !RT_OS_WINDOWS */
2238 *phNative = (RTHCUINTPTR)pThis->hNative;
2239 return VINF_SUCCESS;
2240#endif /* !RT_OS_WINDOWS */
2241}
2242
2243#ifdef RT_OS_WINDOWS
2244
2245/**
2246 * Undos the harm done by WSAEventSelect.
2247 *
2248 * @returns IPRT status code.
2249 * @param pThis The socket handle.
2250 */
2251static int rtSocketPollClearEventAndRestoreBlocking(RTSOCKETINT *pThis)
2252{
2253 int rc = VINF_SUCCESS;
2254 if (pThis->fSubscribedEvts)
2255 {
2256 if (g_pfnWSAEventSelect && g_pfnioctlsocket)
2257 {
2258 if (g_pfnWSAEventSelect(pThis->hNative, WSA_INVALID_EVENT, 0) == 0)
2259 {
2260 pThis->fSubscribedEvts = 0;
2261
2262 /*
2263 * Switch back to blocking mode if that was the state before the
2264 * operation.
2265 */
2266 if (pThis->fBlocking)
2267 {
2268 u_long fNonBlocking = 0;
2269 int rc2 = g_pfnioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking);
2270 if (rc2 != 0)
2271 {
2272 rc = rtSocketError();
2273 AssertMsgFailed(("%Rrc; rc2=%d\n", rc, rc2));
2274 }
2275 }
2276 }
2277 else
2278 {
2279 rc = rtSocketError();
2280 AssertMsgFailed(("%Rrc\n", rc));
2281 }
2282 }
2283 else
2284 rc = VERR_NOT_SUPPORTED;
2285 }
2286 return rc;
2287}
2288
2289
2290/**
2291 * Updates the mask of events we're subscribing to.
2292 *
2293 * @returns IPRT status code.
2294 * @param pThis The socket handle.
2295 * @param fEvents The events we want to subscribe to.
2296 */
2297static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
2298{
2299 LONG fNetworkEvents = 0;
2300 if (fEvents & RTPOLL_EVT_READ)
2301 fNetworkEvents |= FD_READ;
2302 if (fEvents & RTPOLL_EVT_WRITE)
2303 fNetworkEvents |= FD_WRITE;
2304 if (fEvents & RTPOLL_EVT_ERROR)
2305 fNetworkEvents |= FD_CLOSE;
2306 LogFlowFunc(("fNetworkEvents=%#x\n", fNetworkEvents));
2307 int rc;
2308 if (g_pfnWSAEventSelect)
2309 {
2310 if (g_pfnWSAEventSelect(pThis->hNative, pThis->hEvent, fNetworkEvents) == 0)
2311 {
2312 pThis->fSubscribedEvts = fEvents;
2313 return VINF_SUCCESS;
2314 }
2315 rc = rtSocketError();
2316 AssertMsgFailed(("fNetworkEvents=%#x rc=%Rrc\n", fNetworkEvents, rtSocketError()));
2317 }
2318 else
2319 rc = VERR_NOT_SUPPORTED;
2320 return rc;
2321}
2322
2323#endif /* RT_OS_WINDOWS */
2324
2325
2326#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
2327
2328/**
2329 * Checks for pending events.
2330 *
2331 * @returns Event mask or 0.
2332 * @param pThis The socket handle.
2333 * @param fEvents The desired events.
2334 */
2335static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
2336{
2337 uint32_t fRetEvents = 0;
2338
2339 LogFlowFunc(("pThis=%#p fEvents=%#x\n", pThis, fEvents));
2340
2341# ifdef RT_OS_WINDOWS
2342 /* Make sure WSAEnumNetworkEvents returns what we want. */
2343 int rc = VINF_SUCCESS;
2344 if ((pThis->fSubscribedEvts & fEvents) != fEvents)
2345 rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents);
2346
2347 /* Get the event mask, ASSUMES that WSAEnumNetworkEvents doesn't clear stuff. */
2348 if (g_pfnWSAEnumNetworkEvents)
2349 {
2350 WSANETWORKEVENTS NetEvts;
2351 RT_ZERO(NetEvts);
2352 if (g_pfnWSAEnumNetworkEvents(pThis->hNative, pThis->hEvent, &NetEvts) == 0)
2353 {
2354 if ( (NetEvts.lNetworkEvents & FD_READ)
2355 && (fEvents & RTPOLL_EVT_READ)
2356 && NetEvts.iErrorCode[FD_READ_BIT] == 0)
2357 fRetEvents |= RTPOLL_EVT_READ;
2358
2359 if ( (NetEvts.lNetworkEvents & FD_WRITE)
2360 && (fEvents & RTPOLL_EVT_WRITE)
2361 && NetEvts.iErrorCode[FD_WRITE_BIT] == 0)
2362 fRetEvents |= RTPOLL_EVT_WRITE;
2363
2364 if (fEvents & RTPOLL_EVT_ERROR)
2365 {
2366 if (NetEvts.lNetworkEvents & FD_CLOSE)
2367 fRetEvents |= RTPOLL_EVT_ERROR;
2368 else
2369 for (uint32_t i = 0; i < FD_MAX_EVENTS; i++)
2370 if ( (NetEvts.lNetworkEvents & (1L << i))
2371 && NetEvts.iErrorCode[i] != 0)
2372 fRetEvents |= RTPOLL_EVT_ERROR;
2373 }
2374 }
2375 else
2376 rc = rtSocketError();
2377 }
2378 else if (RT_SUCCESS(rc))
2379 rc = VERR_NOT_SUPPORTED;
2380
2381 /* Fall back on select if we hit an error above. */
2382 if (RT_FAILURE(rc))
2383 {
2384 rc = RTSocketSelectOneEx(pThis, fEvents, &fRetEvents, 0);
2385 if (RT_FAILURE(rc))
2386 fRetEvents = 0;
2387 }
2388
2389#else /* RT_OS_OS2 */
2390 int aFds[4] = { pThis->hNative, pThis->hNative, pThis->hNative, -1 };
2391 int rc = os2_select(aFds, 1, 1, 1, 0);
2392 if (rc > 0)
2393 {
2394 if (aFds[0] == pThis->hNative)
2395 fRetEvents |= RTPOLL_EVT_READ;
2396 if (aFds[1] == pThis->hNative)
2397 fRetEvents |= RTPOLL_EVT_WRITE;
2398 if (aFds[2] == pThis->hNative)
2399 fRetEvents |= RTPOLL_EVT_ERROR;
2400 fRetEvents &= fEvents;
2401 }
2402#endif /* RT_OS_OS2 */
2403
2404 LogFlowFunc(("fRetEvents=%#x\n", fRetEvents));
2405 return fRetEvents;
2406}
2407
2408
2409/**
2410 * Internal RTPoll helper that polls the socket handle and, if @a fNoWait is
2411 * clear, starts whatever actions we've got running during the poll call.
2412 *
2413 * @returns 0 if no pending events, actions initiated if @a fNoWait is clear.
2414 * Event mask (in @a fEvents) and no actions if the handle is ready
2415 * already.
2416 * UINT32_MAX (asserted) if the socket handle is busy in I/O or a
2417 * different poll set.
2418 *
2419 * @param hSocket The socket handle.
2420 * @param hPollSet The poll set handle (for access checks).
2421 * @param fEvents The events we're polling for.
2422 * @param fFinalEntry Set if this is the final entry for this handle
2423 * in this poll set. This can be used for dealing
2424 * with duplicate entries.
2425 * @param fNoWait Set if it's a zero-wait poll call. Clear if
2426 * we'll wait for an event to occur.
2427 *
2428 * @remarks There is a potential race wrt duplicate handles when @a fNoWait is
2429 * @c true, we don't currently care about that oddity...
2430 */
2431DECLHIDDEN(uint32_t) rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
2432{
2433 RTSOCKETINT *pThis = hSocket;
2434 AssertPtrReturn(pThis, UINT32_MAX);
2435 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
2436 /** @todo This isn't quite sane. Replace by critsect and open up concurrent
2437 * reads and writes! */
2438 if (rtSocketTryLock(pThis))
2439 pThis->hPollSet = hPollSet;
2440 else
2441 {
2442 AssertReturn(pThis->hPollSet == hPollSet, UINT32_MAX);
2443 ASMAtomicIncU32(&pThis->cUsers);
2444 }
2445
2446 /* (rtSocketPollCheck will reset the event object). */
2447# ifdef RT_OS_WINDOWS
2448 uint32_t fRetEvents = pThis->fEventsSaved;
2449 pThis->fEventsSaved = 0; /* Reset */
2450 fRetEvents |= rtSocketPollCheck(pThis, fEvents);
2451
2452 if ( !fRetEvents
2453 && !fNoWait)
2454 {
2455 pThis->fPollEvts |= fEvents;
2456 if ( fFinalEntry
2457 && pThis->fSubscribedEvts != pThis->fPollEvts)
2458 {
2459 int rc = rtSocketPollUpdateEvents(pThis, pThis->fPollEvts);
2460 if (RT_FAILURE(rc))
2461 {
2462 pThis->fPollEvts = 0;
2463 fRetEvents = UINT32_MAX;
2464 }
2465 }
2466 }
2467# else
2468 uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
2469# endif
2470
2471 if (fRetEvents || fNoWait)
2472 {
2473 if (pThis->cUsers == 1)
2474 {
2475# ifdef RT_OS_WINDOWS
2476 rtSocketPollClearEventAndRestoreBlocking(pThis);
2477# endif
2478 pThis->hPollSet = NIL_RTPOLLSET;
2479 }
2480 ASMAtomicDecU32(&pThis->cUsers);
2481 }
2482
2483 return fRetEvents;
2484}
2485
2486
2487/**
2488 * Called after a WaitForMultipleObjects returned in order to check for pending
2489 * events and stop whatever actions that rtSocketPollStart() initiated.
2490 *
2491 * @returns Event mask or 0.
2492 *
2493 * @param hSocket The socket handle.
2494 * @param fEvents The events we're polling for.
2495 * @param fFinalEntry Set if this is the final entry for this handle
2496 * in this poll set. This can be used for dealing
2497 * with duplicate entries. Only keep in mind that
2498 * this method is called in reverse order, so the
2499 * first call will have this set (when the entire
2500 * set was processed).
2501 * @param fHarvestEvents Set if we should check for pending events.
2502 */
2503DECLHIDDEN(uint32_t) rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry, bool fHarvestEvents)
2504{
2505 RTSOCKETINT *pThis = hSocket;
2506 AssertPtrReturn(pThis, 0);
2507 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, 0);
2508 Assert(pThis->cUsers > 0);
2509 Assert(pThis->hPollSet != NIL_RTPOLLSET);
2510 RT_NOREF_PV(fFinalEntry);
2511
2512 /* Harvest events and clear the event mask for the next round of polling. */
2513 uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
2514# ifdef RT_OS_WINDOWS
2515 pThis->fPollEvts = 0;
2516
2517 /*
2518 * Save the write event if required.
2519 * It is only posted once and might get lost if the another source in the
2520 * pollset with a higher priority has pending events.
2521 */
2522 if ( !fHarvestEvents
2523 && fRetEvents)
2524 {
2525 pThis->fEventsSaved = fRetEvents;
2526 fRetEvents = 0;
2527 }
2528# endif
2529
2530 /* Make the socket blocking again and unlock the handle. */
2531 if (pThis->cUsers == 1)
2532 {
2533# ifdef RT_OS_WINDOWS
2534 rtSocketPollClearEventAndRestoreBlocking(pThis);
2535# endif
2536 pThis->hPollSet = NIL_RTPOLLSET;
2537 }
2538 ASMAtomicDecU32(&pThis->cUsers);
2539 return fRetEvents;
2540}
2541
2542#endif /* RT_OS_WINDOWS || RT_OS_OS2 */
2543
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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