VirtualBox

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

Last change on this file since 28863 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 33.2 KB
Line 
1/* $Id: socket.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * IPRT - Network Sockets.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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#endif /* !RT_OS_WINDOWS */
48#include <limits.h>
49
50#include "internal/iprt.h"
51#include <iprt/socket.h>
52
53#include <iprt/asm.h>
54#include <iprt/assert.h>
55#include <iprt/err.h>
56#include <iprt/mempool.h>
57#include <iprt/poll.h>
58#include <iprt/string.h>
59#include <iprt/thread.h>
60#include <iprt/time.h>
61
62#include "internal/magics.h"
63#include "internal/socket.h"
64
65
66/*******************************************************************************
67* Defined Constants And Macros *
68*******************************************************************************/
69/* non-standard linux stuff (it seems). */
70#ifndef MSG_NOSIGNAL
71# define MSG_NOSIGNAL 0
72#endif
73
74/* Windows has different names for SHUT_XXX. */
75#ifndef SHUT_RDWR
76# ifdef SD_BOTH
77# define SHUT_RDWR SD_BOTH
78# else
79# define SHUT_RDWR 2
80# endif
81#endif
82#ifndef SHUT_WR
83# ifdef SD_SEND
84# define SHUT_WR SD_SEND
85# else
86# define SHUT_WR 1
87# endif
88#endif
89#ifndef SHUT_RD
90# ifdef SD_RECEIVE
91# define SHUT_RD SD_RECEIVE
92# else
93# define SHUT_RD 0
94# endif
95#endif
96
97/* fixup backlevel OSes. */
98#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
99# define socklen_t int
100#endif
101
102/** How many pending connection. */
103#define RTTCP_SERVER_BACKLOG 10
104
105
106/*******************************************************************************
107* Structures and Typedefs *
108*******************************************************************************/
109/**
110 * Socket handle data.
111 *
112 * This is mainly required for implementing RTPollSet on Windows.
113 */
114typedef struct RTSOCKETINT
115{
116 /** Magic number (RTSOCKET_MAGIC). */
117 uint32_t u32Magic;
118 /** Exclusive user count.
119 * This is used to prevent two threads from accessing the handle concurrently.
120 * It can be higher than 1 if this handle is reference multiple times in a
121 * polling set (Windows). */
122 uint32_t volatile cUsers;
123 /** The native socket handle. */
124 RTSOCKETNATIVE hNative;
125 /** Indicates whether the handle has been closed or not. */
126 bool volatile fClosed;
127#ifdef RT_OS_WINDOWS
128 /** The event semaphore we've associated with the socket handle.
129 * This is WSA_INVALID_EVENT if not done. */
130 WSAEVENT hEvent;
131 /** The pollset currently polling this socket. This is NIL if no one is
132 * polling. */
133 RTPOLLSET hPollSet;
134 /** The events we're polling for. */
135 uint32_t fPollEvts;
136 /** The events we're currently subscribing to with WSAEventSelect.
137 * This is ZERO if we're currently not subscribing to anything. */
138 uint32_t fSubscribedEvts;
139#endif /* RT_OS_WINDOWS */
140} RTSOCKETINT;
141
142
143/**
144 * Address union used internally for things like getpeername and getsockname.
145 */
146typedef union RTSOCKADDRUNION
147{
148 struct sockaddr Addr;
149 struct sockaddr_in Ipv4;
150#ifdef IPRT_WITH_TCPIP_V6
151 struct sockaddr_in6 Ipv6;
152#endif
153} RTSOCKADDRUNION;
154
155
156/**
157 * Get the last error as an iprt status code.
158 *
159 * @returns IPRT status code.
160 */
161DECLINLINE(int) rtSocketError(void)
162{
163#ifdef RT_OS_WINDOWS
164 return RTErrConvertFromWin32(WSAGetLastError());
165#else
166 return RTErrConvertFromErrno(errno);
167#endif
168}
169
170
171/**
172 * Resets the last error.
173 */
174DECLINLINE(void) rtSocketErrorReset(void)
175{
176#ifdef RT_OS_WINDOWS
177 WSASetLastError(0);
178#else
179 errno = 0;
180#endif
181}
182
183
184/**
185 * Get the last resolver error as an iprt status code.
186 *
187 * @returns iprt status code.
188 */
189int rtSocketResolverError(void)
190{
191#ifdef RT_OS_WINDOWS
192 return RTErrConvertFromWin32(WSAGetLastError());
193#else
194 switch (h_errno)
195 {
196 case HOST_NOT_FOUND:
197 return VERR_NET_HOST_NOT_FOUND;
198 case NO_DATA:
199 return VERR_NET_ADDRESS_NOT_AVAILABLE;
200 case NO_RECOVERY:
201 return VERR_IO_GEN_FAILURE;
202 case TRY_AGAIN:
203 return VERR_TRY_AGAIN;
204
205 default:
206 return VERR_UNRESOLVED_ERROR;
207 }
208#endif
209}
210
211
212/**
213 * Tries to lock the socket for exclusive usage by the calling thread.
214 *
215 * Call rtSocketUnlock() to unlock.
216 *
217 * @returns @c true if locked, @c false if not.
218 * @param pThis The socket structure.
219 */
220DECLINLINE(bool) rtSocketTryLock(RTSOCKETINT *pThis)
221{
222 return ASMAtomicCmpXchgU32(&pThis->cUsers, 1, 0);
223}
224
225
226/**
227 * Unlocks the socket.
228 *
229 * @param pThis The socket structure.
230 */
231DECLINLINE(void) rtSocketUnlock(RTSOCKETINT *pThis)
232{
233 ASMAtomicCmpXchgU32(&pThis->cUsers, 0, 1);
234}
235
236
237/**
238 * Creates an IPRT socket handle for a native one.
239 *
240 * @returns IPRT status code.
241 * @param ppSocket Where to return the IPRT socket handle.
242 * @param hNative The native handle.
243 */
244int rtSocketCreateForNative(RTSOCKETINT **ppSocket, RTSOCKETNATIVE hNative)
245{
246 RTSOCKETINT *pThis = (RTSOCKETINT *)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pThis));
247 if (!pThis)
248 return VERR_NO_MEMORY;
249 pThis->u32Magic = RTSOCKET_MAGIC;
250 pThis->cUsers = 0;
251 pThis->hNative = hNative;
252 pThis->fClosed = false;
253#ifdef RT_OS_WINDOWS
254 pThis->hEvent = WSA_INVALID_EVENT;
255 pThis->hPollSet = NIL_RTPOLLSET;
256 pThis->fPollEvts = 0;
257 pThis->fSubscribedEvts = 0;
258#endif
259 *ppSocket = pThis;
260 return VINF_SUCCESS;
261}
262
263
264RTDECL(int) RTSocketFromNative(PRTSOCKET phSocket, RTHCINTPTR uNative)
265{
266 AssertReturn(uNative != NIL_RTSOCKETNATIVE, VERR_INVALID_PARAMETER);
267#ifndef RT_OS_WINDOWS
268 AssertReturn(uNative >= 0, VERR_INVALID_PARAMETER);
269#endif
270 AssertPtrReturn(phSocket, VERR_INVALID_POINTER);
271 return rtSocketCreateForNative(phSocket, uNative);
272}
273
274
275/**
276 * Wrapper around socket().
277 *
278 * @returns IPRT status code.
279 * @param phSocket Where to store the handle to the socket on
280 * success.
281 * @param iDomain The protocol family (PF_XXX).
282 * @param iType The socket type (SOCK_XXX).
283 * @param iProtocol Socket parameter, usually 0.
284 */
285int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
286{
287 /*
288 * Create the socket.
289 */
290 RTSOCKETNATIVE hNative = socket(iDomain, iType, iProtocol);
291 if (hNative == NIL_RTSOCKETNATIVE)
292 return rtSocketError();
293
294 /*
295 * Wrap it.
296 */
297 int rc = rtSocketCreateForNative(phSocket, hNative);
298 if (RT_FAILURE(rc))
299 {
300#ifdef RT_OS_WINDOWS
301 closesocket(hNative);
302#else
303 close(hNative);
304#endif
305 }
306 return rc;
307}
308
309
310RTDECL(uint32_t) RTSocketRetain(RTSOCKET hSocket)
311{
312 RTSOCKETINT *pThis = hSocket;
313 AssertPtrReturn(pThis, UINT32_MAX);
314 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
315 return RTMemPoolRetain(pThis);
316}
317
318
319/**
320 * Worker for RTSocketRelease and RTSocketClose.
321 *
322 * @returns IPRT status code.
323 * @param pThis The socket handle instance data.
324 * @param fDestroy Whether we're reaching ref count zero.
325 */
326static int rtSocketCloseIt(RTSOCKETINT *pThis, bool fDestroy)
327{
328 /*
329 * Invalidate the handle structure on destroy.
330 */
331 if (fDestroy)
332 {
333 Assert(ASMAtomicReadU32(&pThis->u32Magic) == RTSOCKET_MAGIC);
334 ASMAtomicWriteU32(&pThis->u32Magic, RTSOCKET_MAGIC_DEAD);
335 }
336
337 int rc = VINF_SUCCESS;
338 if (ASMAtomicCmpXchgBool(&pThis->fClosed, true, false))
339 {
340 /*
341 * Close the native handle.
342 */
343 RTSOCKETNATIVE hNative = pThis->hNative;
344 if (hNative != NIL_RTSOCKETNATIVE)
345 {
346 pThis->hNative = NIL_RTSOCKETNATIVE;
347
348#ifdef RT_OS_WINDOWS
349 if (closesocket(hNative))
350#else
351 if (close(hNative))
352#endif
353 {
354 rc = rtSocketError();
355#ifdef RT_OS_WINDOWS
356 AssertMsgFailed(("\"%s\": closesocket(%p) -> %Rrc\n", (uintptr_t)hNative, rc));
357#else
358 AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", hNative, rc));
359#endif
360 }
361 }
362
363#ifdef RT_OS_WINDOWS
364 /*
365 * Close the event.
366 */
367 WSAEVENT hEvent = pThis->hEvent;
368 if (hEvent == WSA_INVALID_EVENT)
369 {
370 pThis->hEvent = WSA_INVALID_EVENT;
371 WSACloseEvent(hEvent);
372 }
373#endif
374 }
375
376 return rc;
377}
378
379
380RTDECL(uint32_t) RTSocketRelease(RTSOCKET hSocket)
381{
382 RTSOCKETINT *pThis = hSocket;
383 if (pThis == NIL_RTSOCKET)
384 return 0;
385 AssertPtrReturn(pThis, UINT32_MAX);
386 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
387
388 /* get the refcount without killing it... */
389 uint32_t cRefs = RTMemPoolRefCount(pThis);
390 AssertReturn(cRefs != UINT32_MAX, UINT32_MAX);
391 if (cRefs == 1)
392 rtSocketCloseIt(pThis, true);
393
394 return RTMemPoolRelease(RTMEMPOOL_DEFAULT, pThis);
395}
396
397
398RTDECL(int) RTSocketClose(RTSOCKET hSocket)
399{
400 RTSOCKETINT *pThis = hSocket;
401 if (pThis == NIL_RTSOCKET)
402 return VINF_SUCCESS;
403 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
404 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
405
406 uint32_t cRefs = RTMemPoolRefCount(pThis);
407 AssertReturn(cRefs != UINT32_MAX, UINT32_MAX);
408
409 int rc = rtSocketCloseIt(pThis, cRefs == 1);
410
411 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pThis);
412 return rc;
413}
414
415
416RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket)
417{
418 RTSOCKETINT *pThis = hSocket;
419 AssertPtrReturn(pThis, RTHCUINTPTR_MAX);
420 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, RTHCUINTPTR_MAX);
421 return (RTHCUINTPTR)pThis->hNative;
422}
423
424
425RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
426{
427 RTSOCKETINT *pThis = hSocket;
428 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
429 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
430 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
431
432 int rc = VINF_SUCCESS;
433#ifdef RT_OS_WINDOWS
434 if (!SetHandleInformation((HANDLE)pThis->hNative, HANDLE_FLAG_INHERIT, fInheritable ? HANDLE_FLAG_INHERIT : 0))
435 rc = RTErrConvertFromWin32(GetLastError());
436#else
437 if (fcntl(pThis->hNative, F_SETFD, fInheritable ? 0 : FD_CLOEXEC) < 0)
438 rc = RTErrConvertFromErrno(errno);
439#endif
440
441 return rc;
442}
443
444
445RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
446{
447 /*
448 * Validate input.
449 */
450 RTSOCKETINT *pThis = hSocket;
451 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
452 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
453 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
454 AssertPtr(pvBuffer);
455 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
456
457 /*
458 * Read loop.
459 * If pcbRead is NULL we have to fill the entire buffer!
460 */
461 int rc = VINF_SUCCESS;
462 size_t cbRead = 0;
463 size_t cbToRead = cbBuffer;
464 for (;;)
465 {
466 rtSocketErrorReset();
467#ifdef RT_OS_WINDOWS
468 int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
469#else
470 size_t cbNow = cbToRead;
471#endif
472 ssize_t cbBytesRead = recv(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
473 if (cbBytesRead <= 0)
474 {
475 rc = rtSocketError();
476 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
477 if (RT_SUCCESS_NP(rc))
478 {
479 if (!pcbRead)
480 rc = VERR_NET_SHUTDOWN;
481 else
482 {
483 *pcbRead = 0;
484 rc = VINF_SUCCESS;
485 }
486 }
487 break;
488 }
489 if (pcbRead)
490 {
491 /* return partial data */
492 *pcbRead = cbBytesRead;
493 break;
494 }
495
496 /* read more? */
497 cbRead += cbBytesRead;
498 if (cbRead == cbBuffer)
499 break;
500
501 /* next */
502 cbToRead = cbBuffer - cbRead;
503 }
504
505 rtSocketUnlock(pThis);
506 return rc;
507}
508
509
510RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
511{
512 /*
513 * Validate input.
514 */
515 RTSOCKETINT *pThis = hSocket;
516 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
517 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
518 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
519
520 /*
521 * Try write all at once.
522 */
523 int rc = VINF_SUCCESS;
524#ifdef RT_OS_WINDOWS
525 int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
526#else
527 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
528#endif
529 ssize_t cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
530 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
531 rc = VINF_SUCCESS;
532 else if (cbWritten < 0)
533 rc = rtSocketError();
534 else
535 {
536 /*
537 * Unfinished business, write the remainder of the request. Must ignore
538 * VERR_INTERRUPTED here if we've managed to send something.
539 */
540 size_t cbSentSoFar = 0;
541 for (;;)
542 {
543 /* advance */
544 cbBuffer -= (size_t)cbWritten;
545 if (!cbBuffer)
546 break;
547 cbSentSoFar += (size_t)cbWritten;
548 pvBuffer = (char const *)pvBuffer + cbWritten;
549
550 /* send */
551#ifdef RT_OS_WINDOWS
552 cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
553#else
554 cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
555#endif
556 cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
557 if (cbWritten >= 0)
558 AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtSocketError()=%d\n",
559 cbWritten, cbBuffer, rtSocketError()));
560 else
561 {
562 rc = rtSocketError();
563 if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
564 break;
565 cbWritten = 0;
566 rc = VINF_SUCCESS;
567 }
568 }
569 }
570
571 rtSocketUnlock(pThis);
572 return rc;
573}
574
575
576RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
577{
578 /*
579 * Validate input.
580 */
581 RTSOCKETINT *pThis = hSocket;
582 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
583 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
584 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
585
586 /*
587 * Set up the file descriptor sets and do the select.
588 */
589 fd_set fdsetR;
590 FD_ZERO(&fdsetR);
591 FD_SET(pThis->hNative, &fdsetR);
592
593 fd_set fdsetE = fdsetR;
594
595 int rc;
596 if (cMillies == RT_INDEFINITE_WAIT)
597 rc = select(pThis->hNative + 1, &fdsetR, NULL, &fdsetE, NULL);
598 else
599 {
600 struct timeval timeout;
601 timeout.tv_sec = cMillies / 1000;
602 timeout.tv_usec = (cMillies % 1000) * 1000;
603 rc = select(pThis->hNative + 1, &fdsetR, NULL, &fdsetE, &timeout);
604 }
605 if (rc > 0)
606 rc = VINF_SUCCESS;
607 else if (rc == 0)
608 rc = VERR_TIMEOUT;
609 else
610 rc = rtSocketError();
611
612 return rc;
613}
614
615
616RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
617{
618 /*
619 * Validate input, don't lock it because we might want to interrupt a call
620 * active on a different thread.
621 */
622 RTSOCKETINT *pThis = hSocket;
623 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
624 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
625 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
626 AssertReturn(fRead || fWrite, VERR_INVALID_PARAMETER);
627
628 /*
629 * Do the job.
630 */
631 int rc = VINF_SUCCESS;
632 int fHow;
633 if (fRead && fWrite)
634 fHow = SHUT_RDWR;
635 else if (fRead)
636 fHow = SHUT_RD;
637 else
638 fHow = SHUT_WR;
639 if (shutdown(pThis->hNative, fHow) == -1)
640 rc = rtSocketError();
641
642 return rc;
643}
644
645
646/**
647 * Converts from a native socket address to a generic IPRT network address.
648 *
649 * @returns IPRT status code.
650 * @param pSrc The source address.
651 * @param cbSrc The size of the source address.
652 * @param pAddr Where to return the generic IPRT network
653 * address.
654 */
655static int rtSocketConvertAddress(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr)
656{
657 /*
658 * Convert the address.
659 */
660 if ( cbSrc == sizeof(struct sockaddr_in)
661 && pSrc->Addr.sa_family == AF_INET)
662 {
663 RT_ZERO(*pAddr);
664 pAddr->enmType = RTNETADDRTYPE_IPV4;
665 pAddr->uPort = RT_N2H_U16(pSrc->Ipv4.sin_port);
666 pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;
667 }
668#ifdef IPRT_WITH_TCPIP_V6
669 else if ( cbSrc == sizeof(struct sockaddr_in6)
670 && pSrc->Addr.sa_family == AF_INET6)
671 {
672 RT_ZERO(*pAddr);
673 pAddr->enmType = RTNETADDRTYPE_IPV6;
674 pAddr->uPort = RT_N2H_U16(pSrc->Ipv6.sin6_port);
675 pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];
676 pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];
677 pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];
678 pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];
679 }
680#endif
681 else
682 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
683 return VINF_SUCCESS;
684}
685
686
687RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
688{
689 /*
690 * Validate input.
691 */
692 RTSOCKETINT *pThis = hSocket;
693 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
694 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
695 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
696
697 /*
698 * Get the address and convert it.
699 */
700 int rc;
701 RTSOCKADDRUNION u;
702#ifdef RT_OS_WINDOWS
703 int cbAddr = sizeof(u);
704#else
705 socklen_t cbAddr = sizeof(u);
706#endif
707 RT_ZERO(u);
708 if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0)
709 rc = rtSocketConvertAddress(&u, cbAddr, pAddr);
710 else
711 rc = rtSocketError();
712
713 return rc;
714}
715
716
717RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
718{
719 /*
720 * Validate input.
721 */
722 RTSOCKETINT *pThis = hSocket;
723 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
724 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
725 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE);
726
727 /*
728 * Get the address and convert it.
729 */
730 int rc;
731 RTSOCKADDRUNION u;
732#ifdef RT_OS_WINDOWS
733 int cbAddr = sizeof(u);
734#else
735 socklen_t cbAddr = sizeof(u);
736#endif
737 RT_ZERO(u);
738 if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0)
739 rc = rtSocketConvertAddress(&u, cbAddr, pAddr);
740 else
741 rc = rtSocketError();
742
743 return rc;
744}
745
746
747
748/**
749 * Wrapper around bind.
750 *
751 * @returns IPRT status code.
752 * @param hSocket The socket handle.
753 * @param pAddr The socket address to bind to.
754 * @param cbAddr The size of the address structure @a pAddr
755 * points to.
756 */
757int rtSocketBind(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr)
758{
759 /*
760 * Validate input.
761 */
762 RTSOCKETINT *pThis = hSocket;
763 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
764 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
765 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
766
767 int rc = VINF_SUCCESS;
768 if (bind(pThis->hNative, pAddr, cbAddr) != 0)
769 rc = rtSocketError();
770
771 rtSocketUnlock(pThis);
772 return rc;
773}
774
775
776/**
777 * Wrapper around listen.
778 *
779 * @returns IPRT status code.
780 * @param hSocket The socket handle.
781 * @param cMaxPending The max number of pending connections.
782 */
783int rtSocketListen(RTSOCKET hSocket, int cMaxPending)
784{
785 /*
786 * Validate input.
787 */
788 RTSOCKETINT *pThis = hSocket;
789 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
790 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
791 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
792
793 int rc = VINF_SUCCESS;
794 if (listen(pThis->hNative, cMaxPending) != 0)
795 rc = rtSocketError();
796
797 rtSocketUnlock(pThis);
798 return rc;
799}
800
801
802/**
803 * Wrapper around accept.
804 *
805 * @returns IPRT status code.
806 * @param hSocket The socket handle.
807 * @param phClient Where to return the client socket handle on
808 * success.
809 * @param pAddr Where to return the client address.
810 * @param pcbAddr On input this gives the size buffer size of what
811 * @a pAddr point to. On return this contains the
812 * size of what's stored at @a pAddr.
813 */
814int rtSocketAccept(RTSOCKET hSocket, PRTSOCKET phClient, struct sockaddr *pAddr, size_t *pcbAddr)
815{
816 /*
817 * Validate input.
818 * Only lock the socket temporarily while we get the native handle, so that
819 * we can safely shutdown and destroy the socket from a different thread.
820 */
821 RTSOCKETINT *pThis = hSocket;
822 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
823 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
824 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
825
826 /*
827 * Call accept().
828 */
829 rtSocketErrorReset();
830 int rc = VINF_SUCCESS;
831#ifdef RT_OS_WINDOWS
832 int cbAddr = (int)*pcbAddr;
833#else
834 socklen_t cbAddr = *pcbAddr;
835#endif
836 RTSOCKETNATIVE hNativeClient = accept(pThis->hNative, pAddr, &cbAddr);
837 if (hNativeClient != NIL_RTSOCKETNATIVE)
838 {
839 *pcbAddr = cbAddr;
840
841 /*
842 * Wrap the client socket.
843 */
844 rc = rtSocketCreateForNative(phClient, hNativeClient);
845 if (RT_FAILURE(rc))
846 {
847#ifdef RT_OS_WINDOWS
848 closesocket(hNativeClient);
849#else
850 close(hNativeClient);
851#endif
852 }
853 }
854 else
855 rc = rtSocketError();
856
857 rtSocketUnlock(pThis);
858 return rc;
859}
860
861
862/**
863 * Wrapper around connect.
864 *
865 * @returns IPRT status code.
866 * @param hSocket The socket handle.
867 * @param pAddr The socket address to connect to.
868 * @param cbAddr The size of the address structure @a pAddr
869 * points to.
870 */
871int rtSocketConnect(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr)
872{
873 /*
874 * Validate input.
875 */
876 RTSOCKETINT *pThis = hSocket;
877 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
878 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
879 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
880
881 int rc = VINF_SUCCESS;
882 if (connect(pThis->hNative, pAddr, cbAddr) != 0)
883 rc = rtSocketError();
884
885 rtSocketUnlock(pThis);
886 return rc;
887}
888
889
890/**
891 * Wrapper around setsockopt.
892 *
893 * @returns IPRT status code.
894 * @param hSocket The socket handle.
895 * @param iLevel The protocol level, e.g. IPPORTO_TCP.
896 * @param iOption The option, e.g. TCP_NODELAY.
897 * @param pvValue The value buffer.
898 * @param cbValue The size of the value pointed to by pvValue.
899 */
900int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValue, int cbValue)
901{
902 /*
903 * Validate input.
904 */
905 RTSOCKETINT *pThis = hSocket;
906 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
907 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
908 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
909
910 int rc = VINF_SUCCESS;
911 if (setsockopt(pThis->hNative, iLevel, iOption, (const char *)pvValue, cbValue) != 0)
912 rc = rtSocketError();
913
914 rtSocketUnlock(pThis);
915 return rc;
916}
917
918#ifdef RT_OS_WINDOWS
919
920/**
921 * Internal RTPollSetAdd helper that returns the handle that should be added to
922 * the pollset.
923 *
924 * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
925 * @param hSocket The socket handle.
926 * @param fEvents The events we're polling for.
927 * @param ph wher to put the primary handle.
928 */
929int rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PHANDLE ph)
930{
931 RTSOCKETINT *pThis = hSocket;
932 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
933 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
934 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
935
936 int rc = VINF_SUCCESS;
937 if (pThis->hEvent != WSA_INVALID_EVENT)
938 *ph = pThis->hEvent;
939 else
940 {
941 *ph = pThis->hEvent = WSACreateEvent();
942 if (pThis->hEvent == WSA_INVALID_EVENT)
943 rc = rtSocketError();
944 }
945
946 rtSocketUnlock(pThis);
947 return rc;
948}
949
950
951/**
952 * Undos the harm done by WSAEventSelect.
953 *
954 * @returns IPRT status code.
955 * @param pThis The socket handle.
956 */
957static int rtSocketPollClearEventAndMakeBlocking(RTSOCKETINT *pThis)
958{
959 int rc = VINF_SUCCESS;
960 if (pThis->fSubscribedEvts)
961 {
962 if (WSAEventSelect(pThis->hNative, WSA_INVALID_EVENT, 0) == 0)
963 {
964 pThis->fSubscribedEvts = 0;
965
966 u_long fNonBlocking = 0;
967 int rc2 = ioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking);
968 if (rc2 != 0)
969 {
970 rc = rtSocketError();
971 AssertMsgFailed(("%Rrc; rc2=%d\n", rc, rc2));
972 }
973 }
974 else
975 {
976 rc = rtSocketError();
977 AssertMsgFailed(("%Rrc\n", rc));
978 }
979 }
980 return rc;
981}
982
983
984/**
985 * Updates the mask of events we're subscribing to.
986 *
987 * @returns IPRT status code.
988 * @param pThis The socket handle.
989 * @param fEvents The events we want to subscribe to.
990 */
991static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
992{
993 LONG fNetworkEvents = 0;
994 if (fEvents & RTPOLL_EVT_READ)
995 fNetworkEvents |= FD_READ;
996 if (fEvents & RTPOLL_EVT_WRITE)
997 fNetworkEvents |= FD_WRITE;
998 if (fEvents & RTPOLL_EVT_ERROR)
999 fNetworkEvents |= FD_CLOSE;
1000 if (WSAEventSelect(pThis->hNative, pThis->hEvent, fNetworkEvents) == 0)
1001 {
1002 pThis->fSubscribedEvts = fEvents;
1003 return VINF_SUCCESS;
1004 }
1005
1006 int rc = rtSocketError();
1007 AssertMsgFailed(("fNetworkEvents=%#x rc=%Rrc\n", fNetworkEvents, rtSocketError()));
1008 return rc;
1009}
1010
1011
1012/**
1013 * Checks for pending events.
1014 *
1015 * @returns Event mask or 0.
1016 * @param pThis The socket handle.
1017 * @param fEvents The desired events.
1018 */
1019static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
1020{
1021 int rc = VINF_SUCCESS;
1022 uint32_t fRetEvents = 0;
1023
1024 /* Make sure WSAEnumNetworkEvents returns what we want. */
1025 if ((pThis->fSubscribedEvts & fEvents) != fEvents)
1026 rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents);
1027
1028 /* Get the event mask, ASSUMES that WSAEnumNetworkEvents doesn't clear stuff. */
1029 WSANETWORKEVENTS NetEvts;
1030 RT_ZERO(NetEvts);
1031 if (WSAEnumNetworkEvents(pThis->hNative, pThis->hEvent, &NetEvts) == 0)
1032 {
1033 if ( (NetEvts.lNetworkEvents & FD_READ)
1034 && (fEvents & RTPOLL_EVT_READ)
1035 && NetEvts.iErrorCode[FD_READ_BIT] == 0)
1036 fRetEvents |= RTPOLL_EVT_READ;
1037
1038 if ( (NetEvts.lNetworkEvents & FD_WRITE)
1039 && (fEvents & RTPOLL_EVT_WRITE)
1040 && NetEvts.iErrorCode[FD_WRITE_BIT] == 0)
1041 fRetEvents |= RTPOLL_EVT_WRITE;
1042
1043 if (fEvents & RTPOLL_EVT_ERROR)
1044 {
1045 if (NetEvts.lNetworkEvents & FD_CLOSE)
1046 fRetEvents |= RTPOLL_EVT_ERROR;
1047 else
1048 for (uint32_t i = 0; i < FD_MAX_EVENTS; i++)
1049 if ( (NetEvts.lNetworkEvents & (1L << i))
1050 && NetEvts.iErrorCode[i] != 0)
1051 fRetEvents |= RTPOLL_EVT_ERROR;
1052 }
1053 }
1054 else
1055 rc = rtSocketError();
1056
1057 /* Fall back on select if we hit an error above. */
1058 if (RT_FAILURE(rc))
1059 {
1060 /** @todo */
1061 }
1062
1063 return fRetEvents;
1064}
1065
1066
1067/**
1068 * Internal RTPoll helper that polls the socket handle and, if @a fNoWait is
1069 * clear, starts whatever actions we've got running during the poll call.
1070 *
1071 * @returns 0 if no pending events, actions initiated if @a fNoWait is clear.
1072 * Event mask (in @a fEvents) and no actions if the handle is ready
1073 * already.
1074 * UINT32_MAX (asserted) if the socket handle is busy in I/O or a
1075 * different poll set.
1076 *
1077 * @param hSocket The socket handle.
1078 * @param hPollSet The poll set handle (for access checks).
1079 * @param fEvents The events we're polling for.
1080 * @param fFinalEntry Set if this is the final entry for this handle
1081 * in this poll set. This can be used for dealing
1082 * with duplicate entries.
1083 * @param fNoWait Set if it's a zero-wait poll call. Clear if
1084 * we'll wait for an event to occur.
1085 *
1086 * @remarks There is a potential race wrt duplicate handles when @a fNoWait is
1087 * @c true, we don't currently care about that oddity...
1088 */
1089uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
1090{
1091 RTSOCKETINT *pThis = hSocket;
1092 AssertPtrReturn(pThis, UINT32_MAX);
1093 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
1094 if (rtSocketTryLock(pThis))
1095 pThis->hPollSet = hPollSet;
1096 else
1097 {
1098 AssertReturn(pThis->hPollSet == hPollSet, UINT32_MAX);
1099 ASMAtomicIncU32(&pThis->cUsers);
1100 }
1101
1102 /* (rtSocketPollCheck will reset the event object). */
1103 uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
1104 if ( !fRetEvents
1105 && !fNoWait)
1106 {
1107 pThis->fPollEvts |= fEvents;
1108 if ( fFinalEntry
1109 && pThis->fSubscribedEvts != pThis->fPollEvts)
1110 {
1111 int rc = rtSocketPollUpdateEvents(pThis, pThis->fPollEvts);
1112 if (RT_FAILURE(rc))
1113 {
1114 pThis->fPollEvts = 0;
1115 fRetEvents = UINT32_MAX;
1116 }
1117 }
1118 }
1119
1120 if (fRetEvents || fNoWait)
1121 {
1122 if (pThis->cUsers == 1)
1123 {
1124 rtSocketPollClearEventAndMakeBlocking(pThis);
1125 pThis->hPollSet = NIL_RTPOLLSET;
1126 }
1127 ASMAtomicDecU32(&pThis->cUsers);
1128 }
1129
1130 return fRetEvents;
1131}
1132
1133
1134/**
1135 * Called after a WaitForMultipleObjects returned in order to check for pending
1136 * events and stop whatever actions that rtSocketPollStart() initiated.
1137 *
1138 * @returns Event mask or 0.
1139 *
1140 * @param hSocket The socket handle.
1141 * @param fEvents The events we're polling for.
1142 * @param fFinalEntry Set if this is the final entry for this handle
1143 * in this poll set. This can be used for dealing
1144 * with duplicate entries. Only keep in mind that
1145 * this method is called in reverse order, so the
1146 * first call will have this set (when the entire
1147 * set was processed).
1148 */
1149uint32_t rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry)
1150{
1151 RTSOCKETINT *pThis = hSocket;
1152 AssertPtrReturn(pThis, 0);
1153 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, 0);
1154 Assert(pThis->cUsers > 0);
1155 Assert(pThis->hPollSet != NIL_RTPOLLSET);
1156
1157 /* Harvest events and clear the event mask for the next round of polling. */
1158 uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
1159 pThis->fPollEvts = 0;
1160
1161 /* Make the socket blocking again and unlock the handle. */
1162 if (pThis->cUsers == 1)
1163 {
1164 rtSocketPollClearEventAndMakeBlocking(pThis);
1165 pThis->hPollSet = NIL_RTPOLLSET;
1166 }
1167 ASMAtomicDecU32(&pThis->cUsers);
1168 return fRetEvents;
1169}
1170
1171#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