VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/tcp.cpp@ 27288

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

r3/tcp.cpp: Mark all sockets as no-inherit. (TODO: windows)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 37.8 KB
Line 
1/* $Id: tcp.cpp 27288 2010-03-11 16:37:17Z vboxsync $ */
2/** @file
3 * IPRT - TCP/IP.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#ifdef RT_OS_WINDOWS
36# include <winsock.h>
37#else /* !RT_OS_WINDOWS */
38# include <errno.h>
39# include <sys/stat.h>
40# include <sys/socket.h>
41# include <netinet/in.h>
42# include <netinet/tcp.h>
43# include <arpa/inet.h>
44# ifdef IPRT_WITH_TCPIP_V6
45# include <netinet6/in6.h>
46# endif
47# include <sys/un.h>
48# include <netdb.h>
49# include <unistd.h>
50# include <fcntl.h>
51#endif /* !RT_OS_WINDOWS */
52#include <limits.h>
53
54#include "internal/iprt.h"
55#include <iprt/tcp.h>
56
57#include <iprt/asm.h>
58#include <iprt/assert.h>
59#include <iprt/err.h>
60#include <iprt/mempool.h>
61#include <iprt/string.h>
62#include <iprt/thread.h>
63#include <iprt/time.h>
64
65#include "internal/magics.h"
66
67
68/*******************************************************************************
69* Defined Constants And Macros *
70*******************************************************************************/
71/* non-standard linux stuff (it seems). */
72#ifndef MSG_NOSIGNAL
73# define MSG_NOSIGNAL 0
74#endif
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
90/* fixup backlevel OSes. */
91#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
92# define socklen_t int
93#endif
94
95/** How many pending connection. */
96#define RTTCP_SERVER_BACKLOG 10
97
98
99/*******************************************************************************
100* Structures and Typedefs *
101*******************************************************************************/
102/**
103 * TCP Server state.
104 */
105typedef enum RTTCPSERVERSTATE
106{
107 /** Invalid. */
108 RTTCPSERVERSTATE_INVALID = 0,
109 /** Created. */
110 RTTCPSERVERSTATE_CREATED,
111 /** Listener thread is starting up. */
112 RTTCPSERVERSTATE_STARTING,
113 /** Accepting client connections. */
114 RTTCPSERVERSTATE_ACCEPTING,
115 /** Serving a client. */
116 RTTCPSERVERSTATE_SERVING,
117 /** Listener terminating. */
118 RTTCPSERVERSTATE_STOPPING,
119 /** Listener terminated. */
120 RTTCPSERVERSTATE_STOPPED,
121 /** Listener cleans up. */
122 RTTCPSERVERSTATE_DESTROYING
123} RTTCPSERVERSTATE;
124
125/*
126 * Internal representation of the TCP Server handle.
127 */
128typedef struct RTTCPSERVER
129{
130 /** The magic value (RTTCPSERVER_MAGIC). */
131 uint32_t volatile u32Magic;
132 /** The server state. */
133 RTTCPSERVERSTATE volatile enmState;
134 /** The server thread. */
135 RTTHREAD Thread;
136 /** The server socket. */
137 RTSOCKET volatile SockServer;
138 /** The socket to the client currently being serviced.
139 * This is NIL_RTSOCKET when no client is serviced. */
140 RTSOCKET volatile SockClient;
141 /** The connection function. */
142 PFNRTTCPSERVE pfnServe;
143 /** Argument to pfnServer. */
144 void *pvUser;
145} RTTCPSERVER;
146
147typedef union RTSOCKADDRUNION
148{
149 struct sockaddr Addr;
150 struct sockaddr_in Ipv4;
151#ifdef IPRT_WITH_TCPIP_V6
152 struct sockaddr_in6 Ipv6;
153#endif
154} RTSOCKADDRUNION;
155
156/*******************************************************************************
157* Internal Functions *
158*******************************************************************************/
159static DECLCALLBACK(int) rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer);
160static int rtTcpServerListen(PRTTCPSERVER pServer);
161static int rtTcpServerListenCleanup(PRTTCPSERVER pServer);
162static int rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);
163static int rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown);
164static int rtTcpConvertAddress(RTSOCKADDRUNION *pSrc, size_t cbSrc, PRTNETADDR pAddr);
165
166
167
168/**
169 * Get the last error as an iprt status code.
170 *
171 * @returns iprt status code.
172 */
173DECLINLINE(int) rtTcpError(void)
174{
175#ifdef RT_OS_WINDOWS
176 return RTErrConvertFromWin32(WSAGetLastError());
177#else
178 return RTErrConvertFromErrno(errno);
179#endif
180}
181
182
183/**
184 * Resets the last error.
185 */
186DECLINLINE(void) rtTcpErrorReset(void)
187{
188#ifdef RT_OS_WINDOWS
189 WSASetLastError(0);
190#else
191 errno = 0;
192#endif
193}
194
195
196/**
197 * Get the last resolver error as an iprt status code.
198 *
199 * @returns iprt status code.
200 */
201DECLINLINE(int) rtTcpResolverError(void)
202{
203#ifdef RT_OS_WINDOWS
204 return RTErrConvertFromWin32(WSAGetLastError());
205#else
206 switch (h_errno)
207 {
208 case HOST_NOT_FOUND:
209 return VERR_NET_HOST_NOT_FOUND;
210 case NO_DATA:
211 return VERR_NET_ADDRESS_NOT_AVAILABLE;
212 case NO_RECOVERY:
213 return VERR_IO_GEN_FAILURE;
214 case TRY_AGAIN:
215 return VERR_TRY_AGAIN;
216
217 default:
218 return VERR_UNRESOLVED_ERROR;
219 }
220#endif
221}
222
223
224/**
225 * Helper that ensures the correct inheritability of a socket.
226 *
227 * We're currently ignoring failures.
228 *
229 * @param Socket The socket handle.
230 * @param fInheritable The desired inheritability state.
231 */
232static void rtTcpSetInheritance(RTSOCKET Socket, bool fInheritable)
233{
234#ifdef RT_OS_WINDOWS
235 /** @todo Find some magic way to change this... Worst case we have to use
236 * DuplicateHandle w/bInheritable=FALSE and replace the original
237 * handles... */
238#else
239 fcntl(Socket, F_SETFD, fInheritable ? 0 : FD_CLOEXEC);
240#endif
241}
242
243
244/**
245 * Atomicly updates a socket variable.
246 * @returns The old value.
247 * @param pSock The socket variable to update.
248 * @param Sock The new value.
249 */
250DECLINLINE(RTSOCKET) rtTcpAtomicXchgSock(RTSOCKET volatile *pSock, const RTSOCKET Sock)
251{
252 switch (sizeof(RTSOCKET))
253 {
254 case 4: return (RTSOCKET)ASMAtomicXchgS32((int32_t volatile *)pSock, (int32_t)Sock);
255 default:
256 AssertReleaseFailed();
257 return NIL_RTSOCKET;
258 }
259}
260
261
262/**
263 * Tries to change the TCP server state.
264 */
265DECLINLINE(bool) rtTcpServerTrySetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
266{
267 bool fRc;
268 ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
269 return fRc;
270}
271
272/**
273 * Changes the TCP server state.
274 */
275DECLINLINE(void) rtTcpServerSetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
276{
277 bool fRc;
278 ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
279 Assert(fRc); NOREF(fRc);
280}
281
282/**
283 * Closes the a socket (client or server).
284 *
285 * @returns IPRT status code.
286 */
287static int rtTcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg, bool fTryGracefulShutdown)
288{
289 RTSOCKET Sock = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET);
290 if (Sock != NIL_RTSOCKET)
291 {
292 if (!fTryGracefulShutdown)
293 shutdown(Sock, SHUT_RDWR);
294 return rtTcpClose(Sock, pszMsg, fTryGracefulShutdown);
295 }
296 return VINF_TCP_SERVER_NO_CLIENT;
297}
298
299
300/**
301 * Create single connection at a time TCP Server in a separate thread.
302 *
303 * The thread will loop accepting connections and call pfnServe for
304 * each of the incoming connections in turn. The pfnServe function can
305 * return VERR_TCP_SERVER_STOP too terminate this loop. RTTcpServerDestroy()
306 * should be used to terminate the server.
307 *
308 * @returns iprt status code.
309 * @param pszAddress The address for creating a listening socket.
310 * If NULL or empty string the server is bound to all interfaces.
311 * @param uPort The port for creating a listening socket.
312 * @param enmType The thread type.
313 * @param pszThrdName The name of the worker thread.
314 * @param pfnServe The function which will serve a new client connection.
315 * @param pvUser User argument passed to pfnServe.
316 * @param ppServer Where to store the serverhandle.
317 */
318RTR3DECL(int) RTTcpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,
319 PFNRTTCPSERVE pfnServe, void *pvUser, PPRTTCPSERVER ppServer)
320{
321 /*
322 * Validate input.
323 */
324 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
325 AssertPtrReturn(pfnServe, VERR_INVALID_POINTER);
326 AssertPtrReturn(pszThrdName, VERR_INVALID_POINTER);
327 AssertPtrReturn(ppServer, VERR_INVALID_POINTER);
328
329 /*
330 * Create the server.
331 */
332 PRTTCPSERVER pServer;
333 int rc = RTTcpServerCreateEx(pszAddress, uPort, &pServer);
334 if (RT_SUCCESS(rc))
335 {
336 /*
337 * Create the listener thread.
338 */
339 RTMemPoolRetain(pServer);
340 pServer->enmState = RTTCPSERVERSTATE_STARTING;
341 pServer->pvUser = pvUser;
342 pServer->pfnServe = pfnServe;
343 rc = RTThreadCreate(&pServer->Thread, rtTcpServerThread, pServer, 0, enmType, /*RTTHREADFLAGS_WAITABLE*/0, pszThrdName);
344 if (RT_SUCCESS(rc))
345 {
346 /* done */
347 if (ppServer)
348 *ppServer = pServer;
349 else
350 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
351 return rc;
352 }
353 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
354
355 /*
356 * Destroy the server.
357 */
358 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_STARTING);
359 RTTcpServerDestroy(pServer);
360 }
361
362 return rc;
363}
364
365
366/**
367 * Server thread, loops accepting connections until it's terminated.
368 *
369 * @returns iprt status code. (ignored).
370 * @param ThreadSelf Thread handle.
371 * @param pvServer Server handle.
372 */
373static DECLCALLBACK(int) rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer)
374{
375 PRTTCPSERVER pServer = (PRTTCPSERVER)pvServer;
376 int rc;
377 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_STARTING))
378 rc = rtTcpServerListen(pServer);
379 else
380 rc = rtTcpServerListenCleanup(pServer);
381 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
382 NOREF(ThreadSelf);
383 return VINF_SUCCESS;
384}
385
386
387/**
388 * Create single connection at a time TCP Server.
389 * The caller must call RTTcpServerListen() to actually start the server.
390 *
391 * @returns iprt status code.
392 * @param pszAddress The address for creating a listening socket.
393 * If NULL the server is bound to all interfaces.
394 * @param uPort The port for creating a listening socket.
395 * @param ppServer Where to store the serverhandle.
396 */
397RTR3DECL(int) RTTcpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTTCPSERVER ppServer)
398{
399 int rc;
400
401 /*
402 * Validate input.
403 */
404 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
405 AssertPtrReturn(ppServer, VERR_INVALID_PARAMETER);
406
407#ifdef RT_OS_WINDOWS
408 /*
409 * Initialize WinSock and check version.
410 */
411 WORD wVersionRequested = MAKEWORD(1, 1);
412 WSADATA wsaData;
413 rc = WSAStartup(wVersionRequested, &wsaData);
414 if (wsaData.wVersion != wVersionRequested)
415 {
416 AssertMsgFailed(("Wrong winsock version\n"));
417 return VERR_NOT_SUPPORTED;
418 }
419#endif
420
421 /*
422 * Get host listening address.
423 */
424 struct hostent *pHostEnt = NULL;
425 if (pszAddress != NULL && *pszAddress)
426 {
427 pHostEnt = gethostbyname(pszAddress);
428 if (!pHostEnt)
429 {
430 struct in_addr InAddr;
431 InAddr.s_addr = inet_addr(pszAddress);
432 pHostEnt = gethostbyaddr((char *)&InAddr, 4, AF_INET);
433 if (!pHostEnt)
434 {
435 rc = rtTcpResolverError();
436 AssertMsgFailed(("Could not get host address rc=%Rrc\n", rc));
437 return rc;
438 }
439 }
440 }
441
442 /*
443 * Setting up socket.
444 */
445 RTSOCKET WaitSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
446 if (WaitSock != -1)
447 {
448 rtTcpSetInheritance(WaitSock, false /*fInheritable*/);
449
450 /*
451 * Set socket options.
452 */
453 int fFlag = 1;
454 if (!setsockopt(WaitSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&fFlag, sizeof(fFlag)))
455 {
456 /*
457 * Set socket family, address and port.
458 */
459 struct sockaddr_in LocalAddr;
460 RT_ZERO(LocalAddr);
461 LocalAddr.sin_family = AF_INET;
462 LocalAddr.sin_port = htons(uPort);
463 /* if address not specified, use INADDR_ANY. */
464 if (!pHostEnt)
465 LocalAddr.sin_addr.s_addr = INADDR_ANY;
466 else
467 LocalAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);
468
469 /*
470 * Bind a name to a socket.
471 */
472 if (bind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) != -1)
473 {
474 /*
475 * Listen for connections on a socket.
476 */
477 if (listen(WaitSock, RTTCP_SERVER_BACKLOG) != -1)
478 {
479 /*
480 * Create the server handle.
481 */
482 PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
483 if (pServer)
484 {
485 pServer->u32Magic = RTTCPSERVER_MAGIC;
486 pServer->enmState = RTTCPSERVERSTATE_CREATED;
487 pServer->Thread = NIL_RTTHREAD;
488 pServer->SockServer = WaitSock;
489 pServer->SockClient = NIL_RTSOCKET;
490 pServer->pfnServe = NULL;
491 pServer->pvUser = NULL;
492 *ppServer = pServer;
493 return VINF_SUCCESS;
494 }
495
496 /* bail out */
497 rc = VERR_NO_MEMORY;
498 }
499 else
500 {
501 rc = rtTcpError();
502 AssertMsgFailed(("listen() %Rrc\n", rc));
503 }
504 }
505 else
506 {
507 rc = rtTcpError();
508 }
509 }
510 else
511 {
512 rc = rtTcpError();
513 AssertMsgFailed(("setsockopt() %Rrc\n", rc));
514 }
515 rtTcpClose(WaitSock, "RTServerCreateEx", false /*fTryGracefulShutdown*/);
516 }
517 else
518 {
519 rc = rtTcpError();
520 AssertMsgFailed(("socket() %Rrc\n", rc));
521 }
522
523 return rc;
524}
525
526
527/**
528 * Listen for incoming connections.
529 *
530 * The function will loop accepting connections and call pfnServe for
531 * each of the incoming connections in turn. The pfnServe function can
532 * return VERR_TCP_SERVER_STOP too terminate this loop. A stopped server
533 * can only be destroyed.
534 *
535 * @returns IPRT status code.
536 * @retval VERR_TCP_SERVER_STOP if stopped by pfnServe.
537 * @retval VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown.
538 *
539 * @param pServer The server handle as returned from RTTcpServerCreateEx().
540 * @param pfnServe The function which will serve a new client connection.
541 * @param pvUser User argument passed to pfnServe.
542 */
543RTR3DECL(int) RTTcpServerListen(PRTTCPSERVER pServer, PFNRTTCPSERVE pfnServe, void *pvUser)
544{
545 /*
546 * Validate input and retain the instance.
547 */
548 AssertPtrReturn(pfnServe, VERR_INVALID_POINTER);
549 AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
550 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
551 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
552
553 int rc = VERR_INVALID_STATE;
554 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_CREATED))
555 {
556 Assert(!pServer->pfnServe);
557 Assert(!pServer->pvUser);
558 Assert(pServer->Thread == NIL_RTTHREAD);
559 Assert(pServer->SockClient == NIL_RTSOCKET);
560
561 pServer->pfnServe = pfnServe;
562 pServer->pvUser = pvUser;
563 pServer->Thread = RTThreadSelf();
564 Assert(pServer->Thread != NIL_RTTHREAD);
565 rc = rtTcpServerListen(pServer);
566 }
567 else
568 {
569 AssertMsgFailed(("enmState=%d\n", pServer->enmState));
570 rc = VERR_INVALID_STATE;
571 }
572 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
573 return rc;
574}
575
576
577/**
578 * Internal worker common for RTTcpServerListen and the thread created by
579 * RTTcpServerCreate().
580 *
581 * The caller makes sure it has its own memory reference and releases it upon
582 * return.
583 */
584static int rtTcpServerListen(PRTTCPSERVER pServer)
585{
586 /*
587 * Accept connection loop.
588 */
589 for (;;)
590 {
591 /*
592 * Change state.
593 */
594 RTTCPSERVERSTATE enmState = pServer->enmState;
595 RTSOCKET SockServer = pServer->SockServer;
596 if ( enmState != RTTCPSERVERSTATE_ACCEPTING
597 && enmState != RTTCPSERVERSTATE_SERVING)
598 return rtTcpServerListenCleanup(pServer);
599 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))
600 continue;
601
602 /*
603 * Accept connection.
604 */
605 struct sockaddr_in RemoteAddr;
606 RT_ZERO(RemoteAddr);
607 socklen_t cbRemoteAddr = sizeof(RemoteAddr);
608 RTSOCKET Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
609 if (Socket == -1)
610 {
611#ifndef RT_OS_WINDOWS
612 /* These are typical for what can happen during destruction. */
613 if (errno == EBADF || errno == EINVAL || errno == ENOTSOCK)
614 return rtTcpServerListenCleanup(pServer);
615#endif
616 continue;
617 }
618 rtTcpSetInheritance(Socket, false /*fInheritable*/);
619
620 /*
621 * Run a pfnServe callback.
622 */
623 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING))
624 {
625 rtTcpClose(Socket, "rtTcpServerListen", true /*fTryGracefulShutdown*/);
626 return rtTcpServerListenCleanup(pServer);
627 }
628 rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
629 int rc = pServer->pfnServe(Socket, pServer->pvUser);
630 rtTcpServerDestroySocket(&pServer->SockClient, "Listener: client", true /*fTryGracefulShutdown*/);
631
632 /*
633 * Stop the server?
634 */
635 if (rc == VERR_TCP_SERVER_STOP)
636 {
637 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING))
638 {
639 /*
640 * Reset the server socket and change the state to stopped. After that state change
641 * we cannot safely access the handle so we'll have to return here.
642 */
643 SockServer = rtTcpAtomicXchgSock(&pServer->SockServer, NIL_RTSOCKET);
644 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);
645 rtTcpClose(SockServer, "Listener: server stopped", false /*fTryGracefulShutdown*/);
646 }
647 else
648 rtTcpServerListenCleanup(pServer); /* ignore rc */
649 return rc;
650 }
651 }
652}
653
654
655/**
656 * Clean up after listener.
657 */
658static int rtTcpServerListenCleanup(PRTTCPSERVER pServer)
659{
660 /*
661 * Close the server socket, the client one shouldn't be set.
662 */
663 rtTcpServerDestroySocket(&pServer->SockServer, "ListenCleanup", false /*fTryGracefulShutdown*/);
664 Assert(pServer->SockClient == NIL_RTSOCKET);
665
666 /*
667 * Figure the return code and make sure the state is OK.
668 */
669 RTTCPSERVERSTATE enmState = pServer->enmState;
670 switch (enmState)
671 {
672 case RTTCPSERVERSTATE_STOPPING:
673 case RTTCPSERVERSTATE_STOPPED:
674 return VERR_TCP_SERVER_SHUTDOWN;
675
676 case RTTCPSERVERSTATE_ACCEPTING:
677 rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPED, enmState);
678 return VERR_TCP_SERVER_DESTROYED;
679
680 case RTTCPSERVERSTATE_DESTROYING:
681 return VERR_TCP_SERVER_DESTROYED;
682
683 case RTTCPSERVERSTATE_STARTING:
684 case RTTCPSERVERSTATE_SERVING:
685 default:
686 AssertMsgFailedReturn(("pServer=%p enmState=%d\n", pServer, enmState), VERR_INTERNAL_ERROR_4);
687 }
688}
689
690
691/**
692 * Listen and accept one incomming connection.
693 *
694 * This is an alternative to RTTcpServerListen for the use the callbacks are not
695 * possible.
696 *
697 * @returns IPRT status code.
698 * @retval VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown.
699 * @retval VERR_INTERRUPTED if the listening was interrupted.
700 *
701 * @param pServer The server handle as returned from RTTcpServerCreateEx().
702 * @param pSockClient Where to return the socket handle to the client
703 * connection (on success only). Use
704 * RTTcpServerDisconnectClient() to clean it, this must
705 * be done before the next call to RTTcpServerListen2.
706 *
707 * @todo This can easily be extended to support multiple connections by
708 * adding a new state and a RTTcpServerDisconnectClient variant for
709 * closing client sockets.
710 */
711RTR3DECL(int) RTTcpServerListen2(PRTTCPSERVER pServer, PRTSOCKET pSockClient)
712{
713 /*
714 * Validate input and retain the instance.
715 */
716 AssertPtrReturn(pSockClient, VERR_INVALID_HANDLE);
717 *pSockClient = NIL_RTSOCKET;
718 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
719 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
720
721 int rc = VERR_INVALID_STATE;
722 for (;;)
723 {
724 /*
725 * Change state to accepting.
726 */
727 RTTCPSERVERSTATE enmState = pServer->enmState;
728 RTSOCKET SockServer = pServer->SockServer;
729 if ( enmState != RTTCPSERVERSTATE_SERVING
730 && enmState != RTTCPSERVERSTATE_CREATED)
731 {
732 rc = rtTcpServerListenCleanup(pServer);
733 break;
734 }
735 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))
736 continue;
737 Assert(!pServer->pfnServe);
738 Assert(!pServer->pvUser);
739 Assert(pServer->Thread == NIL_RTTHREAD);
740 Assert(pServer->SockClient == NIL_RTSOCKET);
741
742 /*
743 * Accept connection.
744 */
745 struct sockaddr_in RemoteAddr;
746 socklen_t cbRemoteAddr = sizeof(RemoteAddr);
747 RTSOCKET Socket;
748 RT_ZERO(RemoteAddr);
749 rtTcpErrorReset();
750 Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
751 if (Socket == -1)
752 {
753 rc = rtTcpError();
754 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_ACCEPTING))
755 rc = rtTcpServerListenCleanup(pServer);
756 if (RT_FAILURE(rc))
757 break;
758 continue;
759 }
760 rtTcpSetInheritance(Socket, false /*fInheritable*/);
761
762 /*
763 * Chance to the 'serving' state and return the socket.
764 */
765 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING))
766 {
767 RTSOCKET OldSocket = rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
768 Assert(OldSocket == NIL_RTSOCKET); NOREF(OldSocket);
769 *pSockClient = Socket;
770 rc = VINF_SUCCESS;
771 }
772 else
773 {
774 rtTcpClose(Socket, "RTTcpServerListen2", true /*fTryGracefulShutdown*/);
775 rc = rtTcpServerListenCleanup(pServer);
776 }
777 break;
778 }
779
780 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
781 return rc;
782}
783
784
785/**
786 * Terminate the open connection to the server.
787 *
788 * @returns iprt status code.
789 * @param pServer Handle to the server.
790 */
791RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer)
792{
793 /*
794 * Validate input and retain the instance.
795 */
796 AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
797 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
798 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
799
800 int rc = rtTcpServerDestroySocket(&pServer->SockClient, "DisconnectClient: client", true /*fTryGracefulShutdown*/);
801
802 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
803 return rc;
804}
805
806
807/**
808 * Shuts down the server, leaving client connections open.
809 *
810 * @returns IPRT status code.
811 * @param pServer Handle to the server.
812 */
813RTR3DECL(int) RTTcpServerShutdown(PRTTCPSERVER pServer)
814{
815 /*
816 * Validate input and retain the instance.
817 */
818 AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
819 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
820 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
821
822 /*
823 * Try change the state to stopping, then replace and destroy the server socket.
824 */
825 for (;;)
826 {
827 RTTCPSERVERSTATE enmState = pServer->enmState;
828 if ( enmState != RTTCPSERVERSTATE_ACCEPTING
829 && enmState != RTTCPSERVERSTATE_SERVING)
830 {
831 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
832 switch (enmState)
833 {
834 case RTTCPSERVERSTATE_CREATED:
835 case RTTCPSERVERSTATE_STARTING:
836 default:
837 AssertMsgFailed(("%d\n", enmState));
838 return VERR_INVALID_STATE;
839
840 case RTTCPSERVERSTATE_STOPPING:
841 case RTTCPSERVERSTATE_STOPPED:
842 return VINF_SUCCESS;
843
844 case RTTCPSERVERSTATE_DESTROYING:
845 return VERR_TCP_SERVER_DESTROYED;
846 }
847 }
848 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, enmState))
849 {
850 rtTcpServerDestroySocket(&pServer->SockServer, "RTTcpServerShutdown", false /*fTryGracefulShutdown*/);
851 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);
852
853 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
854 return VINF_SUCCESS;
855 }
856 }
857}
858
859
860/**
861 * Closes down and frees a TCP Server.
862 * This will also terminate any open connections to the server.
863 *
864 * @returns iprt status code.
865 * @param pServer Handle to the server.
866 */
867RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer)
868{
869 /*
870 * Validate input and retain the instance.
871 */
872 AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
873 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
874 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); /* paranoia */
875
876 /*
877 * Move the state along so the listener can figure out what's going on.
878 */
879 for (;;)
880 {
881 bool fDestroyable;
882 RTTCPSERVERSTATE enmState = pServer->enmState;
883 switch (enmState)
884 {
885 case RTTCPSERVERSTATE_STARTING:
886 case RTTCPSERVERSTATE_ACCEPTING:
887 case RTTCPSERVERSTATE_SERVING:
888 case RTTCPSERVERSTATE_CREATED:
889 case RTTCPSERVERSTATE_STOPPED:
890 fDestroyable = rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_DESTROYING, enmState);
891 break;
892
893 /* destroyable states */
894 case RTTCPSERVERSTATE_STOPPING:
895 fDestroyable = true;
896 break;
897
898 /*
899 * Everything else means user or internal misbehavior.
900 */
901 default:
902 AssertMsgFailed(("pServer=%p enmState=%d\n", pServer, enmState));
903 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
904 return VERR_INTERNAL_ERROR;
905 }
906 if (fDestroyable)
907 break;
908 }
909
910 /*
911 * Destroy it.
912 */
913 ASMAtomicWriteU32(&pServer->u32Magic, ~RTTCPSERVER_MAGIC);
914 rtTcpServerDestroySocket(&pServer->SockServer, "Destroyer: server", false /*fTryGracefulShutdown*/);
915 rtTcpServerDestroySocket(&pServer->SockClient, "Destroyer: client", true /*fTryGracefulShutdown*/);
916
917 /*
918 * Release it.
919 */
920 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
921 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
922 return VINF_SUCCESS;
923}
924
925
926RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
927{
928 /*
929 * Validate input.
930 */
931 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
932 AssertPtr(pvBuffer);
933
934 /*
935 * Read loop.
936 * If pcbRead is NULL we have to fill the entire buffer!
937 */
938 size_t cbRead = 0;
939 size_t cbToRead = cbBuffer;
940 for (;;)
941 {
942 rtTcpErrorReset();
943#ifdef RT_OS_WINDOWS
944 int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
945#else
946 size_t cbNow = cbToRead;
947#endif
948 ssize_t cbBytesRead = recv(Sock, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
949 if (cbBytesRead <= 0)
950 {
951 int rc = rtTcpError();
952 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
953 if (RT_FAILURE_NP(rc))
954 return rc;
955 if (pcbRead)
956 {
957 *pcbRead = 0;
958 return VINF_SUCCESS;
959 }
960 return VERR_NET_SHUTDOWN;
961 }
962 if (pcbRead)
963 {
964 /* return partial data */
965 *pcbRead = cbBytesRead;
966 break;
967 }
968
969 /* read more? */
970 cbRead += cbBytesRead;
971 if (cbRead == cbBuffer)
972 break;
973
974 /* next */
975 cbToRead = cbBuffer - cbRead;
976 }
977
978 return VINF_SUCCESS;
979}
980
981
982RTR3DECL(int) RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
983{
984 /*
985 * Try write all at once.
986 */
987#ifdef RT_OS_WINDOWS
988 int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
989#else
990 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
991#endif
992 ssize_t cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
993 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
994 return VINF_SUCCESS;
995 if (cbWritten < 0)
996 return rtTcpError();
997
998 /*
999 * Unfinished business, write the remainder of the request. Must ignore
1000 * VERR_INTERRUPTED here if we've managed to send something.
1001 */
1002 size_t cbSentSoFar = 0;
1003 for (;;)
1004 {
1005 /* advance */
1006 cbBuffer -= (size_t)cbWritten;
1007 if (!cbBuffer)
1008 return VINF_SUCCESS;
1009 cbSentSoFar += (size_t)cbWritten;
1010 pvBuffer = (char const *)pvBuffer + cbWritten;
1011
1012 /* send */
1013#ifdef RT_OS_WINDOWS
1014 cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
1015#else
1016 cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
1017#endif
1018 cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
1019 if (cbWritten >= 0)
1020 AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtTcpError()=%d\n",
1021 cbWritten, cbBuffer, rtTcpError()));
1022 else
1023 {
1024 int rc = rtTcpError();
1025 if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
1026 return rc;
1027 cbWritten = 0;
1028 }
1029 }
1030}
1031
1032
1033RTR3DECL(int) RTTcpFlush(RTSOCKET Sock)
1034{
1035 int fFlag = 1;
1036 setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&fFlag, sizeof(fFlag));
1037 fFlag = 0;
1038 setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&fFlag, sizeof(fFlag));
1039
1040 return VINF_SUCCESS;
1041}
1042
1043
1044RTR3DECL(int) RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
1045{
1046 fd_set fdsetR;
1047 FD_ZERO(&fdsetR);
1048 FD_SET(Sock, &fdsetR);
1049
1050 fd_set fdsetE = fdsetR;
1051
1052 int rc;
1053 if (cMillies == RT_INDEFINITE_WAIT)
1054 rc = select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
1055 else
1056 {
1057 struct timeval timeout;
1058 timeout.tv_sec = cMillies / 1000;
1059 timeout.tv_usec = (cMillies % 1000) * 1000;
1060 rc = select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
1061 }
1062 if (rc > 0)
1063 return VINF_SUCCESS;
1064 if (rc == 0)
1065 return VERR_TIMEOUT;
1066 return rtTcpError();
1067}
1068
1069
1070static int rtTcpConvertAddress(RTSOCKADDRUNION *pSrc, size_t cbSrc, PRTNETADDR pAddr)
1071{
1072 /*
1073 * Convert the address.
1074 */
1075 if ( cbSrc == sizeof(struct sockaddr_in)
1076 && pSrc->Addr.sa_family == AF_INET)
1077 {
1078 RT_ZERO(*pAddr);
1079 pAddr->enmType = RTNETADDRTYPE_IPV4;
1080 pAddr->uPort = RT_N2H_U16(pSrc->Ipv4.sin_port);
1081 pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;
1082 }
1083#ifdef IPRT_WITH_TCPIP_V6
1084 else if ( cbSrc == sizeof(struct sockaddr_in6)
1085 && pSrc->Addr.sa_family == AF_INET6)
1086 {
1087 RT_ZERO(*pAddr);
1088 pAddr->enmType = RTNETADDRTYPE_IPV6;
1089 pAddr->uPort = RT_N2H_U16(pSrc->Ipv6.sin6_port);
1090 pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];
1091 pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];
1092 pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];
1093 pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];
1094 }
1095#endif
1096 else
1097 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
1098 return VINF_SUCCESS;
1099}
1100
1101
1102RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
1103{
1104 RTSOCKADDRUNION u;
1105#ifdef RT_OS_WINDOWS
1106 int cbAddr = sizeof(u);
1107#else
1108 socklen_t cbAddr = sizeof(u);
1109#endif
1110 RT_ZERO(u);
1111 if (!getsockname(Sock, &u.Addr, &cbAddr))
1112 return rtTcpConvertAddress(&u, cbAddr, pAddr);
1113 return rtTcpError();
1114}
1115
1116
1117RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
1118{
1119 RTSOCKADDRUNION u;
1120#ifdef RT_OS_WINDOWS
1121 int cbAddr = sizeof(u);
1122#else
1123 socklen_t cbAddr = sizeof(u);
1124#endif
1125 RT_ZERO(u);
1126 if (!getpeername(Sock, &u.Addr, &cbAddr))
1127 return rtTcpConvertAddress(&u, cbAddr, pAddr);
1128 return rtTcpError();
1129}
1130
1131
1132RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
1133{
1134 int rc;
1135
1136 /*
1137 * Validate input.
1138 */
1139 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
1140 AssertPtrReturn(pszAddress, VERR_INVALID_POINTER);
1141
1142#ifdef RT_OS_WINDOWS
1143 /*
1144 * Initialize WinSock and check version.
1145 */
1146 WORD wVersionRequested = MAKEWORD(1, 1);
1147 WSADATA wsaData;
1148 rc = WSAStartup(wVersionRequested, &wsaData);
1149 if (wsaData.wVersion != wVersionRequested)
1150 {
1151 AssertMsgFailed(("Wrong winsock version\n"));
1152 return VERR_NOT_SUPPORTED;
1153 }
1154#endif
1155
1156 /*
1157 * Resolve the address.
1158 */
1159 struct hostent *pHostEnt = NULL;
1160 pHostEnt = gethostbyname(pszAddress);
1161 if (!pHostEnt)
1162 {
1163 struct in_addr InAddr;
1164 InAddr.s_addr = inet_addr(pszAddress);
1165 pHostEnt = gethostbyaddr((char *)&InAddr, 4, AF_INET);
1166 if (!pHostEnt)
1167 {
1168 rc = rtTcpError();
1169 AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
1170 return rc;
1171 }
1172 }
1173
1174 /*
1175 * Create the socket and connect.
1176 */
1177 RTSOCKET Sock = socket(PF_INET, SOCK_STREAM, 0);
1178 if (Sock != -1)
1179 {
1180 rtTcpSetInheritance(Sock, false /*fInheritable*/);
1181
1182 struct sockaddr_in InAddr;
1183 RT_ZERO(InAddr);
1184 InAddr.sin_family = AF_INET;
1185 InAddr.sin_port = htons(uPort);
1186 InAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);
1187 if (!connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
1188 {
1189 *pSock = Sock;
1190 return VINF_SUCCESS;
1191 }
1192 rc = rtTcpError();
1193 rtTcpClose(Sock, "RTTcpClientConnect", false /*fTryGracefulShutdown*/);
1194 }
1195 else
1196 rc = rtTcpError();
1197 return rc;
1198}
1199
1200
1201RTR3DECL(int) RTTcpClientClose(RTSOCKET Sock)
1202{
1203 return rtTcpClose(Sock, "RTTcpClientClose", true /*fTryGracefulShutdown*/);
1204}
1205
1206
1207/**
1208 * Internal close function which does all the proper bitching.
1209 */
1210static int rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown)
1211{
1212 int rc;
1213
1214 /* ignore nil handles. */
1215 if (Sock == NIL_RTSOCKET)
1216 return VINF_SUCCESS;
1217
1218 /*
1219 * Try to gracefully shut it down.
1220 */
1221 if (fTryGracefulShutdown)
1222 {
1223 rc = shutdown(Sock, SHUT_WR);
1224 if (!rc)
1225 {
1226 uint64_t u64Start = RTTimeMilliTS();
1227 for (;;)
1228 {
1229 rc = RTTcpSelectOne(Sock, 1000);
1230 if (rc == VERR_TIMEOUT)
1231 {
1232 if (RTTimeMilliTS() - u64Start > 30000)
1233 break;
1234 }
1235 else if (rc != VINF_SUCCESS)
1236 break;
1237 {
1238 char abBitBucket[16*_1K];
1239 ssize_t cbBytesRead = recv(Sock, &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
1240 if (cbBytesRead == 0)
1241 break; /* orderly shutdown in progress */
1242 if (cbBytesRead < 0)
1243 break; /* some kind of error, never mind which... */
1244 }
1245 } /* forever */
1246 }
1247 }
1248
1249 /*
1250 * Attempt to close it.
1251 */
1252#ifdef RT_OS_WINDOWS
1253 rc = closesocket(Sock);
1254#else
1255 rc = close(Sock);
1256#endif
1257 if (!rc)
1258 return VINF_SUCCESS;
1259 rc = rtTcpError();
1260 AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", pszMsg, Sock, rc));
1261 return rc;
1262}
1263
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