Index: /trunk/include/iprt/err.h
===================================================================
--- /trunk/include/iprt/err.h	(revision 27496)
+++ /trunk/include/iprt/err.h	(revision 27497)
@@ -611,4 +611,6 @@
 /** Status code, typically given as a parameter, that isn't supposed to be used. */
 #define VERR_IGNORED                        (-91)
+/** Concurrent access to the object is not allowed. */
+#define VERR_CONCURRENT_ACCESS              (-92)
 /** @} */
 
Index: /trunk/include/iprt/tcp.h
===================================================================
--- /trunk/include/iprt/tcp.h	(revision 27496)
+++ /trunk/include/iprt/tcp.h	(revision 27497)
@@ -195,5 +195,5 @@
 
 /**
- * Send data from a socket.
+ * Send data to a socket.
  *
  * @returns iprt status code.
Index: /trunk/include/iprt/types.h
===================================================================
--- /trunk/include/iprt/types.h	(revision 27496)
+++ /trunk/include/iprt/types.h	(revision 27497)
@@ -1249,9 +1249,9 @@
 
 /** Socket handle. */
-typedef int RTSOCKET;
+typedef R3R0PTRTYPE(struct RTSOCKETINT *)           RTSOCKET;
 /** Pointer to socket handle. */
-typedef RTSOCKET *PRTSOCKET;
+typedef RTSOCKET                                   *PRTSOCKET;
 /** Nil socket handle. */
-#define NIL_RTSOCKET                                (~(RTSOCKET)0)
+#define NIL_RTSOCKET                                ((RTSOCKET)0)
 
 /** Thread handle.*/
Index: /trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp
===================================================================
--- /trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp	(revision 27496)
+++ /trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp	(revision 27497)
@@ -86,7 +86,7 @@
 #else /* !RT_OS_WINDOWS */
     /** Socket handle of the local socket for server. */
-    RTSOCKET            LocalSocketServer;
+    int                 LocalSocketServer;
     /** Socket handle of the local socket. */
-    RTSOCKET            LocalSocket;
+    int                 LocalSocket;
 #endif /* !RT_OS_WINDOWS */
     /** Thread for listening for new connections. */
@@ -170,5 +170,5 @@
     }
 #else /* !RT_OS_WINDOWS */
-    if (pThis->LocalSocket != NIL_RTSOCKET)
+    if (pThis->LocalSocket != -1)
     {
         ssize_t cbReallyRead;
@@ -176,6 +176,6 @@
         if (cbReallyRead == 0)
         {
-            RTSOCKET tmp = pThis->LocalSocket;
-            pThis->LocalSocket = NIL_RTSOCKET;
+            int tmp = pThis->LocalSocket;
+            pThis->LocalSocket = -1;
             close(tmp);
         }
@@ -256,5 +256,5 @@
     }
 #else /* !RT_OS_WINDOWS */
