VirtualBox

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

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

Runtime/socket+udp: new socket functions needed to provide UDP as part of the runtime

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