VirtualBox

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

Last change on this file since 39091 was 39032, checked in by vboxsync, 13 years ago

IPRT: Fixed unused variable warnings.

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