-    if (pThis->LocalSocket != NIL_RTSOCKET)
+    if (pThis->LocalSocket != -1)
     {
         ssize_t cbWritten;
@@ -262,6 +262,6 @@
         if (cbWritten == 0)
         {
-            RTSOCKET tmp = pThis->LocalSocket;
-            pThis->LocalSocket = NIL_RTSOCKET;
+            int tmp = pThis->LocalSocket;
+            pThis->LocalSocket = -1;
             close(tmp);
         }
@@ -365,5 +365,5 @@
         else
         {
-            if (pThis->LocalSocket != NIL_RTSOCKET)
+            if (pThis->LocalSocket != -1)
             {
                 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance));
@@ -422,6 +422,9 @@
     if (pThis->fIsServer)
     {
-        if (pThis->LocalSocketServer != NIL_RTSOCKET)
+        if (pThis->LocalSocketServer != -1)
+        {
             close(pThis->LocalSocketServer);
+            pThis->LocalSocketServer = -1;
+        }
         if (pThis->pszLocation)
             RTFileDelete(pThis->pszLocation);
@@ -429,6 +432,9 @@
     else
     {
-        if (pThis->LocalSocket != NIL_RTSOCKET)
+        if (pThis->LocalSocket != -1)
+        {
             close(pThis->LocalSocket);
+            pThis->LocalSocket = -1;
+        }
     }
 #endif /* !RT_OS_WINDOWS */
@@ -482,6 +488,6 @@
     pThis->NamedPipe                    = INVALID_HANDLE_VALUE;
 #else /* !RT_OS_WINDOWS */
-    pThis->LocalSocketServer            = NIL_RTSOCKET;
-    pThis->LocalSocket                  = NIL_RTSOCKET;
+    pThis->LocalSocketServer            = -1;
+    pThis->LocalSocket                  = -1;
 #endif /* !RT_OS_WINDOWS */
     pThis->ListenThread                 = NIL_RTTHREAD;
Index: /trunk/src/VBox/Runtime/include/internal/magics.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/magics.h	(revision 27496)
+++ /trunk/src/VBox/Runtime/include/internal/magics.h	(revision 27497)
@@ -127,4 +127,8 @@
 /** RTSEMXROADSINTERNAL::u32Magic value after RTSemXRoadsDestroy. */
 #define RTSEMXROADS_MAGIC_DEAD          UINT32_C(0x20011110)
+/** The magic value for RTSOCKETINT::u32Magic. (Stanislaw Lem) */
+#define RTSOCKET_MAGIC                  UINT32_C(0x19210912)
+/** The magic value for RTSOCKETINT::u32Magic after destruction. */
+#define RTSOCKET_MAGIC_DEAD             UINT32_C(0x20060326)
 /** Magic value for RTSPINLOCKINTERNAL::u32Magic. (Terry Pratchett) */
 #define RTSPINLOCK_MAGIC                UINT32_C(0x19480428)
Index: /trunk/src/VBox/Runtime/r3/tcp.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/tcp.cpp	(revision 27496)
+++ /trunk/src/VBox/Runtime/r3/tcp.cpp	(revision 27497)
@@ -59,4 +59,5 @@
 #include <iprt/err.h>
 #include <iprt/mempool.h>
+#include <iprt/mem.h>
 #include <iprt/string.h>
 #include <iprt/thread.h>
@@ -100,4 +101,48 @@
 *   Structures and Typedefs                                                    *
 *******************************************************************************/
+/**
+ * Socket handle data.
+ *
+ * This is mainly required for implementing RTPollSet on Windows.
+ */
+typedef struct RTSOCKETINT
+{
+    /** Magic number (RTTCPSOCKET_MAGIC). */
+    uint32_t            u32Magic;
+    /** Usage count.  This is used to prevent two threads from accessing the
+     *  handle concurrently. */
+    uint32_t volatile   cUsers;
+#ifdef RT_OS_WINDOWS
+    /** The native socket handle. */
+    SOCKET              hNative;
+    /** The event semaphore we've associated with the socket handle.
+     * This is INVALID_HANDLE_VALUE if not done. */
+    WSAEVENT            hEvent;
+    /** The pollset currently polling this socket.  This is NIL if no one is
+     * polling. */
+    RTPOLLSET           hPollSet;
+    /** The events we're polling for. */
+    uint32_t            fPollEvts;
+#else
+    /** The native socket handle. */
+    int                 hNative;
+#endif
+} RTSOCKETINT;
+
+
+/**
+ * Address union used internally for things like getpeername and getsockname.
+ */
+typedef union RTSOCKADDRUNION
+{
+    struct sockaddr     Addr;
+    struct sockaddr_in  Ipv4;
+#ifdef IPRT_WITH_TCPIP_V6
+    struct sockaddr_in6 Ipv6;
+#endif
+} RTSOCKADDRUNION;
+
+
+
 /**
  * TCP Server state.
@@ -145,12 +190,4 @@
 } RTTCPSERVER;
 
-typedef union RTSOCKADDRUNION
-{
-    struct sockaddr     Addr;
-    struct sockaddr_in  Ipv4;
-#ifdef IPRT_WITH_TCPIP_V6
-    struct sockaddr_in6 Ipv6;
-#endif
-} RTSOCKADDRUNION;
 
 /*******************************************************************************
@@ -162,5 +199,4 @@
 static int  rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);
 static int  rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown);
-static int  rtTcpConvertAddress(RTSOCKADDRUNION *pSrc, size_t cbSrc, PRTNETADDR pAddr);
 
 
@@ -169,7 +205,7 @@
  * Get the last error as an iprt status code.
  *
- * @returns iprt status code.
- */
-DECLINLINE(int) rtTcpError(void)
+ * @returns IPRT status code.
+ */
+DECLINLINE(int) rtSocketError(void)
 {
 #ifdef RT_OS_WINDOWS
@@ -184,5 +220,5 @@
  * Resets the last error.
  */
-DECLINLINE(void) rtTcpErrorReset(void)
+DECLINLINE(void) rtSocketErrorReset(void)
 {
 #ifdef RT_OS_WINDOWS
@@ -199,5 +235,5 @@
  * @returns iprt status code.
  */
-DECLINLINE(int) rtTcpResolverError(void)
+DECLINLINE(int) rtSocketResolverError(void)
 {
 #ifdef RT_OS_WINDOWS
@@ -223,21 +259,745 @@
 
 /**
+ * Tries to lock the socket for exclusive usage by the calling thread.
+ *
+ * Call rtSocketUnlock() to unlock.
+ *
+ * @returns @c true if locked, @c false if not.
+ * @param   pThis               The socket structure.
+ */
+DECLINLINE(bool) rtSocketTryLock(RTSOCKETINT *pThis)
+{
+    return ASMAtomicCmpXchgU32(&pThis->cUsers, 1, 0);
+}
+
+
+/**
+ * Unlocks the socket.
+ *
+ * @param   pThis               The socket structure.
+ */
+DECLINLINE(void) rtSocketUnlock(RTSOCKETINT *pThis)
+{
+    ASMAtomicCmpXchgU32(&pThis->cUsers, 0, 1);
+}
+
+
+/**
+ * Creates an IPRT socket handle for a native one.
+ *
+ * @returns IPRT status code.
+ * @param   ppSocket        Where to return the IPRT socket handle.
+ * @param   hNative         The native handle.
+ */
+int rtSocketCreateForNative(RTSOCKETINT **ppSocket,
+#ifdef RT_OS_WINDOWS
+                            HANDLE hNative
+#else
+                            int hNative
+#endif
+                            )
+{
+    RTSOCKETINT *pThis = (RTSOCKETINT *)RTMemAlloc(sizeof(*pThis));
+    if (!pThis)
+        return VERR_NO_MEMORY;
+    pThis->u32Magic     = RTSOCKET_MAGIC;
+    pThis->cUsers       = 0;
+    pThis->hNative      = hNative;
+#ifdef RT_OS_WINDOWS
+    pThis->hEvent       = INVALID_HANDLE_VALUE;
+    pThis->hPollSet     = 0;
+    pThis->fPollEvts    = 0;
+#endif
+    *ppSocket = pThis;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Wrapper around socket().
+ *
+ * @returns IPRT status code.
+ * @param   phSocket            Where to store the handle to the socket on
+ *                              success.
+ * @param   iDomain             The protocol family (PF_XXX).
+ * @param   iType               The socket type (SOCK_XXX).
+ * @param   iProtocol           Socket parameter, usually 0.
+ */
+static int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
+{
+    /*
+     * Create the socket.
+     */
+#ifdef RT_OS_WINDOWS
+    SOCKET  hNative = socket(iDomain, iType, iProtocol);
+    if (hNative == INVALID_SOCKET)
+        return rtSocketError();
+#else
+    int     hNative = socket(iDomain, iType, iProtocol);
+    if (hNative == -1)
+        return rtSocketError();
+#endif
+
+    /*
+     * Wrap it.
+     */
+    int rc = rtSocketCreateForNative(phSocket, hNative);
+    if (RT_FAILURE(rc))
+    {
+#ifdef RT_OS_WINDOWS
+        closesocket(hNative);
+#else
+        close(hNative);
+#endif
+    }
+    return rc;
+}
+
+
+/**
+ * Destroys the specified handle, freeing associated resources and closing the
+ * socket.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket         The socket handle.  NIL is ignored.
+ *
+ * @remarks This will not perform a graceful shutdown of the socket, it will
+ *          just destroy it.  Use the protocol specific close method if this is
+ *          desired.
+ */
+int rtSocketDestroy(RTSOCKET hSocket)
+{
+    RTSOCKETINT *pThis = hSocket;
+    if (pThis == NIL_RTSOCKET)
+        return VINF_SUCCESS;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+
+    Assert(pThis->cUsers == 0);
+    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSOCKET_MAGIC_DEAD, RTSOCKET_MAGIC), VERR_INVALID_HANDLE);
+
+    /*
+     * Do the cleanup.
+     */
+    int rc = VINF_SUCCESS;
+#ifdef RT_OS_WINDOWS
+    if (pThis->hEvent == INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(pThis->hEvent);
+        pThis->hEvent = INVALID_HANDLE_VALUE;
+    }
+
+    if (pThis->hNative != INVALID_HANDLE_VALUE)
+    {
+        rc = closesocket(pThis->hNative);
+        if (!rc)
+            rc = VINF_SUCCESS;
+        else
+        {
+            rc = rtSocketError();
+            AssertMsgFailed(("\"%s\": closesocket(%p) -> %Rrc\n", pThis->hNative, rc));
+        }
+        pThis->hNative = INVALID_HANDLE_VALUE;
+    }
+
+#else
+    if (pThis->hNative != -1)
+    {
+        if (close(pThis->hNative))
+        {
+            rc = rtSocketError();
+            AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", pThis->hNative, rc));
+        }
+        pThis->hNative = -1;
+    }
+#endif
+
+    return rc;
+}
+
+
+/**
+ * Gets the native socket handle.
+ *
+ * @returns The native socket handle or RTHCUINTPTR_MAX if not invalid.
+ * @param   hSocket             The socket handle.
+ */
+RTHCUINTPTR rtSocketNative(RTSOCKET hSocket)
+{
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, RTHCUINTPTR_MAX);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, RTHCUINTPTR_MAX);
+    return (RTHCUINTPTR)pThis->hNative;
+}
+
+
+/**
  * Helper that ensures the correct inheritability of a socket.
  *
  * We're currently ignoring failures.
  *
- * @param   Socket          The socket handle.
+ * @returns IPRT status code
+ * @param   hSocket         The socket handle.
  * @param   fInheritable    The desired inheritability state.
  */
-static void rtTcpSetInheritance(RTSOCKET Socket, bool fInheritable)
-{
-#ifdef RT_OS_WINDOWS
-    /** @todo Find some magic way to change this...  Worst case we have to use
-     *        DuplicateHandle w/bInheritable=FALSE and replace the original
-     *        handles... */
+int rtSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
+{
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    int rc = VINF_SUCCESS;
+#ifdef RT_OS_WINDOWS
+    if (!SetHandleInformation(pThis->hNative, HANDLE_FLAG_INHERIT, fInheritable ? HANDLE_FLAG_INHERIT : 0))
+        rc = RTErrConvertFromWin32(GetLastError());
 #else
-    fcntl(Socket, F_SETFD, fInheritable ? 0 : FD_CLOEXEC);
-#endif
-}
+    if (fcntl(pThis->hNative, F_SETFD, fInheritable ? 0 : FD_CLOEXEC) < 0)
+        rc = RTErrConvertFromErrno(errno);
+#endif
+    AssertRC(rc); /// @todo remove later.
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Receive data from a socket.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket         The socket handle.
+ * @param   pvBuffer        Where to put the data we read.
+ * @param   cbBuffer        Read buffer size.
+ * @param   pcbRead         Number of bytes read. If NULL the entire buffer
+ *                          will be filled upon successful return. If not NULL a
+ *                          partial read can be done successfully.
+ */
+int rtSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
+    AssertPtr(pvBuffer);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Read loop.
+     * If pcbRead is NULL we have to fill the entire buffer!
+     */
+    int     rc       = VINF_SUCCESS;
+    size_t  cbRead   = 0;
+    size_t  cbToRead = cbBuffer;
+    for (;;)
+    {
+        rtSocketErrorReset();
+#ifdef RT_OS_WINDOWS
+        int    cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
+#else
+        size_t cbNow = cbToRead;
+#endif
+        ssize_t cbBytesRead = recv(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
+        if (cbBytesRead <= 0)
+        {
+            rc = rtSocketError();
+            Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
+            if (RT_SUCCESS_NP(rc))
+            {
+                if (!pcbRead)
+                    rc = VERR_NET_SHUTDOWN;
+                else
+                {
+                    *pcbRead = 0;
+                    rc = VINF_SUCCESS;
+                }
+            }
+            break;
+        }
+        if (pcbRead)
+        {
+            /* return partial data */
+            *pcbRead = cbBytesRead;
+            break;
+        }
+
+        /* read more? */
+        cbRead += cbBytesRead;
+        if (cbRead == cbBuffer)
+            break;
+
+        /* next */
+        cbToRead = cbBuffer - cbRead;
+    }
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Send data to a socket.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param   hSocket         The socket handle.
+ * @param   pvBuffer        Buffer to write data to socket.
+ * @param   cbBuffer        How much to write.
+ */
+int rtSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Try write all at once.
+     */
+    int     rc        = VINF_SUCCESS;
+#ifdef RT_OS_WINDOWS
+    int     cbNow     = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
+#else
+    size_t  cbNow     = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
+#endif
+    ssize_t cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
+    if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
+        rc = VINF_SUCCESS;
+    else if (cbWritten < 0)
+        rc = rtSocketError();
+    else
+    {
+        /*
+         * Unfinished business, write the remainder of the request.  Must ignore
+         * VERR_INTERRUPTED here if we've managed to send something.
+         */
+        size_t cbSentSoFar = 0;
+        for (;;)
+        {
+            /* advance */
+            cbBuffer    -= (size_t)cbWritten;
+            if (!cbBuffer)
+                break;
+            cbSentSoFar += (size_t)cbWritten;
+            pvBuffer     = (char const *)pvBuffer + cbWritten;
+
+            /* send */
+#ifdef RT_OS_WINDOWS
+            cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
+#else
+            cbNow = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
+#endif
+            cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
+            if (cbWritten >= 0)
+                AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtSocketError()=%d\n",
+                                                          cbWritten, cbBuffer, rtSocketError()));
+            else
+            {
+                rc = rtSocketError();
+                if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
+                    break;
+                cbWritten = 0;
+                rc = VINF_SUCCESS;
+            }
+        }
+    }
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Checks if the socket is ready for reading (for I/O multiplexing).
+ *
+ * @returns IPRT status code.
+ * @param   hSocket         The socket handle.
+ * @param   cMillies        Number of milliseconds to wait for the socket.  Use
+ *                          RT_INDEFINITE_WAIT to wait for ever.
+ */
+int rtSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Set up the file descriptor sets and do the select.
+     */
+    fd_set fdsetR;
+    FD_ZERO(&fdsetR);
+    FD_SET(pThis->hNative, &fdsetR);
+
+    fd_set fdsetE = fdsetR;
+
+    int rc;
+    if (cMillies == RT_INDEFINITE_WAIT)
+        rc = select(pThis->hNative + 1, &fdsetR, NULL, &fdsetE, NULL);
+    else
+    {
+        struct timeval timeout;
+        timeout.tv_sec = cMillies / 1000;
+        timeout.tv_usec = (cMillies % 1000) * 1000;
+        rc = select(pThis->hNative + 1, &fdsetR, NULL, &fdsetE, &timeout);
+    }
+    if (rc > 0)
+        rc = VINF_SUCCESS;
+    else if (rc == 0)
+        rc = VERR_TIMEOUT;
+    else
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Shuts down one or both directions of communciation.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket             The socket handle.
+ * @param   fRead               Whether to shutdown our read direction.
+ * @param   fWrite              Whether to shutdown our write direction.
+ */
+static int rtSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(fRead || fWrite, VERR_INVALID_PARAMETER);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Do the job.
+     */
+    int rc = VINF_SUCCESS;
+    int fHow;
+    if (fRead && fWrite)
+        fHow = SHUT_RDWR;
+    else if (fRead)
+        fHow = SHUT_RD;
+    else
+        fHow = SHUT_WR;
+    if (shutdown(pThis->hNative, fHow) == -1)
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Converts from a native socket address to a generic IPRT network address.
+ *
+ * @returns IPRT status code.
+ * @param   pSrc                The source address.
+ * @param   cbSrc               The size of the source address.
+ * @param   pAddr               Where to return the generic IPRT network
+ *                              address.
+ */
+static int rtSocketConvertAddress(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr)
+{
+    /*
+     * Convert the address.
+     */
+    if (   cbSrc == sizeof(struct sockaddr_in)
+        && pSrc->Addr.sa_family == AF_INET)
+    {
+        RT_ZERO(*pAddr);
+        pAddr->enmType      = RTNETADDRTYPE_IPV4;
+        pAddr->uPort        = RT_N2H_U16(pSrc->Ipv4.sin_port);
+        pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;
+    }
+#ifdef IPRT_WITH_TCPIP_V6
+    else if (   cbSrc == sizeof(struct sockaddr_in6)
+             && pSrc->Addr.sa_family == AF_INET6)
+    {
+        RT_ZERO(*pAddr);
+        pAddr->enmType            = RTNETADDRTYPE_IPV6;
+        pAddr->uPort              = RT_N2H_U16(pSrc->Ipv6.sin6_port);
+        pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];
+        pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];
+        pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];
+        pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];
+    }
+#endif
+    else
+        return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Gets the address of the local side.
+ *
+ * @returns IPRT status code.
+ * @param   Sock            Socket descriptor.
+ * @param   pAddr           Where to store the local address on success.
+ */
+int rtSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Get the address and convert it.
+     */
+    int             rc;
+    RTSOCKADDRUNION u;
+#ifdef RT_OS_WINDOWS
+    int             cbAddr = sizeof(u);
+#else
+    socklen_t       cbAddr = sizeof(u);
+#endif
+    RT_ZERO(u);
+    if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0)
+        rc = rtSocketConvertAddress(&u, cbAddr, pAddr);
+    else
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Gets the address of the other party.
+ *
+ * @returns IPRT status code.
+ * @param   Sock            Socket descriptor.
+ * @param   pAddr           Where to store the peer address on success.
+ */
+int rtSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Get the address and convert it.
+     */
+    int             rc;
+    RTSOCKADDRUNION u;
+#ifdef RT_OS_WINDOWS
+    int             cbAddr = sizeof(u);
+#else
+    socklen_t       cbAddr = sizeof(u);
+#endif
+    RT_ZERO(u);
+    if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0)
+        rc = rtSocketConvertAddress(&u, cbAddr, pAddr);
+    else
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Wrapper around bind.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket             The socket handle.
+ * @param   pAddr               The socket address to bind to.
+ * @param   cbAddr              The size of the address structure @a pAddr
+ *                              points to.
+ */
+int rtSocketBind(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    int rc = VINF_SUCCESS;
+    if (bind(pThis->hNative, pAddr, cbAddr) != 0)
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Wrapper around listen.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket             The socket handle.
+ * @param   cMaxPending         The max number of pending connections.
+ */
+int rtSocketListen(RTSOCKET hSocket, int cMaxPending)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    int rc = VINF_SUCCESS;
+    if (listen(pThis->hNative, cMaxPending) != 0)
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Wrapper around accept.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket             The socket handle.
+ * @param   phClient            Where to return the client socket handle on
+ *                              success.
+ * @param   pAddr               Where to return the client address.
+ * @param   pcbAddr             On input this gives the size buffer size of what
+ *                              @a pAddr point to.  On return this contains the
+ *                              size of what's stored at @a pAddr.
+ */
+int rtSocketAccept(RTSOCKET hSocket, PRTSOCKET phClient, struct sockaddr *pAddr, size_t *pcbAddr)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Call accept().
+     */
+    rtSocketErrorReset();
+    int         rc      = VINF_SUCCESS;
+#ifdef RT_OS_WINDOWS
+    int         cbAddr  = (int)*pcbAddr;
+    SOCKET      hNative = accept(pThis->hNative, pAddr, &cbAddr);
+    if (hNative != INVALID_SOCKET)
+#else
+    socklen_t   cbAddr  = *pcbAddr;
+    int         hNative = accept(pThis->hNative, pAddr, &cbAddr);
+    if (hNative != -1)
+#endif
+    {
+        *pcbAddr = cbAddr;
+
+        /*
+         * Wrap the client socket.
+         */
+        rc = rtSocketCreateForNative(phClient, hNative);
+        if (RT_FAILURE(rc))
+        {
+#ifdef RT_OS_WINDOWS
+            closesocket(hNative);
+#else
+            close(hNative);
+#endif
+        }
+    }
+    else
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Wrapper around connect.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket             The socket handle.
+ * @param   pAddr               The socket address to connect to.
+ * @param   cbAddr              The size of the address structure @a pAddr
+ *                              points to.
+ */
+int rtSocketConnect(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    int rc = VINF_SUCCESS;
+    if (connect(pThis->hNative, pAddr, cbAddr) != 0)
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Wrapper around setsockopt.
+ *
+ * @returns IPRT status code.
+ * @param   hSocket             The socket handle.
+ * @param   iLevel              The protocol level, e.g. IPPORTO_TCP.
+ * @param   iOption             The option, e.g. TCP_NODELAY.
+ * @param   pvValue             The value buffer.
+ * @param   cbValue             The size of the value pointed to by pvValue.
+ */
+int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValue, int cbValue)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    int rc = VINF_SUCCESS;
+    if (setsockopt(pThis->hNative, iLevel, iOption, (const char *)pvValue, cbValue) != 0)
+        rc = rtSocketError();
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
 
 
@@ -280,4 +1040,5 @@
 }
 
