tcp.cpp revision 71ab8b3ec752767541ed3ff38ea034958d88726f
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * available from http://www.virtualbox.org. This file is free software;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * General Public License (GPL) as published by the Free Software
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * The contents of this file may alternatively be used under the terms
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * of the Common Development and Distribution License Version 1.0
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
09ed5ee011f3a6cd9d4742216ad3bb7dbf855641vboxsync * VirtualBox OSE distribution, in which case the provisions of the
09ed5ee011f3a6cd9d4742216ad3bb7dbf855641vboxsync * CDDL are applicable instead of those of the GPL.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * You may elect to license modified versions of this file under the
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * terms and conditions of either the GPL or the CDDL or both.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * additional information or have any questions.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/*******************************************************************************
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync* Header Files *
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync*******************************************************************************/
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync#else /* !RT_OS_WINDOWS */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync#endif /* !RT_OS_WINDOWS */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/*******************************************************************************
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync* Defined Constants And Macros *
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync*******************************************************************************/
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* non-standard linux stuff (it seems). */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* fixup backlevel OSes. */
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync/** How many pending connection. */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync/*******************************************************************************
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync* Structures and Typedefs *
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync*******************************************************************************/
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync * TCP Server state.
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** Invalid. */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** Created. */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** Listener thread is starting up. */
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /** Accepting client connections. */
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /** Serving a client. */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** Listener terminating. */
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /** Listener terminated. */
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /** Listener cleans up. */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync * Internal representation of the TCP Server handle.
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsynctypedef struct RTTCPSERVER
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** The magic value (RTTCPSERVER_MAGIC). */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** The server state. */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync /** The server thread. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** The server socket. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /** The socket to the client currently being serviced.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * This is NIL_RTSOCKET when no client is serviced. */
17d67aeb3722c094c6493a3e9a9d0cdfb9453ecdvboxsync /** The connection function. */
17d67aeb3722c094c6493a3e9a9d0cdfb9453ecdvboxsync /** Argument to pfnServer. */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/*******************************************************************************
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync* Internal Functions *
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsync*******************************************************************************/
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsyncstatic DECLCALLBACK(int) rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer);
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsyncstatic int rcTcpServerListenCleanup(PRTTCPSERVER pServer);
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsyncstatic int rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsyncstatic int rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown);
#ifdef RT_OS_WINDOWS
#ifdef RT_OS_WINDOWS
WSASetLastError(0);
errno = 0;
#ifdef RT_OS_WINDOWS
switch (h_errno)
case HOST_NOT_FOUND:
return VERR_NET_HOST_NOT_FOUND;
case NO_DATA:
return VERR_NET_ADDRESS_NOT_AVAILABLE;
case NO_RECOVERY:
return VERR_IO_GEN_FAILURE;
case TRY_AGAIN:
return VERR_TRY_AGAIN;
return VERR_UNRESOLVED_ERROR;
switch (sizeof(RTSOCKET))
return NIL_RTSOCKET;
DECLINLINE(bool) rtTcpServerTrySetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
bool fRc;
return fRc;
DECLINLINE(void) rtTcpServerSetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
bool fRc;
static int rtTcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg, bool fTryGracefulShutdown)
if (!fTryGracefulShutdown)
return VINF_TCP_SERVER_NO_CLIENT;
RTR3DECL(int) RTTcpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,
rc = RTThreadCreate(&pServer->Thread, rtTcpServerThread, pServer, 0, enmType, /*RTTHREADFLAGS_WAITABLE*/0, pszThrdName);
if (ppServer)
return rc;
return rc;
int rc;
return VINF_SUCCESS;
int rc;
#ifdef RT_OS_WINDOWS
return VERR_NOT_SUPPORTED;
if (!pHostEnt)
if (!pHostEnt)
return rc;
if (!pHostEnt)
if (pServer)
return VINF_SUCCESS;
return rc;
return rc;
#ifndef RT_OS_WINDOWS
return rc;
switch (enmState)
case RTTCPSERVERSTATE_STOPPED:
return VERR_TCP_SERVER_SHUTDOWN;
return VERR_TCP_SERVER_DESTROYED;
return VERR_TCP_SERVER_DESTROYED;
case RTTCPSERVERSTATE_SERVING:
int rc = rtTcpServerDestroySocket(&pServer->SockClient, "DisconnectClient: client", true /*fTryGracefulShutdown*/);
return rc;
switch (enmState)
case RTTCPSERVERSTATE_CREATED:
return VERR_INVALID_STATE;
case RTTCPSERVERSTATE_STOPPED:
return VINF_SUCCESS;
return VERR_TCP_SERVER_DESTROYED;
rtTcpServerDestroySocket(&pServer->SockServer, "RTTcpServerShutdown", false /*fTryGracefulShutdown*/);
return VINF_SUCCESS;
bool fDestroyable;
switch (enmState)
case RTTCPSERVERSTATE_SERVING:
case RTTCPSERVERSTATE_CREATED:
case RTTCPSERVERSTATE_STOPPED:
fDestroyable = true;
return VERR_INTERNAL_ERROR;
if (fDestroyable)
rtTcpServerDestroySocket(&pServer->SockServer, "Destroyer: server", false /*fTryGracefulShutdown*/);
return VINF_SUCCESS;
#ifdef RT_OS_WINDOWS
if (cbBytesRead <= 0)
return rc;
if (pcbRead)
*pcbRead = 0;
return VINF_SUCCESS;
return VERR_NET_SHUTDOWN;
if (pcbRead)
return VINF_SUCCESS;
#ifdef RT_OS_WINDOWS
if (cbWritten < 0)
return rtTcpError();
AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d rtTcpError()=%d\n",
} while (cbBuffer);
return VINF_SUCCESS;
fFlag = 0;
return VINF_SUCCESS;
int rc;
if (rc > 0)
return VINF_SUCCESS;
if (rc == 0)
return VERR_TIMEOUT;
return rtTcpError();
int rc;
#ifdef RT_OS_WINDOWS
return VERR_NOT_SUPPORTED;
if (!pHostEnt)
if (!pHostEnt)
return rc;
return VINF_SUCCESS;
return rc;
int rc;
return VINF_SUCCESS;
if (fTryGracefulShutdown)
if (!rc)
if (cbBytesRead == 0)
if (cbBytesRead < 0)
#ifdef RT_OS_WINDOWS
if (!rc)
return VINF_SUCCESS;
return rc;