]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Reorganization of the AsyncSocket API layer into an interface dispatch
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:06 +0000 (11:23 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:06 +0000 (11:23 -0700)
layer and separate disjoint socket implementations.

Common header file change; not applicable to open-vm-tools.

open-vm-tools/lib/asyncsocket/Makefile.am
open-vm-tools/lib/asyncsocket/asyncSocketBase.c [new file with mode: 0644]
open-vm-tools/lib/asyncsocket/asyncSocketBase.h [new file with mode: 0644]
open-vm-tools/lib/asyncsocket/asyncSocketInt.h [deleted file]
open-vm-tools/lib/asyncsocket/asyncSocketInterface.c
open-vm-tools/lib/asyncsocket/asyncSocketVTable.h [new file with mode: 0644]
open-vm-tools/lib/asyncsocket/asyncsocket.c
open-vm-tools/lib/include/asyncsocket.h
open-vm-tools/lib/include/vm_product_versions.h

index 48a484496ea11a742ff59a337c95ec809d94a966..6ab62fd03545632ed2a75700150a4b8c16a2bbe2 100644 (file)
@@ -19,6 +19,7 @@ noinst_LTLIBRARIES = libAsyncSocket.la
 
 libAsyncSocket_la_SOURCES =
 libAsyncSocket_la_SOURCES += asyncsocket.c
+libAsyncSocket_la_SOURCES += asyncSocketBase.c
 libAsyncSocket_la_SOURCES += asyncSocketInterface.c
 
 AM_CFLAGS =
diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketBase.c b/open-vm-tools/lib/asyncsocket/asyncSocketBase.c
new file mode 100644 (file)
index 0000000..d91dece
--- /dev/null
@@ -0,0 +1,767 @@
+/*********************************************************
+ * Copyright (C) 2016 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*********************************************************
+ * The contents of this file are subject to the terms of the Common
+ * Development and Distribution License (the "License") version 1.0
+ * and no later version.  You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ *         http://www.opensource.org/licenses/cddl1.php
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ *********************************************************/
+
+/*
+ * asyncSocketBase.c --
+ *
+ *      This exposes the public functions of the AsyncSocket library.
+ *      This file itself just contains stubs which call the function
+ *      pointers in the socket's virtual table.
+ *
+ */
+
+#include "vmware.h"
+#include "asyncsocket.h"
+#include "asyncSocketBase.h"
+#include "msg.h"
+#include "log.h"
+
+#define LOGLEVEL_MODULE asyncsocket
+#include "loglevel_user.h"
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncSocketInternalIncRef --
+ *
+ *    Increments reference count on AsyncSocket struct and optionally
+ *    takes the lock.  This function is used to implement both Lock
+ *    and AddRef.
+ *
+ * Results:
+ *    New reference count.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+AsyncSocketInternalIncRef(AsyncSocket *asock,   // IN
+                          Bool lock)            // IN
+{
+   if (lock && asock->pollParams.lock) {
+      MXUser_AcquireRecLock(asock->pollParams.lock);
+   }
+   ASSERT(asock->refCount > 0);
+   ++asock->refCount;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncSocketInternalDecRef --
+ *
+ *    Decrements reference count on AsyncSocket struct, freeing it when it
+ *    reaches 0.  If "unlock" is TRUE, releases the lock after decrementing
+ *    the count.
+ *
+ *    This function is used to implement both Unlock and DecRef.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    May free struct.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+AsyncSocketInternalDecRef(AsyncSocket *s, // IN
+                          Bool unlock)    // IN
+{
+   int count = --s->refCount;
+
+   if (unlock && s->pollParams.lock) {
+      MXUser_ReleaseRecLock(s->pollParams.lock);
+   }
+
+   ASSERT(count >= 0);
+   if (UNLIKELY(count == 0)) {
+      ASOCKLOG(1, s, ("Final release; freeing asock struct\n"));
+      VT(s)->destroy(s);
+   } else {
+      ASOCKLOG(1, s, ("Release (count now %d)\n", count));
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketLock --
+ * AsyncSocketUnlock --
+ *
+ *      Acquire/Release the lock provided by the client when creating the
+ *      AsyncSocket object.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketLock(AsyncSocket *asock)   // IN:
+{
+   AsyncSocketInternalIncRef(asock, TRUE);
+}
+
+void
+AsyncSocketUnlock(AsyncSocket *asock)   // IN:
+{
+   AsyncSocketInternalDecRef(asock, TRUE);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketIsLocked --
+ *
+ *      If a lock is associated with the socket, check whether the calling
+ *      thread holds the lock.
+ *
+ * Results:
+ *      TRUE if calling thread holds the lock, or if there is no assoicated
+ *      lock.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+AsyncSocketIsLocked(AsyncSocket *asock)   // IN:
+{
+   if (asock->pollParams.lock && Poll_LockingEnabled()) {
+      return MXUser_IsCurThreadHoldingRecLock(asock->pollParams.lock);
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncSocketAddRef --
+ *
+ *    Increments reference count on AsyncSocket struct.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketAddRef(AsyncSocket *s)         // IN
+{
+   AsyncSocketInternalIncRef(s, FALSE);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncSocketRelease --
+ *
+ *    Decrements reference count on AsyncSocket struct, freeing it when it
+ *    reaches 0.  If "unlock" is TRUE, releases the lock after decrementing
+ *    the count.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    May free struct.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketRelease(AsyncSocket *s)  // IN:
+{
+   AsyncSocketInternalDecRef(s, FALSE);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketGetState --
+ *
+ *      Accessor function for the state in the base class.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+AsyncSocketState
+AsyncSocketGetState(AsyncSocket *asock)         // IN
+{
+   ASSERT(AsyncSocketIsLocked(asock));
+   return asock->state;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketSetState --
+ *
+ *      Modifier function for the state in the base class.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketSetState(AsyncSocket *asock,         // IN/OUT
+                    AsyncSocketState state)     // IN
+{
+   asock->state = state;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncSocketGetPollParams --
+ *
+ *    Accessor function for the pollParams struct in the base socket.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+AsyncSocketPollParams *
+AsyncSocketGetPollParams(AsyncSocket *s)         // IN
+{
+   return &s->pollParams;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncSocketInitSocket --
+ *
+ *    Initialize the AsyncSocket base struct.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketInitSocket(AsyncSocket *s,                          // IN/OUT
+                      AsyncSocketPollParams *pollParams,       // IN
+                      const AsyncSocketVTable *vtable)         // IN
+{
+   /*
+    * The sockets each have a "unique" ID, which is just an
+    * incrementing integer.
+    */
+   static Atomic_uint32 nextid = { 1 };
+
+   s->id = Atomic_ReadInc32(&nextid);
+   s->refCount = 1;
+   s->vt = vtable;
+   if (pollParams) {
+      s->pollParams = *pollParams;
+   } else {
+      s->pollParams.pollClass = POLL_CS_MAIN;
+      s->pollParams.flags = 0;
+      s->pollParams.lock = NULL;
+      s->pollParams.iPoll = NULL;
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_Init --
+ *
+ *      Initialize the various socket subsytems.  Currently just TCP, this
+ *      will expand.
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
+ *
+ * Side effects:
+ *      See subsystems.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_Init(void)
+{
+   return AsyncTCPSocket_Init();
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_GetID --
+ *
+ *      Returns a unique identifier for the asock.
+ *
+ * Results:
+ *      Integer id or ASOCKERR_INVAL.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_GetID(AsyncSocket *asock)         // IN
+{
+   if (!asock) {
+      return ASOCKERR_INVAL;    /* For some reason we return ID 5
+                                   for null pointers! */
+   } else {
+      return asock->id;
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_SetErrorFn --
+ *
+ *      Sets the error handling function for the asock. The error function
+ *      is invoked automatically on I/O errors.
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS or ASOCKERR_INVAL.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_SetErrorFn(AsyncSocket *asock,           // IN/OUT
+                       AsyncSocketErrorFn errorFn,   // IN
+                       void *clientData)             // IN
+{
+   if (!asock) {
+      return ASOCKERR_INVAL;
+   } else {
+      AsyncSocketLock(asock);
+      asock->errorFn = errorFn;
+      asock->errorClientData = clientData;
+      AsyncSocketUnlock(asock);
+      return ASOCKERR_SUCCESS;
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketHandleError --
+ *
+ *      Internal error handling helper. Changes the socket's state to error,
+ *      and calls the registered error handler or closes the socket.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Lots.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketHandleError(AsyncSocket *asock,   // IN
+                       int asockErr)         // IN
+{
+   ASSERT(asock);
+   asock->errorSeen = TRUE;
+   if (asock->errorFn) {
+      ASOCKLOG(3, asock, ("firing error callback (%s)\n",
+                          AsyncSocket_Err2String(asockErr)));
+      asock->errorFn(asockErr, asock, asock->errorClientData);
+   } else {
+      ASOCKLOG(3, asock, ("no error callback, closing socket (%s)\n",
+                          AsyncSocket_Err2String(asockErr)));
+      AsyncSocket_Close(asock);
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketCheckAndDispatchRecv --
+ *
+ *      Check if the recv buffer is full and dispatch the client callback.
+ *
+ *      Handles the possibility that the client registers a new receive buffer
+ *      or closes the socket in their callback.
+ *
+ * Results:
+ *      TRUE if the socket was closed or the receive was cancelled,
+ *      FALSE if the caller should continue to try to receive data.
+ *
+ * Side effects:
+ *      Could fire recv completion or trigger socket destruction.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+AsyncSocketCheckAndDispatchRecv(AsyncSocket *s,  // IN
+                                int *result)     // OUT
+{
+   ASSERT(s);
+   ASSERT(result);
+   ASSERT(s->recvFn);
+   ASSERT(s->recvBuf);
+   ASSERT(s->recvLen > 0);
+   ASSERT(s->recvPos > 0);
+   ASSERT(s->recvPos <= s->recvLen);
+
+   /*
+    * The application may close the socket in this callback.  This
+    * asserts that even if that happens, the socket will not be
+    * immediately freed in the middle of our function.
+    */
+   ASSERT(s->refCount > 1);
+
+   if (s->recvPos == s->recvLen || s->recvFireOnPartial) {
+      void *recvBuf = s->recvBuf;
+      ASOCKLOG(3, s, ("recv buffer full, calling recvFn\n"));
+
+      /*
+       * We do this dance in case the handler frees the buffer (so
+       * that there's no possible window where there are dangling
+       * references here.  Obviously if the handler frees the buffer,
+       * but them fails to register a new one, we'll put back the
+       * dangling reference in the automatic reset case below, but
+       * there's currently a limit to how far we go to shield clients
+       * who use our API in a broken way.
+       */
+
+      s->recvBuf = NULL;
+      s->recvFn(recvBuf, s->recvPos, s, s->recvClientData);
+      if (s->state == AsyncSocketClosed) {
+         ASOCKLG0(s, ("owner closed connection in recv callback\n"));
+         *result = ASOCKERR_CLOSED;
+         return TRUE;
+      } else if (s->recvFn == NULL && s->recvLen == 0) {
+         /*
+          * Further recv is cancelled from within the last recvFn, see
+          * AsyncSocket_CancelRecv(). So exit from the loop.
+          */
+         *result = ASOCKERR_SUCCESS;
+         return TRUE;
+      } else if (s->recvPos > 0) {
+         /*
+          * Automatically reset keeping the current handler.  Checking
+          * that recvPos is still non-zero implies that the
+          * application has not called AsyncSocket_Recv or
+          * _RecvPartial in the callback.
+          */
+         s->recvPos = 0;
+         s->recvBuf = recvBuf;
+         *result = ASOCKERR_SUCCESS;
+         return FALSE;
+      } else {
+         *result = ASOCKERR_SUCCESS;
+         return FALSE;
+      }
+   } else {
+      *result = ASOCKERR_SUCCESS;
+      return FALSE;
+   }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocketSetRecvBuf --
+ *
+ *      Helper function to validate socket state and recvBuf
+ *      parameters before setting the recvBuf values in the base
+ *      class.
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS or ASOCKERR_*.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocketSetRecvBuf(AsyncSocket *asock,  // IN:
+                      void *buf,           // IN:
+                      int len,             // IN:
+                      Bool fireOnPartial,  // IN:
+                      void *cb,            // IN:
+                      void *cbData)        // IN:
+{
+   ASSERT(AsyncSocketIsLocked(asock));
+
+   if (!asock->errorFn) {
+      ASOCKWARN(asock, ("%s: no registered error handler!\n", __FUNCTION__));
+      return ASOCKERR_INVAL;
+   }
+
+   if (!buf || !cb || len <= 0) {
+      ASOCKWARN(asock, ("Recv called with invalid arguments!\n"));
+      return ASOCKERR_INVAL;
+   }
+
+   if (AsyncSocketGetState(asock) != AsyncSocketConnected) {
+      ASOCKWARN(asock, ("recv called but state is not connected!\n"));
+      return ASOCKERR_NOTCONNECTED;
+   }
+
+   if (asock->recvBuf && asock->recvPos != 0) {
+      ASOCKWARN(asock, ("Recv called -- partially read buffer discarded.\n"));
+   }
+
+   asock->recvBuf = buf;
+   asock->recvLen = len;
+   asock->recvFireOnPartial = fireOnPartial;
+   asock->recvFn = cb;
+   asock->recvClientData = cbData;
+   asock->recvPos = 0;
+
+   return ASOCKERR_SUCCESS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * WebSocketCancelRecv --
+ *
+ *    Call this function if you know what you are doing. This should
+ *    be called if you want to synchronously receive the outstanding
+ *    data on the socket.  It returns number of partially read bytes
+ *    (if any). A partially read response may exist as
+ *    AsyncSocketRecvCallback calls the recv callback only when all
+ *    the data has been received.
+ *
+ * Results:
+ *    None
+ *
+ * Side effects:
+ *    Subsequent client call to AsyncSocket_Recv can reinstate async behaviour.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocketCancelRecv(AsyncSocket *asock,         // IN
+                      int *partialRecvd,          // OUT
+                      void **recvBuf,             // OUT
+                      void **recvFn)              // IN
+{
+   if (partialRecvd) {
+      *partialRecvd = asock->recvPos;
+   }
+   if (recvFn) {
+      *recvFn = asock->recvFn;
+   }
+   if (recvBuf) {
+      *recvBuf = asock->recvBuf;
+   }
+
+   asock->recvBuf = NULL;
+   asock->recvFn = NULL;
+   asock->recvPos = 0;
+   asock->recvLen = 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_Err2String --
+ *
+ *      Returns the error string associated with error code.
+ *
+ * Results:
+ *      Error string.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+const char *
+AsyncSocket_Err2String(int err)  // IN
+{
+   return Msg_StripMSGID(AsyncSocket_MsgError(err));
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_MsgError --
+ *
+ *      Returns the message associated with error code.
+ *
+ * Results:
+ *      Message string.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+const char *
+AsyncSocket_MsgError(int asyncSockError)   // IN
+{
+   const char *result = NULL;
+   switch (asyncSockError) {
+   case ASOCKERR_SUCCESS:
+      result = MSGID(asyncsocket.success) "Success";
+      break;
+   case ASOCKERR_GENERIC:
+      result = MSGID(asyncsocket.generic) "Asyncsocket error";
+      break;
+   case ASOCKERR_INVAL:
+      result = MSGID(asyncsocket.invalid) "Invalid parameters";
+      break;
+   case ASOCKERR_TIMEOUT:
+      result = MSGID(asyncsocket.timeout) "Time-out error";
+      break;
+   case ASOCKERR_NOTCONNECTED:
+      result = MSGID(asyncsocket.notconnected) "Local socket not connected";
+      break;
+   case ASOCKERR_REMOTE_DISCONNECT:
+      result = MSGID(asyncsocket.remotedisconnect) "Remote disconnected";
+      break;
+   case ASOCKERR_CLOSED:
+      result = MSGID(asyncsocket.closed) "Closed socket";
+      break;
+   case ASOCKERR_CONNECT:
+      result = MSGID(asyncsocket.connect) "Connection error";
+      break;
+   case ASOCKERR_POLL:
+      result = MSGID(asyncsocket.poll) "Poll registration error";
+      break;
+   case ASOCKERR_BIND:
+      result = MSGID(asyncsocket.bind) "Socket bind error";
+      break;
+   case ASOCKERR_BINDADDRINUSE:
+      result = MSGID(asyncsocket.bindaddrinuse) "Socket bind address already in use";
+      break;
+   case ASOCKERR_LISTEN:
+      result = MSGID(asyncsocket.listen) "Socket listen error";
+      break;
+   case ASOCKERR_CONNECTSSL:
+      result = MSGID(asyncsocket.connectssl) "Connection error: could not negotiate SSL";
+      break;
+   case ASOCKERR_NETUNREACH:
+      result = MSGID(asyncsocket.netunreach) "Network unreachable";
+      break;
+   case ASOCKERR_ADDRUNRESV:
+      result = MSGID(asyncsocket.addrunresv) "Address unresolvable";
+      break;
+   }
+
+   if (!result) {
+      Warning("%s was passed bad code %d\n", __FUNCTION__, asyncSockError);
+      result = MSGID(asyncsocket.unknown) "Unknown error";
+   }
+   return result;
+}
+
+
+/**
+ *-----------------------------------------------------------------------------
+ *
+ * stristr --
+ *
+ *    Do you know strstr from <string.h>?
+ *    So this one is the same, but without the case sensitivity.
+ *
+ * Results:
+ *    return a pointer to the first occurrence of needle in haystack,
+ *    or NULL if needle does not appear in haystack. If needle is zero
+ *    length, the function returns haystack.
+ *
+ * Side effects:
+ *    none
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+const char *
+stristr(const char *haystack,         // IN
+        const char *needle)           // IN
+{
+   if (*needle) {
+      int len = strlen(needle);
+      for (; *haystack; haystack++) {
+         if (strncasecmp(haystack, needle, len) == 0) {
+            return haystack;
+         }
+      }
+      return NULL;
+   } else {
+      return haystack;
+   }
+}
diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketBase.h b/open-vm-tools/lib/asyncsocket/asyncSocketBase.h
new file mode 100644 (file)
index 0000000..13126fe
--- /dev/null
@@ -0,0 +1,89 @@
+/*********************************************************
+ * Copyright (C) 2011,2014-2016 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*********************************************************
+ * The contents of this file are subject to the terms of the Common
+ * Development and Distribution License (the "License") version 1.0
+ * and no later version.  You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ *         http://www.opensource.org/licenses/cddl1.php
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ *********************************************************/
+
+#ifndef __ASYNC_SOCKET_BASE_H__
+#define __ASYNC_SOCKET_BASE_H__
+
+#ifdef USE_SSL_DIRECT
+#include "sslDirect.h"
+#else
+#include "ssl.h"
+#endif
+
+#include "asyncSocketVTable.h"
+
+/*
+ * The abstract base class for all asyncsocket implementations.
+ */
+struct AsyncSocket {
+   uint32 id;
+   uint32 refCount;
+   AsyncSocketPollParams pollParams;
+   AsyncSocketState state;
+
+   Bool errorSeen;
+   AsyncSocketErrorFn errorFn;
+   void *errorClientData;
+
+   void *recvBuf;
+   int recvPos;
+   int recvLen;
+   AsyncSocketRecvFn recvFn;
+   void *recvClientData;
+   Bool recvFireOnPartial;
+
+   const AsyncSocketVTable *vt;
+};
+
+void AsyncSocketInitSocket(AsyncSocket *asock,
+                           AsyncSocketPollParams *params,
+                           const AsyncSocketVTable *vtable);
+
+void AsyncSocketLock(AsyncSocket *asock);
+void AsyncSocketUnlock(AsyncSocket *asock);
+Bool AsyncSocketIsLocked(AsyncSocket *asock);
+void AsyncSocketAddRef(AsyncSocket *asock);
+void AsyncSocketRelease(AsyncSocket *s);
+AsyncSocketState AsyncSocketGetState(AsyncSocket *sock);
+void AsyncSocketSetState(AsyncSocket *sock, AsyncSocketState state);
+int AsyncSocketSetRecvBuf(AsyncSocket *asock, void *buf, int len,
+                           Bool fireOnPartial, void *cb, void *cbData);
+Bool AsyncSocketCheckAndDispatchRecv(AsyncSocket *s, int *result);
+AsyncSocketPollParams *AsyncSocketGetPollParams(AsyncSocket *s);
+void AsyncSocketHandleError(AsyncSocket *asock, int asockErr);
+void AsyncSocketCancelRecv(AsyncSocket *asock, int *partialRecvd,
+                           void **recvBuf, void **recvFn);
+
+
+int AsyncTCPSocket_Init(void);
+
+#endif
diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketInt.h b/open-vm-tools/lib/asyncsocket/asyncSocketInt.h
deleted file mode 100644 (file)
index 5ccca16..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-/*********************************************************
- * Copyright (C) 2011,2014-2016 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
- *
- *********************************************************/
-
-/*********************************************************
- * The contents of this file are subject to the terms of the Common
- * Development and Distribution License (the "License") version 1.0
- * and no later version.  You may not use this file except in
- * compliance with the License.
- *
- * You can obtain a copy of the License at
- *         http://www.opensource.org/licenses/cddl1.php
- *
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- *********************************************************/
-
-#ifndef __ASYNC_SOCKET_INT_H__
-#define __ASYNC_SOCKET_INT_H__
-
-/*
- * asyncsocket.h --
- *
- *      The AsyncSocket object is a fairly simple wrapper around a basic TCP
- *      socket. It's potentially asynchronous for both read and write
- *      operations. Reads are "requested" by registering a receive function
- *      that is called once the requested amount of data has been read from
- *      the socket. Similarly, writes are queued along with a send function
- *      that is called once the data has been written. Errors are reported via
- *      a separate callback.
- */
-
-#define INCLUDE_ALLOW_VMCORE
-#define INCLUDE_ALLOW_USERLEVEL
-#include "includeCheck.h"
-
-#ifdef _WIN32
-/*
- * We redefine strcpy/strcat because the Windows SDK uses it for getaddrinfo().
- * When we upgrade SDKs, this redefinition can go away.
- * Note: Now we are checking if we have secure libs for string operations
- */
-#if !(defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L)
-#define strcpy(dst,src) Str_Strcpy((dst), (src), 0x7FFFFFFF)
-#define strcat(dst,src) Str_Strcat((dst), (src), 0x7FFFFFFF)
-#endif
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <wspiapi.h>
-#include <MSWSock.h>
-#include <windows.h>
-#if !(defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L)
-#undef strcpy
-#undef strcat
-#endif
-#else
-#include <stddef.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/poll.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
-#include "vmware.h"
-#include "random.h"
-
-#ifdef USE_SSL_DIRECT
-#include "sslDirect.h"
-#else
-#include "ssl.h"
-#endif
-
-#ifdef _WIN32
-#define ASOCK_LASTERROR()       WSAGetLastError()
-#define ASOCK_ENOTCONN          WSAENOTCONN
-#define ASOCK_ENOTSOCK          WSAENOTSOCK
-#define ASOCK_EADDRINUSE        WSAEADDRINUSE
-#define ASOCK_ECONNECTING       WSAEWOULDBLOCK
-#define ASOCK_EWOULDBLOCK       WSAEWOULDBLOCK
-#define ASOCK_ENETUNREACH       WSAENETUNREACH
-#else
-#define ASOCK_LASTERROR()       errno
-#define ASOCK_ENOTCONN          ENOTCONN
-#define ASOCK_ENOTSOCK          ENOTSOCK
-#define ASOCK_EADDRINUSE        EADDRINUSE
-#define ASOCK_ECONNECTING       EINPROGRESS
-#define ASOCK_EWOULDBLOCK       EWOULDBLOCK
-#define ASOCK_ENETUNREACH       ENETUNREACH
-#endif
-
-#define WEBSOCKET_HTTP_BUFFER_SIZE  8192
-
-typedef struct WebSocketHttpRequest {
-   char buf[WEBSOCKET_HTTP_BUFFER_SIZE + 1];  /* used for request & response */
-   int32 bufLen;
-   Bool overflow;
-} WebSocketHttpRequest;
-
-typedef enum {
-   WEB_SOCKET_FRAME_OPCODE_BINARY = 0x02,
-   WEB_SOCKET_FRAME_OPCODE_CLOSE = 0x08,
-} WebSocketFrameOpcode;
-
-typedef enum {
-   WEB_SOCKET_STATE_CONNECTING  = 0,
-   WEB_SOCKET_STATE_OPEN        = 1,
-   WEB_SOCKET_STATE_CLOSING     = 2,
-   WEB_SOCKET_STATE_CLOSED      = 3,
-} WebSocketState;
-
-typedef enum {
-   WEB_SOCKET_NEED_FRAME_TYPE          = 0,
-   WEB_SOCKET_NEED_FRAME_SIZE          = 1,
-   WEB_SOCKET_NEED_EXTENDED_FRAME_SIZE = 2,
-   WEB_SOCKET_NEED_FRAME_MASK          = 3,
-   WEB_SOCKET_NEED_FRAME_DATA          = 4,
-} WebSocketDecodeState;
-
-/*
- * Bitmask indicates when masking should be applyed or removed,
- * None at all (rare - RFC 6455 expects masking in at least one
- * direction), applied to frames we receive, or applied to frames
- * we sent. Both is possible (but again rare - RFC 6455 indicates
- * masking is only required on frames from the client/browser to the
- * server.
- */
-typedef enum {
-   WEB_SOCKET_MASKING_NONE = 0,
-   WEB_SOCKET_MASKING_RECV = 1,
-   WEB_SOCKET_MASKING_SEND = 1 << 1,
-} WebSocketMaskingRequired;
-
-typedef enum {
-   ASYNCSOCKET_TYPE_SOCKET =    0,
-   ASYNCSOCKET_TYPE_NAMEDPIPE = 1,
-   ASYNCSOCKET_TYPE_PROXYSOCKET = 2,
-} AsyncSocketType;
-
-/*
- * Output buffer list data type, for the queue of outgoing buffers
- */
-typedef struct SendBufList {
-   struct SendBufList   *next;
-   void                 *buf;
-   int                   len;
-   AsyncSocketSendFn     sendFn;
-   void                 *clientData;
-   /*
-    * If the data needs to be encoded somehow before sending over the
-    * wire, this will point to an internally-allocated buffer
-    * containing the encoded version of buf.  The len field above will
-    * hold the length of the encoded data.
-    */
-   char                 *encodedBuf;
-} SendBufList;
-
-/*
- * Callback to allow user handling of custom upgrade request headers
- */
-typedef int (*AsyncWebSocketUpgradeRequestFn) (AsyncSocket *asock,
-                                            WebSocketHttpRequest *httpRequest);
-
-/*
- * Callback to allow user handling of custom upgrade request headers
- */
-typedef int (*AsyncWebSocketUpgradeResponseFn) (AsyncSocket *asock,
-                                            WebSocketHttpRequest *httpRequest);
-
-typedef enum {
-   CONNECTING_PRIMARY_SOCKET = 0,
-   CONNECTED_PRIMARY_SOCKET,
-   CONNECTING_SECONDARY_SOCKET,
-   CONNECTED_SECONDARY_SOCKET,
-} AsyncProxySocketState;
-
-struct AsyncSocket {
-   uint32 id;
-   AsyncSocketState state;
-   int fd;
-   SSLSock sslSock;
-   AsyncSocketType asockType;
-   const struct AsyncSocketVTable *vt;
-
-   unsigned int refCount;
-   int genericErrno;
-   AsyncSocketErrorFn errorFn;
-   void *errorClientData;
-   Bool errorSeen;
-
-   struct sockaddr_storage localAddr;
-   socklen_t localAddrLen;
-   struct sockaddr_storage remoteAddr;
-   socklen_t remoteAddrLen;
-
-   AsyncSocketConnectFn connectFn;
-   AsyncSocketRecvFn recvFn;
-   AsyncSocketSslAcceptFn sslAcceptFn;
-   AsyncSocketSslConnectFn sslConnectFn;
-   int sslPollFlags;       /* shared by sslAcceptFn, sslConnectFn */
-
-   /* shared by recvFn, connectFn, sslAcceptFn and sslConnectFn */
-   void *clientData;
-
-   AsyncSocketPollParams pollParams;
-   PollerFunction internalConnectFn;
-
-   /* governs optional AsyncSocket_Close() behavior */
-   int flushEnabledMaxWaitMsec;
-   AsyncSocketCloseCb closeCb;
-
-   void *recvBuf;
-   int recvPos;
-   int recvLen;
-   Bool recvCb;
-   Bool recvCbTimer;
-   Bool recvFireOnPartial;
-
-   SendBufList *sendBufList;
-   SendBufList **sendBufTail;
-   int sendPos;
-   Bool sendCb;
-   Bool sendCbTimer;
-   Bool sendCbRT;
-   Bool sendBufFull;
-   Bool sendLowLatency;
-
-   Bool sslConnected;
-
-   uint8 inIPollCb;
-   Bool inRecvLoop;
-   uint32 inBlockingRecv;
-
-   AsyncSocket *listenAsock4;
-   AsyncSocket *listenAsock6;
-
-   struct {
-      Bool expected;
-      int fd;
-   } passFd;
-
-   struct {
-      char *origin;
-      char *host;
-      char *hostname;
-      char *uri;
-      char *cookie;
-      int version;
-      WebSocketMaskingRequired maskingRequirements;
-      WebSocketFrameOpcode frameOpcode;
-      WebSocketState state;
-      void *connectClientData;
-      // Saved error reporting values.
-      AsyncSocketErrorFn errorFn;
-      void *errorClientData;
-      int webSocketError;
-      char *socketBuffer;     // Accumulates incoming data (including framing etc.)
-      char *decodeBuffer;     // Accumulates incoming data after removing framing
-      int32 socketBufferWriteOffset;
-      int32 socketBufferReadOffset;
-      int32 decodeBufferWriteOffset;
-      int32 decodeBufferReadOffset;
-      size_t frameBytesRemaining;
-      size_t frameSize;
-      Bool maskPresent;
-      uint8 maskBytes[4];
-      uint8 maskOffset;
-      const char **streamProtocols;    // null terminated list of protocols
-      const char *streamProtocol;      // points to one of the above.
-      WebSocketDecodeState decodeState;
-      Bool useSSL;
-      void *sslCtx;                   // Optional SSL Context
-      SSLVerifyParam *sslVerifyParam;  // Used for certificate verifications
-      char *upgradeNonceBase64;
-      rqContext *randomContext;
-      uint16 closeStatus;
-      AsyncWebSocketUpgradeRequestFn upgradeRequestPrepareFn;
-      AsyncWebSocketUpgradeResponseFn upgradeResponseProcessFn;
-   } webSocket;
-
-   struct {
-      AsyncProxySocketState proxySocketState;
-      char *secondaryUrl;
-      char *e2ePort;
-      const char *secondaryIP;
-      char *secondaryPort;
-      SSLVerifyParam *secondarySslVerifyParam;
-      const char *akey;
-      const char *label;
-      void *privData;
-      struct TCP2SCTPListenerArg *tcp2sctp;
-      AsyncSocket *primarySocket;
-      AsyncSocket *secondarySocket;
-   } proxySocket;
-
-#ifdef _WIN32
-   struct {
-      char *pipeName;
-      uint32 connectCount;
-      uint32 numInstances;
-      DWORD openMode;
-      DWORD pipeMode;
-      HANDLE pipe;
-      OVERLAPPED rd;
-      OVERLAPPED wr;
-   } namedPipe;
-#endif
-
-   struct {
-      struct VSockSocket *socket;
-      Bool signalCb;
-      Bool sendCb;
-      uint32 opMask;
-      void *partialRecvBuf;
-      uint32 partialRecvLen;
-   } vmci;
-};
-
-typedef struct AsyncSocketVTable {
-   AsyncSocketState (*getState)(AsyncSocket *sock);
-   int (*getGenericErrno)(AsyncSocket *s);
-   int (*getFd)(AsyncSocket *asock);
-   int (*getRemoteIPStr)(AsyncSocket *asock, const char **ipStr);
-   int (*getINETIPStr)(AsyncSocket *asock, int socketFamily, char **ipRetStr);
-   unsigned int (*getPort)(AsyncSocket *asock);
-
-   int (*useNodelay)(AsyncSocket *asock, Bool nodelay);
-   int (*setTCPTimeouts)(AsyncSocket *asock, int keepIdle, int keepIntvl,
-                         int keepCnt);
-   Bool (*setBufferSizes)(AsyncSocket *asock, int sendSz, int recvSz);
-   void (*setSendLowLatencyMode)(AsyncSocket *asock, Bool enable);
-
-   Bool (*connectSSL)(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam,
-                      void *sslContext);
-   void (*startSslConnect)(AsyncSocket *asock,
-                           struct _SSLVerifyParam *verifyParam, void *sslCtx,
-                           AsyncSocketSslConnectFn sslConnectFn,
-                           void *clientData);
-   Bool (*acceptSSL)(AsyncSocket *asock, void *sslCtx);
-   void (*startSslAccept)(AsyncSocket *asock, void *sslCtx,
-                          AsyncSocketSslAcceptFn sslAcceptFn,
-                          void *clientData);
-   int (*flush)(AsyncSocket *asock, int timeoutMS);
-
-   int (*recv)(AsyncSocket *asock, void *buf, int len, Bool partial, void *cb,
-               void *cbData);
-   int (*recvPassedFd)(AsyncSocket *asock, void *buf, int len, void *cb,
-                       void *cbData);
-   int (*getReceivedFd)(AsyncSocket *asock);
-
-   int (*send)(AsyncSocket *asock, void *buf, int len,
-               AsyncSocketSendFn sendFn, void *clientData);
-   int (*isSendBufferFull)(AsyncSocket *asock);
-
-   int (*close)(AsyncSocket *asock);
-   int (*cancelRecv)(AsyncSocket *asock, int *partialRecvd, void **recvBuf,
-                     void **recvFn, Bool cancelOnSend);
-   void (*cancelCbForClose)(AsyncSocket *asock);
-
-   int (*getLocalVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port);
-   int (*getRemoteVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port);
-
-   // WebSocket Specific
-   char *(*getWebSocketURI)(AsyncSocket *asock);
-   char *(*getWebSocketCookie)(AsyncSocket *asock);
-   uint16 (*getWebSocketCloseStatus)(const AsyncSocket *asock);
-   const char *(*getWebSocketProtocol)(AsyncSocket *asock);
-
-   // Internal
-   void (*dispatchConnect)(AsyncSocket *asock, AsyncSocket *newsock);
-   int (*prepareSend)(AsyncSocket *asock, void *buf, int len,
-                      AsyncSocketSendFn sendFn, void *clientData,
-                      Bool *bufferListWasEmpty);
-   int (*sendInternal)(AsyncSocket *asock, Bool bufferListWasEmpty, void *buf,
-                     int len);
-   int (*recvInternal)(AsyncSocket *asock, void *buf, int len);
-   PollerFunction sendCallback;
-   PollerFunction recvCallback;
-   Bool (*hasDataPending)(AsyncSocket *asock);
-   void (*cancelListenCbInternal)(AsyncSocket *asock);
-   void (*cancelRecvCbInternal)(AsyncSocket *asock);
-   void (*cancelCbForCloseInternal)(AsyncSocket *asock);
-   Bool (*cancelCbForConnectingCloseInternal)(AsyncSocket *asock);
-   void (*closeInternal)(AsyncSocket *asock);
-   void (*release)(AsyncSocket *asock);
-} AsyncSocketVTable;
-
-AsyncSocket *AsyncSocketInit(int socketFamily,
-                             AsyncSocketPollParams *pollParams,
-                             int *outError);
-Bool AsyncSocketBind(AsyncSocket *asock, struct sockaddr_storage *addr,
-                     socklen_t addrLen, int *outError);
-Bool AsyncSocketListen(AsyncSocket *asock, AsyncSocketConnectFn connectFn,
-                       void *clientData, int *outError);
-int AsyncSocketResolveAddr(const char *hostname,
-                           unsigned int port,
-                           int family,
-                           Bool passive,
-                           struct sockaddr_storage *addr,
-                           socklen_t *addrLen,
-                           char **addrString);
-AsyncSocket *AsyncSocketConnectWithAsock(AsyncSocket *asock,
-                                         struct sockaddr_storage *addr,
-                                         socklen_t addrLen,
-                                         AsyncSocketConnectFn connectFn,
-                                         void *clientData,
-                                         PollerFunction internalConnectFn,
-                                         AsyncSocketPollParams *pollParams,
-                                         int *outError);
-int AsyncSocketAddRef(AsyncSocket *s);
-int AsyncSocketRelease(AsyncSocket *s, Bool unlock);
-void AsyncSocketLock(AsyncSocket *asock);
-void AsyncSocketUnlock(AsyncSocket *asock);
-Bool AsyncSocketIsLocked(AsyncSocket *asock);
-void AsyncSocketHandleError(AsyncSocket *asock, int asockErr);
-int AsyncSocketFillRecvBuffer(AsyncSocket *s);
-void AsyncSocketDispatchSentBuffer(AsyncSocket *s);
-Bool AsyncSocketCheckAndDispatchRecv(AsyncSocket *s, int *error);
-int AsyncSocketSendInternal(AsyncSocket *asock, void *buf, int len,
-                            AsyncSocketSendFn sendFn, void *clientData,
-                            Bool *bufferListWasEmpty);
-int AsyncSocketSendSocket(AsyncSocket *asock, Bool bufferListWasEmpty,
-                          void *buf, int len);
-void AsyncSocketSendCallback(void *clientData);
-AsyncSocket *AsyncSocketCreate(AsyncSocketPollParams *pollParams);
-void AsyncSocketDispatchConnect(AsyncSocket *asock, AsyncSocket *newsock);
-void AsyncSocketRecvCallback(void *clientData);
-int AsyncSocketRecvSocket(AsyncSocket *asock, void *buf, int len);
-void AsyncSocketCancelListenCbSocket(AsyncSocket *asock);
-void AsyncSocketCancelRecvCbSocket(AsyncSocket *asock);
-void AsyncSocketCancelCbForCloseSocket(AsyncSocket *asock);
-Bool AsyncSocketCancelCbForConnectingCloseSocket(AsyncSocket *asock);
-void AsyncSocketCloseSocket(AsyncSocket *asock);
-#ifndef VMX86_TOOLS
-void AsyncSocketInitWebSocket(AsyncSocket *asock,
-                              void *clientData,
-                              Bool useSSL,
-                              const char *protocols[],
-                              void *sslCtx);
-#endif
-AsyncSocket *AsyncSocketListenImpl(struct sockaddr_storage *addr,
-                                   socklen_t addrLen,
-                                   AsyncSocketConnectFn connectFn,
-                                   void *clientData,
-                                   AsyncSocketPollParams *pollParams,
-                                   Bool isWebSock,
-                                   Bool webSockUseSSL,
-                                   const char *protocols[],
-                                   void *sslCtx,
-                                   int *outError);
-AsyncSocket *AsyncSocketListenerCreate(const char *addrStr,
-                                       unsigned int port,
-                                       AsyncSocketConnectFn connectFn,
-                                       void *clientData,
-                                       AsyncSocketPollParams *pollParams,
-                                       Bool isWebSock,
-                                       Bool webSockUseSSL,
-                                       const char *protocols[],
-                                       void *sslCtx,
-                                       int *outError);
-AsyncSocket *AsyncSocketListenerCreateImpl(const char *addrStr,
-                                           unsigned int port,
-                                           int socketFamily,
-                                           AsyncSocketConnectFn connectFn,
-                                           void *clientData,
-                                           AsyncSocketPollParams *pollParams,
-                                           Bool isWebSock,
-                                           Bool webSockUseSSL,
-                                           const char *protocols[],
-                                           void *sslCtx,
-                                           int *outError);
-
-AsyncSocketState AsyncSocketGetState(AsyncSocket *sock);
-int AsyncSocketGetGenericErrno(AsyncSocket *s);
-int AsyncSocketGetFd(AsyncSocket *asock);
-int AsyncSocketGetRemoteIPStr(AsyncSocket *asock, const char **ipStr);
-int AsyncSocketGetINETIPStr(AsyncSocket *asock, int socketFamily,
-                     char **ipRetStr);
-unsigned int AsyncSocketGetPort(AsyncSocket *asock);
-int AsyncSocketUseNodelay(AsyncSocket *asock, Bool nodelay);
-int AsyncSocketSetTCPTimeouts(AsyncSocket *asock, int keepIdle,
-                       int keepIntvl, int keepCnt);
-Bool AsyncSocketSetBufferSizes(AsyncSocket *asock, int sendSz, int recvSz);
-void AsyncSocketSetSendLowLatencyMode(AsyncSocket *asock, Bool enable);
-Bool AsyncSocketConnectSSL(AsyncSocket *asock,
-                           struct _SSLVerifyParam *verifyParam,
-                           void *sslContext);
-void AsyncSocketStartSslConnect(AsyncSocket *asock, SSLVerifyParam *verifyParam,
-                                void *sslCtx,
-                                AsyncSocketSslConnectFn sslConnectFn,
-                                void *clientData);
-Bool AsyncSocketAcceptSSL(AsyncSocket *asock, void *sslCtx);
-void AsyncSocketStartSslAccept(AsyncSocket *asock, void *sslCtx,
-                        AsyncSocketSslAcceptFn sslAcceptFn,
-                        void *clientData);
-int AsyncSocketFlush(AsyncSocket *asock, int timeoutMS);
-
-int AsyncSocketRecv(AsyncSocket *asock,
-             void *buf, int len, Bool partial, void *cb, void *cbData);
-int AsyncSocketRecvPassedFd(AsyncSocket *asock, void *buf, int len,
-                     void *cb, void *cbData);
-int AsyncSocketGetReceivedFd(AsyncSocket *asock);
-int AsyncSocketSend(AsyncSocket *asock, void *buf, int len,
-             AsyncSocketSendFn sendFn, void *clientData);
-int AsyncSocketIsSendBufferFull(AsyncSocket *asock);
-int AsyncSocketClose(AsyncSocket *asock);
-int AsyncSocketCancelRecv(AsyncSocket *asock, int *partialRecvd,
-                   void **recvBuf, void **recvFn, Bool cancelOnSend);
-void AsyncSocketCancelCbForClose(AsyncSocket *asock);
-int AsyncSocketGetLocalVMCIAddress(AsyncSocket *asock,
-                            uint32 *cid, uint32 *port);
-int AsyncSocketGetRemoteVMCIAddress(AsyncSocket *asock,
-                             uint32 *cid, uint32 *port);
-char *AsyncSocketGetWebSocketURI(AsyncSocket *asock);
-char *AsyncSocketGetWebSocketCookie(AsyncSocket *asock);
-uint16 AsyncSocketGetWebSocketCloseStatus(const AsyncSocket *asock);
-const char *AsyncSocketGetWebSocketProtocol(AsyncSocket *asock);
-
-/*
- * Websocket Connect extension function.
- */
-AsyncSocket *
-AsyncSocket_ConnectWebSocketEx(const char *url,
-                             struct _SSLVerifyParam *sslVerifyParam,
-                             const char *proxyStr,
-                             const char *cookies,
-                             const char *protocols[],
-                             AsyncSocketConnectFn connectFn,
-                             void *clientData,
-                             AsyncSocketConnectFlags flags,
-                             AsyncSocketPollParams *pollParams,
-                             AsyncWebSocketUpgradeRequestFn prepareRequestFn,
-                             AsyncWebSocketUpgradeResponseFn processResponseFn,
-                             void *privData,
-                             int *error);
-
-/*
- * Utilities for building and parsing http request/response strings.
- */
-void WebSocketHttpRequestPrintf(WebSocketHttpRequest *request,
-                                const char *format, ...);
-
-void WebSocketHttpRequestReset(WebSocketHttpRequest *request);
-char *WebSocketHttpRequestGetHeader(const WebSocketHttpRequest *request,
-                                    const char *webKey);
-Bool WebSocketHttpRequestHasHeader(const WebSocketHttpRequest *request,
-                                   const char *key);
-char *WebSocketHttpRequestGetURI(const WebSocketHttpRequest *request);
-char *WebSocketHttpRequestGetVerb(const WebSocketHttpRequest *request);
-char *WebSocketHttpRequestGetPath(const WebSocketHttpRequest *request);
-
-#endif // __ASYNC_SOCKET_INT_H__
index 7d71275bb9019952b2f10a81a986231617cd6138..b58bb4619860b23778687b28b04b9d85e9824fb1 100644 (file)
  *   generally are NOT virtualized.
  */
 
+#include "vmware.h"
 #include "asyncsocket.h"
-#include "asyncSocketInt.h"
+#include "asyncSocketBase.h"
+#include "msg.h"
+#include "log.h"
+
+#define LOGLEVEL_MODULE asyncsocket
+#include "loglevel_user.h"
+
+
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_SetCloseOptions --
+ *
+ *      Enables optional behavior for AsyncSocket_Close():
+ *
+ *      - If flushEnabledMaxWaitMsec is non-zero, the output stream
+ *        will be flushed synchronously before the socket is closed.
+ *        (default is zero: close socket right away without flushing)
+ *
+ *      - If closeCb is set, the callback will be called asynchronously
+ *        when the socket is actually destroyed.
+ *        (default is NULL: no callback)
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+AsyncSocket_SetCloseOptions(AsyncSocket *asock,           // IN
+                            int flushEnabledMaxWaitMsec,  // IN
+                            AsyncSocketCloseFn closeCb)   // IN
+{
+   if (VALID(asock, setCloseOptions)) {
+      AsyncSocketLock(asock);
+      VT(asock)->setCloseOptions(asock, flushEnabledMaxWaitMsec, closeCb);
+      AsyncSocketUnlock(asock);
+   }
+}
 
 
 /*
  */
 
 AsyncSocketState
-AsyncSocket_GetState(AsyncSocket *asock)
+AsyncSocket_GetState(AsyncSocket *asock)         // IN
 {
-   if (!asock) {
-      return ASOCKERR_INVAL;
+   AsyncSocketState ret;
+   if (VALID(asock, getState)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getState(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   ASSERT(asock->vt->getState);
-   return asock->vt->getState(asock);
+   return ret;
 }
 
 
@@ -106,9 +155,15 @@ AsyncSocket_GetState(AsyncSocket *asock)
 int
 AsyncSocket_GetGenericErrno(AsyncSocket *asock)  // IN:
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->getGenericErrno);
-   return asock->vt->getGenericErrno(asock);
+   int ret;
+   if (VALID(asock, getGenericErrno)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getGenericErrno(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = -1;
+   }
+   return ret;
 }
 
 
@@ -129,10 +184,17 @@ AsyncSocket_GetGenericErrno(AsyncSocket *asock)  // IN:
  */
 
 int
-AsyncSocket_GetFd(AsyncSocket *asock)
+AsyncSocket_GetFd(AsyncSocket *asock)         // IN
 {
-   ASSERT(asock->vt->getFd);
-   return asock->vt->getFd(asock);
+   int ret;
+   if (VALID(asock, getFd)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getFd(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = -1;
+   }
+   return ret;
 }
 
 
@@ -146,7 +208,7 @@ AsyncSocket_GetFd(AsyncSocket *asock)
  *      connection.
  *
  * Results:
- *      ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
+ *      ASOCKERR_SUCCESS or ASOCKERR_INVAL.
  *
  * Side effects:
  *
@@ -158,9 +220,15 @@ int
 AsyncSocket_GetRemoteIPStr(AsyncSocket *asock,      // IN
                            const char **ipRetStr)   // OUT
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->getRemoteIPStr);
-   return asock->vt->getRemoteIPStr(asock, ipRetStr);
+   int ret;
+   if (VALID(asock, getRemoteIPStr)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getRemoteIPStr(asock, ipRetStr);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
 
 
@@ -193,8 +261,15 @@ AsyncSocket_GetINETIPStr(AsyncSocket *asock,  // IN
                          int socketFamily,    // IN
                          char **ipRetStr)     // OUT
 {
-   ASSERT(asock->vt->getINETIPStr);
-   return asock->vt->getINETIPStr(asock, socketFamily, ipRetStr);
+   int ret;
+   if (VALID(asock, getINETIPStr)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getINETIPStr(asock, socketFamily, ipRetStr);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
 
 
@@ -218,8 +293,15 @@ AsyncSocket_GetINETIPStr(AsyncSocket *asock,  // IN
 unsigned int
 AsyncSocket_GetPort(AsyncSocket *asock)  // IN
 {
-   ASSERT(asock->vt->getPort);
-   return asock->vt->getPort(asock);
+   int ret;
+   if (VALID(asock, getPort)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getPort(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = MAX_UINT32;
+   }
+   return ret;
 }
 
 
@@ -232,7 +314,7 @@ AsyncSocket_GetPort(AsyncSocket *asock)  // IN
  *      enables Nagle's algorithm, respectively.
  *
  * Results:
- *      ASOCKERR_SUCCESS on success, ASOCKERR_GENERIC otherwise.
+ *      ASOCKERR_SUCCESS on success, ASOCKERR_* otherwise.
  *
  * Side Effects:
  *      Increased bandwidth usage for short messages on this socket
@@ -245,8 +327,15 @@ int
 AsyncSocket_UseNodelay(AsyncSocket *asock,  // IN/OUT:
                        Bool nodelay)        // IN:
 {
-   ASSERT(asock->vt->useNodelay);
-   return asock->vt->useNodelay(asock, nodelay);
+   int ret;
+   if (VALID(asock, useNodelay)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->useNodelay(asock, nodelay);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
 
 
@@ -267,7 +356,7 @@ AsyncSocket_UseNodelay(AsyncSocket *asock,  // IN/OUT:
  *                   the connection if no response is received from the peer.
  *
  * Results:
- *      ASOCKERR_SUCCESS on success, ASOCKERR_GENERIC otherwise.
+ *      ASOCKERR_SUCCESS on success, ASOCKERR_* otherwise.
  *
  * Side Effects:
  *      None.
@@ -275,17 +364,22 @@ AsyncSocket_UseNodelay(AsyncSocket *asock,  // IN/OUT:
  *----------------------------------------------------------------------------
  */
 
-#ifdef VMX86_SERVER
 int
 AsyncSocket_SetTCPTimeouts(AsyncSocket *asock,  // IN/OUT:
                            int keepIdle,        // IN
                            int keepIntvl,       // IN
                            int keepCnt)         // IN
 {
-   ASSERT(asock->vt->setTCPTimeouts);
-   return asock->vt->setTCPTimeouts(asock, keepIdle, keepIntvl, keepCnt);
+   int ret;
+   if (VALID(asock, setTCPTimeouts)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->setTCPTimeouts(asock, keepIdle, keepIntvl, keepCnt);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
-#endif
 
 
 /*
@@ -310,11 +404,15 @@ AsyncSocket_SetBufferSizes(AsyncSocket *asock,  // IN
                            int sendSz,          // IN
                            int recvSz)          // IN
 {
-   if (!asock) {
-      return FALSE;
+   Bool ret;
+   if (VALID(asock, setBufferSizes)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->setBufferSizes(asock, sendSz, recvSz);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = FALSE;
    }
-   ASSERT(asock->vt->setBufferSizes);
-   return asock->vt->setBufferSizes(asock, sendSz, recvSz);
+   return ret;
 }
 
 
@@ -346,8 +444,11 @@ void
 AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock,  // IN
                                   Bool enable)         // IN
 {
-   ASSERT(asock->vt->setSendLowLatencyMode);
-   asock->vt->setSendLowLatencyMode(asock, enable);
+   if (VALID(asock, setSendLowLatencyMode)) {
+      AsyncSocketLock(asock);
+      VT(asock)->setSendLowLatencyMode(asock, enable);
+      AsyncSocketUnlock(asock);
+   }
 }
 
 
@@ -380,10 +481,12 @@ AsyncSocket_StartSslConnect(AsyncSocket *asock,                   // IN
                             AsyncSocketSslConnectFn sslConnectFn, // IN
                             void *clientData)                     // IN
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->startSslConnect);
-   asock->vt->startSslConnect(asock, verifyParam, sslCtx, sslConnectFn,
-                              clientData);
+   if (VALID(asock, startSslConnect)) {
+      AsyncSocketLock(asock);
+      VT(asock)->startSslConnect(asock, verifyParam, sslCtx, sslConnectFn,
+                                 clientData);
+      AsyncSocketUnlock(asock);
+   }
 }
 
 
@@ -409,9 +512,15 @@ AsyncSocket_ConnectSSL(AsyncSocket *asock,          // IN
                        SSLVerifyParam *verifyParam, // IN/OPT
                        void *sslContext)            // IN/OPT
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->connectSSL);
-   return asock->vt->connectSSL(asock, verifyParam, sslContext);
+   Bool ret;
+   if (VALID(asock, connectSSL)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->connectSSL(asock, verifyParam, sslContext);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = FALSE;
+   }
+   return ret;
 }
 
 
@@ -435,12 +544,17 @@ Bool
 AsyncSocket_AcceptSSL(AsyncSocket *asock,    // IN
                       void *sslCtx)          // IN: optional
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->acceptSSL);
-   return asock->vt->acceptSSL(asock, sslCtx);
+   Bool ret;
+   if (VALID(asock, acceptSSL)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->acceptSSL(asock, sslCtx);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = FALSE;
+   }
+   return ret;
 }
 
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -467,9 +581,11 @@ AsyncSocket_StartSslAccept(AsyncSocket *asock,                 // IN
                            AsyncSocketSslAcceptFn sslAcceptFn, // IN
                            void *clientData)                   // IN
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->startSslAccept);
-   asock->vt->startSslAccept(asock, sslCtx, sslAcceptFn, clientData);
+   if (VALID(asock, startSslAccept)) {
+      AsyncSocketLock(asock);
+      VT(asock)->startSslAccept(asock, sslCtx, sslAcceptFn, clientData);
+      AsyncSocketUnlock(asock);
+   }
 }
 
 
@@ -484,7 +600,8 @@ AsyncSocket_StartSslAccept(AsyncSocket *asock,                 // IN
  * Results:
  *      ASOCKERR_SUCCESS if it worked, ASOCKERR_GENERIC on system call
  *      failures, and ASOCKERR_TIMEOUT if we couldn't send enough data
- *      before the timeout expired.
+ *      before the timeout expired.  ASOCKERR_INVAL on invalid
+ *      parameters or operation not implemented on this socket.
  *
  * Side effects:
  *      None.
@@ -495,12 +612,15 @@ int
 AsyncSocket_Flush(AsyncSocket *asock,  // IN
                   int timeoutMS)       // IN
 {
-   if (asock == NULL) {
-      Warning(ASOCKPREFIX "Flush called with invalid arguments!\n");
-      return ASOCKERR_INVAL;
+   int ret;
+   if (VALID(asock, flush)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->flush(asock, timeoutMS);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   ASSERT(asock->vt->flush);
-   return asock->vt->flush(asock, timeoutMS);
+   return ret;
 }
 
 
@@ -533,30 +653,39 @@ AsyncSocket_Flush(AsyncSocket *asock,  // IN
  */
 
 int
-AsyncSocket_Recv(AsyncSocket *asock,
-                 void *buf,
-                 int len,
-                 void *cb,
-                 void *cbData)
+AsyncSocket_Recv(AsyncSocket *asock,         // IN
+                 void *buf,                  // IN (buffer to fill)
+                 int len,                    // IN
+                 void *cb,                   // IN
+                 void *cbData)               // IN
 {
-   ASSERT(asock->vt->recv);
-   if (!asock) {
-      Warning(ASOCKPREFIX "Recv called with invalid arguments!\n");
-      return ASOCKERR_INVAL;
+   int ret;
+   if (VALID(asock, recv)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->recv(asock, buf, len, FALSE, cb, cbData);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-
-   return asock->vt->recv(asock, buf, len, FALSE, cb, cbData);
+   return ret;
 }
 
 int
-AsyncSocket_RecvPartial(AsyncSocket *asock,
-                        void *buf,
-                        int len,
-                        void *cb,
-                        void *cbData)
+AsyncSocket_RecvPartial(AsyncSocket *asock,         // IN
+                        void *buf,                  // IN (buffer to fill)
+                        int len,                    // IN
+                        void *cb,                   // IN
+                        void *cbData)               // IN
 {
-   ASSERT(asock->vt->recv);
-   return asock->vt->recv(asock, buf, len, TRUE, cb, cbData);
+   int ret;
+   if (VALID(asock, recv)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->recv(asock, buf, len, TRUE, cb, cbData);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
 
 
@@ -584,13 +713,15 @@ AsyncSocket_RecvPassedFd(AsyncSocket *asock,  // IN/OUT: socket
                          void *cb,            // IN: completion calback
                          void *cbData)        // IN: callback's data
 {
-   if (!asock) {
-      Warning(ASOCKPREFIX "Recv called with invalid arguments!\n");
-      return ASOCKERR_INVAL;
+   int ret;
+   if (VALID(asock, recvPassedFd)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->recvPassedFd(asock, buf, len, cb, cbData);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-
-   ASSERT(asock->vt->recvPassedFd);
-   return asock->vt->recvPassedFd(asock, buf, len, cb, cbData);
+   return ret;
 }
 
 
@@ -613,13 +744,15 @@ AsyncSocket_RecvPassedFd(AsyncSocket *asock,  // IN/OUT: socket
 int
 AsyncSocket_GetReceivedFd(AsyncSocket *asock)      // IN
 {
-   if (!asock) {
-      Warning(ASOCKPREFIX "Invalid socket while receiving fd!\n");
-      return -1;
+   int ret;
+   if (VALID(asock, getReceivedFd)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getReceivedFd(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = -1;
    }
-
-   ASSERT(asock->vt->getReceivedFd);
-   return asock->vt->getReceivedFd(asock);
+   return ret;
 }
 
 
@@ -651,19 +784,21 @@ AsyncSocket_GetReceivedFd(AsyncSocket *asock)      // IN
  */
 
 int
-AsyncSocket_Send(AsyncSocket *asock,
-                 void *buf,
-                 int len,
-                 AsyncSocketSendFn sendFn,
-                 void *clientData)
+AsyncSocket_Send(AsyncSocket *asock,         // IN
+                 void *buf,                  // IN
+                 int len,                    // IN
+                 AsyncSocketSendFn sendFn,   // IN
+                 void *clientData)           // IN
 {
-   if (!asock || !buf || len <= 0) {
-      Warning(ASOCKPREFIX "Send called with invalid arguments! asynchSock: %p "
-              "buffer: %p length: %d\n", asock, buf, len);
-      return ASOCKERR_INVAL;
+   int ret;
+   if (VALID(asock, send)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->send(asock, buf, len, sendFn, clientData);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   ASSERT(asock->vt->send);
-   return asock->vt->send(asock, buf, len, sendFn, clientData);
+   return ret;
 }
 
 
@@ -679,7 +814,7 @@ AsyncSocket_Send(AsyncSocket *asock,
  * Results:
  *      0: send space probably available,
  *      1: send has reached maximum,
- *      ASOCKERR_GENERIC: null socket.
+ *      ASOCKERR_INVAL: null socket or operation not supported.
  *
  * Side effects:
  *      None.
@@ -688,13 +823,49 @@ AsyncSocket_Send(AsyncSocket *asock,
  */
 
 int
-AsyncSocket_IsSendBufferFull(AsyncSocket *asock)
+AsyncSocket_IsSendBufferFull(AsyncSocket *asock)         // IN
 {
-   if (!asock) {
-      return ASOCKERR_GENERIC;
+   int ret;
+   if (VALID(asock, isSendBufferFull)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->isSendBufferFull(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   ASSERT(asock->vt->isSendBufferFull);
-   return asock->vt->isSendBufferFull(asock);
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_GetNetworkStats --
+ *
+ *      Get network statistics from the active socket.
+ *
+ * Results:
+ *      ASOCKERR_*
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_GetNetworkStats(AsyncSocket *asock,              // IN
+                            AsyncSocketNetworkStats *stats)  // OUT
+{
+   int ret;
+   if (VALID(asock, getNetworkStats)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getNetworkStats(asock, stats);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
 
 
@@ -720,13 +891,18 @@ AsyncSocket_IsSendBufferFull(AsyncSocket *asock)
  */
 
 int
-AsyncSocket_Close(AsyncSocket *asock)
+AsyncSocket_Close(AsyncSocket *asock)         // IN
 {
-   if (!asock) {
-      return ASOCKERR_INVAL;
+   int ret;
+   if (VALID(asock, close)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->close(asock);
+      AsyncSocketRelease(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   ASSERT(asock->vt->close);
-   return asock->vt->close(asock);
+   return ret;
 }
 
 
@@ -768,13 +944,16 @@ AsyncSocket_CancelRecvEx(AsyncSocket *asock,         // IN
                          void **recvFn,              // OUT
                          Bool cancelOnSend)          // IN
 {
-   if (!asock) {
-      Warning(ASOCKPREFIX "Invalid socket while cancelling recv request!\n");
-      return ASOCKERR_INVAL;
+   int ret;
+   if (VALID(asock, cancelRecv)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->cancelRecv(asock, partialRecvd, recvBuf, recvFn,
+                                  cancelOnSend);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   ASSERT(asock->vt->cancelRecv);
-   return asock->vt->cancelRecv(asock, partialRecvd, recvBuf, recvFn,
-                                cancelOnSend);
+   return ret;
 }
 
 
@@ -799,8 +978,11 @@ AsyncSocket_CancelRecvEx(AsyncSocket *asock,         // IN
 void
 AsyncSocket_CancelCbForClose(AsyncSocket *asock)  // IN:
 {
-   ASSERT(asock->vt->cancelCbForClose);
-   asock->vt->cancelCbForClose(asock);
+   if (VALID(asock, cancelCbForClose)) {
+      AsyncSocketLock(asock);
+      VT(asock)->cancelCbForClose(asock);
+      AsyncSocketUnlock(asock);
+   }
 }
 
 
@@ -827,9 +1009,15 @@ AsyncSocket_GetLocalVMCIAddress(AsyncSocket *asock,  // IN
                                 uint32 *cid,         // OUT: optional
                                 uint32 *port)        // OUT: optional
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->getLocalVMCIAddress);
-   return asock->vt->getLocalVMCIAddress(asock, cid, port);
+   int ret;
+   if (VALID(asock, getLocalVMCIAddress)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getLocalVMCIAddress(asock, cid, port);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
 }
 
 
@@ -856,9 +1044,47 @@ AsyncSocket_GetRemoteVMCIAddress(AsyncSocket *asock,  // IN
                                  uint32 *cid,         // OUT: optional
                                  uint32 *port)        // OUT: optional
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->getRemoteVMCIAddress);
-   return asock->vt->getRemoteVMCIAddress(asock, cid, port);
+   int ret;
+   if (VALID(asock, getRemoteVMCIAddress)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getRemoteVMCIAddress(asock, cid, port);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_GetWebSocketError --
+ *
+ *      Return the HTTP error code supplied during a failed WebSocket
+ *      upgrade negotiation.
+ *
+ * Results:
+ *      Numeric HTTP error code, 0 if no error, or -1 on invalid arguments.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_GetWebSocketError(AsyncSocket *asock)    // IN
+{
+   int ret;
+   if (VALID(asock, getWebSocketError)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getWebSocketError(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = -1;
+   }
+   return ret;
 }
 
 
@@ -881,9 +1107,15 @@ AsyncSocket_GetRemoteVMCIAddress(AsyncSocket *asock,  // IN
 char *
 AsyncSocket_GetWebSocketURI(AsyncSocket *asock)    // IN
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->getWebSocketURI);
-   return asock->vt->getWebSocketURI(asock);
+   char *ret;
+   if (VALID(asock, getWebSocketURI)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getWebSocketURI(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = NULL;
+   }
+   return ret;
 }
 
 
@@ -908,11 +1140,15 @@ AsyncSocket_GetWebSocketURI(AsyncSocket *asock)    // IN
 char *
 AsyncSocket_GetWebSocketCookie(AsyncSocket *asock)    // IN
 {
-   ASSERT(asock);
-   if (asock->vt->getWebSocketCookie) {
-      return asock->vt->getWebSocketCookie(asock);
+   char *ret;
+   if (VALID(asock, getWebSocketCookie)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getWebSocketCookie(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = NULL;
    }
-   return NULL;
+   return ret;
 }
 
 
@@ -933,11 +1169,17 @@ AsyncSocket_GetWebSocketCookie(AsyncSocket *asock)    // IN
  */
 
 uint16
-AsyncSocket_GetWebSocketCloseStatus(const AsyncSocket *asock)   // IN
+AsyncSocket_GetWebSocketCloseStatus(AsyncSocket *asock)   // IN
 {
-   ASSERT(asock);
-   ASSERT(asock->vt->getWebSocketCloseStatus);
-   return asock->vt->getWebSocketCloseStatus(asock);
+   uint16 ret;
+   if (VALID(asock, getWebSocketCloseStatus)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getWebSocketCloseStatus(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = 0;
+   }
+   return ret;
 }
 
 
@@ -962,9 +1204,199 @@ AsyncSocket_GetWebSocketCloseStatus(const AsyncSocket *asock)   // IN
 const char *
 AsyncSocket_GetWebSocketProtocol(AsyncSocket *asock)  // IN
 {
-   ASSERT(asock);
-   if (asock->vt->getWebSocketProtocol) {
-      return asock->vt->getWebSocketProtocol(asock);
+   const char *ret;
+   if (VALID(asock, getWebSocketProtocol)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->getWebSocketProtocol(asock);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = NULL;
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_RecvBlocking --
+ *
+ *      Implement "blocking + timeout" operations on the socket. These are
+ *      simple wrappers around the AsyncTCPSocketBlockingWork function, which
+ *      operates on the actual non-blocking socket, using poll to determine
+ *      when it's ok to keep reading/writing. If we can't finish within the
+ *      specified time, we give up and return the ASOCKERR_TIMEOUT error.
+ *
+ *      Note that if these are called from a callback and a lock is being
+ *      used (pollParams.lock), the whole blocking operation takes place
+ *      with that lock held.  Regardless, it is the caller's responsibility
+ *      to make sure the synchronous and asynchronous operations do not mix.
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS if we finished the operation, ASOCKERR_* error codes
+ *      otherwise.
+ *
+ * Side effects:
+ *      Reads/writes the socket.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_RecvBlocking(AsyncSocket *asock,         // IN
+                         void *buf,                  // OUT
+                         int len,                    // IN
+                         int *received,              // OUT
+                         int timeoutMS)              // IN
+{
+   int ret;
+   if (VALID(asock, recvBlocking)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->recvBlocking(asock, buf, len, received, timeoutMS);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_RecvPartialBlocking --
+ *
+ *      Implement "blocking + timeout" version of RecvPartial
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS if we finished the operation, ASOCKERR_* error codes
+ *      otherwise.
+ *
+ * Side effects:
+ *      Reads/writes the socket.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_RecvPartialBlocking(AsyncSocket *asock,         // IN
+                                void *buf,                  // OUT
+                                int len,                    // IN
+                                int *received,              // OUT
+                                int timeoutMS)              // IN
+{
+   int ret;
+   if (VALID(asock, recvPartialBlocking)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->recvPartialBlocking(asock, buf, len, received,
+                                           timeoutMS);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_SendBlocking --
+ *
+ *      Implement "blocking + timeout" version of Send
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS if we finished the operation, ASOCKERR_* error codes
+ *      otherwise.
+ *
+ * Side effects:
+ *      Reads/writes the socket.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_SendBlocking(AsyncSocket *asock,         // IN
+                         void *buf,                  // IN
+                         int len,                    // IN
+                         int *sent,                  // OUT
+                         int timeoutMS)              // IN
+{
+   int ret;
+   if (VALID(asock, sendBlocking)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->sendBlocking(asock, buf, len, sent, timeoutMS);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_DoOneMsg --
+ *
+ *      Spins a socket until the specified amount of time has elapsed or
+ *      data has arrived / been sent.
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS if it worked, ASOCKERR_GENERIC on system call
+ *         failures
+ *      ASOCKERR_TIMEOUT if nothing happened in the allotted time.
+ *
+ * Side effects:
+ *      None.
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_DoOneMsg(AsyncSocket *asock,         // IN
+                     Bool read,                  // IN
+                     int timeoutMS)              // IN
+{
+   int ret;
+   if (VALID(asock, doOneMsg)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->doOneMsg(asock, read, timeoutMS);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
+   }
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_WaitForConnection --
+ *
+ *      Spins a socket currently listening or connecting until the
+ *      connection completes or the allowed time elapses.
+ *
+ * Results:
+ *      ASOCKERR_SUCCESS if it worked, ASOCKERR_GENERIC on failures, and
+ *      ASOCKERR_TIMEOUT if nothing happened in the allotted time.
+ *
+ * Side effects:
+ *      None.
+ *----------------------------------------------------------------------------
+ */
+
+int
+AsyncSocket_WaitForConnection(AsyncSocket *asock,         // IN
+                              int timeoutMS)              // IN
+{
+   int ret;
+   if (VALID(asock, waitForConnection)) {
+      AsyncSocketLock(asock);
+      ret = VT(asock)->waitForConnection(asock, timeoutMS);
+      AsyncSocketUnlock(asock);
+   } else {
+      ret = ASOCKERR_INVAL;
    }
-   return NULL;
+   return ret;
 }
diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketVTable.h b/open-vm-tools/lib/asyncsocket/asyncSocketVTable.h
new file mode 100644 (file)
index 0000000..0228460
--- /dev/null
@@ -0,0 +1,110 @@
+/*********************************************************
+ * Copyright (C) 2011,2014-2016 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*********************************************************
+ * The contents of this file are subject to the terms of the Common
+ * Development and Distribution License (the "License") version 1.0
+ * and no later version.  You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ *         http://www.opensource.org/licenses/cddl1.php
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ *********************************************************/
+
+#ifndef __ASYNC_SOCKET_VTABLE_H__
+#define __ASYNC_SOCKET_VTABLE_H__
+
+#ifdef USE_SSL_DIRECT
+#include "sslDirect.h"
+#else
+#include "ssl.h"
+#endif
+
+
+typedef struct AsyncSocketVTable {
+   AsyncSocketState (*getState)(AsyncSocket *sock);
+   int (*getGenericErrno)(AsyncSocket *s);
+   int (*getFd)(AsyncSocket *asock);
+   int (*getRemoteIPStr)(AsyncSocket *asock, const char **ipStr);
+   int (*getINETIPStr)(AsyncSocket *asock, int socketFamily, char **ipRetStr);
+   unsigned int (*getPort)(AsyncSocket *asock);
+   int (*useNodelay)(AsyncSocket *asock, Bool nodelay);
+   int (*setTCPTimeouts)(AsyncSocket *asock, int keepIdle, int keepIntvl,
+                         int keepCnt);
+   Bool (*setBufferSizes)(AsyncSocket *asock, int sendSz, int recvSz);
+   void (*setSendLowLatencyMode)(AsyncSocket *asock, Bool enable);
+   void (*setCloseOptions)(AsyncSocket *asock, int flushEnabledMaxWaitMsec,
+                           AsyncSocketCloseFn closeCb);
+   Bool (*connectSSL)(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam,
+                      void *sslContext);
+   void (*startSslConnect)(AsyncSocket *asock,
+                           struct _SSLVerifyParam *verifyParam, void *sslCtx,
+                           AsyncSocketSslConnectFn sslConnectFn,
+                           void *clientData);
+   Bool (*acceptSSL)(AsyncSocket *asock, void *sslCtx);
+   void (*startSslAccept)(AsyncSocket *asock, void *sslCtx,
+                          AsyncSocketSslAcceptFn sslAcceptFn,
+                          void *clientData);
+   int (*flush)(AsyncSocket *asock, int timeoutMS);
+   int (*recv)(AsyncSocket *asock, void *buf, int len, Bool partial, void *cb,
+               void *cbData);
+   int (*recvPassedFd)(AsyncSocket *asock, void *buf, int len, void *cb,
+                       void *cbData);
+   int (*getReceivedFd)(AsyncSocket *asock);
+   int (*send)(AsyncSocket *asock, void *buf, int len,
+               AsyncSocketSendFn sendFn, void *clientData);
+   int (*isSendBufferFull)(AsyncSocket *asock);
+   int (*getNetworkStats)(AsyncSocket *asock,
+                          AsyncSocketNetworkStats *stats);
+   int (*close)(AsyncSocket *asock);
+   int (*cancelRecv)(AsyncSocket *asock, int *partialRecvd, void **recvBuf,
+                     void **recvFn, Bool cancelOnSend);
+   void (*cancelCbForClose)(AsyncSocket *asock);
+   int (*getLocalVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port);
+   int (*getRemoteVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port);
+   int (*getWebSocketError)(AsyncSocket *asock);
+   char *(*getWebSocketURI)(AsyncSocket *asock);
+   char *(*getWebSocketCookie)(AsyncSocket *asock);
+   uint16 (*getWebSocketCloseStatus)(AsyncSocket *asock);
+   const char *(*getWebSocketProtocol)(AsyncSocket *asock);
+   int (*recvBlocking)(AsyncSocket *s, void *buf, int len, int *received,
+                      int timeoutMS);
+   int (*recvPartialBlocking)(AsyncSocket *s, void *buf, int len,
+                              int *received, int timeoutMS);
+   int (*sendBlocking)(AsyncSocket *s, void *buf, int len, int *sent,
+                       int timeoutMS);
+   int (*doOneMsg)(AsyncSocket *s, Bool read, int timeoutMS);
+   int (*waitForConnection)(AsyncSocket *s, int timeoutMS);   // IN:
+
+
+   /*
+    * Internal function, called when refcount drops to zero:
+    */
+   void (*destroy)(AsyncSocket *asock);
+} AsyncSocketVTable;
+
+
+#define VT(x) ((x)->vt)
+#define VALID(asock, x) LIKELY(asock && VT(asock)->x)
+
+
+#endif
index efb851e2db3196de6c5c0bac887dd117f8e768c9..a656709185a0c69e1512821e331fdc4019681cab 100644 (file)
@@ -33,7 +33,7 @@
 /*
  * asyncsocket.c --
  *
- *      The AsyncSocket object is a fairly simple wrapper around a basic TCP
+ *      The AsyncTCPSocket object is a fairly simple wrapper around a basic TCP
  *      socket. It's potentially asynchronous for both read and write
  *      operations. Reads are "requested" by registering a receive function
  *      that is called once the requested amount of data has been read from
 #include <errno.h>
 #include <stdarg.h>
 
-#include "str.h"
+#ifdef _WIN32
+/*
+ * We redefine strcpy/strcat because the Windows SDK uses it for getaddrinfo().
+ * When we upgrade SDKs, this redefinition can go away.
+ * Note: Now we are checking if we have secure libs for string operations
+ */
+#if !(defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L)
+#define strcpy(dst,src) Str_Strcpy((dst), (src), 0x7FFFFFFF)
+#define strcat(dst,src) Str_Strcat((dst), (src), 0x7FFFFFFF)
+#endif
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <wspiapi.h>
+#include <MSWSock.h>
+#include <windows.h>
+#if !(defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L)
+#undef strcpy
+#undef strcat
+#endif
+#else
+#include <stddef.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
 
 #include "vmware.h"
+#include "str.h"
+#include "random.h"
 #include "asyncsocket.h"
-#include "asyncSocketInt.h"
+#include "asyncSocketBase.h"
 #include "poll.h"
 #include "log.h"
 #include "err.h"
 #include "vmdblib.h"
 #endif
 
+
+#ifdef _WIN32
+#define ASOCK_LASTERROR()       WSAGetLastError()
+#else
+#define ASOCK_LASTERROR()       errno
+#endif
+
+
 #define LOGLEVEL_MODULE asyncsocket
 #include "loglevel_user.h"
 
  */
 #define ADDR_STRING_LEN (INET6_ADDRSTRLEN + 2 + PORT_STRING_LEN)
 
+
 /*
- * The slots each have a "unique" ID, which is just an incrementing integer.
+ * Output buffer list data type, for the queue of outgoing buffers
  */
-static Atomic_uint32 nextid = { 1 };
+typedef struct SendBufList {
+   struct SendBufList   *next;
+   void                 *buf;
+   int                   len;
+   AsyncSocketSendFn     sendFn;
+   void                 *clientData;
+} SendBufList;
+
+
+typedef struct AsyncTCPSocket {
+   /*
+    * The base class, which is just a vtable:
+    */
+   AsyncSocket base;
+
+   /*
+    * Everything for the TCP AsyncSocket implementation:
+    */
+   int fd;
+   SSLSock sslSock;
+
+   int genericErrno;
+
+   struct sockaddr_storage localAddr;
+   socklen_t localAddrLen;
+   struct sockaddr_storage remoteAddr;
+   socklen_t remoteAddrLen;
+
+   AsyncSocketConnectFn connectFn;
+   AsyncSocketSslAcceptFn sslAcceptFn;
+   AsyncSocketSslConnectFn sslConnectFn;
+   int sslPollFlags;       /* shared by sslAcceptFn, sslConnectFn */
+
+   /* shared by connectFn, sslAcceptFn and sslConnectFn */
+   void *clientData;
+
+   PollerFunction internalConnectFn;
+   PollerFunction internalSendFn;
+   PollerFunction internalRecvFn;
+
+   /* governs optional AsyncSocket_Close() behavior */
+   int flushEnabledMaxWaitMsec;
+   AsyncSocketCloseFn closeCb;
+   void *closeCbData;
+
+   Bool recvCb;
+   Bool recvCbTimer;
+
+   SendBufList *sendBufList;
+   SendBufList **sendBufTail;
+   int sendPos;
+   Bool sendCb;
+   Bool sendCbTimer;
+   Bool sendCbRT;
+   Bool sendBufFull;
+   Bool sendLowLatency;
+
+   Bool sslConnected;
+
+   uint8 inIPollCb;
+   Bool inRecvLoop;
+   Bool inDoOneMsg;
+   uint32 inBlockingRecv;
+
+   struct AsyncTCPSocket *listenAsock4;
+   struct AsyncTCPSocket *listenAsock6;
+
+   struct {
+      Bool expected;
+      int fd;
+   } passFd;
+
+} AsyncTCPSocket;
+
+
 
 /*
  * Local Functions
  */
-static Bool AsyncSocketHasDataPending(AsyncSocket *asock);
-static int AsyncSocketMakeNonBlocking(int fd);
-static void AsyncSocketAcceptCallback(void *clientData);
-static void AsyncSocketConnectCallback(void *clientData);
-static int AsyncSocketBlockingWork(AsyncSocket *asock, Bool read, void *buf, int len,
-                                   int *completed, int timeoutMS, Bool partial);
-static VMwareStatus AsyncSocketPollAdd(AsyncSocket *asock, Bool socket,
-                                       int flags, PollerFunction callback,
-                                       ...);
-static Bool AsyncSocketPollRemove(AsyncSocket *asock, Bool socket,
-                                  int flags, PollerFunction callback);
-static unsigned int AsyncSocketGetPortFromAddr(struct sockaddr_storage *addr);
-static AsyncSocket *AsyncSocketConnect(struct sockaddr_storage *addr,
-                                       socklen_t addrLen,
-                                       AsyncSocketConnectFn connectFn,
-                                       void *clientData,
-                                       AsyncSocketConnectFlags flags,
-                                       AsyncSocketPollParams *pollParams,
-                                       int *outError);
-static int AsyncSocketConnectInternal(AsyncSocket *s);
-static Bool AsyncSocketHasDataPendingSocket(AsyncSocket *asock);
-
-static VMwareStatus AsyncSocketIPollAdd(AsyncSocket *asock, Bool socket,
-                                        int flags, PollerFunction callback,
-                                        int info);
-static Bool AsyncSocketIPollRemove(AsyncSocket *asock, Bool socket, int flags,
-                                   PollerFunction callback);
-static void AsyncSocketIPollSendCallback(void *clientData);
-static void AsyncSocketIPollRecvCallback(void *clientData);
-static Bool AsyncSocketAddListenCbSocket(AsyncSocket *asock);
-static void AsyncSocketSslConnectCallback(void *clientData);
-static void AsyncSocketSslAcceptCallback(void *clientData);
-
-static const AsyncSocketVTable asyncStreamSocketVTable = {
-   AsyncSocketGetState,
-   AsyncSocketGetGenericErrno,
-   AsyncSocketGetFd,
-   AsyncSocketGetRemoteIPStr,
-   AsyncSocketGetINETIPStr,
-   AsyncSocketGetPort,
-   AsyncSocketUseNodelay,
-   AsyncSocketSetTCPTimeouts,
-   AsyncSocketSetBufferSizes,
-   AsyncSocketSetSendLowLatencyMode,
-   AsyncSocketConnectSSL,
-   AsyncSocketStartSslConnect,
-   AsyncSocketAcceptSSL,
-   AsyncSocketStartSslAccept,
-   AsyncSocketFlush,
-   AsyncSocketRecv,
-   AsyncSocketRecvPassedFd,
-   AsyncSocketGetReceivedFd,
-   AsyncSocketSend,
-   AsyncSocketIsSendBufferFull,
-   AsyncSocketClose,
-   AsyncSocketCancelRecv,
-   AsyncSocketCancelCbForClose,
-   AsyncSocketGetLocalVMCIAddress,
-   AsyncSocketGetRemoteVMCIAddress,
-   NULL,
-   NULL,
-   NULL,
-   NULL,
-   AsyncSocketDispatchConnect,
-   AsyncSocketSendInternal,
-   AsyncSocketSendSocket,
-   AsyncSocketRecvSocket,
-   AsyncSocketSendCallback,
-   AsyncSocketRecvCallback,
-   AsyncSocketHasDataPendingSocket,
-   AsyncSocketCancelListenCbSocket,
-   AsyncSocketCancelRecvCbSocket,
-   AsyncSocketCancelCbForCloseSocket,
-   AsyncSocketCancelCbForConnectingCloseSocket,
-   AsyncSocketCloseSocket,
-   NULL,
-};
-
-static const AsyncSocketVTable asyncStreamSocketIPollVTable = {
+static AsyncTCPSocket *AsyncTCPSocketCreate(AsyncSocketPollParams *pollParams);
+static void AsyncTCPSocketSendCallback(void *clientData);
+static void AsyncTCPSocketRecvCallback(void *clientData);
+static int AsyncTCPSocketResolveAddr(const char *hostname,
+                                     unsigned int port,
+                                     int family,
+                                     Bool passive,
+                                     struct sockaddr_storage *addr,
+                                     socklen_t *addrLen,
+                                     char **addrString);
+static AsyncTCPSocket *AsyncTCPSocketAttachToFd(
+   int fd, AsyncSocketPollParams *pollParams, int *outError);
+static Bool AsyncTCPSocketHasDataPending(AsyncTCPSocket *asock);
+static int AsyncTCPSocketMakeNonBlocking(int fd);
+static void AsyncTCPSocketAcceptCallback(void *clientData);
+static void AsyncTCPSocketConnectCallback(void *clientData);
+static int AsyncTCPSocketBlockingWork(AsyncTCPSocket *asock, Bool read,
+                                      void *buf, int len,
+                                      int *completed, int timeoutMS,
+                                      Bool partial);
+static VMwareStatus AsyncTCPSocketPollAdd(AsyncTCPSocket *asock, Bool socket,
+                                          int flags, PollerFunction callback,
+                                          ...);
+static Bool AsyncTCPSocketPollRemove(AsyncTCPSocket *asock, Bool socket,
+                                     int flags, PollerFunction callback);
+static unsigned int AsyncTCPSocketGetPortFromAddr(
+   struct sockaddr_storage *addr);
+static AsyncTCPSocket *AsyncTCPSocketConnect(struct sockaddr_storage *addr,
+                                             socklen_t addrLen,
+                                             AsyncSocketConnectFn connectFn,
+                                             void *clientData,
+                                             AsyncSocketConnectFlags flags,
+                                             AsyncSocketPollParams *pollParams,
+                                             int *outError);
+static int AsyncTCPSocketConnectInternal(AsyncTCPSocket *s);
+
+static VMwareStatus AsyncTCPSocketIPollAdd(AsyncTCPSocket *asock, Bool socket,
+                                           int flags, PollerFunction callback,
+                                           int info);
+static Bool AsyncTCPSocketIPollRemove(AsyncTCPSocket *asock, Bool socket,
+                                      int flags, PollerFunction callback);
+static void AsyncTCPSocketIPollSendCallback(void *clientData);
+static void AsyncTCPSocketIPollRecvCallback(void *clientData);
+static Bool AsyncTCPSocketAddListenCb(AsyncTCPSocket *asock);
+static void AsyncTCPSocketSslConnectCallback(void *clientData);
+static void AsyncTCPSocketSslAcceptCallback(void *clientData);
+
+static Bool AsyncTCPSocketBind(AsyncTCPSocket *asock,
+                               struct sockaddr_storage *addr,
+                               socklen_t addrLen,
+                               int *outError);
+static Bool AsyncTCPSocketListen(AsyncTCPSocket *asock,
+                                 AsyncSocketConnectFn connectFn,
+                                 void *clientData,
+                                 int *outError);
+static AsyncTCPSocket *AsyncTCPSocketInit(int socketFamily,
+                                          AsyncSocketPollParams *pollParams,
+                                          int *outError);
+
+static void AsyncTCPSocketCancelListenCb(AsyncTCPSocket *asock);
+
+
+static int AsyncTCPSocketRegisterRecvCb(AsyncTCPSocket *asock);
+static Bool AsyncTCPSocketCancelCbForConnectingClose(AsyncTCPSocket *asock);
+
+static int AsyncTCPSocketWaitForConnection(AsyncSocket *s, int timeoutMS);
+static int AsyncTCPSocketGetGenericErrno(AsyncSocket *s);
+static int AsyncTCPSocketGetFd(AsyncSocket *asock);
+static int AsyncTCPSocketGetRemoteIPStr(AsyncSocket *asock, const char **ipStr);
+static int AsyncTCPSocketGetINETIPStr(AsyncSocket *asock, int socketFamily,
+                                      char **ipRetStr);
+static unsigned int AsyncTCPSocketGetPort(AsyncSocket *asock);
+static int AsyncTCPSocketUseNodelay(AsyncSocket *asock, Bool nodelay);
+static int AsyncTCPSocketSetTCPTimeouts(AsyncSocket *asock, int keepIdle,
+                                        int keepIntvl, int keepCnt);
+static Bool AsyncTCPSocketSetBufferSizes(AsyncSocket *asock,
+                                         int sendSz, int recvSz);
+static void AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *asock,
+                                                Bool enable);
+static Bool AsyncTCPSocketConnectSSL(AsyncSocket *asock,
+                                     struct _SSLVerifyParam *verifyParam,
+                                     void *sslContext);
+static void AsyncTCPSocketStartSslConnect(AsyncSocket *asock,
+                                          SSLVerifyParam *verifyParam,
+                                          void *sslCtx,
+                                          AsyncSocketSslConnectFn sslConnectFn,
+                                          void *clientData);
+static Bool AsyncTCPSocketAcceptSSL(AsyncSocket *asock, void *sslCtx);
+static void AsyncTCPSocketStartSslAccept(AsyncSocket *asock, void *sslCtx,
+                                         AsyncSocketSslAcceptFn sslAcceptFn,
+                                         void *clientData);
+static int AsyncTCPSocketFlush(AsyncSocket *asock, int timeoutMS);
+static void AsyncTCPSocketCancelRecvCb(AsyncTCPSocket *asock);
+
+static int AsyncTCPSocketRecv(AsyncSocket *asock,
+             void *buf, int len, Bool partial, void *cb, void *cbData);
+static int AsyncTCPSocketRecvPassedFd(AsyncSocket *asock, void *buf, int len,
+                     void *cb, void *cbData);
+static int AsyncTCPSocketGetReceivedFd(AsyncSocket *asock);
+static int AsyncTCPSocketSend(AsyncSocket *asock, void *buf, int len,
+                              AsyncSocketSendFn sendFn, void *clientData);
+static int AsyncTCPSocketIsSendBufferFull(AsyncSocket *asock);
+static int AsyncTCPSocketClose(AsyncSocket *asock);
+static int AsyncTCPSocketCancelRecv(AsyncSocket *asock, int *partialRecvd,
+                                    void **recvBuf, void **recvFn,
+                                    Bool cancelOnSend);
+static void AsyncTCPSocketCancelCbForClose(AsyncSocket *asock);
+static int AsyncTCPSocketGetLocalVMCIAddress(AsyncSocket *asock,
+                            uint32 *cid, uint32 *port);
+static int AsyncTCPSocketGetRemoteVMCIAddress(AsyncSocket *asock,
+                             uint32 *cid, uint32 *port);
+static void AsyncTCPSocketSetCloseOptions(AsyncSocket *asock,
+                                          int flushEnabledMaxWaitMsec,
+                                          AsyncSocketCloseFn closeCb);
+static void AsyncTCPSocketDestroy(AsyncSocket *s);
+static int AsyncTCPSocketRecvBlocking(AsyncSocket *s, void *buf, int len,
+                                      int *received, int timeoutMS);
+static int AsyncTCPSocketRecvPartialBlocking(AsyncSocket *s, void *buf, int len,
+                                             int *received, int timeoutMS);
+static int AsyncTCPSocketSendBlocking(AsyncSocket *s, void *buf, int len,
+                                      int *sent, int timeoutMS);
+static int AsyncTCPSocketDoOneMsg(AsyncSocket *s, Bool read, int timeoutMS);
+
+
+static const AsyncSocketVTable asyncTCPSocketVTable = {
    AsyncSocketGetState,
-   AsyncSocketGetGenericErrno,
-   AsyncSocketGetFd,
-   AsyncSocketGetRemoteIPStr,
-   AsyncSocketGetINETIPStr,
-   AsyncSocketGetPort,
-   AsyncSocketUseNodelay,
-   AsyncSocketSetTCPTimeouts,
-   AsyncSocketSetBufferSizes,
-   AsyncSocketSetSendLowLatencyMode,
-   AsyncSocketConnectSSL,
-   AsyncSocketStartSslConnect,
-   AsyncSocketAcceptSSL,
-   AsyncSocketStartSslAccept,
-   AsyncSocketFlush,
-   AsyncSocketRecv,
-   AsyncSocketRecvPassedFd,
-   AsyncSocketGetReceivedFd,
-   AsyncSocketSend,
-   AsyncSocketIsSendBufferFull,
-   AsyncSocketClose,
-   AsyncSocketCancelRecv,
-   AsyncSocketCancelCbForClose,
-   AsyncSocketGetLocalVMCIAddress,
-   AsyncSocketGetRemoteVMCIAddress,
-   NULL,
-   NULL,
-   NULL,
-   NULL,
-   AsyncSocketDispatchConnect,
-   AsyncSocketSendInternal,
-   AsyncSocketSendSocket,
-   AsyncSocketRecvSocket,
-   AsyncSocketIPollSendCallback,
-   AsyncSocketIPollRecvCallback,
-   AsyncSocketHasDataPendingSocket,
-   AsyncSocketCancelListenCbSocket,
-   AsyncSocketCancelRecvCbSocket,
-   AsyncSocketCancelCbForCloseSocket,
-   AsyncSocketCancelCbForConnectingCloseSocket,
-   AsyncSocketCloseSocket,
-   NULL,
+   AsyncTCPSocketGetGenericErrno,
+   AsyncTCPSocketGetFd,
+   AsyncTCPSocketGetRemoteIPStr,
+   AsyncTCPSocketGetINETIPStr,
+   AsyncTCPSocketGetPort,
+   AsyncTCPSocketUseNodelay,
+   AsyncTCPSocketSetTCPTimeouts,
+   AsyncTCPSocketSetBufferSizes,
+   AsyncTCPSocketSetSendLowLatencyMode,
+   AsyncTCPSocketSetCloseOptions,
+   AsyncTCPSocketConnectSSL,
+   AsyncTCPSocketStartSslConnect,
+   AsyncTCPSocketAcceptSSL,
+   AsyncTCPSocketStartSslAccept,
+   AsyncTCPSocketFlush,
+   AsyncTCPSocketRecv,
+   AsyncTCPSocketRecvPassedFd,
+   AsyncTCPSocketGetReceivedFd,
+   AsyncTCPSocketSend,
+   AsyncTCPSocketIsSendBufferFull,
+   NULL,                        /* getNetworkStats */
+   AsyncTCPSocketClose,
+   AsyncTCPSocketCancelRecv,
+   AsyncTCPSocketCancelCbForClose,
+   AsyncTCPSocketGetLocalVMCIAddress,
+   AsyncTCPSocketGetRemoteVMCIAddress,
+   NULL,                        /* getWebSocketError */
+   NULL,                        /* getWebSocketURI */
+   NULL,                        /* getWebSocketCookie */
+   NULL,                        /* getWebSocketCloseStatus */
+   NULL,                        /* getWebSocketProtocol */
+   AsyncTCPSocketRecvBlocking,
+   AsyncTCPSocketRecvPartialBlocking,
+   AsyncTCPSocketSendBlocking,
+   AsyncTCPSocketDoOneMsg,
+   AsyncTCPSocketWaitForConnection,
+   AsyncTCPSocketDestroy
 };
 
 
 /*
- *----------------------------------------------------------------------------
+ *----------------------------------------------------------------------
  *
- * AsyncSocketLock --
- * AsyncSocketUnlock --
+ * BaseSocket --
  *
- *      Acquire/Release the lock provided by the client when creating the
- *      AsyncSocket object.
+ *      Return a pointer to the tcp socket's base class.
  *
- * Results:
- *      None.
+ *----------------------------------------------------------------------
+ */
+
+static INLINE AsyncSocket *
+BaseSocket(AsyncTCPSocket *s)
+{
+   ASSERT((void *)s == (void *)&s->base);
+   return &s->base;
+}
+
+
+/*
+ *----------------------------------------------------------------------
  *
- * Side effects:
- *      None.
+ * TCPSocket --
  *
- *----------------------------------------------------------------------------
+ *      Cast a generic AsyncSocket pointer to AsyncTCPSocket, after
+ *      asserting this is legal.
+ *
+ *----------------------------------------------------------------------
  */
 
-INLINE void
-AsyncSocketLock(AsyncSocket *asock)   // IN:
+static INLINE AsyncTCPSocket *
+TCPSocket(AsyncSocket *s)
 {
-   if (asock->pollParams.lock) {
-      MXUser_AcquireRecLock(asock->pollParams.lock);
-   }
+   ASSERT(s->vt == &asyncTCPSocketVTable);
+   ASSERT(s == &((AsyncTCPSocket *)s)->base);
+   return (AsyncTCPSocket *)s;
 }
 
 
-INLINE void
-AsyncSocketUnlock(AsyncSocket *asock)   // IN:
+/*
+ *----------------------------------------------------------------------
+ *
+ * TCPSocketLock --
+ * TCPSocketUnlock --
+ * TCPSocketIsLocked --
+ * TCPSocketAddRef --
+ * TCPSocketRelease --
+ * TCPSocketPollParams --
+ * TCPSocketGetState --
+ * TCPSocketSetState --
+ * TCPSocketHandleError --
+ *
+ *      AsyncTCPSocket versions of base class interfaces.  These
+ *      simply invoke the corresponding function on the base class
+ *      pointer.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static INLINE void
+AsyncTCPSocketLock(AsyncTCPSocket *asock)
+{
+   AsyncSocketLock(BaseSocket(asock));
+}
+
+static INLINE void
+AsyncTCPSocketUnlock(AsyncTCPSocket *asock)
 {
-   if (asock->pollParams.lock) {
-      MXUser_ReleaseRecLock(asock->pollParams.lock);
-   }
+   AsyncSocketUnlock(BaseSocket(asock));
+}
+
+static INLINE Bool
+AsyncTCPSocketIsLocked(AsyncTCPSocket *asock)
+{
+   return AsyncSocketIsLocked(BaseSocket(asock));
+}
+
+static INLINE void
+AsyncTCPSocketAddRef(AsyncTCPSocket *asock)
+{
+   AsyncSocketAddRef(BaseSocket(asock));
+}
+
+static INLINE void
+AsyncTCPSocketRelease(AsyncTCPSocket *asock)
+{
+   AsyncSocketRelease(BaseSocket(asock));
+}
+
+static INLINE AsyncSocketPollParams *
+AsyncTCPSocketPollParams(AsyncTCPSocket *asock)
+{
+   return AsyncSocketGetPollParams(BaseSocket(asock));
+}
+
+static INLINE Bool
+AsyncTCPSocketGetState(AsyncTCPSocket *asock)
+{
+   return AsyncSocketGetState(BaseSocket(asock));
+}
+
+static INLINE void
+AsyncTCPSocketSetState(AsyncTCPSocket *asock, AsyncSocketState state)
+{
+   AsyncSocketSetState(BaseSocket(asock), state);
+}
+
+static INLINE void
+AsyncTCPSocketHandleError(AsyncTCPSocket *asock, int error)
+{
+   AsyncSocketHandleError(BaseSocket(asock), error);
 }
 
 
 /*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketIsLocked --
+ *----------------------------------------------------------------------
  *
- *      If a lock is associated with the socket, check whether the calling
- *      thread holds the lock.
+ * TCPSOCKWARN --
+ * TCPSOCKLOG --
+ * TCPSOCKLG0 --
  *
- * Results:
- *      TRUE if calling thread holds the lock, or if there is no assoicated
- *      lock.
+ *      AsyncTCPSocket versions of base class logging macros.  These
+ *      simply invoke the corresponding macro on the base class
+ *      pointer.
  *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
+ *----------------------------------------------------------------------
  */
 
-INLINE Bool
-AsyncSocketIsLocked(AsyncSocket *asock)   // IN:
-{
-   if (asock->pollParams.lock && Poll_LockingEnabled()) {
-      return MXUser_IsCurThreadHoldingRecLock(asock->pollParams.lock);
-   }
-   return TRUE;
-}
+#define TCPSOCKWARN(a,b) ASOCKWARN(BaseSocket(a), b)
+#define TCPSOCKLOG(a,b,c) ASOCKLOG(a, BaseSocket(b), c)
+#define TCPSOCKLG0(a,b) ASOCKLG0(BaseSocket(a), b)
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_Init --
+ * AsyncTCPSocket_Init --
  *
  *      Initializes the host's socket library. NOP on Posix.
  *      On Windows, calls WSAStartup().
@@ -323,7 +550,7 @@ AsyncSocketIsLocked(AsyncSocket *asock)   // IN:
  */
 
 int
-AsyncSocket_Init(void)
+AsyncTCPSocket_Init(void)
 {
 #ifdef _WIN32
    WSADATA wsaData;
@@ -338,12 +565,13 @@ AsyncSocket_Init(void)
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_Err2String --
+ * AsyncTCPSocketGetFd --
  *
- *      Returns the error string associated with error code.
+ *      Returns the fd for this socket.  If listening, return one of
+ *      the asock6/asock4 fds.
  *
  * Results:
- *      Error string.
+ *      File descriptor.
  *
  * Side effects:
  *      None.
@@ -351,117 +579,29 @@ AsyncSocket_Init(void)
  *----------------------------------------------------------------------------
  */
 
-const char *
-AsyncSocket_Err2String(int err)  // IN
+static int
+AsyncTCPSocketGetFd(AsyncSocket *base)         // IN
 {
-   return Msg_StripMSGID(AsyncSocket_MsgError(err));
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocket_MsgError --
- *
- *      Returns the message associated with error code.
- *
- * Results:
- *      Message string.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
+   AsyncTCPSocket *asock = TCPSocket(base);
 
-const char *
-AsyncSocket_MsgError(int asyncSockError)   // IN
-{
-   const char *result = NULL;
-   switch (asyncSockError) {
-   case ASOCKERR_SUCCESS:
-      result = MSGID(asyncsocket.success) "Success";
-      break;
-   case ASOCKERR_GENERIC:
-      result = MSGID(asyncsocket.generic) "Asyncsocket error";
-      break;
-   case ASOCKERR_INVAL:
-      result = MSGID(asyncsocket.invalid) "Invalid parameters";
-      break;
-   case ASOCKERR_TIMEOUT:
-      result = MSGID(asyncsocket.timeout) "Time-out error";
-      break;
-   case ASOCKERR_NOTCONNECTED:
-      result = MSGID(asyncsocket.notconnected) "Local socket not connected";
-      break;
-   case ASOCKERR_REMOTE_DISCONNECT:
-      result = MSGID(asyncsocket.remotedisconnect) "Remote disconnected";
-      break;
-   case ASOCKERR_CLOSED:
-      result = MSGID(asyncsocket.closed) "Closed socket";
-      break;
-   case ASOCKERR_CONNECT:
-      result = MSGID(asyncsocket.connect) "Connection error";
-      break;
-   case ASOCKERR_POLL:
-      result = MSGID(asyncsocket.poll) "Poll registration error";
-      break;
-   case ASOCKERR_BIND:
-      result = MSGID(asyncsocket.bind) "Socket bind error";
-      break;
-   case ASOCKERR_BINDADDRINUSE:
-      result = MSGID(asyncsocket.bindaddrinuse) "Socket bind address already in use";
-      break;
-   case ASOCKERR_LISTEN:
-      result = MSGID(asyncsocket.listen) "Socket listen error";
-      break;
-   case ASOCKERR_CONNECTSSL:
-      result = MSGID(asyncsocket.connectssl) "Connection error: could not negotiate SSL";
-      break;
-   case ASOCKERR_NETUNREACH:
-      result = MSGID(asyncsocket.netunreach) "Network unreachable";
-      break;
-   case ASOCKERR_ADDRUNRESV:
-      result = MSGID(asyncsocket.addrunresv) "Address unresolvable";
-      break;
-   }
-
-   if (!result) {
-      Warning("%s was passed bad code %d\n", __FUNCTION__, asyncSockError);
-      result = MSGID(asyncsocket.unknown) "Unknown error";
+   if (asock->fd != -1) {
+      return asock->fd;
+   } else if (asock->listenAsock4 && asock->listenAsock4->fd != -1) {
+      return asock->listenAsock4->fd;
+   } else if (asock->listenAsock6 && asock->listenAsock6->fd != -1) {
+      return asock->listenAsock6->fd;
+   } else {
+      return -1;
    }
-   return result;
-}
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketGetFd --
- *
- *      Returns the fd for this socket.
- *
- * Results:
- *      File descriptor.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-int
-AsyncSocketGetFd(AsyncSocket *s)
-{
-   return s->fd;
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetAddr --
+ * AsyncTCPSocketGetAddr --
  *
- *      Given an AsyncSocket object, return the sockaddr associated with the
+ *      Given an AsyncTCPSocket object, return the sockaddr associated with the
  *      requested address family's file descriptor if available.
  *
  *      Passing AF_UNSPEC to socketFamily will provide you with the first
@@ -479,16 +619,15 @@ AsyncSocketGetFd(AsyncSocket *s)
  */
 
 static int
-AsyncSocketGetAddr(AsyncSocket *asock,                // IN
-                   int socketFamily,                  // IN
-                   struct sockaddr_storage *outAddr,  // OUT
-                   socklen_t *outAddrLen)             // IN/OUT
+AsyncTCPSocketGetAddr(AsyncTCPSocket *asock,             // IN
+                      int socketFamily,                  // IN
+                      struct sockaddr_storage *outAddr,  // OUT
+                      socklen_t *outAddrLen)             // IN/OUT
 {
-   AsyncSocket *tempAsock;
+   AsyncTCPSocket *tempAsock;
    int tempFd;
    struct sockaddr_storage addr;
    socklen_t addrLen = sizeof addr;
-   int ret = ASOCKERR_GENERIC;
 
    if (asock->fd != -1) {
       tempAsock = asock;
@@ -502,36 +641,32 @@ AsyncSocketGetAddr(AsyncSocket *asock,                // IN
       return ASOCKERR_INVAL;
    }
 
-   AsyncSocketLock(tempAsock);
+   ASSERT(AsyncTCPSocketIsLocked(tempAsock));
    tempFd = tempAsock->fd;
 
    if (getsockname(tempFd, (struct sockaddr*)&addr, &addrLen) == 0) {
       if (socketFamily != AF_UNSPEC && addr.ss_family != socketFamily) {
-         ret = ASOCKERR_INVAL;
-         goto outWithLock;
+         return ASOCKERR_INVAL;
       }
 
       memcpy(outAddr, &addr, Min(*outAddrLen, addrLen));
       *outAddrLen = addrLen;
-      ret = ASOCKERR_SUCCESS;
+      return ASOCKERR_SUCCESS;
    } else {
-      ASOCKWARN(tempAsock, ("%s: could not locate socket.\n", __FUNCTION__));
+      TCPSOCKWARN(tempAsock, ("%s: could not locate socket.\n", __FUNCTION__));
+      return ASOCKERR_GENERIC;
    }
-
- outWithLock:
-   AsyncSocketUnlock(tempAsock);
-   return ret;
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetRemoteIPStr --
+ * AsyncTCPSocketGetRemoteIPStr --
  *
- *      Given an AsyncSocket object, returns the remote IP address associated
- *      with it, or an error if the request is meaningless for the underlying
- *      connection.
+ *      Given an AsyncTCPSocket object, returns the remote IP address
+ *      associated with it, or an error if the request is meaningless
+ *      for the underlying connection.
  *
  * Results:
  *      ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
@@ -542,18 +677,18 @@ AsyncSocketGetAddr(AsyncSocket *asock,                // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketGetRemoteIPStr(AsyncSocket *asock,      // IN
-                          const char **ipRetStr)   // OUT
+static int
+AsyncTCPSocketGetRemoteIPStr(AsyncSocket *base,      // IN
+                             const char **ipRetStr)  // OUT
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    int ret = ASOCKERR_SUCCESS;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
    ASSERT(ipRetStr != NULL);
 
    if (ipRetStr == NULL || asock == NULL ||
-       asock->state != AsyncSocketConnected ||
+       AsyncTCPSocketGetState(asock) != AsyncSocketConnected ||
        (asock->remoteAddrLen != sizeof (struct sockaddr_in) &&
         asock->remoteAddrLen != sizeof (struct sockaddr_in6))) {
       ret = ASOCKERR_GENERIC;
@@ -576,9 +711,9 @@ AsyncSocketGetRemoteIPStr(AsyncSocket *asock,      // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetINETIPStr --
+ * AsyncTCPSocketGetINETIPStr --
  *
- *      Given an AsyncSocket object, returns the IP addresses associated with
+ *      Given an AsyncTCPSocket object, returns the IP addresses associated with
  *      the requested address family's file descriptor if available.
  *
  *      Passing AF_UNSPEC to socketFamily will provide you with the first
@@ -597,37 +732,36 @@ AsyncSocketGetRemoteIPStr(AsyncSocket *asock,      // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketGetINETIPStr(AsyncSocket *asock,  // IN
-                        int socketFamily,    // IN
-                        char **ipRetStr)     // OUT
+static int
+AsyncTCPSocketGetINETIPStr(AsyncSocket *base,   // IN
+                           int socketFamily,    // IN
+                           char **ipRetStr)     // OUT
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    struct sockaddr_storage addr;
    socklen_t addrLen = sizeof addr;
    int ret;
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   ret = AsyncSocketGetAddr(asock, socketFamily, &addr, &addrLen);
+   ret = AsyncTCPSocketGetAddr(asock, socketFamily, &addr, &addrLen);
    if (ret == ASOCKERR_SUCCESS) {
       char addrBuf[NI_MAXHOST];
 
       if (ipRetStr == NULL) {
-         ASOCKWARN(asock, ("%s: Output string is not usable.\n",
-                           __FUNCTION__));
+         TCPSOCKWARN(asock, ("%s: Output string is not usable.\n",
+                             __FUNCTION__));
          ret = ASOCKERR_INVAL;
       } else if (Posix_GetNameInfo((struct sockaddr *)&addr, addrLen, addrBuf,
                                    sizeof addrBuf, NULL, 0,
                                    NI_NUMERICHOST) == 0) {
          *ipRetStr = Util_SafeStrdup(addrBuf);
       } else {
-         ASOCKWARN(asock, ("%s: could not find IP address.\n", __FUNCTION__));
+         TCPSOCKWARN(asock, ("%s: could not find IP address.\n", __FUNCTION__));
          ret = ASOCKERR_GENERIC;
       }
    }
 
-   AsyncSocketUnlock(asock);
-
    return ret;
 }
 
@@ -635,9 +769,9 @@ AsyncSocketGetINETIPStr(AsyncSocket *asock,  // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetLocalVMCIAddress --
+ * AsyncTCPSocketGetLocalVMCIAddress --
  *
- *      Given an AsyncSocket object, returns the local VMCI context ID and
+ *      Given an AsyncTCPSocket object, returns the local VMCI context ID and
  *      port number associated with it, or an error if the request is
  *      meaningless for the underlying connection.
  *
@@ -650,11 +784,12 @@ AsyncSocketGetINETIPStr(AsyncSocket *asock,  // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketGetLocalVMCIAddress(AsyncSocket *asock,  // IN
-                               uint32 *cid,         // OUT: optional
-                               uint32 *port)        // OUT: optional
+static int
+AsyncTCPSocketGetLocalVMCIAddress(AsyncSocket *base,   // IN
+                                  uint32 *cid,         // OUT: optional
+                                  uint32 *port)        // OUT: optional
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    ASSERT(asock);
 
    if (asock->localAddrLen != sizeof(struct sockaddr_vm)) {
@@ -676,9 +811,9 @@ AsyncSocketGetLocalVMCIAddress(AsyncSocket *asock,  // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetRemoteVMCIAddress --
+ * AsyncTCPSocketGetRemoteVMCIAddress --
  *
- *      Given an AsyncSocket object, returns the remote VMCI context ID and
+ *      Given an AsyncTCPSocket object, returns the remote VMCI context ID and
  *      port number associated with it, or an error if the request is
  *      meaningless for the underlying connection.
  *
@@ -691,11 +826,12 @@ AsyncSocketGetLocalVMCIAddress(AsyncSocket *asock,  // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketGetRemoteVMCIAddress(AsyncSocket *asock,  // IN
-                                uint32 *cid,         // OUT: optional
-                                uint32 *port)        // OUT: optional
+static int
+AsyncTCPSocketGetRemoteVMCIAddress(AsyncSocket *base,   // IN
+                                   uint32 *cid,         // OUT: optional
+                                   uint32 *port)        // OUT: optional
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    ASSERT(asock);
 
    if (asock->remoteAddrLen != sizeof(struct sockaddr_vm)) {
@@ -717,12 +853,12 @@ AsyncSocketGetRemoteVMCIAddress(AsyncSocket *asock,  // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketListenImpl --
+ * AsyncTCPSocketListenImpl --
  *
  *      Initializes, binds, and listens on pre-populated address structure.
  *
  * Results:
- *      New AsyncSocket in listening state or NULL on error.
+ *      New AsyncTCPSocket in listening state or NULL on error.
  *
  * Side effects:
  *      Creates new socket, binds and listens.
@@ -730,29 +866,20 @@ AsyncSocketGetRemoteVMCIAddress(AsyncSocket *asock,  // IN
  *----------------------------------------------------------------------------
  */
 
-AsyncSocket *
-AsyncSocketListenImpl(struct sockaddr_storage *addr,      // IN
-                      socklen_t addrLen,                  // IN
-                      AsyncSocketConnectFn connectFn,     // IN
-                      void *clientData,                   // IN
-                      AsyncSocketPollParams *pollParams,  // IN: optional
-                      Bool isWebSock,                     // IN
-                      Bool webSockUseSSL,                 // IN:
-                      const char *protocols[],            // IN: optional
-                      void *sslCtx,                       // IN: optional
-                      int *outError)                      // OUT: optional
+static AsyncTCPSocket *
+AsyncTCPSocketListenImpl(struct sockaddr_storage *addr,      // IN
+                         socklen_t addrLen,                  // IN
+                         AsyncSocketConnectFn connectFn,     // IN
+                         void *clientData,                   // IN
+                         AsyncSocketPollParams *pollParams,  // IN: optional
+                         int *outError)                      // OUT: optional
 {
-   AsyncSocket *asock = AsyncSocketInit(addr->ss_family, pollParams, outError);
+   AsyncTCPSocket *asock = AsyncTCPSocketInit(addr->ss_family, pollParams,
+                                              outError);
 
    if (asock != NULL) {
-#ifndef VMX86_TOOLS
-      if (isWebSock) {
-         AsyncSocketInitWebSocket(asock, clientData, webSockUseSSL, protocols, sslCtx);
-      }
-#endif
-
-      if (AsyncSocketBind(asock, addr, addrLen, outError) &&
-          AsyncSocketListen(asock, connectFn, clientData, outError)) {
+      if (AsyncTCPSocketBind(asock, addr, addrLen, outError) &&
+          AsyncTCPSocketListen(asock, connectFn, clientData, outError)) {
          return asock;
       }
    }
@@ -764,14 +891,14 @@ AsyncSocketListenImpl(struct sockaddr_storage *addr,      // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketListenerCreateImpl --
+ * AsyncTCPSocketListenerCreateImpl --
  *
  *      Listens on specified address and/or port for resolved/requested socket
  *      family and accepts new connections. Fires the connect callback with
- *      new AsyncSocket object for each connection.
+ *      new AsyncTCPSocket object for each connection.
  *
  * Results:
- *      New AsyncSocket in listening state or NULL on error.
+ *      New AsyncTCPSocket in listening state or NULL on error.
  *
  * Side effects:
  *      Creates new socket, binds and listens.
@@ -779,37 +906,34 @@ AsyncSocketListenImpl(struct sockaddr_storage *addr,      // IN
  *----------------------------------------------------------------------------
  */
 
-AsyncSocket *
-AsyncSocketListenerCreateImpl(const char *addrStr,                // IN: optional
-                              unsigned int port,                  // IN: optional
-                              int socketFamily,                   // IN
-                              AsyncSocketConnectFn connectFn,     // IN
-                              void *clientData,                   // IN
-                              AsyncSocketPollParams *pollParams,  // IN
-                              Bool isWebSock,                     // IN
-                              Bool webSockUseSSL,                 // IN
-                              const char *protocols[],            // IN: optional
-                              void *sslCtx,                       // IN: optional
-                              int *outError)                      // OUT: optional
+static AsyncTCPSocket *
+AsyncTCPSocketListenerCreateImpl(
+   const char *addrStr,                // IN: optional
+   unsigned int port,                  // IN: optional
+   int socketFamily,                   // IN
+   AsyncSocketConnectFn connectFn,     // IN
+   void *clientData,                   // IN
+   AsyncSocketPollParams *pollParams,  // IN
+   int *outError)                      // OUT: optional
 {
-   AsyncSocket *asock = NULL;
+   AsyncTCPSocket *asock = NULL;
    struct sockaddr_storage addr;
    socklen_t addrLen;
    char *ipString = NULL;
-   int getaddrinfoError = AsyncSocketResolveAddr(addrStr, port, socketFamily,
-                                                 TRUE, &addr, &addrLen,
-                                                 &ipString);
+   int getaddrinfoError = AsyncTCPSocketResolveAddr(addrStr, port, socketFamily,
+                                                    TRUE, &addr, &addrLen,
+                                                    &ipString);
 
    if (getaddrinfoError == 0) {
-      asock = AsyncSocketListenImpl(&addr, addrLen, connectFn, clientData,
-                                    pollParams, isWebSock, webSockUseSSL,
-                                    protocols, sslCtx, outError);
+      asock = AsyncTCPSocketListenImpl(&addr, addrLen, connectFn, clientData,
+                                       pollParams,
+                                       outError);
 
       if (asock) {
-         ASOCKLG0(asock,
+         TCPSOCKLG0(asock,
                   ("Created new %s %s listener for (%s)\n",
                    addr.ss_family == AF_INET ? "IPv4" : "IPv6",
-                   isWebSock ? "web socket" : "socket", ipString));
+                   "socket", ipString));
       } else {
          Log(ASOCKPREFIX "Could not create %s listener socket, error %d: %s\n",
              addr.ss_family == AF_INET ? "IPv4" : "IPv6", *outError,
@@ -819,7 +943,7 @@ AsyncSocketListenerCreateImpl(const char *addrStr,                // IN: optiona
    } else {
       Log(ASOCKPREFIX "Could not resolve listener socket address.\n");
       if (outError) {
-         *outError = ASOCKERR_LISTEN;
+         *outError = ASOCKERR_ADDRUNRESV;
       }
    }
 
@@ -830,11 +954,11 @@ AsyncSocketListenerCreateImpl(const char *addrStr,                // IN: optiona
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketListenerCreate --
+ * AsyncSocket_Listen --
  *
  *      Listens on specified address and/or port for all resolved socket
  *      families and accepts new connections. Fires the connect callback with
- *      new AsyncSocket object for each connection.
+ *      new AsyncTCPSocket object for each connection.
  *
  *      If address string is present and that string is not the "localhost"
  *      loopback, then we will listen on resolved address only.
@@ -857,7 +981,7 @@ AsyncSocketListenerCreateImpl(const char *addrStr,                // IN: optiona
  *      If address string is NULL, port cannot be 0.
  *
  * Results:
- *      New AsyncSocket in listening state or NULL on error.
+ *      New AsyncTCPSocket in listening state or NULL on error.
  *
  * Side effects:
  *      Creates new socket/s, binds and listens.
@@ -866,37 +990,37 @@ AsyncSocketListenerCreateImpl(const char *addrStr,                // IN: optiona
  */
 
 AsyncSocket *
-AsyncSocketListenerCreate(const char *addrStr,                // IN: optional
-                          unsigned int port,                  // IN: optional
-                          AsyncSocketConnectFn connectFn,     // IN
-                          void *clientData,                   // IN
-                          AsyncSocketPollParams *pollParams,  // IN
-                          Bool isWebSock,                     // IN
-                          Bool webSockUseSSL,                 // IN
-                          const char *protocols[],            // IN: optional
-                          void *sslCtx,                       // IN: optional
-                          int *outError)                      // OUT: optional
+AsyncSocket_Listen(const char *addrStr,                // IN: optional
+                   unsigned int port,                  // IN: optional
+                   AsyncSocketConnectFn connectFn,     // IN
+                   void *clientData,                   // IN
+                   AsyncSocketPollParams *pollParams,  // IN
+                   int *outError)                      // OUT: optional
 {
    if (addrStr != NULL && *addrStr != '\0' &&
        Str_Strcmp(addrStr, "localhost")) {
-      return AsyncSocketListenerCreateImpl(addrStr, port, AF_UNSPEC, connectFn,
-                                           clientData, pollParams, FALSE,
-                                           FALSE, protocols, sslCtx, outError);
+      AsyncTCPSocket *asock;
+
+      asock = AsyncTCPSocketListenerCreateImpl(addrStr, port, AF_UNSPEC,
+                                               connectFn,
+                                               clientData, pollParams,
+                                               outError);
+      return BaseSocket(asock);
    } else {
       Bool localhost = addrStr != NULL && !Str_Strcmp(addrStr, "localhost");
       unsigned int tempPort = port;
-      AsyncSocket *asock6 = NULL;
-      AsyncSocket *asock4 = NULL;
+      AsyncTCPSocket *asock6 = NULL;
+      AsyncTCPSocket *asock4 = NULL;
       int tempError4;
       int tempError6;
 
-      asock6 = AsyncSocketListenerCreateImpl(addrStr, port, AF_INET6,
-                                             connectFn, clientData, pollParams,
-                                             isWebSock, webSockUseSSL, protocols,
-                                             sslCtx, &tempError6);
+      asock6 = AsyncTCPSocketListenerCreateImpl(addrStr, port, AF_INET6,
+                                                connectFn, clientData,
+                                                pollParams,
+                                                &tempError6);
 
       if (localhost && port == 0) {
-         tempPort = AsyncSocket_GetPort(asock6);
+         tempPort = AsyncSocket_GetPort(BaseSocket(asock6));
          if (tempPort == MAX_UINT32) {
             Log(ASOCKPREFIX
                 "Could not resolve IPv6 listener socket port number.\n");
@@ -904,24 +1028,23 @@ AsyncSocketListenerCreate(const char *addrStr,                // IN: optional
          }
       }
 
-      asock4 = AsyncSocketListenerCreateImpl(addrStr, tempPort, AF_INET,
-                                             connectFn, clientData, pollParams,
-                                             isWebSock, webSockUseSSL,
-                                             protocols, sslCtx, &tempError4);
+      asock4 = AsyncTCPSocketListenerCreateImpl(addrStr, tempPort, AF_INET,
+                                                connectFn, clientData,
+                                                pollParams,
+                                                &tempError4);
 
       if (localhost && port == 0 && tempError4 == ASOCKERR_BINDADDRINUSE) {
          Log(ASOCKPREFIX "Failed to reuse IPv6 localhost port number for IPv4 "
              "listener socket.\n");
-         AsyncSocket_Close(asock6);
+         AsyncSocket_Close(BaseSocket(asock6));
 
          tempError4 = ASOCKERR_SUCCESS;
-         asock4 = AsyncSocketListenerCreateImpl(addrStr, port, AF_INET,
-                                                connectFn, clientData,
-                                                pollParams, isWebSock,
-                                                webSockUseSSL, protocols,
-                                                sslCtx, &tempError4);
+         asock4 = AsyncTCPSocketListenerCreateImpl(addrStr, port, AF_INET,
+                                                   connectFn, clientData,
+                                                   pollParams,
+                                                   &tempError4);
 
-         tempPort = AsyncSocket_GetPort(asock4);
+         tempPort = AsyncSocket_GetPort(BaseSocket(asock4));
          if (tempPort == MAX_UINT32) {
             Log(ASOCKPREFIX
                 "Could not resolve IPv4 listener socket port number.\n");
@@ -929,39 +1052,31 @@ AsyncSocketListenerCreate(const char *addrStr,                // IN: optional
          }
 
          tempError6 = ASOCKERR_SUCCESS;
-         asock6 = AsyncSocketListenerCreateImpl(addrStr, tempPort, AF_INET6,
-                                                connectFn, clientData,
-                                                pollParams, isWebSock,
-                                                webSockUseSSL, protocols,
-                                                sslCtx, &tempError6);
+         asock6 = AsyncTCPSocketListenerCreateImpl(addrStr, tempPort, AF_INET6,
+                                                   connectFn, clientData,
+                                                   pollParams,
+                                                   &tempError6);
 
          if (!asock6 && tempError6 == ASOCKERR_BINDADDRINUSE) {
             Log(ASOCKPREFIX "Failed to reuse IPv4 localhost port number for "
                 "IPv6 listener socket.\n");
-            AsyncSocket_Close(asock4);
+            AsyncSocket_Close(BaseSocket(asock4));
          }
       }
 
       if (asock6 && asock4) {
-         AsyncSocket *asock;
+         AsyncTCPSocket *asock;
 
-         asock = AsyncSocketCreate(NULL);
-         asock->state = AsyncSocketListening;
-         asock->asockType = ASYNCSOCKET_TYPE_SOCKET;
+         asock = AsyncTCPSocketCreate(pollParams);
+         AsyncTCPSocketSetState(asock, AsyncSocketListening);
          asock->listenAsock6 = asock6;
          asock->listenAsock4 = asock4;
 
-         if (asock->pollParams.iPoll == NULL) {
-            asock->vt = &asyncStreamSocketVTable;
-         } else {
-            asock->vt = &asyncStreamSocketIPollVTable;
-         }
-
-         return asock;
+         return BaseSocket(asock);
       } else if (asock6) {
-         return asock6;
+         return BaseSocket(asock6);
       } else if (asock4) {
-         return asock4;
+         return BaseSocket(asock4);
       }
 
       if (outError) {
@@ -983,14 +1098,14 @@ AsyncSocketListenerCreate(const char *addrStr,                // IN: optional
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketListenerCreateLoopback --
+ * AsyncTCPSocketListenerCreateLoopback --
  *
  *      Listens on loopback interface and port for all resolved socket
  *      families and accepts new connections. Fires the connect callback with
- *      new AsyncSocket object for each connection.
+ *      new AsyncTCPSocket object for each connection.
  *
  * Results:
- *      New AsyncSocket in listening state or NULL on error.
+ *      New AsyncTCPSocket in listening state or NULL on error.
  *
  * Side effects:
  *      Creates new socket/s, binds and listens.
@@ -998,17 +1113,15 @@ AsyncSocketListenerCreate(const char *addrStr,                // IN: optional
  *----------------------------------------------------------------------------
  */
 
-static AsyncSocket *
-AsyncSocketListenerCreateLoopback(unsigned int port,                  // IN
-                                  AsyncSocketConnectFn connectFn,     // IN
-                                  void *clientData,                   // IN
-                                  AsyncSocketPollParams *pollParams,  // IN
-                                  Bool isWebSock,                     // IN
-                                  Bool webSockUseSSL,                 // IN
-                                  int *outError)                      // OUT: optional
+AsyncSocket *
+AsyncSocket_ListenLoopback(unsigned int port,                  // IN
+                           AsyncSocketConnectFn connectFn,     // IN
+                           void *clientData,                   // IN
+                           AsyncSocketPollParams *pollParams,  // IN
+                           int *outError)                      // OUT: optional
 {
-   AsyncSocket *asock6 = NULL;
-   AsyncSocket *asock4 = NULL;
+   AsyncTCPSocket *asock6 = NULL;
+   AsyncTCPSocket *asock4 = NULL;
    int tempError4;
    int tempError6;
 
@@ -1017,36 +1130,27 @@ AsyncSocketListenerCreateLoopback(unsigned int port,                  // IN
     * not work for IPv6 on old Linux versions like 2.6.18. So,
     * using IP address for both the cases to be consistent.
     */
-   asock6 = AsyncSocketListenerCreateImpl("::1", port, AF_INET6,
-                                          connectFn, clientData, pollParams,
-                                          isWebSock, webSockUseSSL,
-                                          NULL, NULL, &tempError6);
+   asock6 = AsyncTCPSocketListenerCreateImpl("::1", port, AF_INET6,
+                                             connectFn, clientData, pollParams,
+                                             &tempError6);
 
-   asock4 = AsyncSocketListenerCreateImpl("127.0.0.1", port, AF_INET,
-                                          connectFn, clientData, pollParams,
-                                          isWebSock, webSockUseSSL,
-                                          NULL, NULL, &tempError4);
+   asock4 = AsyncTCPSocketListenerCreateImpl("127.0.0.1", port, AF_INET,
+                                             connectFn, clientData, pollParams,
+                                             &tempError4);
 
    if (asock6 && asock4) {
-      AsyncSocket *asock;
+      AsyncTCPSocket *asock;
 
-      asock = AsyncSocketCreate(NULL);
-      asock->state = AsyncSocketListening;
-      asock->asockType = ASYNCSOCKET_TYPE_SOCKET;
+      asock = AsyncTCPSocketCreate(pollParams);
+      AsyncTCPSocketSetState(asock, AsyncSocketListening);
       asock->listenAsock6 = asock6;
       asock->listenAsock4 = asock4;
 
-      if (asock->pollParams.iPoll == NULL) {
-         asock->vt = &asyncStreamSocketVTable;
-      } else {
-         asock->vt = &asyncStreamSocketIPollVTable;
-      }
-
-      return asock;
+      return BaseSocket(asock);
    } else if (asock6) {
-      return asock6;
+      return BaseSocket(asock6);
    } else if (asock4) {
-      return asock4;
+      return BaseSocket(asock4);
    }
 
    if (outError) {
@@ -1067,95 +1171,13 @@ AsyncSocketListenerCreateLoopback(unsigned int port,                  // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_Listen --
- *
- *      Listens on specified address and/or port for all resolved socket
- *      families and accepts new connections. Fires the connect callback with
- *      new AsyncSocket object for each connection.
- *
- *      If address string is present and that string is not the "localhost"
- *      loopback, then we will listen on resolved address only.
- *
- *      If address string is NULL or is "localhost" we will listen on all
- *      address families that will resolve on the host.
- *
- *      If port requested is 0, we will let the system assign the first
- *      available port.
- *
- *      If address string is NULL and port requested is not 0, we will listen
- *      on any address for all resolved protocols for the port requested.
- *
- *      If address string is "localhost" and port is 0, we will use the first
- *      port we are given if the host supports multiple address families.
- *      If by chance we try to bind on a port that is available for one
- *      protocol and not the other, we will attempt a second time with the
- *      order of address families reversed.
- *
- *      If address string is NULL, port cannot be 0.
- *
- * Results:
- *      New AsyncSocket in listening state or NULL on error.
- *
- * Side effects:
- *      Creates new socket/s, binds and listens.
- *
- *----------------------------------------------------------------------------
- */
-
-AsyncSocket *
-AsyncSocket_Listen(const char *addrStr,                // IN: optional
-                   unsigned int port,                  // IN: optional
-                   AsyncSocketConnectFn connectFn,     // IN
-                   void *clientData,                   // IN
-                   AsyncSocketPollParams *pollParams,  // IN
-                   int *outError)                      // OUT: optional
-{
-   return AsyncSocketListenerCreate(addrStr, port, connectFn, clientData,
-                                    pollParams, FALSE, FALSE, NULL, NULL,
-                                    outError);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocket_ListenLoopback --
- *
- *      Listens on loopback interface and port for all resolved socket
- *      families and accepts new connections. Fires the connect callback with
- *      new AsyncSocket object for each connection.
- *
- * Results:
- *      New AsyncSocket in listening state or NULL on error.
- *
- * Side effects:
- *      Creates new socket/s, binds and listens.
- *
- *----------------------------------------------------------------------------
- */
-
-AsyncSocket *
-AsyncSocket_ListenLoopback(unsigned int port,                  // IN
-                           AsyncSocketConnectFn connectFn,     // IN
-                           void *clientData,                   // IN
-                           AsyncSocketPollParams *pollParams,  // IN
-                           int *outError)                      // OUT: optional
-{
-   return AsyncSocketListenerCreateLoopback(port, connectFn, clientData,
-                                            pollParams, FALSE, FALSE, outError);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocket_ListenVMCI --
+ * AsyncTCPSocket_ListenVMCI --
  *
  *      Listens on the specified port and accepts new connections. Fires the
- *      connect callback with new AsyncSocket object for each connection.
+ *      connect callback with new AsyncTCPSocket object for each connection.
  *
  * Results:
- *      New AsyncSocket in listening state or NULL on error.
+ *      New AsyncTCPSocket in listening state or NULL on error.
  *
  * Side effects:
  *      Creates new socket, binds and listens.
@@ -1172,7 +1194,7 @@ AsyncSocket_ListenVMCI(unsigned int cid,                  // IN
                        int *outError)                     // OUT
 {
    struct sockaddr_vm addr;
-   AsyncSocket *asock;
+   AsyncTCPSocket *asock;
    int vsockDev = -1;
 
    memset(&addr, 0, sizeof addr);
@@ -1180,24 +1202,25 @@ AsyncSocket_ListenVMCI(unsigned int cid,                  // IN
    addr.svm_cid = cid;
    addr.svm_port = port;
 
-   asock = AsyncSocketListenImpl((struct sockaddr_storage *)&addr, sizeof addr,
-                                 connectFn, clientData, pollParams, FALSE,
-                                 FALSE, NULL, NULL, outError);
+   asock = AsyncTCPSocketListenImpl((struct sockaddr_storage *)&addr,
+                                    sizeof addr,
+                                    connectFn, clientData, pollParams,
+                                    outError);
 
    VMCISock_ReleaseAFValueFd(vsockDev);
-   return asock;
+   return BaseSocket(asock);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketInit --
+ * AsyncTCPSocketInit --
  *
  *      This is an internal routine that sets up a SOCK_STREAM (TCP) socket.
  *
  * Results:
- *      New AsyncSocket or NULL on error.
+ *      New AsyncTCPSocket or NULL on error.
  *
  * Side effects:
  *      Creates new socket.
@@ -1205,12 +1228,12 @@ AsyncSocket_ListenVMCI(unsigned int cid,                  // IN
  *----------------------------------------------------------------------------
  */
 
-AsyncSocket *
-AsyncSocketInit(int socketFamily,                  // IN
-                AsyncSocketPollParams *pollParams, // IN
-                int *outError)                     // OUT
+static AsyncTCPSocket *
+AsyncTCPSocketInit(int socketFamily,                  // IN
+                   AsyncSocketPollParams *pollParams, // IN
+                   int *outError)                     // OUT
 {
-   AsyncSocket *asock = NULL;
+   AsyncTCPSocket *asock = NULL;
    int error = ASOCKERR_GENERIC;
    int sysErr;
    int fd;
@@ -1230,7 +1253,7 @@ AsyncSocketInit(int socketFamily,                  // IN
     * Wrap it with an asock object
     */
 
-   if ((asock = AsyncSocket_AttachToFd(fd, pollParams, &error)) == NULL) {
+   if ((asock = AsyncTCPSocketAttachToFd(fd, pollParams, &error)) == NULL) {
       goto error;
    }
 
@@ -1251,7 +1274,7 @@ errorNoFd:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetPortFromAddr --
+ * AsyncTCPSocketGetPortFromAddr --
  *
  *      This is an internal routine that gets a port given an address.  The
  *      address must be in either AF_INET, AF_INET6 or AF_VMCI format.
@@ -1266,7 +1289,7 @@ errorNoFd:
  */
 
 static unsigned int
-AsyncSocketGetPortFromAddr(struct sockaddr_storage *addr)
+AsyncTCPSocketGetPortFromAddr(struct sockaddr_storage *addr)         // IN
 {
    ASSERT(NULL != addr);
 
@@ -1294,9 +1317,9 @@ AsyncSocketGetPortFromAddr(struct sockaddr_storage *addr)
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetPort --
+ * AsyncTCPSocketGetPort --
  *
- *      Given an AsyncSocket object, returns the port number associated with
+ *      Given an AsyncTCPSocket object, returns the port number associated with
  *      the requested address family's file descriptor if available.
  *
  * Results:
@@ -1308,10 +1331,11 @@ AsyncSocketGetPortFromAddr(struct sockaddr_storage *addr)
  *----------------------------------------------------------------------------
  */
 
-unsigned int
-AsyncSocketGetPort(AsyncSocket *asock)  // IN
+static unsigned int
+AsyncTCPSocketGetPort(AsyncSocket *base)  // IN
 {
-   AsyncSocket *tempAsock;
+   AsyncTCPSocket *asock = TCPSocket(base);
+   AsyncTCPSocket *tempAsock;
    struct sockaddr_storage addr;
    socklen_t addrLen = sizeof addr;
    unsigned int ret = MAX_UINT32;
@@ -1326,14 +1350,16 @@ AsyncSocketGetPort(AsyncSocket *asock)  // IN
       return ret;
    }
 
-   AsyncSocketLock(tempAsock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketIsLocked(tempAsock));
 
-   if (AsyncSocketGetAddr(tempAsock, AF_UNSPEC, &addr, &addrLen) ==
+   if (AsyncTCPSocketGetAddr(tempAsock, AF_UNSPEC, &addr, &addrLen) ==
        ASOCKERR_SUCCESS) {
-      ret = AsyncSocketGetPortFromAddr(&addr);
+      return AsyncTCPSocketGetPortFromAddr(&addr);
+   } else {
+      return MAX_UINT32;
    }
 
-   AsyncSocketUnlock(tempAsock);
 
    return ret;
 }
@@ -1342,7 +1368,7 @@ AsyncSocketGetPort(AsyncSocket *asock)  // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketOSVersionSupportsV4Mapped --
+ * AsyncTCPSocketOSVersionSupportsV4Mapped --
  *
  *      Determine if runtime environment supports IPv4-mapped IPv6 addressed
  *      and all the functionality needed to deal with this scenario.
@@ -1357,7 +1383,7 @@ AsyncSocketGetPort(AsyncSocket *asock)  // IN
  */
 
 static Bool
-AsyncSocketOSVersionSupportsV4Mapped()
+AsyncTCPSocketOSVersionSupportsV4Mapped(void)
 {
 #if defined(_WIN32) && !defined(VM_WIN_UWP)
    OSVERSIONINFOW osvi = {sizeof(OSVERSIONINFOW)};
@@ -1381,7 +1407,7 @@ AsyncSocketOSVersionSupportsV4Mapped()
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketBind --
+ * AsyncTCPSocketBind --
  *
  *      This is an internal routine that binds a socket to a port.
  *
@@ -1394,11 +1420,11 @@ AsyncSocketOSVersionSupportsV4Mapped()
  *----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketBind(AsyncSocket *asock,             // IN
-                struct sockaddr_storage *addr,  // IN
-                socklen_t addrLen,              // IN
-                int *outError)                  // OUT
+static Bool
+AsyncTCPSocketBind(AsyncTCPSocket *asock,          // IN
+                   struct sockaddr_storage *addr,  // IN
+                   socklen_t addrLen,              // IN
+                   int *outError)                  // OUT
 {
    int error = ASOCKERR_BIND;
    int sysErr;
@@ -1408,8 +1434,8 @@ AsyncSocketBind(AsyncSocket *asock,             // IN
    ASSERT(NULL != asock->sslSock);
    ASSERT(NULL != addr);
 
-   port = AsyncSocketGetPortFromAddr(addr);
-   ASOCKLG0(asock, ("creating new listening socket on port %d\n", port));
+   port = AsyncTCPSocketGetPortFromAddr(addr);
+   TCPSOCKLG0(asock, ("creating new listening socket on port %d\n", port));
 
 #ifndef _WIN32
    /*
@@ -1460,11 +1486,11 @@ AsyncSocketBind(AsyncSocket *asock,             // IN
     * systems that have IPV6_V6ONLY define. There is no good solution for the
     * case where we cannot enable IPV6_V6ONLY, if we error in this case and do
     * not have a IPv4 option then we render the application useless.
-    * See AsyncSocketAcceptInternal for the IN6_IS_ADDR_V4MAPPED validation
+    * See AsyncTCPSocketAcceptInternal for the IN6_IS_ADDR_V4MAPPED validation
     * for incomming addresses to close this loophole.
     */
 
-   if (addr->ss_family == AF_INET6 && AsyncSocketOSVersionSupportsV4Mapped()) {
+   if (addr->ss_family == AF_INET6 && AsyncTCPSocketOSVersionSupportsV4Mapped()) {
       int on = 1;
 
       if (setsockopt(asock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
@@ -1507,7 +1533,7 @@ error:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketListen --
+ * AsyncTCPSocketListen --
  *
  *      This is an internal routine that calls listen() on a socket.
  *
@@ -1520,11 +1546,11 @@ error:
  *----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketListen(AsyncSocket *asock,                // IN
-                  AsyncSocketConnectFn connectFn,    // IN
-                  void *clientData,                  // IN
-                  int *outError)                     // OUT
+static Bool
+AsyncTCPSocketListen(AsyncTCPSocket *asock,             // IN
+                     AsyncSocketConnectFn connectFn,    // IN
+                     void *clientData,                  // IN
+                     int *outError)                     // OUT
 {
    VMwareStatus pollStatus;
    int error;
@@ -1555,22 +1581,23 @@ AsyncSocketListen(AsyncSocket *asock,                // IN
     * is ready for accept.
     */
 
-   AsyncSocketLock(asock);
-   pollStatus = AsyncSocketPollAdd(asock, TRUE,
+   AsyncTCPSocketLock(asock);
+   pollStatus = AsyncTCPSocketPollAdd(asock, TRUE,
                                    POLL_FLAG_READ | POLL_FLAG_PERIODIC,
-                                   AsyncSocketAcceptCallback);
+                                   AsyncTCPSocketAcceptCallback);
 
    if (pollStatus != VMWARE_STATUS_SUCCESS) {
-      ASOCKWARN(asock, ("could not register accept callback!\n"));
+      TCPSOCKWARN(asock,
+                ("could not register accept callback!\n"));
       error = ASOCKERR_POLL;
-      AsyncSocketUnlock(asock);
+      AsyncTCPSocketUnlock(asock);
       goto error;
    }
-   asock->state = AsyncSocketListening;
+   AsyncTCPSocketSetState(asock, AsyncSocketListening);
 
    asock->connectFn = connectFn;
    asock->clientData = clientData;
-   AsyncSocketUnlock(asock);
+   AsyncTCPSocketUnlock(asock);
 
    return TRUE;
 
@@ -1589,36 +1616,36 @@ error:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketConnectImpl --
+ * AsyncTCPSocketConnectImpl --
  *
- *      AsyncSocket AF_INET/AF_INET6 connect.
+ *      AsyncTCPSocket AF_INET/AF_INET6 connect.
  *
  *      NOTE: This function can block.
  *
  * Results:
- *      AsyncSocket * on success and NULL on failure.
+ *      AsyncTCPSocket * on success and NULL on failure.
  *      On failure, error is returned in *outError.
  *
  * Side effects:
- *      Allocates an AsyncSocket, registers a poll callback.
+ *      Allocates an AsyncTCPSocket, registers a poll callback.
  *
  *----------------------------------------------------------------------------
  */
 
-static AsyncSocket *
-AsyncSocketConnectImpl(int socketFamily,
-                       const char *hostname,
-                       unsigned int port,
-                       AsyncSocketConnectFn connectFn,
-                       void *clientData,
-                       AsyncSocketConnectFlags flags,
-                       AsyncSocketPollParams *pollParams,
-                       int *outError)
+static AsyncTCPSocket *
+AsyncTCPSocketConnectImpl(int socketFamily,                  // IN
+                          const char *hostname,              // IN
+                          unsigned int port,                 // IN
+                          AsyncSocketConnectFn connectFn,    // IN
+                          void *clientData,                  // IN
+                          AsyncSocketConnectFlags flags,     // IN
+                          AsyncSocketPollParams *pollParams, // IN
+                          int *outError)                     // OUT: optional
 {
    struct sockaddr_storage addr;
    int getaddrinfoError;
    int error;
-   AsyncSocket *asock;
+   AsyncTCPSocket *asock;
    char *ipString = NULL;
    socklen_t addrLen;
 
@@ -1626,12 +1653,13 @@ AsyncSocketConnectImpl(int socketFamily,
     * Resolve the hostname.  Handles dotted decimal strings, too.
     */
 
-   getaddrinfoError = AsyncSocketResolveAddr(hostname, port, socketFamily,
-                                             FALSE, &addr, &addrLen, &ipString);
+   getaddrinfoError = AsyncTCPSocketResolveAddr(hostname, port, socketFamily,
+                                                FALSE, &addr, &addrLen,
+                                                &ipString);
    if (0 != getaddrinfoError) {
       Log(ASOCKPREFIX "Failed to resolve %s address '%s' and port %u\n",
           socketFamily == AF_INET ? "IPv4" : "IPv6", hostname, port);
-      error = ASOCKERR_CONNECT;
+      error = ASOCKERR_ADDRUNRESV;
       goto error;
    }
 
@@ -1639,12 +1667,12 @@ AsyncSocketConnectImpl(int socketFamily,
        socketFamily == AF_INET ? "IPv4" : "IPv6", ipString, hostname);
    free(ipString);
 
-   asock = AsyncSocketConnect(&addr, addrLen, connectFn, clientData,
-                              flags, pollParams, &error);
+   asock = AsyncTCPSocketConnect(&addr, addrLen, connectFn, clientData,
+                                 flags, pollParams, &error);
    if (!asock) {
-      Warning(ASOCKPREFIX "%s connection attempt failed\n",
-              socketFamily == AF_INET ? "IPv4" : "IPv6");
-      error = ASOCKERR_CONNECT;
+      Warning(ASOCKPREFIX "%s connection attempt failed: %s\n",
+              socketFamily == AF_INET ? "IPv4" : "IPv6",
+              AsyncSocket_MsgError(error));
       goto error;
    }
 
@@ -1662,34 +1690,34 @@ error:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_Connect --
+ * AsyncTCPSocket_Connect --
  *
- *      AsyncSocket connect. Connection is attempted with AF_INET socket
+ *      AsyncTCPSocket connect. Connection is attempted with AF_INET socket
  *      family, when that fails AF_INET6 is attempted.
  *
  *      NOTE: This function can block.
  *
  * Results:
- *      AsyncSocket * on success and NULL on failure.
+ *      AsyncTCPSocket * on success and NULL on failure.
  *      On failure, error is returned in *outError.
  *
  * Side effects:
- *      Allocates an AsyncSocket, registers a poll callback.
+ *      Allocates an AsyncTCPSocket, registers a poll callback.
  *
  *----------------------------------------------------------------------------
  */
 
 AsyncSocket *
-AsyncSocket_Connect(const char *hostname,
-                    unsigned int port,
-                    AsyncSocketConnectFn connectFn,
-                    void *clientData,
-                    AsyncSocketConnectFlags flags,
-                    AsyncSocketPollParams *pollParams,
-                    int *outError)
+AsyncSocket_Connect(const char *hostname,                // IN
+                    unsigned int port,                   // IN
+                    AsyncSocketConnectFn connectFn,      // IN
+                    void *clientData,                    // IN
+                    AsyncSocketConnectFlags flags,       // IN
+                    AsyncSocketPollParams *pollParams,   // IN
+                    int *outError)                       // OUT: optional
 {
    int error = ASOCKERR_CONNECT;
-   AsyncSocket *asock = NULL;
+   AsyncTCPSocket *asock = NULL;
 
    if (!connectFn || !hostname) {
       error = ASOCKERR_INVAL;
@@ -1697,10 +1725,10 @@ AsyncSocket_Connect(const char *hostname,
       goto error;
    }
 
-   asock = AsyncSocketConnectImpl(AF_INET, hostname, port, connectFn,
+   asock = AsyncTCPSocketConnectImpl(AF_INET, hostname, port, connectFn,
                                   clientData, flags, pollParams, &error);
    if (!asock) {
-      asock = AsyncSocketConnectImpl(AF_INET6, hostname, port, connectFn,
+      asock = AsyncTCPSocketConnectImpl(AF_INET6, hostname, port, connectFn,
                                      clientData, flags, pollParams, &error);
    }
 
@@ -1709,16 +1737,16 @@ error:
       *outError = error;
    }
 
-   return asock;
+   return BaseSocket(asock);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_ConnectVMCI --
+ * AsyncTCPSocket_ConnectVMCI --
  *
- *      AsyncSocket AF_VMCI constructor. Connects to the specified cid:port,
+ *      AsyncTCPSocket AF_VMCI constructor. Connects to the specified cid:port,
  *      and passes the caller a valid asock via the callback once the
  *      connection has been established.
  *
@@ -1726,7 +1754,7 @@ error:
  *      ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
  *
  * Side effects:
- *      Allocates an AsyncSocket, registers a poll callback.
+ *      Allocates an AsyncTCPSocket, registers a poll callback.
  *
  *----------------------------------------------------------------------------
  */
@@ -1738,11 +1766,11 @@ AsyncSocket_ConnectVMCI(unsigned int cid,                  // IN
                         void *clientData,                  // IN
                         AsyncSocketConnectFlags flags,     // IN
                         AsyncSocketPollParams *pollParams, // IN
-                        int *outError)                     // OUT
+                        int *outError)                     // OUT: optional
 {
    int vsockDev = -1;
    struct sockaddr_vm addr;
-   AsyncSocket *asock;
+   AsyncTCPSocket *asock;
 
    memset(&addr, 0, sizeof addr);
    addr.svm_family = VMCISock_GetAFValueFd(&vsockDev);
@@ -1751,12 +1779,12 @@ AsyncSocket_ConnectVMCI(unsigned int cid,                  // IN
 
    Log(ASOCKPREFIX "creating new socket, connecting to %u:%u\n", cid, port);
 
-   asock = AsyncSocketConnect((struct sockaddr_storage *)&addr,
-                              sizeof addr, connectFn, clientData,
-                              flags, pollParams, outError);
+   asock = AsyncTCPSocketConnect((struct sockaddr_storage *)&addr,
+                                 sizeof addr, connectFn, clientData,
+                                 flags, pollParams, outError);
 
    VMCISock_ReleaseAFValueFd(vsockDev);
-   return asock;
+   return BaseSocket(asock);
 }
 
 
@@ -1766,7 +1794,7 @@ AsyncSocket_ConnectVMCI(unsigned int cid,                  // IN
  *
  * AsyncSocket_ConnectUnixDomain --
  *
- *      AsyncSocket AF_UNIX constructor. Connects to the specified unix socket,
+ *      AsyncTCPSocket AF_UNIX constructor. Connects to the specified unix socket,
  *      and passes the caller a valid asock via the callback once the
  *      connection has been established.
  *
@@ -1774,7 +1802,7 @@ AsyncSocket_ConnectVMCI(unsigned int cid,                  // IN
  *      ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
  *
  * Side effects:
- *      Allocates an AsyncSocket, registers a poll callback.
+ *      Allocates an AsyncTCPSocket, registers a poll callback.
  *
  *----------------------------------------------------------------------------
  */
@@ -1788,7 +1816,7 @@ AsyncSocket_ConnectUnixDomain(const char *path,                  // IN
                               int *outError)                     // OUT
 {
    struct sockaddr_un addr;
-   AsyncSocket *asock;
+   AsyncTCPSocket *asock;
 
    memset(&addr, 0, sizeof addr);
    addr.sun_family = AF_UNIX;
@@ -1801,11 +1829,11 @@ AsyncSocket_ConnectUnixDomain(const char *path,                  // IN
 
    Log(ASOCKPREFIX "creating new socket, connecting to %s\n", path);
 
-   asock = AsyncSocketConnect((struct sockaddr_storage *)&addr,
+   asock = AsyncTCPSocketConnect((struct sockaddr_storage *)&addr,
                               sizeof addr, connectFn, clientData,
                               flags, pollParams, outError);
 
-   return asock;
+   return BaseSocket(asock);
 }
 #endif
 
@@ -1813,7 +1841,7 @@ AsyncSocket_ConnectUnixDomain(const char *path,                  // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketConnectErrorCheck --
+ * AsyncTCPSocketConnectErrorCheck --
  *
  *      Check for error on a connecting socket and fire the connect callback
  *      is any error is found.  This is only used on Windows.
@@ -1828,15 +1856,15 @@ AsyncSocket_ConnectUnixDomain(const char *path,                  // IN
  */
 
 static void
-AsyncSocketConnectErrorCheck(void *data)  // IN: AsyncSocket *
+AsyncTCPSocketConnectErrorCheck(void *data)  // IN: AsyncTCPSocket *
 {
-   AsyncSocket *asock = data;
+   AsyncTCPSocket *asock = data;
    Bool removed;
    PollerFunction func = NULL;
 
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   if (asock->state == AsyncSocketConnecting) {
+   if (AsyncTCPSocketGetState(asock) == AsyncSocketConnecting) {
       int sockErr = 0;
       int sockErrLen = sizeof sockErr;
 
@@ -1850,18 +1878,18 @@ AsyncSocketConnectErrorCheck(void *data)  // IN: AsyncSocket *
       } else {
          asock->genericErrno = ASOCK_LASTERROR();
       }
-      ASOCKLG0(asock, ("Connection failed: %s\n",
+      TCPSOCKLG0(asock, ("Connection failed: %s\n",
                        Err_Errno2String(asock->genericErrno)));
       /* Remove connect callback. */
-      removed = AsyncSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
+      removed = AsyncTCPSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
                                       asock->internalConnectFn);
       ASSERT(removed);
       func = asock->internalConnectFn;
    }
 
    /* Remove this callback. */
-   removed = AsyncSocketPollRemove(asock, FALSE, POLL_FLAG_PERIODIC,
-                                   AsyncSocketConnectErrorCheck);
+   removed = AsyncTCPSocketPollRemove(asock, FALSE, POLL_FLAG_PERIODIC,
+                                   AsyncTCPSocketConnectErrorCheck);
    ASSERT(removed);
    asock->internalConnectFn = NULL;
 
@@ -1874,31 +1902,31 @@ AsyncSocketConnectErrorCheck(void *data)  // IN: AsyncSocket *
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketConnect --
- * AsyncSocketConnectWithAsock --
+ * AsyncTCPSocketConnect --
  *
- *      Internal AsyncSocket constructor.
+ *      Internal AsyncTCPSocket constructor.
  *
  * Results:
  *      ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
  *
  * Side effects:
- *      Allocates an AsyncSocket, registers a poll callback.
+ *      Allocates an AsyncTCPSocket, registers a poll callback.
  *
  *----------------------------------------------------------------------------
  */
 
-static AsyncSocket *
-AsyncSocketConnect(struct sockaddr_storage *addr,
-                   socklen_t addrLen,
-                   AsyncSocketConnectFn connectFn,
-                   void *clientData,
-                   AsyncSocketConnectFlags flags,
-                   AsyncSocketPollParams *pollParams,
-                   int *outError)
+static AsyncTCPSocket *
+AsyncTCPSocketConnect(struct sockaddr_storage *addr,         // IN
+                      socklen_t addrLen,                     // IN
+                      AsyncSocketConnectFn connectFn,        // IN
+                      void *clientData,                      // IN
+                      AsyncSocketConnectFlags flags,         // IN
+                      AsyncSocketPollParams *pollParams,     // IN
+                      int *outError)                         // OUT
 {
    int fd;
-   AsyncSocket *asock = NULL;
+   VMwareStatus pollStatus;
+   AsyncTCPSocket *asock = NULL;
    int error = ASOCKERR_GENERIC;
    int sysErr;
 
@@ -1925,38 +1953,11 @@ AsyncSocketConnect(struct sockaddr_storage *addr,
     * Wrap it with an asock
     */
 
-   if ((asock = AsyncSocket_AttachToFd(fd, pollParams, &error)) == NULL) {
+   if ((asock = AsyncTCPSocketAttachToFd(fd, pollParams, &error)) == NULL) {
       SSLGeneric_close(fd);
       goto error;
    }
 
-   return AsyncSocketConnectWithAsock(asock, addr, addrLen, connectFn,
-                                      clientData, AsyncSocketConnectCallback,
-                                      pollParams, outError);
-
-error:
-   if (outError) {
-      *outError = error;
-   }
-
-   return NULL;
-}
-
-AsyncSocket *
-AsyncSocketConnectWithAsock(AsyncSocket *asock,
-                            struct sockaddr_storage *addr,
-                            socklen_t addrLen,
-                            AsyncSocketConnectFn connectFn,
-                            void *clientData,
-                            PollerFunction internalConnectFn,
-                            AsyncSocketPollParams *pollParams,
-                            int *outError)
-{
-   VMwareStatus pollStatus;
-   int sysErr;
-   int error = ASOCKERR_GENERIC;
-
-   ASSERT(internalConnectFn != NULL);
 
    /*
     * Call connect(), which can either succeed immediately or return an error
@@ -1968,28 +1969,29 @@ AsyncSocketConnectWithAsock(AsyncSocket *asock,
     * as a one-time (RTime) callback instead.
     */
 
-   AsyncSocketLock(asock);
+   AsyncTCPSocketLock(asock);
    if (connect(asock->fd, (struct sockaddr *)addr, addrLen) != 0) {
       if (ASOCK_LASTERROR() == ASOCK_ECONNECTING) {
          ASSERT(!(vmx86_server && addr->ss_family == AF_UNIX));
-         ASOCKLOG(1, asock, ("registering write callback for socket connect\n"));
-         pollStatus = AsyncSocketPollAdd(asock, TRUE, POLL_FLAG_WRITE,
-                                         internalConnectFn);
+         TCPSOCKLOG(1, asock,
+                    ("registering write callback for socket connect\n"));
+         pollStatus = AsyncTCPSocketPollAdd(asock, TRUE, POLL_FLAG_WRITE,
+                                            AsyncTCPSocketConnectCallback);
          if (vmx86_win32 && pollStatus == VMWARE_STATUS_SUCCESS &&
-             asock->pollParams.iPoll == NULL) {
+             AsyncTCPSocketPollParams(asock)->iPoll == NULL) {
             /*
              * Work around WSAPoll's bug of not reporting failed connection
              * by periodically (500 ms) checking for error.
              */
-            pollStatus = AsyncSocketPollAdd(asock, FALSE, POLL_FLAG_PERIODIC,
-                                            AsyncSocketConnectErrorCheck,
-                                            500 * 1000);
+            pollStatus = AsyncTCPSocketPollAdd(asock, FALSE, POLL_FLAG_PERIODIC,
+                                               AsyncTCPSocketConnectErrorCheck,
+                                               500 * 1000);
             if (pollStatus == VMWARE_STATUS_SUCCESS) {
-               asock->internalConnectFn = internalConnectFn;
+               asock->internalConnectFn = AsyncTCPSocketConnectCallback;
             } else {
-               ASOCKLG0(asock, ("failed to register periodic error check\n"));
-               AsyncSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
-                                     internalConnectFn);
+               TCPSOCKLG0(asock, ("failed to register periodic error check\n"));
+               AsyncTCPSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
+                                        AsyncTCPSocketConnectCallback);
             }
          }
       } else {
@@ -2006,19 +2008,19 @@ AsyncSocketConnectWithAsock(AsyncSocket *asock,
          goto errorHaveAsock;
       }
    } else {
-      ASOCKLOG(2, asock,
+      TCPSOCKLOG(2, asock,
                ("socket connected, registering RTime callback for connect\n"));
-      pollStatus = AsyncSocketPollAdd(asock, FALSE, 0,
-                                      internalConnectFn, 0);
+      pollStatus = AsyncTCPSocketPollAdd(asock, FALSE, 0,
+                                         AsyncTCPSocketConnectCallback, 0);
    }
 
    if (pollStatus != VMWARE_STATUS_SUCCESS) {
-      ASOCKWARN(asock, ("failed to register callback in connect!\n"));
+      TCPSOCKWARN(asock, ("failed to register callback in connect!\n"));
       error = ASOCKERR_POLL;
       goto errorHaveAsock;
    }
 
-   asock->state = AsyncSocketConnecting;
+   AsyncTCPSocketSetState(asock, AsyncSocketConnecting);
    asock->connectFn = connectFn;
    asock->clientData = clientData;
 
@@ -2026,15 +2028,16 @@ AsyncSocketConnectWithAsock(AsyncSocket *asock,
    asock->remoteAddr = *addr;
    asock->remoteAddrLen = addrLen;
 
-   AsyncSocketUnlock(asock);
+   AsyncTCPSocketUnlock(asock);
 
    return asock;
 
 errorHaveAsock:
    SSL_Shutdown(asock->sslSock);
-   AsyncSocketUnlock(asock);
+   AsyncTCPSocketUnlock(asock);
    free(asock);
 
+error:
    if (outError) {
       *outError = error;
    }
@@ -2046,9 +2049,10 @@ errorHaveAsock:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketCreate --
+ * AsyncTCPSocketCreate --
  *
- *      AsyncSocket constructor for fields common to all AsyncSocket types.
+ *      AsyncSocket constructor for fields common to all TCP-based
+ *      AsyncSocket types.
  *
  * Results:
  *      New AsyncSocket object.
@@ -2059,28 +2063,27 @@ errorHaveAsock:
  *----------------------------------------------------------------------------
  */
 
-AsyncSocket *
-AsyncSocketCreate(AsyncSocketPollParams *pollParams) // IN
+static AsyncTCPSocket *
+AsyncTCPSocketCreate(AsyncSocketPollParams *pollParams) // IN
 {
-   AsyncSocket *s;
+   AsyncTCPSocket *s;
 
    s = Util_SafeCalloc(1, sizeof *s);
-   s->id = Atomic_ReadInc32(&nextid);
-   s->state = AsyncSocketConnected;
+
+   AsyncSocketInitSocket(BaseSocket(s), pollParams, &asyncTCPSocketVTable);
+
    s->fd = -1;
-   s->refCount = 1;
    s->inRecvLoop = FALSE;
    s->sendBufFull = FALSE;
    s->sendBufTail = &(s->sendBufList);
    s->passFd.fd = -1;
 
-   if (pollParams) {
-      s->pollParams = *pollParams;
+   if (pollParams && pollParams->iPoll) {
+      s->internalSendFn = AsyncTCPSocketIPollSendCallback;
+      s->internalRecvFn = AsyncTCPSocketIPollRecvCallback;
    } else {
-      s->pollParams.pollClass = POLL_CS_MAIN;
-      s->pollParams.flags = 0;
-      s->pollParams.lock = NULL;
-      s->pollParams.iPoll = NULL;
+      s->internalSendFn = AsyncTCPSocketSendCallback;
+      s->internalRecvFn = AsyncTCPSocketRecvCallback;
    }
 
    return s;
@@ -2090,13 +2093,13 @@ AsyncSocketCreate(AsyncSocketPollParams *pollParams) // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_AttachToSSLSock --
+ * AsyncTCPSocketAttachToSSLSock --
  *
- *      AsyncSocket constructor. Wraps an existing SSLSock object with an
- *      AsyncSocket and returns the latter.
+ *      AsyncTCPSocket constructor. Wraps an existing SSLSock object with an
+ *      AsyncTCPSocket and returns the latter.
  *
  * Results:
- *      New AsyncSocket object or NULL on error.
+ *      New AsyncTCPSocket object or NULL on error.
  *
  * Side effects:
  *      Allocates memory, makes the underlying fd for the socket non-blocking.
@@ -2104,12 +2107,12 @@ AsyncSocketCreate(AsyncSocketPollParams *pollParams) // IN
  *----------------------------------------------------------------------------
  */
 
-AsyncSocket *
-AsyncSocket_AttachToSSLSock(SSLSock sslSock,
-                            AsyncSocketPollParams *pollParams,
-                            int *outError)
+static AsyncTCPSocket *
+AsyncTCPSocketAttachToSSLSock(SSLSock sslSock,                   // IN
+                              AsyncSocketPollParams *pollParams, // IN
+                              int *outError)                     // OUT
 {
-   AsyncSocket *s;
+   AsyncTCPSocket *s;
    int fd;
    int error;
 
@@ -2117,7 +2120,7 @@ AsyncSocket_AttachToSSLSock(SSLSock sslSock,
 
    fd = SSL_GetFd(sslSock);
 
-   if ((AsyncSocketMakeNonBlocking(fd)) != ASOCKERR_SUCCESS) {
+   if ((AsyncTCPSocketMakeNonBlocking(fd)) != ASOCKERR_SUCCESS) {
       int sysErr = ASOCK_LASTERROR();
       Warning(ASOCKPREFIX "failed to make fd %d non-blocking!: %d, %s\n",
               fd, sysErr, Err_Errno2String(sysErr));
@@ -2125,19 +2128,14 @@ AsyncSocket_AttachToSSLSock(SSLSock sslSock,
       goto error;
    }
 
-   s = AsyncSocketCreate(pollParams);
+   s = AsyncTCPSocketCreate(pollParams);
+   AsyncTCPSocketSetState(s, AsyncSocketConnected);
    s->sslSock = sslSock;
    s->fd = fd;
-   s->asockType = ASYNCSOCKET_TYPE_SOCKET;
-   if (s->pollParams.iPoll == NULL) {
-      s->vt = &asyncStreamSocketVTable;
-   } else {
-      s->vt = &asyncStreamSocketIPollVTable;
-   }
 
    /* From now on socket is ours. */
    SSL_SetCloseOnShutdownFlag(sslSock);
-   ASOCKLOG(1, s, ("new asock id %u attached to fd %d\n", s->id, s->fd));
+   TCPSOCKLOG(1, s, ("new asock id %u attached to fd %d\n", s->base.id, s->fd));
 
    return s;
 
@@ -2153,28 +2151,28 @@ error:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_AttachToFd --
+ * AsyncTCPSocketAttachToFd --
  *
- *      AsyncSocket constructor. Wraps a valid socket fd with an AsyncSocket
- *      object.
+ *      AsyncTCPSocket constructor. Wraps a valid socket fd with an
+ *      AsyncTCPSocket object.
  *
  * Results:
- *      New AsyncSocket or NULL on error.
+ *      New AsyncTCPSocket or NULL on error.
  *
  * Side effects:
- *      If function succeeds, fd is owned by AsyncSocket and should not be
+ *      If function succeeds, fd is owned by AsyncTCPSocket and should not be
  *      used (f.e. closed) anymore.
  *
  *----------------------------------------------------------------------------
  */
 
-AsyncSocket *
-AsyncSocket_AttachToFd(int fd,
-                       AsyncSocketPollParams *pollParams,
-                       int *outError)
+static AsyncTCPSocket *
+AsyncTCPSocketAttachToFd(int fd,                             // IN
+                         AsyncSocketPollParams *pollParams,  // IN
+                         int *outError)                      // OUT
 {
    SSLSock sslSock;
-   AsyncSocket *asock;
+   AsyncTCPSocket *asock;
 
    /*
     * Create a new SSL socket object with the current socket
@@ -2188,7 +2186,7 @@ AsyncSocket_AttachToFd(int fd,
 
       return NULL;
    }
-   asock = AsyncSocket_AttachToSSLSock(sslSock, pollParams, outError);
+   asock = AsyncTCPSocketAttachToSSLSock(sslSock, pollParams, outError);
    if (asock) {
       return asock;
    }
@@ -2201,7 +2199,62 @@ AsyncSocket_AttachToFd(int fd,
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketUseNodelay --
+ * AsyncSocket_AttachToFd --
+ *
+ *      Wrap a pre-existing file descriptor in an AsyncSocket entity.
+ *
+ * Results:
+ *      New AsyncSocket or NULL on error.
+ *
+ * Side effects:
+ *      If function succeeds, fd is owned by AsyncSocket and should not be
+ *      used (f.e. closed) anymore.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+AsyncSocket *
+AsyncSocket_AttachToFd(int fd,                            // IN
+                       AsyncSocketPollParams *pollParams, // IN
+                       int *outError)                     // OUT
+{
+   AsyncTCPSocket *asock;
+   asock = AsyncTCPSocketAttachToFd(fd, pollParams, outError);
+   return BaseSocket(asock);
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncSocket_AttachToSSLSock --
+ *
+ *      Wrap a pre-existing SSLSock in an AsyncSocket entity.
+ *
+ * Results:
+ *      New AsyncSocket or NULL on error.
+ *
+ * Side effects:
+ *      If function succeeds, fd is owned by AsyncSocket and should not be
+ *      used (f.e. closed) anymore.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+AsyncSocket *
+AsyncSocket_AttachToSSLSock(SSLSock sslSock,                   // IN
+                            AsyncSocketPollParams *pollParams, // IN
+                            int *outError)                     // OUT
+{
+   AsyncTCPSocket *asock;
+   asock = AsyncTCPSocketAttachToSSLSock(sslSock, pollParams, outError);
+   return BaseSocket(asock);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * AsyncTCPSocketUseNodelay --
  *
  *      Sets or unset TCP_NODELAY on the socket, which disables or
  *      enables Nagle's algorithm, respectively.
@@ -2216,22 +2269,21 @@ AsyncSocket_AttachToFd(int fd,
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketUseNodelay(AsyncSocket *asock,  // IN/OUT:
-                      Bool nodelay)        // IN:
+static int
+AsyncTCPSocketUseNodelay(AsyncSocket *base,  // IN/OUT:
+                         Bool nodelay)       // IN:
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    int flag = nodelay ? 1 : 0;
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
    if (setsockopt(asock->fd, IPPROTO_TCP, TCP_NODELAY,
                   (const void *) &flag, sizeof(flag)) != 0) {
       asock->genericErrno = Err_Errno();
       LOG(0, (ASOCKPREFIX "could not set TCP_NODELAY, error %d: %s\n",
               Err_Errno(), Err_ErrString()));
-      AsyncSocketUnlock(asock);
       return ASOCKERR_GENERIC;
    } else {
-      AsyncSocketUnlock(asock);
       return ASOCKERR_SUCCESS;
    }
 }
@@ -2240,7 +2292,7 @@ AsyncSocketUseNodelay(AsyncSocket *asock,  // IN/OUT:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketSetTCPTimeouts --
+ * AsyncTCPSocketSetTCPTimeouts --
  *
  *      Allow caller to set a number of TCP-specific timeout
  *      parameters on the socket for the active connection.
@@ -2262,19 +2314,18 @@ AsyncSocketUseNodelay(AsyncSocket *asock,  // IN/OUT:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketSetTCPTimeouts(AsyncSocket *asock,  // IN/OUT:
-                          int keepIdle,        // IN
-                          int keepIntvl,       // IN
-                          int keepCnt)         // IN
+static int
+AsyncTCPSocketSetTCPTimeouts(AsyncSocket *base,  // IN/OUT:
+                             int keepIdle,       // IN
+                             int keepIntvl,      // IN
+                             int keepCnt)        // IN
 {
 #ifdef VMX86_SERVER
+   AsyncTCPSocket *asock = TCPSocket(base);
    int val;
    int opt;
 
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
    val = keepIdle;
    opt = TCP_KEEPIDLE;
@@ -2297,14 +2348,12 @@ AsyncSocketSetTCPTimeouts(AsyncSocket *asock,  // IN/OUT:
       goto error;
    }
 
-   AsyncSocketUnlock(asock);
    return ASOCKERR_SUCCESS;
 
 error:
    asock->genericErrno = Err_Errno();
    LOG(0, (ASOCKPREFIX "could not set TCP Timeout %d, error %d: %s\n",
            opt, Err_Errno(), Err_ErrString()));
-   AsyncSocketUnlock(asock);
 #endif
    return ASOCKERR_GENERIC;
 }
@@ -2313,9 +2362,10 @@ error:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketRecvSocket --
+ * AsyncTCPSocketRegisterRecvCb --
  *
- *      Does the socket specific portion of a AsyncSocket_Recv call.
+ *      Register poll callbacks as required to be notified when data is ready
+ *      following a AsyncTCPSocket_Recv call.
  *
  * Results:
  *      ASOCKERR_*.
@@ -2326,10 +2376,8 @@ error:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketRecvSocket(AsyncSocket *asock, // IN:
-                      void *buf,          // IN: unused
-                      int len)            // IN: unused
+static int
+AsyncTCPSocketRegisterRecvCb(AsyncTCPSocket *asock) // IN:
 {
    int retVal = ASOCKERR_SUCCESS;
 
@@ -2340,23 +2388,23 @@ AsyncSocketRecvSocket(AsyncSocket *asock, // IN:
        * Register the Poll callback
        */
 
-      ASOCKLOG(3, asock, ("installing recv periodic poll callback\n"));
+      TCPSOCKLOG(3, asock, ("installing recv periodic poll callback\n"));
 
-      pollStatus = AsyncSocketPollAdd(asock, TRUE,
+      pollStatus = AsyncTCPSocketPollAdd(asock, TRUE,
                                       POLL_FLAG_READ | POLL_FLAG_PERIODIC,
-                                      asock->vt->recvCallback);
+                                      asock->internalRecvFn);
 
       if (pollStatus != VMWARE_STATUS_SUCCESS) {
-         ASOCKWARN(asock, ("failed to install recv callback!\n"));
+         TCPSOCKWARN(asock, ("failed to install recv callback!\n"));
          retVal = ASOCKERR_POLL;
          goto out;
       }
       asock->recvCb = TRUE;
    }
 
-   if (AsyncSocketHasDataPending(asock) && !asock->inRecvLoop) {
-      ASOCKLOG(0, asock, ("installing recv RTime poll callback\n"));
-      if (AsyncSocketPollAdd(asock, FALSE, 0, asock->vt->recvCallback, 0) !=
+   if (AsyncTCPSocketHasDataPending(asock) && !asock->inRecvLoop) {
+      TCPSOCKLOG(0, asock, ("installing recv RTime poll callback\n"));
+      if (AsyncTCPSocketPollAdd(asock, FALSE, 0, asock->internalRecvFn, 0) !=
           VMWARE_STATUS_SUCCESS) {
          retVal = ASOCKERR_POLL;
          goto out;
@@ -2372,12 +2420,12 @@ out:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_Recv --
+ * AsyncTCPSocket_Recv --
  *
  *      Registers a callback that will fire once the specified amount of data
  *      has been received on the socket.
  *
- *      In the case of AsyncSocket_RecvPartial, the callback is fired
+ *      In the case of AsyncTCPSocket_RecvPartial, the callback is fired
  *      once all or part of the data has been received on the socket.
  *
  *      Data that was not retrieved at the last call of SSL_read() could still
@@ -2386,20 +2434,20 @@ out:
  *      for reading since there might not be any data in the underlying network
  *      socket layer. Hence in the read callback, we keep spinning until all
  *      all the data buffered inside the SSL layer is retrieved before
- *      returning to the poll loop (See AsyncSocketFillRecvBuffer()).
+ *      returning to the poll loop (See AsyncTCPSocketFillRecvBuffer()).
  *
  *      However, we might not have come out of Poll in the first place, e.g.
- *      if this is the first call to AsyncSocket_Recv() after creating a new
+ *      if this is the first call to AsyncTCPSocket_Recv() after creating a new
  *      connection. In this situation, if there is buffered SSL data pending,
  *      we have to schedule an RTTime callback to force retrieval of the data.
- *      This could also happen if the client calls AsyncSocket_RecvBlocking,
+ *      This could also happen if the client calls AsyncTCPSocket_RecvBlocking,
  *      some data is left in the SSL layer, and the client then calls
- *      AsyncSocket_Recv. We use the inRecvLoop variable to detect and handle
+ *      AsyncTCPSocket_Recv. We use the inRecvLoop variable to detect and handle
  *      this condition, i.e., if inRecvLoop is FALSE, we need to schedule the
  *      RTime callback.
  *
  *      TCP usage:
- *      AsyncSocket_Recv(AsyncSocket *asock,
+ *      AsyncTCPSocket_Recv(AsyncTCPSocket *asock,
  *                       void *buf,
  *                       int len,
  *                       AsyncSocketRecvFn recvFn,
@@ -2414,27 +2462,22 @@ out:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketRecv(AsyncSocket *asock,  // IN:
-                void *buf,           // IN: unused
-                int len,             // IN: unused
-                Bool fireOnPartial,  // IN:
-                void *cb,            // IN:
-                void *cbData)        // IN:
+static int
+AsyncTCPSocketRecv(AsyncSocket *base,   // IN:
+                   void *buf,           // IN: unused
+                   int len,             // IN: unused
+                   Bool fireOnPartial,  // IN:
+                   void *cb,            // IN:
+                   void *cbData)        // IN:
 {
-   AsyncSocketRecvFn recvFn = NULL;
-   void *clientData = NULL;
+   AsyncTCPSocket *asock = TCPSocket(base);
    int retVal;
 
-   if (!asock->errorFn) {
-      ASOCKWARN(asock, ("%s: no registered error handler!\n", __FUNCTION__));
-
+   if (!asock->base.errorFn) {
+      TCPSOCKWARN(asock, ("%s: no registered error handler!\n", __FUNCTION__));
       return ASOCKERR_INVAL;
    }
 
-   recvFn = cb;
-   clientData = cbData;
-
    /*
     * XXX We might want to allow passing NULL for the recvFn, to indicate that
     *     the client is no longer interested in reading from the socket. This
@@ -2442,57 +2485,40 @@ AsyncSocketRecv(AsyncSocket *asock,  // IN:
     *     then the client->server half of the connection is closed.
     */
 
-   if (!buf || !recvFn || len <= 0) {
+   if (!buf || !cb || len <= 0) {
       Warning(ASOCKPREFIX "Recv called with invalid arguments!\n");
-
       return ASOCKERR_INVAL;
    }
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   if (asock->state != AsyncSocketConnected) {
-      ASOCKWARN(asock, ("recv called but state is not connected!\n"));
-      retVal = ASOCKERR_NOTCONNECTED;
-      goto outHaveLock;
+   if (AsyncTCPSocketGetState(asock) != AsyncSocketConnected) {
+      TCPSOCKWARN(asock, ("recv called but state is not connected!\n"));
+      return ASOCKERR_NOTCONNECTED;
    }
 
    if (asock->inBlockingRecv) {
-      ASOCKWARN(asock, ("Recv called while a blocking recv is pending.\n"));
-      retVal = ASOCKERR_INVAL;
-      goto outHaveLock;
-   }
-
-   if (asock->recvBuf && asock->recvPos != 0) {
-      ASOCKWARN(asock, ("Recv called -- partially read buffer discarded.\n"));
+      TCPSOCKWARN(asock, ("Recv called while a blocking recv is pending.\n"));
+      return ASOCKERR_INVAL;
    }
 
-   ASSERT(asock->vt);
-   ASSERT(asock->vt->recvInternal);
-   retVal = asock->vt->recvInternal(asock, buf, len);
+   retVal = AsyncTCPSocketRegisterRecvCb(asock);
    if (retVal != ASOCKERR_SUCCESS) {
-      goto outHaveLock;
+      return retVal;
    }
 
-   asock->recvBuf = buf;
-   asock->recvFn = recvFn;
-   asock->recvLen = len;
-   asock->recvFireOnPartial = fireOnPartial;
-   asock->recvPos = 0;
-   asock->clientData = clientData;
-   retVal = ASOCKERR_SUCCESS;
-
-outHaveLock:
-   AsyncSocketUnlock(asock);
-   return retVal;
+   AsyncSocketSetRecvBuf(BaseSocket(asock), buf, len, fireOnPartial,
+                         cb, cbData);
+   return ASOCKERR_SUCCESS;
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketRecvPassedFd --
+ * AsyncTCPSocketRecvPassedFd --
  *
- *      See AsyncSocket_Recv.  Besides that it allows for receiving one
+ *      See AsyncTCPSocket_Recv.  Besides that it allows for receiving one
  *      file descriptor...
  *
  * Results:
@@ -2504,35 +2530,33 @@ outHaveLock:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketRecvPassedFd(AsyncSocket *asock,  // IN/OUT: socket
-                        void *buf,           // OUT: buffer with data
-                        int len,             // IN: length
-                        void *cb,            // IN: completion calback
-                        void *cbData)        // IN: callback's data
+static int
+AsyncTCPSocketRecvPassedFd(AsyncSocket *base,   // IN/OUT: socket
+                           void *buf,           // OUT: buffer with data
+                           int len,             // IN: length
+                           void *cb,            // IN: completion calback
+                           void *cbData)        // IN: callback's data
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    int err;
 
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-
-   if (!asock->errorFn) {
-      ASOCKWARN(asock, ("%s: no registered error handler!\n", __FUNCTION__));
+   if (!asock->base.errorFn) {
+      TCPSOCKWARN(asock, ("%s: no registered error handler!\n", __FUNCTION__));
 
       return ASOCKERR_INVAL;
    }
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
    if (asock->passFd.fd != -1) {
       SSLGeneric_close(asock->passFd.fd);
       asock->passFd.fd = -1;
    }
    asock->passFd.expected = TRUE;
 
-   err = AsyncSocket_Recv(asock, buf, len, cb, cbData);
+   err = AsyncTCPSocketRecv(BaseSocket(asock), buf, len, FALSE, cb, cbData);
    if (err != ASOCKERR_SUCCESS) {
       asock->passFd.expected = FALSE;
    }
-   AsyncSocketUnlock(asock);
 
    return err;
 }
@@ -2541,7 +2565,7 @@ AsyncSocketRecvPassedFd(AsyncSocket *asock,  // IN/OUT: socket
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketPoll --
+ * AsyncTCPSocketPoll --
  *
  *      Blocks on the specified socket until there's data pending or a
  *      timeout occurs.
@@ -2562,10 +2586,10 @@ AsyncSocketRecvPassedFd(AsyncSocket *asock,  // IN/OUT: socket
  */
 
 static int
-AsyncSocketPoll(AsyncSocket *s,          // IN:
-                Bool read,               // IN:
-                int timeoutMS,           // IN:
-                AsyncSocket **outAsock)  // OUT:
+AsyncTCPSocketPoll(AsyncTCPSocket *s,          // IN:
+                   Bool read,                  // IN:
+                   int timeoutMS,              // IN:
+                   AsyncTCPSocket **outAsock)  // OUT:
 {
 #ifndef _WIN32
    struct pollfd p[2];
@@ -2581,17 +2605,15 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
    struct fd_set rwfds;
    struct fd_set exceptfds;
 #endif
-   AsyncSocket *asock[2];
+   AsyncTCPSocket *asock[2];
    int numSock = 0;
    int i;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
    ASSERT(*outAsock == NULL);
 
    if (read && s->fd == -1) {
       if (!s->listenAsock4 && !s->listenAsock6) {
-         ASSERT(FALSE);
-         ASOCKLG0(s, ("%s: Failed to find listener socket.\n", __FUNCTION__));
+         TCPSOCKLG0(s, ("%s: Failed to find listener socket.\n", __FUNCTION__));
          return ASOCKERR_GENERIC;
       }
 
@@ -2619,7 +2641,9 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
          p[i].events = read ? POLLIN : POLLOUT;
       }
 
+      AsyncTCPSocketUnlock(s);
       retval = poll(p, numSock, timeoutMS);
+      AsyncTCPSocketLock(s);
 #else
       tv.tv_sec = timeoutMS / 1000;
       tv.tv_usec = (timeoutMS % 1000) * 1000;
@@ -2632,8 +2656,10 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
          FD_SET(asock[i]->fd, &exceptfds);
       }
 
+      AsyncTCPSocketUnlock(s);
       retval = select(1, read ? &rwfds : NULL, read ? NULL : &rwfds,
                       &exceptfds, timeoutMS >= 0 ? &tv : NULL);
+      AsyncTCPSocketLock(s);
 #endif
 
       switch (retval) {
@@ -2665,7 +2691,7 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
                               (void *) &sockErr, (void *) &sockErrLen) == 0) {
                   if (sockErr) {
                      asock[i]->genericErrno = sockErr;
-                     ASOCKLG0(asock[i],
+                     TCPSOCKLG0(asock[i],
                               ("%s: Socket error lookup returned %d: %s\n",
                                __FUNCTION__, sockErr,
                                Err_Errno2String(sockErr)));
@@ -2673,7 +2699,7 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
                } else {
                   sysErr = ASOCK_LASTERROR();
                   asock[i]->genericErrno = sysErr;
-                  ASOCKLG0(asock[i],
+                  TCPSOCKLG0(asock[i],
                            ("%s: Last socket error %d: %s\n",
                             __FUNCTION__, sysErr, Err_Errno2String(sysErr)));
                }
@@ -2703,15 +2729,15 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
          }
 #endif
 
-         ASOCKWARN(s, ("%s: Failed to return a ready socket.\n",
-                       __FUNCTION__));
+         TCPSOCKWARN(s, ("%s: Failed to return a ready socket.\n",
+                         __FUNCTION__));
          return ASOCKERR_GENERIC;
       }
       case 0:
          /*
           * No sockets were ready within the specified time.
           */
-         ASOCKLG0(s, ("%s: Timeout waiting for a ready socket.\n",
+         TCPSOCKLG0(s, ("%s: Timeout waiting for a ready socket.\n",
                       __FUNCTION__));
          return ASOCKERR_TIMEOUT;
 
@@ -2723,15 +2749,15 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
              * We were somehow interrupted by signal. Let's loop and retry.
              */
 
-            ASOCKLG0(s, ("%s: Socket interrupted by a signal.\n",
+            TCPSOCKLG0(s, ("%s: Socket interrupted by a signal.\n",
                          __FUNCTION__));
             continue;
          }
 
          s->genericErrno = sysErr;
 
-         ASOCKLG0(s, ("%s: Failed with error %d: %s\n", __FUNCTION__, sysErr,
-                      Err_Errno2String(sysErr)));
+         TCPSOCKLG0(s, ("%s: Failed with error %d: %s\n", __FUNCTION__, sysErr,
+                   Err_Errno2String(sysErr)));
          return ASOCKERR_GENERIC;
       }
       default:
@@ -2744,12 +2770,12 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_RecvBlocking --
- * AsyncSocket_RecvPartialBlocking --
- * AsyncSocket_SendBlocking --
+ * AsyncTCPSocketRecvBlocking --
+ * AsyncTCPSocketRecvPartialBlocking --
+ * AsyncTCPSocketSendBlocking --
  *
  *      Implement "blocking + timeout" operations on the socket. These are
- *      simple wrappers around the AsyncSocketBlockingWork function, which
+ *      simple wrappers around the AsyncTCPSocketBlockingWork function, which
  *      operates on the actual non-blocking socket, using poll to determine
  *      when it's ok to keep reading/writing. If we can't finish within the
  *      specified time, we give up and return the ASOCKERR_TIMEOUT error.
@@ -2769,43 +2795,46 @@ AsyncSocketPoll(AsyncSocket *s,          // IN:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocket_RecvBlocking(AsyncSocket *s,
-                         void *buf,
-                         int len,
-                         int *received,
-                         int timeoutMS)
+static int
+AsyncTCPSocketRecvBlocking(AsyncSocket *base,     // IN
+                           void *buf,             // OUT
+                           int len,               // IN
+                           int *received,         // OUT
+                           int timeoutMS)         // IN
 {
-   return AsyncSocketBlockingWork(s, TRUE, buf, len, received, timeoutMS,
-                                  FALSE);
+   AsyncTCPSocket *s = TCPSocket(base);
+   return AsyncTCPSocketBlockingWork(s, TRUE, buf, len, received, timeoutMS,
+                                     FALSE);
 }
 
-int
-AsyncSocket_RecvPartialBlocking(AsyncSocket *s,
-                                void *buf,
-                                int len,
-                                int *received,
-                                int timeoutMS)
+static int
+AsyncTCPSocketRecvPartialBlocking(AsyncSocket *base,     // IN
+                                  void *buf,             // OUT
+                                  int len,               // IN
+                                  int *received,         // OUT
+                                  int timeoutMS)         // IN
 {
-   return AsyncSocketBlockingWork(s, TRUE, buf, len, received, timeoutMS,
-                                  TRUE);
+   AsyncTCPSocket *s = TCPSocket(base);
+   return AsyncTCPSocketBlockingWork(s, TRUE, buf, len, received, timeoutMS,
+                                     TRUE);
 }
 
-int
-AsyncSocket_SendBlocking(AsyncSocket *s,
-                         void *buf,
-                         int len,
-                         int *sent,
-                         int timeoutMS)
+static int
+AsyncTCPSocketSendBlocking(AsyncSocket *base,         // IN
+                           void *buf,                 // OUT
+                           int len,                   // IN
+                           int *sent,                 // OUT
+                           int timeoutMS)             // IN
 {
-   return AsyncSocketBlockingWork(s, FALSE, buf, len, sent, timeoutMS, FALSE);
+   AsyncTCPSocket *s = TCPSocket(base);
+   return AsyncTCPSocketBlockingWork(s, FALSE, buf, len, sent, timeoutMS, FALSE);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketBlockingWork --
+ * AsyncTCPSocketBlockingWork --
  *
  *      Try to complete the specified read/write operation within the
  *      specified time.
@@ -2818,30 +2847,26 @@ AsyncSocket_SendBlocking(AsyncSocket *s,
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketBlockingWork(AsyncSocket *s,  // IN:
-                        Bool read,       // IN:
-                        void *buf,       // IN/OUT:
-                        int len,         // IN:
-                        int *completed,  // OUT:
-                        int timeoutMS,   // IN:
-                        Bool partial)    // IN:
+static int
+AsyncTCPSocketBlockingWork(AsyncTCPSocket *s,  // IN:
+                           Bool read,          // IN:
+                           void *buf,          // IN/OUT:
+                           int len,            // IN:
+                           int *completed,     // OUT:
+                           int timeoutMS,      // IN:
+                           Bool partial)       // IN:
 {
    VmTimeType now, done;
    int sysErr;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_PROXYSOCKET);
-
    if (s == NULL || buf == NULL || len <= 0) {
       Warning(ASOCKPREFIX "Recv called with invalid arguments!\n");
 
       return ASOCKERR_INVAL;
    }
 
-   if (s->state != AsyncSocketConnected) {
-      ASOCKWARN(s, ("recv called but state is not connected!\n"));
-
+   if (AsyncTCPSocketGetState(s) != AsyncSocketConnected) {
+      TCPSOCKWARN(s, ("recv called but state is not connected!\n"));
       return ASOCKERR_NOTCONNECTED;
    }
 
@@ -2852,10 +2877,10 @@ AsyncSocketBlockingWork(AsyncSocket *s,  // IN:
    done = now + timeoutMS;
    do {
       int numBytes, error;
-      AsyncSocket *asock = NULL;
+      AsyncTCPSocket *asock = NULL;
 
-      if ((error = AsyncSocketPoll(s, read, done - now, &asock)) !=
-          ASOCKERR_SUCCESS) {
+      error = AsyncTCPSocketPoll(s, read, done - now, &asock);
+      if (error != ASOCKERR_SUCCESS) {
          return error;
       }
 
@@ -2871,13 +2896,13 @@ AsyncSocketBlockingWork(AsyncSocket *s,  // IN:
          }
          buf = (uint8*)buf + numBytes;
       } else if (numBytes == 0) {
-         ASOCKLG0(s, ("blocking %s detected peer closed connection\n",
-                      read ? "recv" : "send"));
+         TCPSOCKLG0(s, ("blocking %s detected peer closed connection\n",
+                        read ? "recv" : "send"));
          return ASOCKERR_REMOTE_DISCONNECT;
       } else if ((sysErr = ASOCK_LASTERROR()) != ASOCK_EWOULDBLOCK) {
          s->genericErrno = sysErr;
-         ASOCKWARN(s, ("blocking %s error %d: %s\n", read ? "recv" : "send",
-                       sysErr, Err_Errno2String(sysErr)));
+         TCPSOCKWARN(s, ("blocking %s error %d: %s\n", read ? "recv" : "send",
+                         sysErr, Err_Errno2String(sysErr)));
 
          return ASOCKERR_GENERIC;
       }
@@ -2892,83 +2917,7 @@ AsyncSocketBlockingWork(AsyncSocket *s,  // IN:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketSendSocket --
- *
- *      Does the socket specific portion of a AsyncSocket_Send call.
- *
- * Results:
- *      ASOCKERR_*.
- *
- * Side effects:
- *      May register poll callback or perform I/O.
- *
- *----------------------------------------------------------------------------
- */
-
-int
-AsyncSocketSendSocket(AsyncSocket *asock,      // IN:
-                      Bool bufferListWasEmpty, // IN:
-                      void *buf,               // IN: unused
-                      int len)                 // IN: unused
-{
-   int retVal = ASOCKERR_SUCCESS;
-
-   if (bufferListWasEmpty && !asock->sendCb) {
-#ifdef _WIN32
-      /*
-       * If the send buffer list was empty, we schedule a one-time callback
-       * to "prime" the output. This is necessary to support the FD_WRITE
-       * network event semantic for sockets on Windows (see WSAEventSelect
-       * documentation). The event won't signal unless a previous write() on
-       * the socket failed with WSAEWOULDBLOCK, so we have to perform at
-       * least one partial write before we can start polling for write.
-       *
-       * XXX: This can be a device callback once all poll implementations
-       * know to get around this Windows quirk.  Both PollVMX and PollDefault
-       * already make 0-byte send() to force WSAEWOULDBLOCK.
-       */
-
-      if (AsyncSocketPollAdd(asock, FALSE, 0, asock->vt->sendCallback,
-                             asock->pollParams.iPoll != NULL ? 1 : 0)
-          != VMWARE_STATUS_SUCCESS) {
-         retVal = ASOCKERR_POLL;
-         return retVal;
-      }
-      asock->sendCbTimer = TRUE;
-      asock->sendCb = TRUE;
-#else
-      if (asock->sendLowLatency) {
-         /*
-          * For low-latency sockets, call the callback directly from
-          * this thread.  It is non-blocking and will schedule device
-          * callbacks if necessary to complete the operation.
-          *
-          * Unfortunately we can't make this the default as current
-          * consumers of asyncsocket are not expecting the completion
-          * callback to be invoked prior to the call to
-          * AsyncSocket_Send() returning.
-          */
-         asock->vt->sendCallback((void *)asock);
-      } else {
-         if (AsyncSocketPollAdd(asock, TRUE, POLL_FLAG_WRITE,
-                                asock->vt->sendCallback)
-             != VMWARE_STATUS_SUCCESS) {
-            retVal = ASOCKERR_POLL;
-            return retVal;
-         }
-         asock->sendCb = TRUE;
-      }
-#endif
-   }
-
-   return retVal;
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketSend --
+ * AsyncTCPSocketSend --
  *
  *      Queues the provided data for sending on the socket. If a send callback
  *      is provided, the callback is fired after the data has been written to
@@ -2992,16 +2941,18 @@ AsyncSocketSendSocket(AsyncSocket *asock,      // IN:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketSend(AsyncSocket *asock,
-                void *buf,
-                int len,
-                AsyncSocketSendFn sendFn,
-                void *clientData)
+static int
+AsyncTCPSocketSend(AsyncSocket *base,         // IN
+                   void *buf,                 // IN
+                   int len,                   // IN
+                   AsyncSocketSendFn sendFn,  // IN
+                   void *clientData)          // IN
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    int retVal;
    Bool bufferListWasEmpty = FALSE;
    SendBufList **pcur;
+   SendBufList *newBuf;
 
    /*
     * Note: I think it should be fine to send with a length of zero and a
@@ -3010,42 +2961,91 @@ AsyncSocketSend(AsyncSocket *asock,
     * the <= zero check instead of just a < zero check.  --Jeremy.
     */
 
-   if (!asock || !buf || len <= 0) {
-      Warning(ASOCKPREFIX "Send called with invalid arguments! asynchSock: %p "
-              "buffer: %p length: %d\n", asock, buf, len);
+   if (!buf || len <= 0) {
+      Warning(ASOCKPREFIX "Send called with invalid arguments!"
+              "buffer: %p length: %d\n", buf, len);
 
       return ASOCKERR_INVAL;
    }
 
    LOG(2, ("%s: sending %d bytes\n", __FUNCTION__, len));
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   if (asock->state != AsyncSocketConnected) {
-      ASOCKWARN(asock, ("send called but state is not connected!\n"));
-      retVal = ASOCKERR_NOTCONNECTED;
-      goto outHaveLock;
+   if (AsyncTCPSocketGetState(asock) != AsyncSocketConnected) {
+      TCPSOCKWARN(asock, ("send called but state is not connected!\n"));
+      return ASOCKERR_NOTCONNECTED;
    }
 
-   ASSERT(asock->vt);
-   ASSERT(asock->vt->prepareSend);
-   retVal = asock->vt->prepareSend(asock, buf, len, sendFn, clientData,
-                                   &bufferListWasEmpty);
-   if (retVal != ASOCKERR_SUCCESS) {
-      ASOCKLOG(1, asock, ("Failed to prepare buffer:%p for send. Error:%d\n",
-                          buf, retVal));
-      goto outUndoAppend;
-   }
+   /*
+    * Allocate and initialize new send buffer entry
+    */
+   newBuf = Util_SafeCalloc(1, sizeof *newBuf);
+   newBuf->buf = buf;
+   newBuf->len = len;
+   newBuf->sendFn = sendFn;
+   newBuf->clientData = clientData;
 
-   ASSERT(asock->vt->sendInternal);
-   retVal = asock->vt->sendInternal(asock, bufferListWasEmpty, buf, len);
-   if (retVal != ASOCKERR_SUCCESS) {
-      ASOCKLOG(1, asock, ("Failed to send buffer:%p. Error:%d\n", buf, retVal));
-      goto outUndoAppend;
+   /*
+    * Append new send buffer to the tail of list.
+    */
+   *asock->sendBufTail = newBuf;
+   asock->sendBufTail = &(newBuf->next);
+   bufferListWasEmpty = (asock->sendBufList == newBuf);
+
+   if (bufferListWasEmpty && !asock->sendCb) {
+#ifdef _WIN32
+      /*
+       * If the send buffer list was empty, we schedule a one-time callback
+       * to "prime" the output. This is necessary to support the FD_WRITE
+       * network event semantic for sockets on Windows (see WSAEventSelect
+       * documentation). The event won't signal unless a previous write() on
+       * the socket failed with WSAEWOULDBLOCK, so we have to perform at
+       * least one partial write before we can start polling for write.
+       *
+       * XXX: This can be a device callback once all poll implementations
+       * know to get around this Windows quirk.  Both PollVMX and PollDefault
+       * already make 0-byte send() to force WSAEWOULDBLOCK.
+       */
+
+      if (AsyncTCPSocketPollAdd(asock, FALSE, 0, asock->internalSendFn,
+                                AsyncTCPSocketPollParams(asock)->iPoll != NULL
+                                ? 1 : 0)
+          != VMWARE_STATUS_SUCCESS) {
+         retVal = ASOCKERR_POLL;
+         TCPSOCKLOG(1, asock, ("Failed to register poll callback for send\n"));
+         goto outUndoAppend;
+      }
+      asock->sendCbTimer = TRUE;
+      asock->sendCb = TRUE;
+#else
+      if (asock->sendLowLatency) {
+         /*
+          * For low-latency sockets, call the callback directly from
+          * this thread.  It is non-blocking and will schedule device
+          * callbacks if necessary to complete the operation.
+          *
+          * Unfortunately we can't make this the default as current
+          * consumers of asyncsocket are not expecting the completion
+          * callback to be invoked prior to the call to
+          * AsyncTCPSocket_Send() returning.
+          */
+         asock->internalSendFn((void *)asock);
+      } else {
+         if (AsyncTCPSocketPollAdd(asock, TRUE, POLL_FLAG_WRITE,
+                                   asock->internalSendFn)
+             != VMWARE_STATUS_SUCCESS) {
+            retVal = ASOCKERR_POLL;
+            TCPSOCKLOG(1, asock,
+                       ("Failed to register poll callback for send\n"));
+            goto outUndoAppend;
+         }
+         asock->sendCb = TRUE;
+      }
+#endif
    }
 
-   retVal = ASOCKERR_SUCCESS;
-   goto outHaveLock;
+   return ASOCKERR_SUCCESS;
 
 outUndoAppend:
    /*
@@ -3067,8 +3067,6 @@ outUndoAppend:
       }
    }
 
-outHaveLock:
-   AsyncSocketUnlock(asock);
    return retVal;
 }
 
@@ -3076,7 +3074,7 @@ outHaveLock:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketResolveAddr --
+ * AsyncTCPSocketResolveAddr --
  *
  *      Resolves a hostname and port.
  *
@@ -3088,14 +3086,15 @@ outHaveLock:
  *
  *----------------------------------------------------------------------------
  */
-int
-AsyncSocketResolveAddr(const char *hostname,
-                       unsigned int port,
-                       int family,
-                       Bool passive,
-                       struct sockaddr_storage *addr,
-                       socklen_t *addrLen,
-                       char **addrString)
+
+static int
+AsyncTCPSocketResolveAddr(const char *hostname,          // IN
+                          unsigned int port,             // IN
+                          int family,                    // IN
+                          Bool passive,                  // IN
+                          struct sockaddr_storage *addr, // OUT
+                          socklen_t *addrLen,            // OUT
+                          char **addrString)             // OUT
 {
    struct addrinfo hints;
    struct addrinfo *aiTop = NULL;
@@ -3182,76 +3181,7 @@ bye:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketCheckAndDispatchRecv --
- *
- *      Check if the recv buffer is full and dispatch the client callback.
- *
- *      Handles the possibility that the client registers a new receive buffer
- *      or closes the socket in their callback.
- *
- * Results:
- *      TRUE if the socket was closed or the receive was cancelled,
- *      FALSE if the caller should continue to try to receive data.
- *
- * Side effects:
- *      Could fire recv completion or trigger socket destruction.
- *
- *----------------------------------------------------------------------------
- */
-
-Bool
-AsyncSocketCheckAndDispatchRecv(AsyncSocket *s,  // IN
-                                int *result)     // OUT
-{
-   ASSERT(s);
-   ASSERT(result);
-   ASSERT(s->recvFn);
-   ASSERT(s->recvBuf);
-   ASSERT(s->recvLen > 0);
-   ASSERT(s->recvPos <= s->recvLen);
-
-   if (s->recvPos == s->recvLen || s->recvFireOnPartial) {
-      void *recvBuf = s->recvBuf;
-      ASOCKLOG(3, s, ("recv buffer full, calling recvFn\n"));
-
-      /*
-       * We do this dance in case the handler frees the buffer (so
-       * that there's no possible window where there are dangling
-       * references here.  Obviously if the handler frees the buffer,
-       * but them fails to register a new one, we'll put back the
-       * dangling reference in the automatic reset case below, but
-       * there's currently a limit to how far we go to shield clients
-       * who use our API in a broken way.
-       */
-
-      s->recvBuf = NULL;
-      s->recvFn(recvBuf, s->recvPos, s, s->clientData);
-      if (s->state == AsyncSocketClosed) {
-         ASOCKLG0(s, ("owner closed connection in recv callback\n"));
-         *result = ASOCKERR_CLOSED;
-         return TRUE;
-      } else if (s->recvFn == NULL && s->recvLen == 0) {
-         /*
-          * Further recv is cancelled from within the last recvFn, see
-          * AsyncSocket_CancelRecv(). So exit from the loop.
-          */
-         *result = ASOCKERR_SUCCESS;
-         return TRUE;
-      } else if (s->recvLen - s->recvPos == 0) {
-         /* Automatically reset keeping the current handler */
-         s->recvPos = 0;
-         s->recvBuf = recvBuf;
-      }
-   }
-
-   return FALSE;
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketFillRecvBuffer --
+ * AsyncTCPSocketFillRecvBuffer --
  *
  *      Called when an asock has data ready to be read via the poll callback.
  *
@@ -3267,8 +3197,8 @@ AsyncSocketCheckAndDispatchRecv(AsyncSocket *s,  // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketFillRecvBuffer(AsyncSocket *s)
+static int
+AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s)         // IN
 {
    int recvd;
    int needed;
@@ -3276,9 +3206,8 @@ AsyncSocketFillRecvBuffer(AsyncSocket *s)
    int result;
    int pending = 0;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(AsyncSocketIsLocked(s));
-   ASSERT(s->state == AsyncSocketConnected);
+   ASSERT(AsyncTCPSocketIsLocked(s));
+   ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnected);
 
    /*
     * When a socket has received all its desired content and FillRecvBuffer is
@@ -3289,17 +3218,17 @@ AsyncSocketFillRecvBuffer(AsyncSocket *s)
     * called twice for the same receive event.
     */
 
-   needed = s->recvLen - s->recvPos;
-   if (!s->recvBuf && needed == 0) {
+   needed = s->base.recvLen - s->base.recvPos;
+   if (!s->base.recvBuf && needed == 0) {
       return ASOCKERR_SUCCESS;
    }
 
    ASSERT(needed > 0);
 
-   AsyncSocketAddRef(s);
+   AsyncTCPSocketAddRef(s);
 
    /*
-    * See comment in AsyncSocket_Recv
+    * See comment in AsyncTCPSocket_Recv
     */
 
    s->inRecvLoop = TRUE;
@@ -3314,27 +3243,30 @@ AsyncSocketFillRecvBuffer(AsyncSocket *s)
          int fd;
 
          recvd = SSL_RecvDataAndFd(s->sslSock,
-                                   (uint8 *) s->recvBuf + s->recvPos,
+                                   (uint8 *) s->base.recvBuf +
+                                   s->base.recvPos,
                                    needed, &fd);
          if (fd != -1) {
             s->passFd.fd = fd;
             s->passFd.expected = FALSE;
          }
       } else {
-         recvd = SSL_Read(s->sslSock, (uint8 *) s->recvBuf + s->recvPos,
+         recvd = SSL_Read(s->sslSock,
+                          (uint8 *) s->base.recvBuf +
+                          s->base.recvPos,
                           needed);
       }
-      ASOCKLOG(3, s, ("need\t%d\trecv\t%d\tremain\t%d\n", needed, recvd,
-                      needed - recvd));
+      TCPSOCKLOG(3, s, ("need\t%d\trecv\t%d\tremain\t%d\n", needed, recvd,
+                        needed - recvd));
 
       if (recvd > 0) {
          s->sslConnected = TRUE;
-         s->recvPos += recvd;
-         if (AsyncSocketCheckAndDispatchRecv(s, &result)) {
+         s->base.recvPos += recvd;
+         if (AsyncSocketCheckAndDispatchRecv(&s->base, &result)) {
             goto exit;
          }
       } else if (recvd == 0) {
-         ASOCKLG0(s, ("recv detected client closed connection\n"));
+         TCPSOCKLG0(s, ("recv detected client closed connection\n"));
          /*
           * We treat this as an error so that the owner can detect closing
           * of connection by peer (via the error handler callback).
@@ -3342,10 +3274,10 @@ AsyncSocketFillRecvBuffer(AsyncSocket *s)
          result = ASOCKERR_REMOTE_DISCONNECT;
          goto exit;
       } else if ((sysErr = ASOCK_LASTERROR()) == ASOCK_EWOULDBLOCK) {
-         ASOCKLOG(4, s, ("recv would block\n"));
+         TCPSOCKLOG(4, s, ("recv would block\n"));
          break;
       } else {
-         ASOCKLG0(s, ("recv error %d: %s\n", sysErr,
+         TCPSOCKLG0(s, ("recv error %d: %s\n", sysErr,
                       Err_Errno2String(sysErr)));
          s->genericErrno = sysErr;
          result = ASOCKERR_GENERIC;
@@ -3359,7 +3291,7 @@ AsyncSocketFillRecvBuffer(AsyncSocket *s)
        * buffered in userspace already (SSL_Pending).
        */
 
-      needed = s->recvLen - s->recvPos;
+      needed = s->base.recvLen - s->base.recvPos;
       ASSERT(needed > 0);
 
       pending = SSL_Pending(s->sslSock);
@@ -3384,7 +3316,7 @@ AsyncSocketFillRecvBuffer(AsyncSocket *s)
 
 exit:
    s->inRecvLoop = FALSE;
-   AsyncSocketRelease(s, FALSE);
+   AsyncTCPSocketRelease(s);
 
    return result;
 }
@@ -3393,7 +3325,7 @@ exit:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketDispatchSentBuffer --
+ * AsyncTCPSocketDispatchSentBuffer --
  *
  *      Pop off the head of the send buffer list and call its callback.
  *
@@ -3406,9 +3338,11 @@ exit:
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketDispatchSentBuffer(AsyncSocket *s)
+static int
+AsyncTCPSocketDispatchSentBuffer(AsyncTCPSocket *s)         // IN
 {
+   int result = ASOCKERR_SUCCESS;
+
    /*
     * We're done with the current buffer, so pop it off and nuke it.
     * We do the list management *first*, so that the list is in a
@@ -3423,31 +3357,34 @@ AsyncSocketDispatchSentBuffer(AsyncSocket *s)
       s->sendBufTail = &(s->sendBufList);
    }
    s->sendPos = 0;
-   free(tmp.encodedBuf);
    free(head);
 
    if (tmp.sendFn) {
       /*
-       * XXX
-       * Firing the send completion could trigger the socket's
-       * destruction (since the callback could turn around and call
-       * AsyncSocket_Close()). Since we're in the middle of a loop on
-       * the asock's queue, we avoid a use-after-free by deferring
-       * the actual freeing of the asock structure. This is shady but
-       * it works. --rrdharan
+       * Firing the send completion cannot trigger immediate
+       * destruction of the socket because we hold a refCount across
+       * this and all other application callbacks.  If the socket is
+       * closed, however, we need to bubble the information up to the
+       * caller in the same way as we do in the Recv callback case.
        */
-
-      tmp.sendFn(tmp.buf, tmp.len, s, tmp.clientData);
+      ASSERT(s->base.refCount > 1);
+      tmp.sendFn(tmp.buf, tmp.len, BaseSocket(s), tmp.clientData);
+      if (AsyncTCPSocketGetState(s) == AsyncSocketClosed) {
+         TCPSOCKLG0(s, ("owner closed connection in send callback\n"));
+         result = ASOCKERR_CLOSED;
+      }
    }
+
+   return result;
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketWriteBuffers --
+ * AsyncTCPSocketWriteBuffers --
  *
- *      The meat of AsyncSocket's sending functionality.  This function
+ *      The meat of AsyncTCPSocket's sending functionality.  This function
  *      actually writes to the wire assuming there's space in the buffers
  *      for the socket.
  *
@@ -3461,52 +3398,49 @@ AsyncSocketDispatchSentBuffer(AsyncSocket *s)
  */
 
 static int
-AsyncSocketWriteBuffers(AsyncSocket *s)
+AsyncTCPSocketWriteBuffers(AsyncTCPSocket *s)         // IN
 {
    int result;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(AsyncSocketIsLocked(s));
+   ASSERT(AsyncTCPSocketIsLocked(s));
 
    if (s->sendBufList == NULL) {
       return ASOCKERR_SUCCESS;     /* Vacuously true */
    }
 
-   if (s->state != AsyncSocketConnected) {
-      ASOCKWARN(s, ("write buffers on a disconnected socket (%d)!\n",
-                    s->state));
+   if (AsyncTCPSocketGetState(s) != AsyncSocketConnected) {
+      TCPSOCKWARN(s, ("write buffers on a disconnected socket!\n"));
       return ASOCKERR_GENERIC;
    }
 
-   AsyncSocketAddRef(s);
+   AsyncTCPSocketAddRef(s);
 
-   while (s->sendBufList && s->state == AsyncSocketConnected) {
+   while (s->sendBufList && AsyncTCPSocketGetState(s) == AsyncSocketConnected) {
       SendBufList *head = s->sendBufList;
       int error = 0;
       int sent = 0;
       int left = head->len - s->sendPos;
       int sizeToSend = head->len;
 
-      if (head->encodedBuf) {
-         sent = SSL_Write(s->sslSock,
-                          (uint8 *) head->encodedBuf + s->sendPos, left);
-      } else {
-         sent = SSL_Write(s->sslSock,
-                          (uint8 *) head->buf + s->sendPos, left);
-      }
-      ASOCKLOG(3, s, ("left\t%d\tsent\t%d\tremain\t%d\n",
+      sent = SSL_Write(s->sslSock,
+                       (uint8 *) head->buf + s->sendPos, left);
+
+      TCPSOCKLOG(3, s, ("left\t%d\tsent\t%d\tremain\t%d\n",
                       left, sent, left - sent));
       if (sent > 0) {
          s->sendBufFull = FALSE;
          s->sslConnected = TRUE;
          if ((s->sendPos += sent) == sizeToSend) {
-            AsyncSocketDispatchSentBuffer(s);
+            result = AsyncTCPSocketDispatchSentBuffer(s);
+            if (result != ASOCKERR_SUCCESS) {
+               goto exit;
+            }
          }
       } else if (sent == 0) {
-         ASOCKLG0(s, ("socket write() should never return 0.\n"));
+         TCPSOCKLG0(s, ("socket write() should never return 0.\n"));
          NOT_REACHED();
       } else if ((error = ASOCK_LASTERROR()) != ASOCK_EWOULDBLOCK) {
-         ASOCKLG0(s, ("send error %d: %s\n", error, Err_Errno2String(error)));
+         TCPSOCKLG0(s, ("send error %d: %s\n", error, Err_Errno2String(error)));
          s->genericErrno = error;
          result = ASOCKERR_GENERIC;
          goto exit;
@@ -3527,7 +3461,7 @@ AsyncSocketWriteBuffers(AsyncSocket *s)
    result = ASOCKERR_SUCCESS;
 
 exit:
-   AsyncSocketRelease(s, FALSE);
+   AsyncTCPSocketRelease(s);
 
    return result;
 }
@@ -3536,12 +3470,12 @@ exit:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketAcceptInternal --
+ * AsyncTCPSocketAcceptInternal --
  *
  *      The meat of 'accept'.  This function can be invoked either via a
  *      poll callback or blocking. We call accept to get the new socket fd,
  *      create a new asock, and call the newFn callback previously supplied
- *      by the call to AsyncSocket_Listen.
+ *      by the call to AsyncTCPSocket_Listen.
  *
  * Results:
  *      ASOCKERR_SUCCESS if everything works, else an error code.
@@ -3557,24 +3491,23 @@ exit:
  */
 
 static int
-AsyncSocketAcceptInternal(AsyncSocket *s)
+AsyncTCPSocketAcceptInternal(AsyncTCPSocket *s)         // IN
 {
-   AsyncSocket *newsock;
+   AsyncTCPSocket *newsock;
    int sysErr;
    int fd;
    struct sockaddr_storage remoteAddr;
    socklen_t remoteAddrLen = sizeof remoteAddr;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(AsyncSocketIsLocked(s));
-   ASSERT(s->state == AsyncSocketListening);
+   ASSERT(AsyncTCPSocketIsLocked(s));
+   ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketListening);
 
    if ((fd = accept(s->fd, (struct sockaddr *)&remoteAddr,
                     &remoteAddrLen)) == -1) {
       sysErr = ASOCK_LASTERROR();
       s->genericErrno = sysErr;
       if (sysErr == ASOCK_EWOULDBLOCK) {
-         ASOCKWARN(s, ("spurious accept notification\n"));
+         TCPSOCKWARN(s, ("spurious accept notification\n"));
 
          return ASOCKERR_GENERIC;
 #ifndef _WIN32
@@ -3587,12 +3520,12 @@ AsyncSocketAcceptInternal(AsyncSocket *s)
           */
 
       } else if (sysErr == ECONNABORTED) {
-         ASOCKLG0(s, ("accept: new connection was aborted\n"));
+         TCPSOCKLG0(s, ("accept: new connection was aborted\n"));
 
          return ASOCKERR_GENERIC;
 #endif
       } else {
-         ASOCKWARN(s, ("accept failed on fd %d, error %d: %s\n",
+         TCPSOCKWARN(s, ("accept failed on fd %d, error %d: %s\n",
                        s->fd, sysErr, Err_Errno2String(sysErr)));
 
          return ASOCKERR_ACCEPT;
@@ -3600,7 +3533,7 @@ AsyncSocketAcceptInternal(AsyncSocket *s)
    }
 
    if (remoteAddr.ss_family == AF_INET6 &&
-       AsyncSocketOSVersionSupportsV4Mapped()) {
+       AsyncTCPSocketOSVersionSupportsV4Mapped()) {
       struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&remoteAddr;
 
       /*
@@ -3610,15 +3543,16 @@ AsyncSocketAcceptInternal(AsyncSocket *s)
        */
 
       if (IN6_IS_ADDR_V4MAPPED(&(addr6->sin6_addr))) {
-         ASOCKWARN(s, ("accept rejected on fd %d due to a IPv4-mapped IPv6 "
-                       "remote connection address.\n", s->fd));
+         TCPSOCKWARN(s,
+                   ("accept rejected on fd %d due to a IPv4-mapped IPv6 "
+                    "remote connection address.\n", s->fd));
          SSLGeneric_close(fd);
 
          return ASOCKERR_ACCEPT;
       }
    }
 
-   newsock = AsyncSocket_AttachToFd(fd, &s->pollParams, NULL);
+   newsock = AsyncTCPSocketAttachToFd(fd, AsyncTCPSocketPollParams(s), NULL);
    if (!newsock) {
       SSLGeneric_close(fd);
 
@@ -3627,12 +3561,14 @@ AsyncSocketAcceptInternal(AsyncSocket *s)
 
    newsock->remoteAddr = remoteAddr;
    newsock->remoteAddrLen = remoteAddrLen;
-   newsock->state = AsyncSocketConnected;
-   newsock->vt = s->vt;
+   AsyncTCPSocketSetState(newsock, AsyncSocketConnected);
+   newsock->internalRecvFn = s->internalRecvFn;
+   newsock->internalSendFn = s->internalSendFn;
 
-   ASSERT(s->vt);
-   ASSERT(s->vt->dispatchConnect);
-   s->vt->dispatchConnect(s, newsock);
+   /*
+    * Fire the connect callback:
+    */
+   s->connectFn(BaseSocket(newsock), s->clientData);
 
    return ASOCKERR_SUCCESS;
 }
@@ -3641,7 +3577,7 @@ AsyncSocketAcceptInternal(AsyncSocket *s)
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketConnectInternal --
+ * AsyncTCPSocketConnectInternal --
  *
  *      The meat of connect.  This function is invoked either via a poll
  *      callback or the blocking API and verifies that connect() succeeded
@@ -3658,13 +3594,12 @@ AsyncSocketAcceptInternal(AsyncSocket *s)
  */
 
 static int
-AsyncSocketConnectInternal(AsyncSocket *s)
+AsyncTCPSocketConnectInternal(AsyncTCPSocket *s)         // IN
 {
    int optval = 0, optlen = sizeof optval, sysErr;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(AsyncSocketIsLocked(s));
-   ASSERT(s->state == AsyncSocketConnecting);
+   ASSERT(AsyncTCPSocketIsLocked(s));
+   ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnecting);
 
    /* Remove when bug 859728 is fixed */
    if (vmx86_server && s->remoteAddr.ss_family == AF_UNIX) {
@@ -3683,7 +3618,7 @@ AsyncSocketConnectInternal(AsyncSocket *s)
 
    if (optval != 0) {
       s->genericErrno = optval;
-      ASOCKLOG(1, s, ("connection SO_ERROR: %s\n", Err_Errno2String(optval)));
+      TCPSOCKLOG(1, s, ("connection SO_ERROR: %s\n", Err_Errno2String(optval)));
 
       return ASOCKERR_GENERIC;
    }
@@ -3700,8 +3635,8 @@ AsyncSocketConnectInternal(AsyncSocket *s)
    }
 
 done:
-   s->state = AsyncSocketConnected;
-   s->connectFn(s, s->clientData);
+   AsyncTCPSocketSetState(s, AsyncSocketConnected);
+   s->connectFn(BaseSocket(s), s->clientData);
 
    return ASOCKERR_SUCCESS;
 }
@@ -3710,7 +3645,7 @@ done:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetGenericErrno --
+ * AsyncTCPSocketGetGenericErrno --
  *
  *      Used when an ASOCKERR_GENERIC is returned due to a system error.
  *      The errno that was returned by the system is stored in the asock
@@ -3728,19 +3663,19 @@ done:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketGetGenericErrno(AsyncSocket *s)  // IN:
+static int
+AsyncTCPSocketGetGenericErrno(AsyncSocket *base)  // IN:
 {
-   ASSERT(s);
-
-   return s->genericErrno;
+   AsyncTCPSocket *asock = TCPSocket(base);
+   ASSERT(asock);
+   return asock->genericErrno;
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_WaitForConnection --
+ * AsyncTCPSocketWaitForConnection --
  *
  *      Spins a socket currently listening or connecting until the
  *      connection completes or the allowed time elapses.
@@ -3754,37 +3689,31 @@ AsyncSocketGetGenericErrno(AsyncSocket *s)  // IN:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocket_WaitForConnection(AsyncSocket *s,  // IN:
-                              int timeoutMS)   // IN:
+static int
+AsyncTCPSocketWaitForConnection(AsyncSocket *base,  // IN:
+                                int timeoutMS)      // IN:
 {
+   AsyncTCPSocket *s = TCPSocket(base);
    Bool read = FALSE;
    int error;
    VmTimeType now, done;
    Bool removed = FALSE;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_PROXYSOCKET);
-
-   AsyncSocketLock(s);
+   ASSERT(AsyncTCPSocketIsLocked(s));
 
-   if (s->state == AsyncSocketConnected) {
-      error = ASOCKERR_SUCCESS;
-      AsyncSocketUnlock(s);
-      goto out;
+   if (AsyncTCPSocketGetState(s) == AsyncSocketConnected) {
+      return ASOCKERR_SUCCESS;
    }
 
-   if (s->state != AsyncSocketListening &&
-       s->state != AsyncSocketConnecting) {
-      error = ASOCKERR_GENERIC;
-      AsyncSocketUnlock(s);
-      goto out;
+   if (AsyncTCPSocketGetState(s) != AsyncSocketListening &&
+       AsyncTCPSocketGetState(s) != AsyncSocketConnecting) {
+      return ASOCKERR_GENERIC;
    }
 
-   read = s->state == AsyncSocketListening;
+   read = AsyncTCPSocketGetState(s) == AsyncSocketListening;
 
    /*
-    * For listening sockets, unregister AsyncSocketAcceptCallback before
+    * For listening sockets, unregister AsyncTCPSocketAcceptCallback before
     * starting polling and re-register before returning.
     *
     * ConnectCallback() is either registered as a device or rtime callback
@@ -3794,53 +3723,48 @@ AsyncSocket_WaitForConnection(AsyncSocket *s,  // IN:
    if (read) {
       if (s->fd == -1) {
          if (s->listenAsock4) {
-            AsyncSocketLock(s->listenAsock4);
-            AsyncSocketCancelListenCbSocket(s->listenAsock4);
-            AsyncSocketUnlock(s->listenAsock4);
+            ASSERT(AsyncTCPSocketIsLocked(s->listenAsock4));
+            AsyncTCPSocketCancelListenCb(s->listenAsock4);
          }
          if (s->listenAsock6) {
-            AsyncSocketLock(s->listenAsock6);
-            AsyncSocketCancelListenCbSocket(s->listenAsock6);
-            AsyncSocketUnlock(s->listenAsock6);
+            ASSERT(AsyncTCPSocketIsLocked(s->listenAsock6));
+            AsyncTCPSocketCancelListenCb(s->listenAsock6);
          }
       } else {
-         AsyncSocketCancelListenCbSocket(s);
+         AsyncTCPSocketCancelListenCb(s);
       }
 
       removed = TRUE;
    } else {
-      removed = AsyncSocketPollRemove(s, TRUE, POLL_FLAG_WRITE,
-                                      AsyncSocketConnectCallback)
-         || AsyncSocketPollRemove(s, FALSE, 0, AsyncSocketConnectCallback);
+      removed = (AsyncTCPSocketPollRemove(s, TRUE, POLL_FLAG_WRITE,
+                                          AsyncTCPSocketConnectCallback) ||
+                 AsyncTCPSocketPollRemove(s, FALSE, 0,
+                                          AsyncTCPSocketConnectCallback));
       ASSERT(removed);
       if (s->internalConnectFn) {
-         removed = AsyncSocketPollRemove(s, FALSE, POLL_FLAG_PERIODIC,
-                                         AsyncSocketConnectErrorCheck);
+         removed = AsyncTCPSocketPollRemove(s, FALSE, POLL_FLAG_PERIODIC,
+                                            AsyncTCPSocketConnectErrorCheck);
          ASSERT(removed);
          s->internalConnectFn = NULL;
       }
    }
 
-   AsyncSocketUnlock(s);
-
    now = Hostinfo_SystemTimerUS() / 1000;
    done = now + timeoutMS;
 
    do {
-      AsyncSocket *asock = NULL;
+      AsyncTCPSocket *asock = NULL;
 
-      if ((error = AsyncSocketPoll(s, read,
-                                   done - now, &asock)) != ASOCKERR_SUCCESS) {
+      error = AsyncTCPSocketPoll(s, read, done - now, &asock);
+      if (error != ASOCKERR_SUCCESS) {
          goto out;
       }
 
-      AsyncSocketLock(asock);
-
       now = Hostinfo_SystemTimerUS() / 1000;
 
       if (read) {
-         if (AsyncSocketAcceptInternal(asock) != ASOCKERR_SUCCESS) {
-            ASOCKLG0(s, ("wait for connection: accept failed\n"));
+         if (AsyncTCPSocketAcceptInternal(asock) != ASOCKERR_SUCCESS) {
+            TCPSOCKLG0(s, ("wait for connection: accept failed\n"));
 
             /*
              * Just fall through, we'll loop and try again as long as we still
@@ -3849,16 +3773,12 @@ AsyncSocket_WaitForConnection(AsyncSocket *s,  // IN:
 
          } else {
             error = ASOCKERR_SUCCESS;
-            AsyncSocketUnlock(asock);
             goto out;
          }
       } else {
-         error = AsyncSocketConnectInternal(asock);
-         AsyncSocketUnlock(asock);
+         error = AsyncTCPSocketConnectInternal(asock);
          goto out;
       }
-
-      AsyncSocketUnlock(asock);
    } while ((now < done && timeoutMS > 0) || (timeoutMS < 0));
 
    error = ASOCKERR_TIMEOUT;
@@ -3866,27 +3786,23 @@ AsyncSocket_WaitForConnection(AsyncSocket *s,  // IN:
 out:
    if (read && removed) {
       if (s->fd == -1) {
-         if (s->listenAsock4 && s->listenAsock4->state != AsyncSocketClosed) {
-            AsyncSocketLock(s->listenAsock4);
-            if (!AsyncSocketAddListenCbSocket(s->listenAsock4)) {
+         if (s->listenAsock4 &&
+             AsyncTCPSocketGetState(s->listenAsock4) != AsyncSocketClosed) {
+            if (!AsyncTCPSocketAddListenCb(s->listenAsock4)) {
                error = ASOCKERR_POLL;
             }
-            AsyncSocketUnlock(s->listenAsock4);
          }
 
-         if (s->listenAsock6 && s->listenAsock6->state != AsyncSocketClosed) {
-            AsyncSocketLock(s->listenAsock6);
-            if (!AsyncSocketAddListenCbSocket(s->listenAsock6)) {
+         if (s->listenAsock6 &&
+             AsyncTCPSocketGetState(s->listenAsock6) != AsyncSocketClosed) {
+            if (!AsyncTCPSocketAddListenCb(s->listenAsock6)) {
                error = ASOCKERR_POLL;
             }
-            AsyncSocketUnlock(s->listenAsock6);
          }
-      } else if (s->state != AsyncSocketClosed) {
-         AsyncSocketLock(s);
-         if (!AsyncSocketAddListenCbSocket(s)) {
+      } else if (AsyncTCPSocketGetState(s) != AsyncSocketClosed) {
+         if (!AsyncTCPSocketAddListenCb(s)) {
             error = ASOCKERR_POLL;
          }
-         AsyncSocketUnlock(s);
       }
    }
 
@@ -3897,7 +3813,7 @@ out:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_DoOneMsg --
+ * AsyncTCPSocketDoOneMsg --
  *
  *      Spins a socket until the specified amount of time has elapsed or
  *      data has arrived / been sent.
@@ -3912,21 +3828,17 @@ out:
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocket_DoOneMsg(AsyncSocket *s, // IN
-                     Bool read,      // IN
-                     int timeoutMS)  // IN
+static int
+AsyncTCPSocketDoOneMsg(AsyncSocket *base, // IN
+                       Bool read,         // IN
+                       int timeoutMS)     // IN
 {
+   AsyncTCPSocket *s = TCPSocket(base);
+   AsyncTCPSocket *asock = NULL;
    int retVal;
-   AsyncSocket *asock = NULL;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_PROXYSOCKET);
-
-   if (!s) {
-      Warning(ASOCKPREFIX "DoOneMsg called with invalid paramters.\n");
-      return ASOCKERR_INVAL;
-   }
+   ASSERT(AsyncTCPSocketIsLocked(s));
+   ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnected);
 
    if (read) {
       /*
@@ -3938,65 +3850,61 @@ AsyncSocket_DoOneMsg(AsyncSocket *s, // IN
        * after reading the data.
        */
 
-      AsyncSocketLock(s);
-      ASSERT(s->state == AsyncSocketConnected);
       ASSERT(s->recvCb); /* We are supposed to call someone... */
-      AsyncSocketAddRef(s);
-      s->vt->cancelRecvCbInternal(s);
+      AsyncTCPSocketAddRef(s);
+      AsyncTCPSocketCancelRecvCb(s);
       s->recvCb = TRUE;  /* We need to know if the callback cancel recv. */
 
       s->inBlockingRecv++;
-      AsyncSocketUnlock(s); /* We may sleep in poll. */
-      retVal = AsyncSocketPoll(s, read, timeoutMS, &asock);
-      AsyncSocketLock(s);
+      retVal = AsyncTCPSocketPoll(s, read, timeoutMS, &asock);
       s->inBlockingRecv--;
       if (retVal != ASOCKERR_SUCCESS) {
          if (retVal == ASOCKERR_GENERIC) {
-            ASOCKWARN(s, ("%s: failed to poll on the socket during read.\n",
-                          __FUNCTION__));
+            TCPSOCKWARN(s, ("%s: failed to poll on the socket during read.\n",
+                       __FUNCTION__));
          }
       } else {
          ASSERT(asock == s);
-         retVal = AsyncSocketFillRecvBuffer(s);
+         s->inDoOneMsg = TRUE;
+         retVal = AsyncTCPSocketFillRecvBuffer(s);
+         s->inDoOneMsg = FALSE;
       }
 
       /*
-       * If socket got closed in AsyncSocketFillRecvBuffer, we cannot add poll
-       * callback - AsyncSocket_Close() would remove it if we would not remove
-       * it above.
+       * If socket got closed in AsyncTCPSocketFillRecvBuffer, we
+       * cannot add poll callback - AsyncSocket_Close() would remove
+       * it if we would not remove it above.
        */
 
-      if (s->state != AsyncSocketClosed && s->recvCb) {
-         ASSERT(s->refCount > 1); /* We should not be last user of socket. */
-         ASSERT(s->state == AsyncSocketConnected);
+      if (AsyncTCPSocketGetState(s) != AsyncSocketClosed && s->recvCb) {
+         ASSERT(s->base.refCount > 1); /* We shouldn't be last user of socket. */
+         ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnected);
          /*
-          * If AsyncSocketPoll or AsyncSocketFillRecvBuffer fails, do not
+          * If AsyncTCPSocketPoll or AsyncTCPSocketFillRecvBuffer fails, do not
           * add the recv callback as it may never fire.
           */
          s->recvCb = FALSE;  /* For re-registering the poll callback. */
          if (retVal == ASOCKERR_SUCCESS || retVal == ASOCKERR_TIMEOUT) {
-            retVal = s->vt->recvInternal(s, (uint8 *)s->recvBuf + s->recvPos,
-                                         s->recvLen - s->recvPos);
+            retVal = AsyncTCPSocketRegisterRecvCb(s);
          }
          if (retVal != ASOCKERR_SUCCESS) {
-            s->recvBuf = NULL;
+            s->base.recvBuf = NULL;
          }
       }
-      /* This may destroy socket s if it is in AsyncSocketClosed state now. */
-      AsyncSocketRelease(s, TRUE);
+      AsyncTCPSocketRelease(s);
    } else {
-      if ((retVal = AsyncSocketPoll(s, read, timeoutMS, &asock)) !=
-          ASOCKERR_SUCCESS) {
+      AsyncTCPSocketAddRef(s);
+      retVal = AsyncTCPSocketPoll(s, read, timeoutMS, &asock);
+      if (retVal != ASOCKERR_SUCCESS) {
          if (retVal == ASOCKERR_GENERIC) {
-            ASOCKWARN(s, ("%s: failed to poll on the socket during write.\n",
-                          __FUNCTION__));
+            TCPSOCKWARN(s, ("%s: failed to poll on the socket during write.\n",
+                            __FUNCTION__));
          }
       } else {
          ASSERT(asock == s);
-         AsyncSocketLock(s);
-         retVal = AsyncSocketWriteBuffers(s);
-         AsyncSocketUnlock(s);
+         retVal = AsyncTCPSocketWriteBuffers(s);
       }
+      AsyncTCPSocketRelease(s);
    }
 
    return retVal;
@@ -4006,7 +3914,7 @@ AsyncSocket_DoOneMsg(AsyncSocket *s, // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketFlush --
+ * AsyncTCPSocketFlush --
  *
  *      Try to send any pending out buffers until we run out of buffers, or
  *      the timeout expires.
@@ -4021,26 +3929,25 @@ AsyncSocket_DoOneMsg(AsyncSocket *s, // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketFlush(AsyncSocket *s,  // IN
-                 int timeoutMS)   // IN
+static int
+AsyncTCPSocketFlush(AsyncSocket *base,  // IN
+                    int timeoutMS)      // IN
 {
+   AsyncTCPSocket *s = TCPSocket(base);
    VmTimeType now, done;
    int retVal;
 
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-
    if (s == NULL) {
       Warning(ASOCKPREFIX "Flush called with invalid arguments!\n");
 
       return ASOCKERR_INVAL;
    }
 
-   AsyncSocketLock(s);
-   AsyncSocketAddRef(s);
+   ASSERT(AsyncTCPSocketIsLocked(s));
+   AsyncTCPSocketAddRef(s);
 
-   if (s->state != AsyncSocketConnected) {
-      ASOCKWARN(s, ("flush called but state is not connected!\n"));
+   if (AsyncTCPSocketGetState(s) != AsyncSocketConnected) {
+      TCPSOCKWARN(s, ("flush called but state is not connected!\n"));
       retVal = ASOCKERR_INVAL;
       goto outHaveLock;
    }
@@ -4049,22 +3956,19 @@ AsyncSocketFlush(AsyncSocket *s,  // IN
    done = now + timeoutMS;
 
    while (s->sendBufList) {
-      AsyncSocket *asock = NULL;
-
-      AsyncSocketUnlock(s); /* We may sleep in poll. */
-      retVal = AsyncSocketPoll(s, FALSE, done - now, &asock);
-      AsyncSocketLock(s);
+      AsyncTCPSocket *asock = NULL;
 
+      retVal = AsyncTCPSocketPoll(s, FALSE, done - now, &asock);
       if (retVal != ASOCKERR_SUCCESS) {
-         ASOCKWARN(s, ("flush failed\n"));
+         TCPSOCKWARN(s, ("flush failed\n"));
          goto outHaveLock;
       }
 
       ASSERT(asock == s);
-      if ((retVal = AsyncSocketWriteBuffers(s)) != ASOCKERR_SUCCESS) {
+      if ((retVal = AsyncTCPSocketWriteBuffers(s)) != ASOCKERR_SUCCESS) {
          goto outHaveLock;
       }
-      ASSERT(s->state == AsyncSocketConnected);
+      ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnected);
 
       /* Setting timeoutMS to -1 means never timeout. */
       if (timeoutMS >= 0) {
@@ -4072,7 +3976,7 @@ AsyncSocketFlush(AsyncSocket *s,  // IN
 
          /* Don't timeout if you've sent everything */
          if (now > done && s->sendBufList) {
-            ASOCKWARN(s, ("flush timed out\n"));
+            TCPSOCKWARN(s, ("flush timed out\n"));
             retVal = ASOCKERR_TIMEOUT;
             goto outHaveLock;
          }
@@ -4082,51 +3986,12 @@ AsyncSocketFlush(AsyncSocket *s,  // IN
    retVal = ASOCKERR_SUCCESS;
 
 outHaveLock:
-   AsyncSocketRelease(s, TRUE);
+   AsyncTCPSocketRelease(s);
 
    return retVal;
 }
 
 
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocket_SetErrorFn --
- *
- *      Sets the error handling function for the asock. The error function
- *      is invoked automatically on I/O errors. Passing NULL as the error
- *      function restores the default behavior, which is to just destroy the
- *      AsyncSocket on any errors.
- *
- * Results:
- *      ASOCKERR_SUCCESS or ASOCKERR_INVAL.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-int
-AsyncSocket_SetErrorFn(AsyncSocket *asock,           // IN/OUT
-                       AsyncSocketErrorFn errorFn,   // IN
-                       void *clientData)             // IN
-{
-   if (!asock) {
-      Warning(ASOCKPREFIX "%s called with invalid arguments!\n",
-              __FUNCTION__);
-
-      return ASOCKERR_INVAL;
-   }
-   AsyncSocketLock(asock);
-   asock->errorFn = errorFn;
-   asock->errorClientData = clientData;
-   AsyncSocketUnlock(asock);
-
-   return ASOCKERR_SUCCESS;
-}
-
-
 /*
  *----------------------------------------------------------------------------
  *
@@ -4143,16 +4008,16 @@ AsyncSocket_SetErrorFn(AsyncSocket *asock,           // IN/OUT
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketCancelListenCbSocket(AsyncSocket *asock)  // IN:
+static void
+AsyncTCPSocketCancelListenCb(AsyncTCPSocket *asock)  // IN:
 {
    Bool removed;
 
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   removed = AsyncSocketPollRemove(asock, TRUE,
-                                   POLL_FLAG_READ | POLL_FLAG_PERIODIC,
-                                   AsyncSocketAcceptCallback);
+   removed = AsyncTCPSocketPollRemove(asock, TRUE,
+                                      POLL_FLAG_READ | POLL_FLAG_PERIODIC,
+                                      AsyncTCPSocketAcceptCallback);
    ASSERT(removed);
 }
 
@@ -4160,7 +4025,7 @@ AsyncSocketCancelListenCbSocket(AsyncSocket *asock)  // IN:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketAddListenCbSocket --
+ * AsyncTCPSocketAddListenCb --
  *
  *      Socket specific code for adding callbacks for a listening socket.
  *
@@ -4174,18 +4039,18 @@ AsyncSocketCancelListenCbSocket(AsyncSocket *asock)  // IN:
  */
 
 static Bool
-AsyncSocketAddListenCbSocket(AsyncSocket *asock)  // IN:
+AsyncTCPSocketAddListenCb(AsyncTCPSocket *asock)  // IN:
 {
    VMwareStatus pollStatus;
 
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   pollStatus = AsyncSocketPollAdd(asock, TRUE, POLL_FLAG_READ |
-                                                POLL_FLAG_PERIODIC,
-                                   AsyncSocketAcceptCallback);
+   pollStatus = AsyncTCPSocketPollAdd(asock, TRUE,
+                                      POLL_FLAG_READ | POLL_FLAG_PERIODIC,
+                                      AsyncTCPSocketAcceptCallback);
 
    if (pollStatus != VMWARE_STATUS_SUCCESS) {
-      ASOCKWARN(asock, ("failed to install listen accept callback!\n"));
+      TCPSOCKWARN(asock, ("failed to install listen accept callback!\n"));
    }
 
    return pollStatus == VMWARE_STATUS_SUCCESS;
@@ -4195,7 +4060,7 @@ AsyncSocketAddListenCbSocket(AsyncSocket *asock)  // IN:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketCancelRecvCbSocket --
+ * AsyncTCPSocketCancelRecvCb --
  *
  *      Socket specific code for canceling callbacks when a receive
  *      request is being canceled.
@@ -4209,22 +4074,23 @@ AsyncSocketAddListenCbSocket(AsyncSocket *asock)  // IN:
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketCancelRecvCbSocket(AsyncSocket *asock)  // IN:
+static void
+AsyncTCPSocketCancelRecvCb(AsyncTCPSocket *asock)  // IN:
 {
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
    if (asock->recvCbTimer) {
-      AsyncSocketPollRemove(asock, FALSE, 0, asock->vt->recvCallback);
+      AsyncTCPSocketPollRemove(asock, FALSE, 0, asock->internalRecvFn);
       asock->recvCbTimer = FALSE;
    }
    if (asock->recvCb) {
       Bool removed;
-      ASOCKLOG(1, asock, ("Removing poll recv callback while cancelling recv.\n"));
-      removed = AsyncSocketPollRemove(asock, TRUE,
-                                      POLL_FLAG_READ | POLL_FLAG_PERIODIC,
-                                      asock->vt->recvCallback);
-      VERIFY(removed || asock->pollParams.iPoll);
+      TCPSOCKLOG(1, asock,
+                 ("Removing poll recv callback while cancelling recv.\n"));
+      removed = AsyncTCPSocketPollRemove(asock, TRUE,
+                                         POLL_FLAG_READ | POLL_FLAG_PERIODIC,
+                                         asock->internalRecvFn);
+      VERIFY(removed || AsyncTCPSocketPollParams(asock)->iPoll);
       asock->recvCb = FALSE;
    }
 }
@@ -4233,10 +4099,18 @@ AsyncSocketCancelRecvCbSocket(AsyncSocket *asock)  // IN:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketCancelCbForCloseSocket --
+ * AsyncTCPSocketCancelCbForClose --
+ *
+ *      Cancel future asynchronous send and recv by unregistering
+ *      their Poll callbacks, and change the socket state to
+ *      AsyncTCPSocketCBCancelled if the socket state is AsyncTCPSocketConnected.
  *
- *      Socket specific code for canceling callbacks when a socket is
- *      being closed.
+ *      The function can be called in a send/recv error handler before
+ *      actually closing the socket in a separate thread, to prevent other
+ *      code calling AsyncTCPSocket_Send/Recv from re-registering the
+ *      callbacks again. The next operation should be just AsyncSocket_Close().
+ *      This helps to avoid unnecessary send/recv callbacks before the
+ *      socket is closed.
  *
  * Results:
  *      None.
@@ -4249,11 +4123,18 @@ AsyncSocketCancelRecvCbSocket(AsyncSocket *asock)  // IN:
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketCancelCbForCloseSocket(AsyncSocket *asock)  // IN:
+static void
+AsyncTCPSocketCancelCbForClose(AsyncSocket *base)  // IN:
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    Bool removed;
 
+   ASSERT(AsyncTCPSocketIsLocked(asock));
+
+   if (AsyncTCPSocketGetState(asock) == AsyncSocketConnected) {
+      AsyncTCPSocketSetState(asock, AsyncSocketCBCancelled);
+   }
+
    /*
     * Remove the read and write poll callbacks.
     *
@@ -4276,26 +4157,29 @@ AsyncSocketCancelCbForCloseSocket(AsyncSocket *asock)  // IN:
     * handler invoked.
     */
 
-   ASSERT(!asock->recvBuf || asock->recvCb);
+   ASSERT(!asock->base.recvBuf || asock->base.recvFn);
 
    if (asock->recvCbTimer) {
-      AsyncSocketPollRemove(asock, FALSE, 0, asock->vt->recvCallback);
+      AsyncTCPSocketPollRemove(asock, FALSE, 0, asock->internalRecvFn);
       asock->recvCbTimer = FALSE;
    }
    if (asock->recvCb) {
-      ASOCKLOG(1, asock, ("recvCb is non-NULL, removing recv callback\n"));
-      removed = AsyncSocketPollRemove(asock, TRUE,
-                                      POLL_FLAG_READ | POLL_FLAG_PERIODIC,
-                                      asock->vt->recvCallback);
+      TCPSOCKLOG(1, asock, ("recvCb is non-NULL, removing recv callback\n"));
+      removed = AsyncTCPSocketPollRemove(asock, TRUE,
+                                         POLL_FLAG_READ | POLL_FLAG_PERIODIC,
+                                         asock->internalRecvFn);
       /* Callback might be temporarily removed in AsyncSocket_DoOneMsg. */
-      ASSERT_NOT_TESTED(removed || asock->pollParams.iPoll);
+      ASSERT_NOT_TESTED(removed ||
+                        asock->inDoOneMsg ||
+                        AsyncTCPSocketPollParams(asock)->iPoll);
 
       asock->recvCb = FALSE;
-      asock->recvBuf = NULL;
+      asock->base.recvBuf = NULL;
    }
 
    if (asock->sendCb) {
-      ASOCKLOG(1, asock, ("sendBufList is non-NULL, removing send callback\n"));
+      TCPSOCKLOG(1, asock,
+                 ("sendBufList is non-NULL, removing send callback\n"));
 
       /*
        * The send callback could be either a device or RTime callback, so
@@ -4303,60 +4187,24 @@ AsyncSocketCancelCbForCloseSocket(AsyncSocket *asock)  // IN:
        */
 
       if (asock->sendCbTimer) {
-         removed = AsyncSocketPollRemove(asock, FALSE, 0,
-                                         asock->vt->sendCallback);
+         removed = AsyncTCPSocketPollRemove(asock, FALSE, 0,
+                                         asock->internalSendFn);
       } else {
-         removed = AsyncSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
-                                         asock->vt->sendCallback);
+         removed = AsyncTCPSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
+                                         asock->internalSendFn);
       }
-      ASSERT(removed || asock->pollParams.iPoll);
+      ASSERT(removed || AsyncTCPSocketPollParams(asock)->iPoll);
       asock->sendCb = FALSE;
       asock->sendCbTimer = FALSE;
    }
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketCancelCbForCloseInt --
- *
- *      Cancel future asynchronous send and recv by unregistering
- *      their Poll callbacks, and change the socket state to
- *      AsyncSocketCBCancelled if the socket state is AsyncSocketConnected.
- *
- *      The function can be called in a send/recv error handler before
- *      actually closing the socket in a separate thread, to prevent other
- *      code calling AsyncSocket_Send/Recv from re-registering the
- *      callbacks again. The next operation should be just AsyncSocket_Close().
- *      This helps to avoid unnecessary send/recv callbacks before the
- *      socket is closed.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Unregisters send/recv Poll callbacks, and fires the send
- *      triggers for any remaining output buffers. May also change
- *      the socket state.
- *
- *----------------------------------------------------------------------------
- */
-
-static void
-AsyncSocketCancelCbForCloseInt(AsyncSocket *asock)  // IN:
-{
-   ASSERT(AsyncSocketIsLocked(asock));
-
-   if (asock->state == AsyncSocketConnected) {
-      asock->state = AsyncSocketCBCancelled;
-   }
-
-   ASSERT(asock->vt);
-   ASSERT(asock->vt->cancelCbForCloseInternal);
-   asock->vt->cancelCbForCloseInternal(asock);
 
-   AsyncSocketAddRef(asock);
+   /*
+    * Go through any send buffers on the list and fire their
+    * callbacks, reflecting back how much of each buffer has been
+    * submitted to the kernel.  For the first buffer in the list that
+    * may be non-zero, for subsequent buffers it will be zero.
+    */
+   AsyncTCPSocketAddRef(asock);
    while (asock->sendBufList) {
       /*
        * Pop each remaining buffer and fire its completion callback.
@@ -4365,80 +4213,22 @@ AsyncSocketCancelCbForCloseInt(AsyncSocket *asock)  // IN:
       SendBufList *cur = asock->sendBufList;
       int pos = asock->sendPos;
 
-      /*
-       * Free the encoded data if it exists.
-       */
-      free(cur->encodedBuf);
       asock->sendBufList = asock->sendBufList->next;
       asock->sendPos = 0;
 
       if (cur->sendFn) {
-         cur->sendFn(cur->buf, pos, asock, cur->clientData);
+         cur->sendFn(cur->buf, pos, BaseSocket(asock), cur->clientData);
       }
       free(cur);
    }
-   AsyncSocketRelease(asock, FALSE);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketCancelCbForClose --
- *
- *      This is the external version of AsyncSocketCancelCbForCloseInt().  It
- *      takes care of acquiring any necessary lock before calling the internal
- *      function.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-void
-AsyncSocketCancelCbForClose(AsyncSocket *asock)  // IN:
-{
-   AsyncSocketLock(asock);
-   AsyncSocketCancelCbForCloseInt(asock);
-   AsyncSocketUnlock(asock);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketCloseSocket --
- *
- *      AsyncSocket destructor for SSL sockets.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Closes the socket fd.
- *
- *----------------------------------------------------------------------------
- */
-
-void
-AsyncSocketCloseSocket(AsyncSocket *asock) // IN
-{
-   SSL_Shutdown(asock->sslSock);
-
-   if (asock->passFd.fd != -1) {
-      SSLGeneric_close(asock->passFd.fd);
-   }
+   AsyncTCPSocketRelease(asock);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketCancelCbForConnectingCloseSocket --
+ * AsyncTCPSocketCancelCbForConnectingClose --
  *
  *      Cancels outstanding connect requests for a socket that is going
  *      away.
@@ -4452,19 +4242,20 @@ AsyncSocketCloseSocket(AsyncSocket *asock) // IN
  *----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketCancelCbForConnectingCloseSocket(AsyncSocket *asock) // IN
+static Bool
+AsyncTCPSocketCancelCbForConnectingClose(AsyncTCPSocket *asock) // IN
 {
-   return AsyncSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
-                                AsyncSocketConnectCallback)
-      || AsyncSocketPollRemove(asock, FALSE, 0, AsyncSocketConnectCallback);
+   return (AsyncTCPSocketPollRemove(asock, TRUE, POLL_FLAG_WRITE,
+                                    AsyncTCPSocketConnectCallback) ||
+           AsyncTCPSocketPollRemove(asock, FALSE, 0,
+                                    AsyncTCPSocketConnectCallback));
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocket_SetCloseOptions --
+ * AsyncTCPSocketSetCloseOptions --
  *
  *      Enables optional behavior for AsyncSocket_Close():
  *
@@ -4485,26 +4276,24 @@ AsyncSocketCancelCbForConnectingCloseSocket(AsyncSocket *asock) // IN
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocket_SetCloseOptions(AsyncSocket *asock,          // IN
-                            int flushEnabledMaxWaitMsec, // IN
-                            AsyncSocketCloseCb closeCb)  // IN
+static void
+AsyncTCPSocketSetCloseOptions(AsyncSocket *base,           // IN
+                              int flushEnabledMaxWaitMsec, // IN
+                              AsyncSocketCloseFn closeCb)  // IN
 {
-   if (!asock) {
-      Warning("%s() called with NULL asock!\n", __FUNCTION__);
-      return;
-   }
+   AsyncTCPSocket *asock = TCPSocket(base);
    asock->flushEnabledMaxWaitMsec = flushEnabledMaxWaitMsec;
    asock->closeCb = closeCb;
+   VERIFY(closeCb == NULL);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketClose --
+ * AsyncTCPSocketClose --
  *
- *      AsyncSocket destructor. The destructor should be safe to call at any
+ *      AsyncTCPSocket destructor. The destructor should be safe to call at any
  *      time.  It's invoked automatically for I/O errors on slots that have no
  *      error handler set, and should be called manually by the error handler
  *      as necessary. It could also be called as part of the normal program
@@ -4520,28 +4309,25 @@ AsyncSocket_SetCloseOptions(AsyncSocket *asock,          // IN
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketClose(AsyncSocket *asock)   // IN
+static int
+AsyncTCPSocketClose(AsyncSocket *base)   // IN
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    Bool isListener = TRUE;
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   if (asock->state == AsyncSocketClosed) {
+   if (AsyncTCPSocketGetState(asock) == AsyncSocketClosed) {
       Warning("%s() called on already closed asock!\n", __FUNCTION__);
-      AsyncSocketUnlock(asock);
-
       return ASOCKERR_CLOSED;
    }
 
    if (asock->listenAsock4 || asock->listenAsock6) {
-      ASSERT(asock->refCount == 1);
-
       if (asock->listenAsock4) {
-         AsyncSocket_Close(asock->listenAsock4);
+         AsyncSocket_Close(BaseSocket(asock->listenAsock4));
       }
       if (asock->listenAsock6) {
-         AsyncSocket_Close(asock->listenAsock6);
+         AsyncSocket_Close(BaseSocket(asock->listenAsock6));
       }
    } else {
       Bool removed;
@@ -4549,14 +4335,16 @@ AsyncSocketClose(AsyncSocket *asock)   // IN
 
       isListener = FALSE;
 
-      /* Flush output if requested via AsyncSocket_SetCloseOptions(). */
+      /* Flush output if requested via AsyncTCPSocket_SetCloseOptions(). */
       if (asock->flushEnabledMaxWaitMsec &&
-          asock->state == AsyncSocketConnected &&
-          !asock->errorSeen) {
-         int ret = AsyncSocket_Flush(asock, asock->flushEnabledMaxWaitMsec);
+          AsyncTCPSocketGetState(asock) == AsyncSocketConnected &&
+          !asock->base.errorSeen) {
+         int ret = AsyncTCPSocketFlush(BaseSocket(asock),
+                                       asock->flushEnabledMaxWaitMsec);
          if (ret != ASOCKERR_SUCCESS) {
-            ASOCKWARN(asock, ("AsyncSocket_Flush failed: %s. Closing now.\n",
-                              AsyncSocket_Err2String(ret)));
+            TCPSOCKWARN(asock,
+                        ("AsyncTCPSocket_Flush failed: %s. Closing now.\n",
+                         AsyncSocket_Err2String(ret)));
          }
       }
 
@@ -4565,38 +4353,34 @@ AsyncSocketClose(AsyncSocket *asock)   // IN
        * right thing accordingly
        */
 
-      ASOCKLOG(1, asock, ("closing socket\n"));
-      oldState = asock->state;
-      asock->state = AsyncSocketClosed;
-
-      ASSERT(asock->vt);
+      TCPSOCKLOG(1, asock, ("closing socket\n"));
+      oldState = AsyncTCPSocketGetState(asock);
+      AsyncTCPSocketSetState(asock, AsyncSocketClosed);
 
       switch(oldState) {
       case AsyncSocketListening:
-         ASOCKLOG(1, asock, ("old state was listening, removing accept "
-                             "callback\n"));
-         ASSERT(asock->vt->cancelListenCbInternal);
-         asock->vt->cancelListenCbInternal(asock);
+         TCPSOCKLOG(1, asock, ("old state was listening, removing accept "
+                               "callback\n"));
+         AsyncTCPSocketCancelListenCb(asock);
          break;
 
       case AsyncSocketConnecting:
-         ASOCKLOG(1, asock, ("old state was connecting, removing connect "
-                             "callback\n"));
-         ASSERT(asock->vt->cancelCbForConnectingCloseInternal);
-         removed = asock->vt->cancelCbForConnectingCloseInternal(asock);
+         TCPSOCKLOG(1, asock, ("old state was connecting, removing connect "
+                               "callback\n"));
+         removed = AsyncTCPSocketCancelCbForConnectingClose(asock);
          if (!removed) {
-            ASOCKLOG(1, asock, ("connect callback is not present in the poll "
-                                "list.\n"));
+            TCPSOCKLOG(1, asock, ("connect callback is not present in the poll "
+                                  "list.\n"));
          }
          break;
 
       case AsyncSocketConnected:
-         ASOCKLOG(1, asock, ("old state was connected\n"));
-         AsyncSocketCancelCbForCloseInt(asock);
+         TCPSOCKLOG(1, asock, ("old state was connected\n"));
+         AsyncTCPSocketCancelCbForClose(BaseSocket(asock));
          break;
 
       case AsyncSocketCBCancelled:
-         ASOCKLOG(1, asock, ("old state was CB-cancelled\n"));
+         TCPSOCKLOG(1, asock, ("old state was CB-cancelled\n"));
          break;
 
       default:
@@ -4604,30 +4388,34 @@ AsyncSocketClose(AsyncSocket *asock)   // IN
       }
 
       if (asock->internalConnectFn) {
-         removed = AsyncSocketPollRemove(asock, FALSE, POLL_FLAG_PERIODIC,
-                                         AsyncSocketConnectErrorCheck);
+         removed = AsyncTCPSocketPollRemove(asock, FALSE, POLL_FLAG_PERIODIC,
+                                            AsyncTCPSocketConnectErrorCheck);
          ASSERT(removed);
          asock->internalConnectFn = NULL;
       }
 
       if (asock->sslConnectFn && asock->sslPollFlags > 0) {
-         removed = AsyncSocketPollRemove(asock, TRUE, asock->sslPollFlags,
-                                         AsyncSocketSslConnectCallback);
+         removed = AsyncTCPSocketPollRemove(asock, TRUE, asock->sslPollFlags,
+                                            AsyncTCPSocketSslConnectCallback);
          ASSERT(removed);
       }
 
       if (asock->sslAcceptFn && asock->sslPollFlags > 0) {
-         removed = AsyncSocketPollRemove(asock, TRUE, asock->sslPollFlags,
-                                         AsyncSocketSslAcceptCallback);
+         removed = AsyncTCPSocketPollRemove(asock, TRUE, asock->sslPollFlags,
+                                            AsyncTCPSocketSslAcceptCallback);
          ASSERT(removed);
       }
       asock->sslPollFlags = 0;
 
-      ASSERT(asock->vt->closeInternal);
-      asock->vt->closeInternal(asock);
-   }
+      /*
+       * Close the underlying SSL sockets.
+       */
+      SSL_Shutdown(asock->sslSock);
 
-   AsyncSocketRelease(asock, TRUE);
+      if (asock->passFd.fd != -1) {
+         SSLGeneric_close(asock->passFd.fd);
+      }
+   }
 
    return ASOCKERR_SUCCESS;
 }
@@ -4636,32 +4424,7 @@ AsyncSocketClose(AsyncSocket *asock)   // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketGetState --
- *
- *      Returns the state of the provided asock or ASOCKERR_INVAL.  Note that
- *      unless this is called from a callback function, the state should be
- *      treated as transient (except the state AsyncSocketClosed).
- *
- * Results:
- *      AsyncSocketState enum.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-AsyncSocketState
-AsyncSocketGetState(AsyncSocket *asock)
-{
-   return (asock ? asock->state : ASOCKERR_INVAL);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketIsSendBufferFull --
+ * AsyncTCPSocketIsSendBufferFull --
  *
  *      Indicate if socket send buffer is full.  Note that unless this is
  *      called from a callback function, the return value should be treated
@@ -4678,118 +4441,22 @@ AsyncSocketGetState(AsyncSocket *asock)
  *----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketIsSendBufferFull(AsyncSocket *asock)
-{
-   return (asock ? asock->sendBufFull : ASOCKERR_GENERIC);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocket_GetID --
- *
- *      Returns a unique identifier for the asock.
- *
- * Results:
- *      Integer id or ASOCKERR_INVAL.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-int
-AsyncSocket_GetID(AsyncSocket *asock)
-{
-   return (asock ? asock->id : ASOCKERR_INVAL);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketSendInternal --
- *
- *      Internal send method for 'regular' socket connections, allocates & prepares
- *      a buffer and enqueues it.
- *
- * Results:
- *      ASOCKERR_SUCCESS if there are no errors.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-int
-AsyncSocketSendInternal(AsyncSocket *asock,         // IN
-                        void *buf,                  // IN
-                        int len,                    // IN
-                        AsyncSocketSendFn sendFn,   // IN
-                        void *clientData,           // IN
-                        Bool *bufferListWasEmpty)   // IN
+static int
+AsyncTCPSocketIsSendBufferFull(AsyncSocket *base)         // IN
 {
-   SendBufList *newBuf;
-   ASSERT(bufferListWasEmpty);
-
-   /*
-    * Allocate and initialize new send buffer entry
-    */
-
-   newBuf = Util_SafeCalloc(1, sizeof *newBuf);
-   newBuf->buf = buf;
-   newBuf->len = len;
-   newBuf->sendFn = sendFn;
-   newBuf->clientData = clientData;
-
-   /*
-    * Append new send buffer to the tail of list.
-    */
-
-   *asock->sendBufTail = newBuf;
-   asock->sendBufTail = &(newBuf->next);
-   if (asock->sendBufList == newBuf) {
-      *bufferListWasEmpty = TRUE;
-   }
-
-   return ASOCKERR_SUCCESS;
+   AsyncTCPSocket *asock = TCPSocket(base);
+   return asock->sendBufFull;
 }
 
 
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketDispatchConnect --
- *
- *      Simple dispatch to call the connect callback for the socket pair.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-void
-AsyncSocketDispatchConnect(AsyncSocket *asock,
-                           AsyncSocket *newsock)
-{
-   asock->connectFn(newsock, asock->clientData);
-}
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketHasDataPendingSocket --
+ * AsyncTCPSocketHasDataPending --
  *
- *      Determine if the SSL socket has any pending/unread data.
+ *      Determine if SSL has any pending/unread data.
  *
  * Results:
  *      TRUE if this socket has pending data.
@@ -4801,7 +4468,7 @@ AsyncSocketDispatchConnect(AsyncSocket *asock,
  */
 
 static Bool
-AsyncSocketHasDataPendingSocket(AsyncSocket *asock) // IN
+AsyncTCPSocketHasDataPending(AsyncTCPSocket *asock)   // IN:
 {
    return SSL_Pending(asock->sslSock);
 }
@@ -4810,33 +4477,7 @@ AsyncSocketHasDataPendingSocket(AsyncSocket *asock) // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketHasDataPending --
- *
- *      Determine if the SSL or WebSocket has any pending/unread data.
- *
- * Results:
- *      TRUE if this socket has pending data.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------------
- */
-
-static Bool
-AsyncSocketHasDataPending(AsyncSocket *asock)   // IN:
-{
-   ASSERT(asock->vt);
-   ASSERT(asock->vt->hasDataPending);
-
-   return asock->vt->hasDataPending(asock);
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketMakeNonBlocking --
+ * AsyncTCPSocketMakeNonBlocking --
  *
  *      Make the specified socket non-blocking if it isn't already.
  *
@@ -4850,7 +4491,7 @@ AsyncSocketHasDataPending(AsyncSocket *asock)   // IN:
  */
 
 static int
-AsyncSocketMakeNonBlocking(int fd)
+AsyncTCPSocketMakeNonBlocking(int fd)         // IN
 {
 #ifdef _WIN32
    int retval;
@@ -4885,40 +4526,6 @@ AsyncSocketMakeNonBlocking(int fd)
 }
 
 
-/*
- *----------------------------------------------------------------------------
- *
- * AsyncSocketHandleError --
- *
- *      Internal error handling helper. Changes the socket's state to error,
- *      and calls the registered error handler or closes the socket.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Lots.
- *
- *----------------------------------------------------------------------------
- */
-
-void
-AsyncSocketHandleError(AsyncSocket *asock, int asockErr)
-{
-   ASSERT(asock);
-   asock->errorSeen = TRUE;
-   if (asock->errorFn) {
-      ASOCKLOG(3, asock, ("firing error callback (%s)\n",
-                          AsyncSocket_Err2String(asockErr)));
-      asock->errorFn(asockErr, asock, asock->errorClientData);
-   } else {
-      ASOCKLOG(3, asock, ("no error callback, closing socket (%s)\n",
-                          AsyncSocket_Err2String(asockErr)));
-      AsyncSocket_Close(asock);
-   }
-}
-
-
 /*
  *----------------------------------------------------------------------------
  *
@@ -4927,7 +4534,7 @@ AsyncSocketHandleError(AsyncSocket *asock, int asockErr)
  *      Poll callback for listening fd waiting to complete an accept
  *      operation. We call accept to get the new socket fd, create a new
  *      asock, and call the newFn callback previously supplied by the call to
- *      AsyncSocket_Listen.
+ *      AsyncTCPSocket_Listen.
  *
  * Results:
  *      None.
@@ -4939,37 +4546,36 @@ AsyncSocketHandleError(AsyncSocket *asock, int asockErr)
  */
 
 static void
-AsyncSocketAcceptCallback(void *clientData)
+AsyncTCPSocketAcceptCallback(void *clientData)         // IN
 {
-   AsyncSocket *asock = clientData;
+   AsyncTCPSocket *asock = clientData;
    int retval;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(asock->pollParams.iPoll == NULL);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->iPoll == NULL);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   AsyncSocketAddRef(asock);
-   retval = AsyncSocketAcceptInternal(asock);
+   AsyncTCPSocketAddRef(asock);
+   retval = AsyncTCPSocketAcceptInternal(asock);
 
    /*
-    * See comment for return value of AsyncSocketAcceptInternal().
+    * See comment for return value of AsyncTCPSocketAcceptInternal().
     */
 
    if (retval == ASOCKERR_ACCEPT) {
-      AsyncSocketHandleError(asock, retval);
+      AsyncTCPSocketHandleError(asock, retval);
    }
-   AsyncSocketRelease(asock, FALSE);
+   AsyncTCPSocketRelease(asock);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketConnectCallback --
+ * AsyncTCPSocketConnectCallback --
  *
  *      Poll callback for connecting fd. Calls through to
- *      AsyncSocketConnectInternal to do the real work.
+ *      AsyncTCPSocketConnectInternal to do the real work.
  *
  * Results:
  *      None.
@@ -4981,30 +4587,29 @@ AsyncSocketAcceptCallback(void *clientData)
  */
 
 static void
-AsyncSocketConnectCallback(void *clientData)
+AsyncTCPSocketConnectCallback(void *clientData)         // IN
 {
-   AsyncSocket *asock = clientData;
+   AsyncTCPSocket *asock = clientData;
    int retval;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(asock->pollParams.iPoll == NULL);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->iPoll == NULL);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   AsyncSocketAddRef(asock);
-   retval = AsyncSocketConnectInternal(asock);
+   AsyncTCPSocketAddRef(asock);
+   retval = AsyncTCPSocketConnectInternal(asock);
    if (retval != ASOCKERR_SUCCESS) {
       ASSERT(retval == ASOCKERR_GENERIC); /* Only one we're expecting */
-      AsyncSocketHandleError(asock, retval);
+      AsyncTCPSocketHandleError(asock, retval);
    }
-   AsyncSocketRelease(asock, FALSE);
+   AsyncTCPSocketRelease(asock);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketRecvCallback --
+ * AsyncTCPSocketRecvCallback --
  *
  *      Poll callback for input waiting on the socket. We try to pull off the
  *      remaining data requested by the current receive function.
@@ -5018,36 +4623,35 @@ AsyncSocketConnectCallback(void *clientData)
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketRecvCallback(void *clientData)
+static void
+AsyncTCPSocketRecvCallback(void *clientData)         // IN
 {
-   AsyncSocket *asock = clientData;
+   AsyncTCPSocket *asock = clientData;
    int error;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   AsyncSocketAddRef(asock);
+   AsyncTCPSocketAddRef(asock);
 
-   error = AsyncSocketFillRecvBuffer(asock);
+   error = AsyncTCPSocketFillRecvBuffer(asock);
    if (error == ASOCKERR_GENERIC || error == ASOCKERR_REMOTE_DISCONNECT) {
-      AsyncSocketHandleError(asock, error);
+      AsyncTCPSocketHandleError(asock, error);
    }
 
-   AsyncSocketRelease(asock, FALSE);
+   AsyncTCPSocketRelease(asock);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketIPollRecvCallback --
+ * AsyncTCPSocketIPollRecvCallback --
  *
  *      Poll callback for input waiting on the socket.  IVmdbPoll does not
  *      handle callback locks, so this function first locks the asyncsocket
  *      and verify that the recv callback has not been cancelled before
- *      calling AsyncSocketFillRecvBuffer to do the real work.
+ *      calling AsyncTCPSocketFillRecvBuffer to do the real work.
  *
  * Results:
  *      None.
@@ -5059,49 +4663,50 @@ AsyncSocketRecvCallback(void *clientData)
  */
 
 static void
-AsyncSocketIPollRecvCallback(void *clientData)  // IN:
+AsyncTCPSocketIPollRecvCallback(void *clientData)  // IN:
 {
 #ifdef VMX86_TOOLS
    NOT_IMPLEMENTED();
 #else
-   AsyncSocket *asock = clientData;
+   AsyncTCPSocket *asock = clientData;
    MXUserRecLock *lock;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(asock->pollParams.lock == NULL ||
-          !MXUser_IsCurThreadHoldingRecLock(asock->pollParams.lock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->lock == NULL ||
+          !MXUser_IsCurThreadHoldingRecLock(
+             AsyncTCPSocketPollParams(asock)->lock));
 
-   AsyncSocketLock(asock);
+   AsyncTCPSocketLock(asock);
    if (asock->recvCbTimer) {
       /* IVmdbPoll only has periodic callbacks. */
-      AsyncSocketIPollRemove(asock, FALSE, 0, asock->vt->recvCallback);
+      AsyncTCPSocketIPollRemove(asock, FALSE, 0, asock->internalRecvFn);
       asock->recvCbTimer = FALSE;
    }
    asock->inIPollCb |= IN_IPOLL_RECV;
-   lock = asock->pollParams.lock;
+   lock = AsyncTCPSocketPollParams(asock)->lock;
    if (asock->recvCb && asock->inBlockingRecv == 0) {
       /*
        * There is no need to take a reference here -- the fact that this
        * callback is running means AsyncsocketIPollRemove would not release a
        * reference if it is called.
        */
-      int error = AsyncSocketFillRecvBuffer(asock);
+      int error = AsyncTCPSocketFillRecvBuffer(asock);
 
       if (error == ASOCKERR_GENERIC || error == ASOCKERR_REMOTE_DISCONNECT) {
-         AsyncSocketHandleError(asock, error);
+         AsyncTCPSocketHandleError(asock, error);
       }
    }
 
    asock->inIPollCb &= ~IN_IPOLL_RECV;
    if (asock->recvCb) {
-      AsyncSocketUnlock(asock);
+      AsyncTCPSocketUnlock(asock);
    } else {
       /*
        * Callback has been unregistered.  Per above, we need to release the
        * reference explicitly.
        */
-      AsyncSocketRelease(asock, TRUE);
+      AsyncTCPSocketRelease(asock);
+      AsyncTCPSocketUnlock(asock);
       if (lock != NULL) {
          MXUser_DecRefRecLock(lock);
       }
@@ -5113,7 +4718,7 @@ AsyncSocketIPollRecvCallback(void *clientData)  // IN:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketSendCallback --
+ * AsyncTCPSocketSendCallback --
  *
  *      Poll callback for output socket buffer space available (socket is
  *      writable). We iterate over all the remaining buffers in our queue,
@@ -5129,22 +4734,22 @@ AsyncSocketIPollRecvCallback(void *clientData)  // IN:
  *----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketSendCallback(void *clientData)
+static void
+AsyncTCPSocketSendCallback(void *clientData)         // IN
 {
-   AsyncSocket *s = clientData;
+   AsyncTCPSocket *s = clientData;
    int retval;
 
    ASSERT(s);
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-   ASSERT(AsyncSocketIsLocked(s));
+   ASSERT(AsyncTCPSocketIsLocked(s));
 
-   AsyncSocketAddRef(s);
-   s->sendCb = FALSE; /* AsyncSocketSendCallback is never periodic */
+   AsyncTCPSocketAddRef(s);
+   s->sendCb = FALSE; /* AsyncTCPSocketSendCallback is never periodic */
    s->sendCbTimer = FALSE;
-   retval = AsyncSocketWriteBuffers(s);
-   if (retval != ASOCKERR_SUCCESS) {
-      AsyncSocketHandleError(s, retval);
+   retval = AsyncTCPSocketWriteBuffers(s);
+   if (retval != ASOCKERR_SUCCESS &&
+       retval != ASOCKERR_CLOSED) {
+      AsyncTCPSocketHandleError(s, retval);
    } else if (s->sendBufList && !s->sendCb) {
       VMwareStatus pollStatus;
 
@@ -5161,33 +4766,33 @@ AsyncSocketSendCallback(void *clientData)
        */
 
       if (!s->sslConnected) {
-         pollStatus = AsyncSocketPollAdd(s, FALSE, 0,
-                                         s->vt->sendCallback, 100000);
+         pollStatus = AsyncTCPSocketPollAdd(s, FALSE, 0,
+                                         s->internalSendFn, 100000);
          VERIFY(pollStatus == VMWARE_STATUS_SUCCESS);
          s->sendCbTimer = TRUE;
       } else
 #endif
       {
-         pollStatus = AsyncSocketPollAdd(s, TRUE, POLL_FLAG_WRITE,
-                                         s->vt->sendCallback);
+         pollStatus = AsyncTCPSocketPollAdd(s, TRUE, POLL_FLAG_WRITE,
+                                         s->internalSendFn);
          VERIFY(pollStatus == VMWARE_STATUS_SUCCESS);
       }
       s->sendCb = TRUE;
    }
-   AsyncSocketRelease(s, FALSE);
+   AsyncTCPSocketRelease(s);
 }
 
 
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketIPollSendCallback --
+ * AsyncTCPSocketIPollSendCallback --
  *
  *      IVmdbPoll callback for output socket buffer space available.  IVmdbPoll
  *      does not handle callback locks, so this function first locks the
  *      asyncsocket and verify that the send callback has not been cancelled.
  *      IVmdbPoll only has periodic callbacks, so this function unregisters
- *      itself before calling AsyncSocketSendCallback to do the real work.
+ *      itself before calling AsyncTCPSocketSendCallback to do the real work.
  *
  * Results:
  *      None.
@@ -5199,20 +4804,19 @@ AsyncSocketSendCallback(void *clientData)
  */
 
 static void
-AsyncSocketIPollSendCallback(void *clientData)  // IN:
+AsyncTCPSocketIPollSendCallback(void *clientData)  // IN:
 {
 #ifdef VMX86_TOOLS
    NOT_IMPLEMENTED();
 #else
-   AsyncSocket *s = clientData;
+   AsyncTCPSocket *s = clientData;
    MXUserRecLock *lock;
 
    ASSERT(s);
-   ASSERT(s->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
 
-   AsyncSocketLock(s);
+   AsyncTCPSocketLock(s);
    s->inIPollCb |= IN_IPOLL_SEND;
-   lock = s->pollParams.lock;
+   lock = AsyncTCPSocketPollParams(s)->lock;
    if (s->sendCb) {
       /*
        * Unregister this callback as we want the non-periodic behavior.  There
@@ -5221,17 +4825,18 @@ AsyncSocketIPollSendCallback(void *clientData)  // IN:
        * We would release that reference at the end.
        */
       if (s->sendCbTimer) {
-         AsyncSocketIPollRemove(s, FALSE, 0, AsyncSocketIPollSendCallback);
+         AsyncTCPSocketIPollRemove(s, FALSE, 0, AsyncTCPSocketIPollSendCallback);
       } else {
-         AsyncSocketIPollRemove(s, TRUE, POLL_FLAG_WRITE,
-                                AsyncSocketIPollSendCallback);
+         AsyncTCPSocketIPollRemove(s, TRUE, POLL_FLAG_WRITE,
+                                   AsyncTCPSocketIPollSendCallback);
       }
 
-      AsyncSocketSendCallback(s);
+      AsyncTCPSocketSendCallback(s);
    }
 
    s->inIPollCb &= ~IN_IPOLL_SEND;
-   AsyncSocketRelease(s, TRUE);
+   AsyncTCPSocketRelease(s);
+   AsyncTCPSocketUnlock(s);
    if (lock != NULL) {
       MXUser_DecRefRecLock(lock);
    }
@@ -5242,80 +4847,7 @@ AsyncSocketIPollSendCallback(void *clientData)  // IN:
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketAddRef --
- *
- *    Increments reference count on AsyncSocket struct.
- *
- * Results:
- *    New reference count.
- *
- * Side effects:
- *    None.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-AsyncSocketAddRef(AsyncSocket *s)
-{
-   ASSERT(s && s->refCount > 0);
-   ASOCKLOG(1, s, ("%s (count now %d)\n", __FUNCTION__, s->refCount + 1));
-
-   return ++s->refCount;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * AsyncSocketRelease --
- *
- *    Decrements reference count on AsyncSocket struct, freeing it when it
- *    reaches 0.  If "unlock" is TRUE, releases the lock after decrementing
- *    the count.
- *
- * Results:
- *    New reference count; 0 if freed.
- *
- * Side effects:
- *    May free struct.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-AsyncSocketRelease(AsyncSocket *s,  // IN:
-                   Bool unlock)     // IN: release lock
-{
-   int count = --s->refCount;
-
-   if (unlock) {
-      AsyncSocketUnlock(s);
-   }
-   if (0 == count) {
-      ASOCKLOG(1, s, ("Final release; freeing asock struct\n"));
-
-      if (s->closeCb) {
-         s->closeCb(s);
-      }
-
-      if (s->vt && s->vt->release) {
-         s->vt->release(s);
-      }
-      free(s);
-
-      return 0;
-   }
-   ASOCKLOG(1, s, ("Release (count now %d)\n", count));
-
-   return count;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * AsyncSocketPollAdd --
+ * AsyncTCPSocketPollAdd --
  *
  *    Add a poll callback.  Wrapper for Poll_Callback since we always call
  *    it in one of two basic forms.
@@ -5331,17 +4863,15 @@ AsyncSocketRelease(AsyncSocket *s,  // IN:
  *-----------------------------------------------------------------------------
  */
 
-VMwareStatus
-AsyncSocketPollAdd(AsyncSocket *asock,
-                   Bool socket,
-                   int flags,
-                   PollerFunction callback,
-                   ...)
+static VMwareStatus
+AsyncTCPSocketPollAdd(AsyncTCPSocket *asock,         // IN
+                      Bool socket,                   // IN
+                      int flags,                     // IN
+                      PollerFunction callback,       // IN
+                      ...)                           // IN
 {
    int type, info;
 
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-
    if (socket) {
       ASSERT(asock->fd != -1);
       type = POLL_DEVICE;
@@ -5357,21 +4887,21 @@ AsyncSocketPollAdd(AsyncSocket *asock,
       va_end(marker);
    }
 
-   if (asock->pollParams.iPoll != NULL) {
-      return AsyncSocketIPollAdd(asock, socket, flags, callback, info);
+   if (AsyncTCPSocketPollParams(asock)->iPoll != NULL) {
+      return AsyncTCPSocketIPollAdd(asock, socket, flags, callback, info);
    }
 
-   return Poll_Callback(asock->pollParams.pollClass,
-                        flags | asock->pollParams.flags,
+   return Poll_Callback(AsyncTCPSocketPollParams(asock)->pollClass,
+                        flags | AsyncTCPSocketPollParams(asock)->flags,
                         callback, asock, type, info,
-                        asock->pollParams.lock);
+                        AsyncTCPSocketPollParams(asock)->lock);
 }
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketPollRemove --
+ * AsyncTCPSocketPollRemove --
  *
  *    Remove a poll callback.  Wrapper for Poll_CallbackRemove since we
  *    always call it in one of two basic forms.
@@ -5385,18 +4915,16 @@ AsyncSocketPollAdd(AsyncSocket *asock,
  *-----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketPollRemove(AsyncSocket *asock,
-                      Bool socket,
-                      int flags,
-                      PollerFunction callback)
+static Bool
+AsyncTCPSocketPollRemove(AsyncTCPSocket *asock,         // IN
+                         Bool socket,                   // IN
+                         int flags,                     // IN
+                         PollerFunction callback)       // IN
 {
    int type;
 
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
-
-   if (asock->pollParams.iPoll != NULL) {
-      return AsyncSocketIPollRemove(asock, socket, flags, callback);
+   if (AsyncTCPSocketPollParams(asock)->iPoll != NULL) {
+      return AsyncTCPSocketIPollRemove(asock, socket, flags, callback);
    }
 
    if (socket) {
@@ -5407,8 +4935,8 @@ AsyncSocketPollRemove(AsyncSocket *asock,
       type = POLL_REALTIME;
    }
 
-   return Poll_CallbackRemove(asock->pollParams.pollClass,
-                              flags | asock->pollParams.flags,
+   return Poll_CallbackRemove(AsyncTCPSocketPollParams(asock)->pollClass,
+                              flags | AsyncTCPSocketPollParams(asock)->flags,
                               callback, asock, type);
 }
 
@@ -5416,7 +4944,7 @@ AsyncSocketPollRemove(AsyncSocket *asock,
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketIPollAdd --
+ * AsyncTCPSocketIPollAdd --
  *
  *    Add a poll callback.  Wrapper for IVmdbPoll.Register[Timer].
  *
@@ -5432,11 +4960,11 @@ AsyncSocketPollRemove(AsyncSocket *asock,
  */
 
 static VMwareStatus
-AsyncSocketIPollAdd(AsyncSocket *asock,
-                    Bool socket,
-                    int flags,
-                    PollerFunction callback,
-                    int info)
+AsyncTCPSocketIPollAdd(AsyncTCPSocket *asock,         // IN
+                       Bool socket,                   // IN
+                       int flags,                     // IN
+                       PollerFunction callback,       // IN
+                       int info)                      // IN
 {
 #ifdef VMX86_TOOLS
    return VMWARE_STATUS_ERROR;
@@ -5445,16 +4973,16 @@ AsyncSocketIPollAdd(AsyncSocket *asock,
    VmdbRet ret;
    IVmdbPoll *poll;
 
-   ASSERT(asock->pollParams.iPoll);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->iPoll);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
    /* Protect asyncsocket and lock from disappearing */
-   AsyncSocketAddRef(asock);
-   if (asock->pollParams.lock != NULL) {
-      MXUser_IncRefRecLock(asock->pollParams.lock);
+   AsyncTCPSocketAddRef(asock);
+   if (AsyncTCPSocketPollParams(asock)->lock != NULL) {
+      MXUser_IncRefRecLock(AsyncTCPSocketPollParams(asock)->lock);
    }
 
-   poll = asock->pollParams.iPoll;
+   poll = AsyncTCPSocketPollParams(asock)->iPoll;
 
    if (socket) {
       int pollFlags = (flags & POLL_FLAG_READ) != 0 ? VMDB_PRF_READ
@@ -5468,10 +4996,10 @@ AsyncSocketIPollAdd(AsyncSocket *asock,
    if (ret != VMDB_S_OK) {
       Log(ASOCKPREFIX "failed to register callback (%s %d): error %d\n",
           socket ? "socket" : "delay", info, ret);
-      if (asock->pollParams.lock != NULL) {
-         MXUser_DecRefRecLock(asock->pollParams.lock);
+      if (AsyncTCPSocketPollParams(asock)->lock != NULL) {
+         MXUser_DecRefRecLock(AsyncTCPSocketPollParams(asock)->lock);
       }
-      AsyncSocketRelease(asock, FALSE);
+      AsyncTCPSocketRelease(asock);
       status = VMWARE_STATUS_ERROR;
    }
 
@@ -5483,7 +5011,7 @@ AsyncSocketIPollAdd(AsyncSocket *asock,
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketIPollRemove --
+ * AsyncTCPSocketIPollRemove --
  *
  *    Remove a poll callback.  Wrapper for IVmdbPoll.Unregister[Timer].
  *
@@ -5499,10 +5027,10 @@ AsyncSocketIPollAdd(AsyncSocket *asock,
  */
 
 static Bool
-AsyncSocketIPollRemove(AsyncSocket *asock,
-                       Bool socket,
-                       int flags,
-                       PollerFunction callback)
+AsyncTCPSocketIPollRemove(AsyncTCPSocket *asock,         // IN
+                          Bool socket,                   // IN
+                          int flags,                     // IN
+                          PollerFunction callback)       // IN
 {
 #ifdef VMX86_TOOLS
    return FALSE;
@@ -5510,10 +5038,10 @@ AsyncSocketIPollRemove(AsyncSocket *asock,
    IVmdbPoll *poll;
    Bool ret;
 
-   ASSERT(asock->pollParams.iPoll);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->iPoll);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   poll = asock->pollParams.iPoll;
+   poll = AsyncTCPSocketPollParams(asock)->iPoll;
 
    if (socket) {
       int pollFlags = (flags & POLL_FLAG_READ) != 0 ? VMDB_PRF_READ
@@ -5526,17 +5054,17 @@ AsyncSocketIPollRemove(AsyncSocket *asock,
 
    if (ret &&
        !((asock->inIPollCb & IN_IPOLL_RECV) != 0 &&
-         callback == asock->vt->recvCallback) &&
+         callback == asock->internalRecvFn) &&
        !((asock->inIPollCb & IN_IPOLL_SEND) != 0 &&
-         callback == asock->vt->sendCallback)) {
-      MXUserRecLock *lock = asock->pollParams.lock;
+         callback == asock->internalSendFn)) {
+      MXUserRecLock *lock = AsyncTCPSocketPollParams(asock)->lock;
 
       /*
        * As the callback has been unregistered and we are not currently in
        * the callback being removed, we can safely release the reference taken
        * when registering the callback.
        */
-      AsyncSocketRelease(asock, FALSE);
+      AsyncTCPSocketRelease(asock);
       if (lock != NULL) {
          MXUser_DecRefRecLock(lock);
       }
@@ -5550,74 +5078,54 @@ AsyncSocketIPollRemove(AsyncSocket *asock,
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketCancelRecv --
+ * AsyncTCPSocketCancelRecv --
  *
  *    Call this function if you know what you are doing. This should be
  *    called if you want to synchronously receive the outstanding data on
  *    the socket. It removes the recv poll callback. It also returns number of
  *    partially read bytes (if any). A partially read response may exist as
- *    AsyncSocketRecvCallback calls the recv callback only when all the data
+ *    AsyncTCPSocketRecvCallback calls the recv callback only when all the data
  *    has been received.
  *
  * Results:
  *    ASOCKERR_SUCCESS or ASOCKERR_INVAL.
  *
  * Side effects:
- *    Subsequent client call to AsyncSocket_Recv can reinstate async behaviour.
+ *    Subsequent client call to AsyncTCPSocket_Recv can reinstate async behaviour.
  *
  *-----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketCancelRecv(AsyncSocket *asock,         // IN
-                      int *partialRecvd,          // OUT
-                      void **recvBuf,             // OUT
-                      void **recvFn,              // OUT
-                      Bool cancelOnSend)          // IN
+static int
+AsyncTCPSocketCancelRecv(AsyncSocket *base,          // IN
+                         int *partialRecvd,          // OUT
+                         void **recvBuf,             // OUT
+                         void **recvFn,              // OUT
+                         Bool cancelOnSend)          // IN
 {
-   int retVal;
+   AsyncTCPSocket *asock = TCPSocket(base);
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   if (asock->state != AsyncSocketConnected) {
+   if (AsyncTCPSocketGetState(asock) != AsyncSocketConnected) {
       Warning(ASOCKPREFIX "Failed to cancel request on disconnected socket!\n");
-      retVal = ASOCKERR_INVAL;
-      goto outHaveLock;
+      return ASOCKERR_INVAL;
    }
 
    if (asock->inBlockingRecv) {
       Warning(ASOCKPREFIX "Cannot cancel request while a blocking recv is "
                           "pending.\n");
-      retVal = ASOCKERR_INVAL;
-      goto outHaveLock;
+      return ASOCKERR_INVAL;
    }
 
    if (!cancelOnSend && (asock->sendBufList || asock->sendCb)) {
       Warning(ASOCKPREFIX "Can't cancel request as socket has send operation "
               "pending.\n");
-      retVal = ASOCKERR_INVAL;
-      goto outHaveLock;
+      return ASOCKERR_INVAL;
    }
 
-   ASSERT(asock->vt);
-   ASSERT(asock->vt->cancelRecvCbInternal);
-   asock->vt->cancelRecvCbInternal(asock);
-
-   if (partialRecvd && asock->recvLen > 0) {
-      ASOCKLOG(1, asock, ("Partially read %d bytes out of %d bytes while "
-                          "cancelling recv request.\n", asock->recvPos, asock->recvLen));
-      *partialRecvd = asock->recvPos;
-   }
-   if (recvFn) {
-      *recvFn = asock->recvFn;
-   }
-   if (recvBuf) {
-      *recvBuf = asock->recvBuf;
-   }
-   asock->recvBuf = NULL;
-   asock->recvFn = NULL;
-   asock->recvPos = 0;
-   asock->recvLen = 0;
+   AsyncTCPSocketCancelRecvCb(asock);
+   AsyncSocketCancelRecv(BaseSocket(asock), partialRecvd, recvBuf, recvFn);
 
    if (asock->passFd.fd != -1) {
       SSLGeneric_close(asock->passFd.fd);
@@ -5625,18 +5133,14 @@ AsyncSocketCancelRecv(AsyncSocket *asock,         // IN
    }
    asock->passFd.expected = FALSE;
 
-   retVal = ASOCKERR_SUCCESS;
-
-outHaveLock:
-   AsyncSocketUnlock(asock);
-   return retVal;
+   return ASOCKERR_SUCCESS;
 }
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketGetReceivedFd --
+ * AsyncTCPSocketGetReceivedFd --
  *
  *    Retrieve received file descriptor from socket.
  *
@@ -5649,27 +5153,22 @@ outHaveLock:
  *-----------------------------------------------------------------------------
  */
 
-int
-AsyncSocketGetReceivedFd(AsyncSocket *asock)      // IN
+static int
+AsyncTCPSocketGetReceivedFd(AsyncSocket *base)      // IN
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    int fd;
 
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   AsyncSocketLock(asock);
-
-   if (asock->state != AsyncSocketConnected) {
+   if (AsyncTCPSocketGetState(asock) != AsyncSocketConnected) {
       Warning(ASOCKPREFIX "Failed to receive fd on disconnected socket!\n");
-      AsyncSocketUnlock(asock);
-
       return -1;
    }
    fd = asock->passFd.fd;
    asock->passFd.fd = -1;
    asock->passFd.expected = FALSE;
 
-   AsyncSocketUnlock(asock);
-
    return fd;
 }
 
@@ -5677,7 +5176,7 @@ AsyncSocketGetReceivedFd(AsyncSocket *asock)      // IN
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketConnectSSL --
+ * AsyncTCPSocketConnectSSL --
  *
  *    Initialize the socket's SSL object, by calling SSL_ConnectAndVerify.
  *    NOTE: This call is blocking.
@@ -5691,14 +5190,14 @@ AsyncSocketGetReceivedFd(AsyncSocket *asock)      // IN
  *-----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketConnectSSL(AsyncSocket *asock,           // IN
-                      SSLVerifyParam *verifyParam, // IN/OPT
-                      void *sslContext)            // IN/OPT
+static Bool
+AsyncTCPSocketConnectSSL(AsyncSocket *base,           // IN
+                         SSLVerifyParam *verifyParam, // IN/OPT
+                         void *sslContext)            // IN/OPT
 {
 #ifndef USE_SSL_DIRECT
+   AsyncTCPSocket *asock = TCPSocket(base);
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
 
    if (sslContext == NULL) {
       sslContext = SSL_DefaultContext();
@@ -5715,7 +5214,7 @@ AsyncSocketConnectSSL(AsyncSocket *asock,           // IN
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketAcceptSSL --
+ * AsyncTCPSocketAcceptSSL --
  *
  *    Initialize the socket's SSL object, by calling SSL_Accept or
  *    SSL_AcceptWithContext.
@@ -5729,13 +5228,13 @@ AsyncSocketConnectSSL(AsyncSocket *asock,           // IN
  *-----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketAcceptSSL(AsyncSocket *asock,     // IN
-                     void *sslCtx)           // IN: optional
+static Bool
+AsyncTCPSocketAcceptSSL(AsyncSocket *base,  // IN
+                        void *sslCtx)       // IN: optional
 {
 #ifndef USE_SSL_DIRECT
+   AsyncTCPSocket *asock = TCPSocket(base);
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
 
    if (sslCtx) {
       return SSL_AcceptWithContext(asock->sslSock, sslCtx);
@@ -5751,7 +5250,7 @@ AsyncSocketAcceptSSL(AsyncSocket *asock,     // IN
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketSslConnectCallback --
+ * AsyncTCPSocketSslConnectCallback --
  *
  *      Poll callback to redrive an outstanding ssl connect operation.
  *
@@ -5765,43 +5264,43 @@ AsyncSocketAcceptSSL(AsyncSocket *asock,     // IN
  */
 
 static void
-AsyncSocketSslConnectCallback(void *clientData)  // IN
+AsyncTCPSocketSslConnectCallback(void *clientData)  // IN
 {
 #ifndef USE_SSL_DIRECT
    int sslOpCode;
    VMwareStatus pollStatus;
-   AsyncSocket *asock = clientData;
+   AsyncTCPSocket *asock = clientData;
 
    ASSERT(asock);
-   ASSERT(asock->pollParams.iPoll == NULL);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->iPoll == NULL);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   AsyncSocketAddRef(asock);
+   AsyncTCPSocketAddRef(asock);
 
    /* Only set if poll callback is registered */
    asock->sslPollFlags = 0;
 
    sslOpCode = SSL_TryCompleteConnect(asock->sslSock);
    if (sslOpCode > 0) {
-      (*asock->sslConnectFn)(TRUE, asock, asock->clientData);
+      (*asock->sslConnectFn)(TRUE, BaseSocket(asock), asock->clientData);
    } else if (sslOpCode < 0) {
-      (*asock->sslConnectFn)(FALSE, asock, asock->clientData);
+      (*asock->sslConnectFn)(FALSE, BaseSocket(asock), asock->clientData);
    } else {
       asock->sslPollFlags = SSL_WantRead(asock->sslSock) ?
                             POLL_FLAG_READ : POLL_FLAG_WRITE;
 
       /* register the poll callback to redrive the SSL connect */
-      pollStatus = AsyncSocketPollAdd(asock, TRUE, asock->sslPollFlags,
-                                      AsyncSocketSslConnectCallback);
+      pollStatus = AsyncTCPSocketPollAdd(asock, TRUE, asock->sslPollFlags,
+                                      AsyncTCPSocketSslConnectCallback);
 
       if (pollStatus != VMWARE_STATUS_SUCCESS) {
-         ASOCKWARN(asock, ("failed to reinstall ssl connect callback!\n"));
+         TCPSOCKWARN(asock, ("failed to reinstall ssl connect callback!\n"));
          asock->sslPollFlags = 0;
-         (*asock->sslConnectFn)(FALSE, asock, asock->clientData);
+         (*asock->sslConnectFn)(FALSE, BaseSocket(asock), asock->clientData);
       }
    }
 
-   AsyncSocketRelease(asock, FALSE);
+   AsyncTCPSocketRelease(asock);
 #else
    NOT_IMPLEMENTED();
 #endif
@@ -5811,7 +5310,7 @@ AsyncSocketSslConnectCallback(void *clientData)  // IN
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketStartSslConnect --
+ * AsyncTCPSocketStartSslConnect --
  *
  *    Start an asynchronous SSL connect operation.
  *
@@ -5834,42 +5333,39 @@ AsyncSocketSslConnectCallback(void *clientData)  // IN
  *-----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketStartSslConnect(AsyncSocket *asock,                   // IN
-                           SSLVerifyParam *verifyParam,          // IN/OPT
-                           void *sslCtx,                         // IN
-                           AsyncSocketSslConnectFn sslConnectFn, // IN
-                           void *clientData)                     // IN
+static void
+AsyncTCPSocketStartSslConnect(AsyncSocket *base,                    // IN
+                              SSLVerifyParam *verifyParam,          // IN/OPT
+                              void *sslCtx,                         // IN
+                              AsyncSocketSslConnectFn sslConnectFn, // IN
+                              void *clientData)                     // IN
 {
 #ifndef USE_SSL_DIRECT
+   AsyncTCPSocket *asock = TCPSocket(base);
    Bool ok;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
    ASSERT(sslConnectFn);
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
    if (asock->sslConnectFn || asock->sslAcceptFn) {
-      ASOCKWARN(asock, ("An SSL operation was already initiated.\n"));
-      goto done;
+      TCPSOCKWARN(asock, ("An SSL operation was already initiated.\n"));
+      return;
    }
 
    ok = SSL_SetupConnectAndVerifyWithContext(asock->sslSock, verifyParam,
                                              sslCtx);
    if (!ok) {
       /* Something went wrong already */
-      (*sslConnectFn)(FALSE, asock, clientData);
-      goto done;
+      (*sslConnectFn)(FALSE, BaseSocket(asock), clientData);
+      return;
    }
 
    asock->sslConnectFn = sslConnectFn;
    asock->clientData = clientData;
 
-   AsyncSocketSslConnectCallback(asock);
-
-done:
-   AsyncSocketUnlock(asock);
+   AsyncTCPSocketSslConnectCallback(asock);
 #else
    NOT_IMPLEMENTED();
 #endif
@@ -5879,7 +5375,7 @@ done:
 /*
  *----------------------------------------------------------------------------
  *
- * AsyncSocketSslAcceptCallback --
+ * AsyncTCPSocketSslAcceptCallback --
  *
  *      Poll callback for redrive an outstanding ssl accept operation
  *
@@ -5893,49 +5389,49 @@ done:
  */
 
 static void
-AsyncSocketSslAcceptCallback(void *clientData)
+AsyncTCPSocketSslAcceptCallback(void *clientData)         // IN
 {
    int sslOpCode;
-   AsyncSocket *asock = clientData;
+   AsyncTCPSocket *asock = clientData;
    VMwareStatus pollStatus;
 
    ASSERT(asock);
-   ASSERT(asock->pollParams.iPoll == NULL);
-   ASSERT(AsyncSocketIsLocked(asock));
+   ASSERT(AsyncTCPSocketPollParams(asock)->iPoll == NULL);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
-   AsyncSocketAddRef(asock);
+   AsyncTCPSocketAddRef(asock);
 
    /* Only set if poll callback is registered */
    asock->sslPollFlags = 0;
 
    sslOpCode = SSL_TryCompleteAccept(asock->sslSock);
    if (sslOpCode > 0) {
-      (*asock->sslAcceptFn)(TRUE, asock, asock->clientData);
+      (*asock->sslAcceptFn)(TRUE, BaseSocket(asock), asock->clientData);
    } else if (sslOpCode < 0) {
-      (*asock->sslAcceptFn)(FALSE, asock, asock->clientData);
+      (*asock->sslAcceptFn)(FALSE, BaseSocket(asock), asock->clientData);
    } else {
       asock->sslPollFlags = SSL_WantRead(asock->sslSock) ?
                             POLL_FLAG_READ : POLL_FLAG_WRITE;
 
       /* register the poll callback to redrive the SSL accept */
-      pollStatus = AsyncSocketPollAdd(asock, TRUE, asock->sslPollFlags,
-                                      AsyncSocketSslAcceptCallback);
+      pollStatus = AsyncTCPSocketPollAdd(asock, TRUE, asock->sslPollFlags,
+                                      AsyncTCPSocketSslAcceptCallback);
 
       if (pollStatus != VMWARE_STATUS_SUCCESS) {
-         ASOCKWARN(asock, ("failed to reinstall ssl accept callback!\n"));
+         TCPSOCKWARN(asock, ("failed to reinstall ssl accept callback!\n"));
          asock->sslPollFlags = 0;
-         (*asock->sslAcceptFn)(FALSE, asock, asock->clientData);
+         (*asock->sslAcceptFn)(FALSE, BaseSocket(asock), asock->clientData);
       }
    }
 
-   AsyncSocketRelease(asock, FALSE);
+   AsyncTCPSocketRelease(asock);
 }
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketStartSslAccept --
+ * AsyncTCPSocketStartSslAccept --
  *
  *    Start an asynchronous SSL accept operation.
  *
@@ -5961,46 +5457,43 @@ AsyncSocketSslAcceptCallback(void *clientData)
  *-----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketStartSslAccept(AsyncSocket *asock,                 // IN
-                          void *sslCtx,                       // IN
-                          AsyncSocketSslAcceptFn sslAcceptFn, // IN
-                          void *clientData)                   // IN
+static void
+AsyncTCPSocketStartSslAccept(AsyncSocket *base,                  // IN
+                             void *sslCtx,                       // IN
+                             AsyncSocketSslAcceptFn sslAcceptFn, // IN
+                             void *clientData)                   // IN
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    Bool ok;
 
    ASSERT(asock);
-   ASSERT(asock->asockType != ASYNCSOCKET_TYPE_NAMEDPIPE);
    ASSERT(sslAcceptFn);
 
-   AsyncSocketLock(asock);
+   ASSERT(AsyncTCPSocketIsLocked(asock));
 
    if (asock->sslAcceptFn || asock->sslConnectFn) {
-      ASOCKWARN(asock, ("An SSL operation was already initiated.\n"));
-      goto done;
+      TCPSOCKWARN(asock, ("An SSL operation was already initiated.\n"));
+      return;
    }
 
    ok = SSL_SetupAcceptWithContext(asock->sslSock, sslCtx);
    if (!ok) {
       /* Something went wrong already */
-      (*sslAcceptFn)(FALSE, asock, clientData);
-      goto done;
+      (*sslAcceptFn)(FALSE, BaseSocket(asock), clientData);
+      return;
    }
 
    asock->sslAcceptFn = sslAcceptFn;
    asock->clientData = clientData;
 
-   AsyncSocketSslAcceptCallback(asock);
-
-done:
-   AsyncSocketUnlock(asock);
+   AsyncTCPSocketSslAcceptCallback(asock);
 }
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketSetBufferSizes --
+ * AsyncTCPSocketSetBufferSizes --
  *
  *    Set socket level recv/send buffer sizes if they are less than given sizes.
  *
@@ -6014,11 +5507,12 @@ done:
  *-----------------------------------------------------------------------------
  */
 
-Bool
-AsyncSocketSetBufferSizes(AsyncSocket *asock,  // IN
-                          int sendSz,          // IN
-                          int recvSz)          // IN
+static Bool
+AsyncTCPSocketSetBufferSizes(AsyncSocket *base,   // IN
+                             int sendSz,          // IN
+                             int recvSz)          // IN
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    int err;
    int buffSz;
    int len = sizeof buffSz;
@@ -6074,11 +5568,11 @@ AsyncSocketSetBufferSizes(AsyncSocket *asock,  // IN
 /*
  *-----------------------------------------------------------------------------
  *
- * AsyncSocketSetSendLowLatencyMode --
+ * AsyncTCPSocketSetSendLowLatencyMode --
  *
  *    Put the socket into a mode where we attempt to issue sends
- *    directly from within AsyncSocket_Send().  Ordinarily, we would
- *    set up a Poll callback from within AsyncSocket_Send(), which
+ *    directly from within AsyncTCPSocket_Send().  Ordinarily, we would
+ *    set up a Poll callback from within AsyncTCPSocket_Send(), which
  *    introduces some non-zero latency to the send path.  In
  *    low-latency-send mode, that delay is potentially avoided.  This
  *    does introduce a behavioural change; the send completion
@@ -6095,26 +5589,50 @@ AsyncSocketSetBufferSizes(AsyncSocket *asock,  // IN
  *-----------------------------------------------------------------------------
  */
 
-void
-AsyncSocketSetSendLowLatencyMode(AsyncSocket *asock,  // IN
-                                 Bool enable)         // IN
+static void
+AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *base,  // IN
+                                    Bool enable)        // IN
 {
+   AsyncTCPSocket *asock = TCPSocket(base);
    asock->sendLowLatency = enable;
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AsyncTCPSocketDestroy --
+ *
+ *    Free the AsyncTCPSocket struct and all of its child storage.
+ *
+ * Result
+ *    None
+ *
+ * Side-effects
+ *    Releases memory.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+AsyncTCPSocketDestroy(AsyncSocket *base)         // IN/OUT
+{
+   free(base);
+}
+
+
 #ifndef _WIN32
 /*
  *-----------------------------------------------------------------------------
  *
  * AsyncSocket_ListenSocketUDS --
  *
- *      Listens on the specified unix domain socket, and accepts new socket
- *      connections. Fires the connect callback with new AsyncSocket object for
- *      each connection.
+ *      Listens on the specified unix domain socket, and accepts new
+ *      socket connections. Fires the connect callback with new
+ *      AsyncTCPSocket object for each connection.
  *
  * Results:
- *      New AsyncSocket in listening state or NULL on error
+ *      New AsyncTCPSocket in listening state or NULL on error
  *
  * Side effects:
  *      Creates new Unix domain socket, binds and listens.
@@ -6130,6 +5648,7 @@ AsyncSocket_ListenSocketUDS(const char *pipeName,               // IN
                             int *outError)                      // OUT
 {
    struct sockaddr_un addr;
+   AsyncTCPSocket *asock;
 
    memset(&addr, 0, sizeof addr);
    addr.sun_family = AF_UNIX;
@@ -6137,9 +5656,10 @@ AsyncSocket_ListenSocketUDS(const char *pipeName,               // IN
 
    Log(ASOCKPREFIX "creating new socket listening on %s\n", pipeName);
 
-   return AsyncSocketListenImpl((struct sockaddr_storage *)&addr,
-                                sizeof addr,
-                                connectFn, clientData, pollParams, FALSE,
-                                FALSE, NULL, NULL, outError);
+   asock = AsyncTCPSocketListenImpl((struct sockaddr_storage *)&addr,
+                                    sizeof addr, connectFn, clientData,
+                                    pollParams, outError);
+
+   return BaseSocket(asock);
 }
 #endif
index 0ae1c3a8b280d0c4570e8949d43d5aacae3771e5..2575c3359057c51132fb328f067819031e633300 100644 (file)
 #define INCLUDE_ALLOW_USERLEVEL
 #include "includeCheck.h"
 
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#endif
-
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -77,6 +73,30 @@ extern "C" {
 #define ASOCKERR_NETUNREACH        14
 #define ASOCKERR_ADDRUNRESV        15
 
+/*
+ * Cross-platform codes for AsyncSocket_GetGenericError():
+ */
+#ifdef _WIN32
+#define ASOCK_ENOTCONN          WSAENOTCONN
+#define ASOCK_ENOTSOCK          WSAENOTSOCK
+#define ASOCK_EADDRINUSE        WSAEADDRINUSE
+#define ASOCK_ECONNECTING       WSAEWOULDBLOCK
+#define ASOCK_EWOULDBLOCK       WSAEWOULDBLOCK
+#define ASOCK_ENETUNREACH       WSAENETUNREACH
+#define ASOCK_ECONNRESET        WSAECONNRESET
+#define ASOCK_ECONNABORTED      WSAECONNABORTED
+#define ASOCK_EPIPE             ERROR_NO_DATA
+#else
+#define ASOCK_ENOTCONN          ENOTCONN
+#define ASOCK_ENOTSOCK          ENOTSOCK
+#define ASOCK_EADDRINUSE        EADDRINUSE
+#define ASOCK_ECONNECTING       EINPROGRESS
+#define ASOCK_EWOULDBLOCK       EWOULDBLOCK
+#define ASOCK_ENETUNREACH       ENETUNREACH
+#define ASOCK_ECONNRESET        ECONNRESET
+#define ASOCK_ECONNABORTED      ECONNABORTED
+#define ASOCK_EPIPE             EPIPE
+#endif
 
 /*
  * Websocket close status codes --
@@ -160,6 +180,15 @@ typedef enum AsyncSocketState {
    AsyncSocketClosed,
 } AsyncSocketState;
 
+
+typedef struct AsyncSocketNetworkStats {
+   uint32 cwndBytes;             /* maximum outstanding bytes */
+   uint32 rttSmoothedAvgMillis;  /* rtt average in milliseconds */
+   uint32 rttSmoothedVarMillis;  /* rtt variance in milliseconds */
+   uint32 queuedBytes;           /* unsent bytes in send queue */
+   uint32 inflightBytes;         /* current outstanding bytes */
+} AsyncSocketNetworkStats;
+
 AsyncSocketState AsyncSocket_GetState(AsyncSocket *sock);
 
 const char * AsyncSocket_Err2String(int err);
@@ -217,7 +246,7 @@ typedef void (*AsyncSocketSslAcceptFn) (Bool status, AsyncSocket *asock,
                                         void *clientData);
 typedef void (*AsyncSocketSslConnectFn) (Bool status, AsyncSocket *asock,
                                          void *clientData);
-typedef void (*AsyncSocketCloseCb) (AsyncSocket *asock);
+typedef void (*AsyncSocketCloseFn) (AsyncSocket *asock, void *clientData);
 
 /*
  * Listen on port and fire callback with new asock
@@ -239,7 +268,6 @@ AsyncSocket *AsyncSocket_ListenVMCI(unsigned int cid,
                                     void *clientData,
                                     AsyncSocketPollParams *pollParams,
                                     int *outError);
-#ifndef VMX86_TOOLS
 AsyncSocket *AsyncSocket_ListenWebSocket(const char *addrStr,
                                          unsigned int port,
                                          Bool useSSL,
@@ -269,16 +297,14 @@ AsyncSocket *AsyncSocket_ListenWebSocketUDS(const char *pipeName,
                                             void *clientData,
                                             AsyncSocketPollParams *pollParams,
                                             int *outError);
-
 AsyncSocket *AsyncSocket_ListenSocketUDS(const char *pipeName,
                                          AsyncSocketConnectFn connectFn,
                                          void *clientData,
                                          AsyncSocketPollParams *pollParams,
                                          int *outError);
-
-#endif
 #endif
 
+
 /*
  * Connect to address:port and fire callback with new asock
  */
@@ -322,7 +348,6 @@ AsyncSocket_CreateNamedPipe(const char *pipeName,
                             int *error);
 #endif
 
-#if !defined VMX86_TOOLS || TARGET_OS_IPHONE
 AsyncSocket *
 AsyncSocket_ConnectWebSocket(const char *url,
                              struct _SSLVerifyParam *sslVerifyParam,
@@ -346,7 +371,6 @@ AsyncSocket_ConnectProxySocket(const char *url,
                                AsyncSocketConnectFlags flags,
                                AsyncSocketPollParams *pollParams,
                                int *error);
-#endif
 
 /*
  * Initiate SSL connection on existing asock, with optional cert verification
@@ -383,10 +407,8 @@ int AsyncSocket_UseNodelay(AsyncSocket *asock, Bool nodelay);
 /*
  * Set TCP timeout values on this AsyncSocket.
  */
-#ifdef VMX86_SERVER
 int AsyncSocket_SetTCPTimeouts(AsyncSocket *asock, int keepIdle,
                                int keepIntvl, int keepCnt);
-#endif
 
 /*
  * Waits until at least one packet is received or times out.
@@ -449,6 +471,8 @@ int AsyncSocket_Send(AsyncSocket *asock, void *buf, int len,
                       AsyncSocketSendFn sendFn, void *clientData);
 
 int AsyncSocket_IsSendBufferFull(AsyncSocket *asock);
+int AsyncSocket_GetNetworkStats(AsyncSocket *asock,
+                                AsyncSocketNetworkStats *stats);
 int AsyncSocket_CancelRecv(AsyncSocket *asock, int *partialRecvd, void **recvBuf,
                            void **recvFn);
 int AsyncSocket_CancelRecvEx(AsyncSocket *asock, int *partialRecvd, void **recvBuf,
@@ -477,14 +501,7 @@ Bool AsyncSocket_SetBufferSizes(AsyncSocket *asock,  // IN
  */
 void AsyncSocket_SetCloseOptions(AsyncSocket *asock,
                                  int flushEnabledMaxWaitMsec,
-                                 AsyncSocketCloseCb closeCb);
-
-/*
- * Send websocket close frame.
- */
-int
-AsyncSocket_SendWebSocketCloseFrame(AsyncSocket *asock,
-                                    uint16 closeStatus);
+                                 AsyncSocketCloseFn closeCb);
 
 /*
  * Close the connection and destroy the asock.
@@ -504,7 +521,7 @@ char *AsyncSocket_GetWebSocketCookie(AsyncSocket *asock);
 /*
  * Retrieve the close status, if received, for a websocket connection
  */
-uint16 AsyncSocket_GetWebSocketCloseStatus(const AsyncSocket *asock);
+uint16 AsyncSocket_GetWebSocketCloseStatus(AsyncSocket *asock);
 
 /*
  * Set low-latency mode for sends:
@@ -521,11 +538,6 @@ const char *AsyncSocket_GetWebSocketProtocol(AsyncSocket *asock);
  */
 int AsyncSocket_GetWebSocketError(AsyncSocket *asock);
 
-/*
- * Get error code for proxySocket failure
- */
-int AsyncSocket_GetProxySocketError(AsyncSocket *asock);
-
 const char * stristr(const char *s, const char *find);
 
 /*
index 21490143848bb4f6b4eea8b7e426e26584d5cdf9..d3d3b0cad47c7fcc027dac6545c5a023e6f1406b 100644 (file)
@@ -39,7 +39,7 @@
 #if defined(VMX86_VIEWCLIENT)
    #define PRODUCT_VERSION    4,1,0,PRODUCT_BUILD_NUMBER_NUMERIC
 #elif defined(VMX86_VMRC) /* check VMX86_VMRC before VMX86_DESKTOP */
-   #define PRODUCT_VERSION    8,1,0,PRODUCT_BUILD_NUMBER_NUMERIC   /* VMRC_VERSION_NUMBER below has to match this */
+   #define PRODUCT_VERSION    9,0,0,PRODUCT_BUILD_NUMBER_NUMERIC   /* VMRC_VERSION_NUMBER below has to match this */
 #elif defined(VMX86_FLEX) /* check VMX86_FLEX before VMX86_DESKTOP */
    #define PRODUCT_VERSION    8,0,0,PRODUCT_BUILD_NUMBER_NUMERIC   /* FLEX_VERSION_NUMBER below has to match this */
 #elif defined(VMX86_TOOLS)
 #define WORKSTATION_VERSION "e.x.p"
 #define PLAYER_VERSION_NUMBER "12.0.0" /* this version number should always match real Player version number */
 #define PLAYER_VERSION "e.x.p"
-#define VMRC_VERSION_NUMBER "8.1.0" /* this version number should always match real VMRC version number */
-#define VMRC_VERSION "8.1.0"
+#define VMRC_VERSION_NUMBER "9.0.0" /* this version number should always match real VMRC version number */
+#define VMRC_VERSION "9.0.0"
 #define FLEX_CLIENT_VERSION_NUMBER "8.0.0"
 #define FLEX_CLIENT_VERSION "e.x.p"
 
  */
 #define PRODUCT_MAC_DESKTOP_VERSION_STRING_FOR_LICENSE "8.0"
 #define PRODUCT_PLAYER_VERSION_STRING_FOR_LICENSE "12.0"
-#define PRODUCT_VMRC_VERSION_STRING_FOR_LICENSE "8.1"
+#define PRODUCT_VMRC_VERSION_STRING_FOR_LICENSE "9.0"
 #define PRODUCT_FLEX_VERSION_STRING_FOR_LICENSE "8.0"
 
 #if defined(VMX86_TOOLS)