+
 /**
  * Closes the a socket (client or server).
@@ -287,10 +1048,10 @@
 static int rtTcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg, bool fTryGracefulShutdown)
 {
-    RTSOCKET Sock = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET);
-    if (Sock != NIL_RTSOCKET)
+    RTSOCKET hSocket = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET);
+    if (hSocket != NIL_RTSOCKET)
     {
         if (!fTryGracefulShutdown)
-            shutdown(Sock, SHUT_RDWR);
-        return rtTcpClose(Sock, pszMsg, fTryGracefulShutdown);
+            rtSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/);
+        return rtTcpClose(hSocket, pszMsg, fTryGracefulShutdown);
     }
     return VINF_TCP_SERVER_NO_CLIENT;
@@ -433,5 +1194,5 @@
             if (!pHostEnt)
             {
-                rc = rtTcpResolverError();
+                rc = rtSocketResolverError();
                 AssertMsgFailed(("Could not get host address rc=%Rrc\n", rc));
                 return rc;
@@ -443,8 +1204,9 @@
      * Setting up socket.
      */
-    RTSOCKET WaitSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (WaitSock != -1)
-    {
-        rtTcpSetInheritance(WaitSock, false /*fInheritable*/);
+    RTSOCKET WaitSock;
+    rc = rtSocketCreate(&WaitSock, AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (RT_SUCCESS(rc))
+    {
+        rtSocketSetInheritance(WaitSock, false /*fInheritable*/);
 
         /*
@@ -452,5 +1214,5 @@
          */
         int fFlag = 1;
-        if (!setsockopt(WaitSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&fFlag, sizeof(fFlag)))
+        if (!rtSocketSetOpt(WaitSock, SOL_SOCKET, SO_REUSEADDR, &fFlag, sizeof(fFlag)))
         {
             /*
@@ -468,55 +1230,35 @@
 
             /*
-             * Bind a name to a socket.
+             * Bind a name to a socket and set it listening for connections.
              */
-            if (bind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) != -1)
+            rc = rtSocketBind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr));
+            if (RT_SUCCESS(rc))
+                rc = rtSocketListen(WaitSock, RTTCP_SERVER_BACKLOG);
+            if (RT_SUCCESS(rc))
             {
                 /*
-                 * Listen for connections on a socket.
+                 * Create the server handle.
                  */
-                if (listen(WaitSock, RTTCP_SERVER_BACKLOG) != -1)
+                PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
+                if (pServer)
                 {
-                    /*
-                     * Create the server handle.
-                     */
-                    PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
-                    if (pServer)
-                    {
-                        pServer->u32Magic   = RTTCPSERVER_MAGIC;
-                        pServer->enmState   = RTTCPSERVERSTATE_CREATED;
-                        pServer->Thread     = NIL_RTTHREAD;
-                        pServer->SockServer = WaitSock;
-                        pServer->SockClient = NIL_RTSOCKET;
-                        pServer->pfnServe   = NULL;
-                        pServer->pvUser     = NULL;
-                        *ppServer = pServer;
-                        return VINF_SUCCESS;
-                    }
-
-                    /* bail out */
-                    rc = VERR_NO_MEMORY;
+                    pServer->u32Magic   = RTTCPSERVER_MAGIC;
+                    pServer->enmState   = RTTCPSERVERSTATE_CREATED;
+                    pServer->Thread     = NIL_RTTHREAD;
+                    pServer->SockServer = WaitSock;
+                    pServer->SockClient = NIL_RTSOCKET;
+                    pServer->pfnServe   = NULL;
+                    pServer->pvUser     = NULL;
+                    *ppServer = pServer;
+                    return VINF_SUCCESS;
                 }
-                else
-                {
-                    rc = rtTcpError();
-                    AssertMsgFailed(("listen() %Rrc\n", rc));
-                }
+
+                /* bail out */
+                rc = VERR_NO_MEMORY;
             }
-            else
-            {
-                rc = rtTcpError();
-            }
         }
         else
