VirtualBox

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

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

IPRT/r3/socket.cpp: OS/2 has trouble sending buffers larger than 64KB, so join the windows code in limiting and split reads/writes.

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