-        {
-            rc = rtTcpError();
-            AssertMsgFailed(("setsockopt() %Rrc\n", rc));
-        }
+            AssertMsgFailed(("rtSocketSetOpt: %Rrc\n", rc));
         rtTcpClose(WaitSock, "RTServerCreateEx", false /*fTryGracefulShutdown*/);
-    }
-    else
-    {
-        rc = rtTcpError();
-        AssertMsgFailed(("socket() %Rrc\n", rc));
     }
 
@@ -604,17 +1346,18 @@
          */
         struct sockaddr_in  RemoteAddr;
+        size_t              cbRemoteAddr = sizeof(RemoteAddr);
+        RTSOCKET            Socket;
         RT_ZERO(RemoteAddr);
-        socklen_t           cbRemoteAddr = sizeof(RemoteAddr);
-        RTSOCKET Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
-        if (Socket == -1)
-        {
-#ifndef RT_OS_WINDOWS
+        int rc = rtSocketAccept(SockServer, &Socket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
+        if (RT_FAILURE(rc))
+        {
             /* These are typical for what can happen during destruction. */
-            if (errno == EBADF || errno == EINVAL || errno == ENOTSOCK)
+            if (   rc == VERR_INVALID_HANDLE
+                || rc == VERR_INVALID_PARAMETER
+                || rc == VERR_NET_NOT_SOCKET)
                 return rtTcpServerListenCleanup(pServer);
-#endif
             continue;
         }
-        rtTcpSetInheritance(Socket, false /*fInheritable*/);
+        rtSocketSetInheritance(Socket, false /*fInheritable*/);
 
         /*
@@ -627,5 +1370,5 @@
         }
         rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
-        int rc = pServer->pfnServe(Socket, pServer->pvUser);
+        rc = pServer->pfnServe(Socket, pServer->pvUser);
         rtTcpServerDestroySocket(&pServer->SockClient, "Listener: client", true /*fTryGracefulShutdown*/);
 
@@ -744,12 +1487,10 @@
          */
         struct sockaddr_in  RemoteAddr;
-        socklen_t           cbRemoteAddr = sizeof(RemoteAddr);
+        size_t              cbRemoteAddr = sizeof(RemoteAddr);
         RTSOCKET            Socket;
         RT_ZERO(RemoteAddr);
-        rtTcpErrorReset();
-        Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
-        if (Socket == -1)
-        {
-            rc = rtTcpError();
+        rc = rtSocketAccept(SockServer, &Socket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
+        if (RT_FAILURE(rc))
+        {
             if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_ACCEPTING))
                 rc = rtTcpServerListenCleanup(pServer);
@@ -758,5 +1499,5 @@
             continue;
         }
-        rtTcpSetInheritance(Socket, false /*fInheritable*/);
+        rtSocketSetInheritance(Socket, false /*fInheritable*/);
 
         /*
@@ -924,210 +1665,4 @@
 
 
-RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
-{
-    /*
-     * Validate input.
-     */
-    AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
-    AssertPtr(pvBuffer);
-
-    /*
-     * Read loop.
-     * If pcbRead is NULL we have to fill the entire buffer!
-     */
-    size_t cbRead = 0;
-    size_t cbToRead = cbBuffer;
-    for (;;)
-    {
-        rtTcpErrorReset();
-#ifdef RT_OS_WINDOWS
-        int    cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
-#else
-        size_t cbNow = cbToRead;
-#endif
-        ssize_t cbBytesRead = recv(Sock, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
-        if (cbBytesRead <= 0)
-        {
-            int rc = rtTcpError();
-            Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
-            if (RT_FAILURE_NP(rc))
-                return rc;
-            if (pcbRead)
-            {
-                *pcbRead = 0;
-                return VINF_SUCCESS;
-            }
-            return VERR_NET_SHUTDOWN;
-        }
-        if (pcbRead)
-        {
-            /* return partial data */
-            *pcbRead = cbBytesRead;
-            break;
-        }
-
-        /* read more? */
-        cbRead += cbBytesRead;
-        if (cbRead == cbBuffer)
-            break;
-
-        /* next */
-        cbToRead = cbBuffer - cbRead;
-    }
-
-    return VINF_SUCCESS;
-}
-
-
-RTR3DECL(int)  RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
-{
-    /*
-     * Try write all at once.
-     */
-#ifdef RT_OS_WINDOWS
-    int     cbNow     = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
-#else
-    size_t  cbNow     = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
-#endif
-    ssize_t cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
-    if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
-        return VINF_SUCCESS;
-    if (cbWritten < 0)
-        return rtTcpError();
-
-    /*
-     * Unfinished business, write the remainder of the request.  Must ignore
-     * VERR_INTERRUPTED here if we've managed to send something.
-     */
-    size_t cbSentSoFar = 0;
-    for (;;)
-    {
-        /* advance */
-        cbBuffer    -= (size_t)cbWritten;
-        if (!cbBuffer)
-            return VINF_SUCCESS;
-        cbSentSoFar += (size_t)cbWritten;
-        pvBuffer     = (char const *)pvBuffer + cbWritten;
-
-        /* send */
-#ifdef RT_OS_WINDOWS
-        cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
-#else
-        cbNow = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
-#endif
-        cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
-        if (cbWritten >= 0)
-            AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtTcpError()=%d\n",
-                                                      cbWritten, cbBuffer, rtTcpError()));
-        else
-        {
-            int rc = rtTcpError();
-            if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
-                return rc;
-            cbWritten = 0;
-        }
-    }
-}
-
-
-RTR3DECL(int)  RTTcpFlush(RTSOCKET Sock)
-{
-    int fFlag = 1;
-    setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&fFlag, sizeof(fFlag));
-    fFlag = 0;
-    setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&fFlag, sizeof(fFlag));
-
-    return VINF_SUCCESS;
-}
-
-
-RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
-{
-    fd_set fdsetR;
-    FD_ZERO(&fdsetR);
-    FD_SET(Sock, &fdsetR);
-
-    fd_set fdsetE = fdsetR;
-
-    int rc;
-    if (cMillies == RT_INDEFINITE_WAIT)
-        rc = select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
-    else
-    {
-        struct timeval timeout;
-        timeout.tv_sec = cMillies / 1000;
-        timeout.tv_usec = (cMillies % 1000) * 1000;
-        rc = select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
-    }
-    if (rc > 0)
-        return VINF_SUCCESS;
-    if (rc == 0)
-        return VERR_TIMEOUT;
-    return rtTcpError();
-}
-
-
-static int rtTcpConvertAddress(RTSOCKADDRUNION *pSrc, size_t cbSrc, PRTNETADDR pAddr)
-{
-    /*
-     * Convert the address.
-     */
-    if (   cbSrc == sizeof(struct sockaddr_in)
-        && pSrc->Addr.sa_family == AF_INET)
-    {
-        RT_ZERO(*pAddr);
-        pAddr->enmType      = RTNETADDRTYPE_IPV4;
-        pAddr->uPort        = RT_N2H_U16(pSrc->Ipv4.sin_port);
-        pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;
-    }
-#ifdef IPRT_WITH_TCPIP_V6
-    else if (   cbSrc == sizeof(struct sockaddr_in6)
-             && pSrc->Addr.sa_family == AF_INET6)
-    {
-        RT_ZERO(*pAddr);
-        pAddr->enmType            = RTNETADDRTYPE_IPV6;
-        pAddr->uPort              = RT_N2H_U16(pSrc->Ipv6.sin6_port);
-        pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];
-        pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];
-        pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];
-        pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];
-    }
-#endif
-    else
-        return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
-    return VINF_SUCCESS;
-}
-
-
-RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
-{
-    RTSOCKADDRUNION u;
-#ifdef RT_OS_WINDOWS
-    int             cbAddr = sizeof(u);
-#else
-    socklen_t       cbAddr = sizeof(u);
-#endif
-    RT_ZERO(u);
-    if (!getsockname(Sock, &u.Addr, &cbAddr))
-        return rtTcpConvertAddress(&u, cbAddr, pAddr);
-    return rtTcpError();
-}
-
-
-RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
-{
-    RTSOCKADDRUNION u;
-#ifdef RT_OS_WINDOWS
-    int             cbAddr = sizeof(u);
-#else
-    socklen_t       cbAddr = sizeof(u);
-#endif
-    RT_ZERO(u);
-    if (!getpeername(Sock, &u.Addr, &cbAddr))
-        return rtTcpConvertAddress(&u, cbAddr, pAddr);
-    return rtTcpError();
-}
-
-
 RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
 {
@@ -1166,5 +1701,5 @@
         if (!pHostEnt)
         {
-            rc = rtTcpError();
+            rc = rtSocketError();
             AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
             return rc;
@@ -1175,8 +1710,9 @@
      * Create the socket and connect.
      */
-    RTSOCKET Sock = socket(PF_INET, SOCK_STREAM, 0);
-    if (Sock != -1)
-    {
-        rtTcpSetInheritance(Sock, false /*fInheritable*/);
+    RTSOCKET Sock;
+    rc = rtSocketCreate(&Sock, PF_INET, SOCK_STREAM, 0);
+    if (RT_SUCCESS(rc))
+    {
+        rtSocketSetInheritance(Sock, false /*fInheritable*/);
 
         struct sockaddr_in InAddr;
@@ -1185,14 +1721,13 @@
         InAddr.sin_port = htons(uPort);
         InAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);
-        if (!connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
+        rc = rtSocketConnect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr));
+        if (RT_SUCCESS(rc))
         {
             *pSock = Sock;
             return VINF_SUCCESS;
         }
-        rc = rtTcpError();
+
         rtTcpClose(Sock, "RTTcpClientConnect", false /*fTryGracefulShutdown*/);
     }
-    else
-        rc = rtTcpError();
     return rc;
 }
@@ -1221,11 +1756,11 @@
     if (fTryGracefulShutdown)
     {
-        rc = shutdown(Sock, SHUT_WR);
-        if (!rc)
+        rc = rtSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);
+        if (RT_SUCCESS(rc))
         {
             uint64_t u64Start = RTTimeMilliTS();
             for (;;)
             {
-                rc = RTTcpSelectOne(Sock, 1000);
+                rc = rtSocketSelectOne(Sock, 1000);
                 if (rc == VERR_TIMEOUT)
                 {
@@ -1237,5 +1772,5 @@
                 {
                     char abBitBucket[16*_1K];
-                    ssize_t cbBytesRead = recv(Sock, &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
+                    ssize_t cbBytesRead = recv(rtSocketNative(Sock), &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
                     if (cbBytesRead == 0)
                         break; /* orderly shutdown in progress */
@@ -1248,16 +1783,51 @@
 
     /*
-     * Attempt to close it.
-     */
-#ifdef RT_OS_WINDOWS
-    rc = closesocket(Sock);
-#else
-    rc = close(Sock);
-#endif
-    if (!rc)
-        return VINF_SUCCESS;
-    rc = rtTcpError();
-    AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", pszMsg, Sock, rc));
-    return rc;
-}
-
+     * Destroy the socket handle.
+     */
+    return rtSocketDestroy(Sock);
+}
+
+
+RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
+{
+    return rtSocketRead(Sock, pvBuffer, cbBuffer, pcbRead);
+}
+
+
+RTR3DECL(int)  RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
+{
+    return rtSocketWrite(Sock, pvBuffer, cbBuffer);
+}
+
+
+RTR3DECL(int)  RTTcpFlush(RTSOCKET Sock)
+{
+
+    int fFlag = 1;
+    int rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));
+    if (RT_SUCCESS(rc))
+    {
+        fFlag = 0;
+        rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));
+    }
+    return rc;
+}
+
+
+RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
+{
+    return rtSocketSelectOne(Sock, cMillies);
+}
+
+
+RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
+{
+    return rtSocketGetLocalAddress(Sock, pAddr);
+}
+
+
+RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
+{
+    return rtSocketGetPeerAddress(Sock, pAddr);
+}
+
