/*
* 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().
*/
int
-AsyncSocket_Init(void)
+AsyncTCPSocket_Init(void)
{
#ifdef _WIN32
WSADATA wsaData;
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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
*/
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;
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.
*----------------------------------------------------------------------------
*/
-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;
/*
*----------------------------------------------------------------------------
*
- * 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
*----------------------------------------------------------------------------
*/
-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;
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*
*----------------------------------------------------------------------------
*/
-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)) {
/*
*----------------------------------------------------------------------------
*
- * 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.
*
*----------------------------------------------------------------------------
*/
-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)) {
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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;
}
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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,
} else {
Log(ASOCKPREFIX "Could not resolve listener socket address.\n");
if (outError) {
- *outError = ASOCKERR_LISTEN;
+ *outError = ASOCKERR_ADDRUNRESV;
}
}
/*
*----------------------------------------------------------------------------
*
- * 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.
* 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.
*/
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");
}
}
- 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");
}
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) {
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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;
* 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) {
/*
*----------------------------------------------------------------------------
*
- * 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.
int *outError) // OUT
{
struct sockaddr_vm addr;
- AsyncSocket *asock;
+ AsyncTCPSocket *asock;
int vsockDev = -1;
memset(&addr, 0, sizeof addr);
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.
*----------------------------------------------------------------------------
*/
-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;
* Wrap it with an asock object
*/
- if ((asock = AsyncSocket_AttachToFd(fd, pollParams, &error)) == NULL) {
+ if ((asock = AsyncTCPSocketAttachToFd(fd, pollParams, &error)) == NULL) {
goto error;
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*/
static unsigned int
-AsyncSocketGetPortFromAddr(struct sockaddr_storage *addr)
+AsyncTCPSocketGetPortFromAddr(struct sockaddr_storage *addr) // IN
{
ASSERT(NULL != 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:
*----------------------------------------------------------------------------
*/
-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;
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;
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketOSVersionSupportsV4Mapped --
+ * AsyncTCPSocketOSVersionSupportsV4Mapped --
*
* Determine if runtime environment supports IPv4-mapped IPv6 addressed
* and all the functionality needed to deal with this scenario.
*/
static Bool
-AsyncSocketOSVersionSupportsV4Mapped()
+AsyncTCPSocketOSVersionSupportsV4Mapped(void)
{
#if defined(_WIN32) && !defined(VM_WIN_UWP)
OSVERSIONINFOW osvi = {sizeof(OSVERSIONINFOW)};
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketBind --
+ * AsyncTCPSocketBind --
*
* This is an internal routine that binds a socket to a port.
*
*----------------------------------------------------------------------------
*/
-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;
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
/*
* 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,
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketListen --
+ * AsyncTCPSocketListen --
*
* This is an internal routine that calls listen() on a socket.
*
*----------------------------------------------------------------------------
*/
-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;
* 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;
/*
*----------------------------------------------------------------------------
*
- * 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;
* 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;
}
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;
}
/*
*----------------------------------------------------------------------------
*
- * 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;
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);
}
*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.
*
* ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
*
* Side effects:
- * Allocates an AsyncSocket, registers a poll callback.
+ * Allocates an AsyncTCPSocket, registers a poll callback.
*
*----------------------------------------------------------------------------
*/
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);
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);
}
*
* 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.
*
* ASOCKERR_SUCCESS or ASOCKERR_GENERIC.
*
* Side effects:
- * Allocates an AsyncSocket, registers a poll callback.
+ * Allocates an AsyncTCPSocket, registers a poll callback.
*
*----------------------------------------------------------------------------
*/
int *outError) // OUT
{
struct sockaddr_un addr;
- AsyncSocket *asock;
+ AsyncTCPSocket *asock;
memset(&addr, 0, sizeof addr);
addr.sun_family = AF_UNIX;
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
/*
*----------------------------------------------------------------------------
*
- * 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.
*/
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;
} 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;
/*
*----------------------------------------------------------------------------
*
- * 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;
* 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
* 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 {
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;
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;
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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;
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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;
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));
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;
/*
*----------------------------------------------------------------------------
*
- * 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
return NULL;
}
- asock = AsyncSocket_AttachToSSLSock(sslSock, pollParams, outError);
+ asock = AsyncTCPSocketAttachToSSLSock(sslSock, pollParams, outError);
if (asock) {
return asock;
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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;
}
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketSetTCPTimeouts --
+ * AsyncTCPSocketSetTCPTimeouts --
*
* Allow caller to set a number of TCP-specific timeout
* parameters on the socket for the active connection.
*----------------------------------------------------------------------------
*/
-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;
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;
}
/*
*----------------------------------------------------------------------------
*
- * 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_*.
*----------------------------------------------------------------------------
*/
-int
-AsyncSocketRecvSocket(AsyncSocket *asock, // IN:
- void *buf, // IN: unused
- int len) // IN: unused
+static int
+AsyncTCPSocketRegisterRecvCb(AsyncTCPSocket *asock) // IN:
{
int retVal = ASOCKERR_SUCCESS;
* 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;
/*
*----------------------------------------------------------------------------
*
- * 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
* 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,
*----------------------------------------------------------------------------
*/
-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
* 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:
*----------------------------------------------------------------------------
*/
-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;
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketPoll --
+ * AsyncTCPSocketPoll --
*
* Blocks on the specified socket until there's data pending or a
* timeout occurs.
*/
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];
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;
}
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;
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) {
(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)));
} 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)));
}
}
#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;
* 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:
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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.
*----------------------------------------------------------------------------
*/
-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;
}
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;
}
}
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;
}
/*
*----------------------------------------------------------------------------
*
- * 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
*----------------------------------------------------------------------------
*/
-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
* 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:
/*
}
}
-outHaveLock:
- AsyncSocketUnlock(asock);
return retVal;
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketResolveAddr --
+ * AsyncTCPSocketResolveAddr --
*
* Resolves a hostname and port.
*
*
*----------------------------------------------------------------------------
*/
-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;
/*
*----------------------------------------------------------------------------
*
- * 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.
*
*----------------------------------------------------------------------------
*/
-int
-AsyncSocketFillRecvBuffer(AsyncSocket *s)
+static int
+AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN
{
int recvd;
int needed;
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
* 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;
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).
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;
* 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);
exit:
s->inRecvLoop = FALSE;
- AsyncSocketRelease(s, FALSE);
+ AsyncTCPSocketRelease(s);
return result;
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketDispatchSentBuffer --
+ * AsyncTCPSocketDispatchSentBuffer --
*
* Pop off the head of the send buffer list and call its callback.
*
*----------------------------------------------------------------------------
*/
-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
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.
*
*/
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;
result = ASOCKERR_SUCCESS;
exit:
- AsyncSocketRelease(s, FALSE);
+ AsyncTCPSocketRelease(s);
return result;
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*/
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
*/
} 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;
}
if (remoteAddr.ss_family == AF_INET6 &&
- AsyncSocketOSVersionSupportsV4Mapped()) {
+ AsyncTCPSocketOSVersionSupportsV4Mapped()) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&remoteAddr;
/*
*/
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);
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;
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketConnectInternal --
+ * AsyncTCPSocketConnectInternal --
*
* The meat of connect. This function is invoked either via a poll
* callback or the blocking API and verifies that connect() succeeded
*/
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) {
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;
}
}
done:
- s->state = AsyncSocketConnected;
- s->connectFn(s, s->clientData);
+ AsyncTCPSocketSetState(s, AsyncSocketConnected);
+ s->connectFn(BaseSocket(s), s->clientData);
return ASOCKERR_SUCCESS;
}
/*
*----------------------------------------------------------------------------
*
- * 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
*----------------------------------------------------------------------------
*/
-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.
*----------------------------------------------------------------------------
*/
-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
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
} 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;
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);
}
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocket_DoOneMsg --
+ * AsyncTCPSocketDoOneMsg --
*
* Spins a socket until the specified amount of time has elapsed or
* data has arrived / been sent.
*----------------------------------------------------------------------------
*/
-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) {
/*
* 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;
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketFlush --
+ * AsyncTCPSocketFlush --
*
* Try to send any pending out buffers until we run out of buffers, or
* the timeout expires.
*----------------------------------------------------------------------------
*/
-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;
}
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) {
/* 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;
}
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;
-}
-
-
/*
*----------------------------------------------------------------------------
*
*----------------------------------------------------------------------------
*/
-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);
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketAddListenCbSocket --
+ * AsyncTCPSocketAddListenCb --
*
* Socket specific code for adding callbacks for a listening socket.
*
*/
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;
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketCancelRecvCbSocket --
+ * AsyncTCPSocketCancelRecvCb --
*
* Socket specific code for canceling callbacks when a receive
* request is being canceled.
*----------------------------------------------------------------------------
*/
-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;
}
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*----------------------------------------------------------------------------
*/
-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.
*
* 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
*/
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.
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.
*----------------------------------------------------------------------------
*/
-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():
*
*----------------------------------------------------------------------------
*/
-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
*----------------------------------------------------------------------------
*/
-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;
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)));
}
}
* 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:
}
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;
}
/*
*----------------------------------------------------------------------------
*
- * 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
*----------------------------------------------------------------------------
*/
-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.
*/
static Bool
-AsyncSocketHasDataPendingSocket(AsyncSocket *asock) // IN
+AsyncTCPSocketHasDataPending(AsyncTCPSocket *asock) // IN:
{
return SSL_Pending(asock->sslSock);
}
/*
*----------------------------------------------------------------------------
*
- * 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.
*
*/
static int
-AsyncSocketMakeNonBlocking(int fd)
+AsyncTCPSocketMakeNonBlocking(int fd) // IN
{
#ifdef _WIN32
int retval;
}
-/*
- *----------------------------------------------------------------------------
- *
- * 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);
- }
-}
-
-
/*
*----------------------------------------------------------------------------
*
* 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.
*/
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.
*/
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.
*----------------------------------------------------------------------------
*/
-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.
*/
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);
}
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketSendCallback --
+ * AsyncTCPSocketSendCallback --
*
* Poll callback for output socket buffer space available (socket is
* writable). We iterate over all the remaining buffers in our queue,
*----------------------------------------------------------------------------
*/
-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;
*/
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.
*/
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
* 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);
}
/*
*-----------------------------------------------------------------------------
*
- * 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.
*-----------------------------------------------------------------------------
*/
-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;
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.
*-----------------------------------------------------------------------------
*/
-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) {
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);
}
/*
*-----------------------------------------------------------------------------
*
- * AsyncSocketIPollAdd --
+ * AsyncTCPSocketIPollAdd --
*
* Add a poll callback. Wrapper for IVmdbPoll.Register[Timer].
*
*/
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;
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
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;
}
/*
*-----------------------------------------------------------------------------
*
- * AsyncSocketIPollRemove --
+ * AsyncTCPSocketIPollRemove --
*
* Remove a poll callback. Wrapper for IVmdbPoll.Unregister[Timer].
*
*/
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;
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
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);
}
/*
*-----------------------------------------------------------------------------
*
- * 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);
}
asock->passFd.expected = FALSE;
- retVal = ASOCKERR_SUCCESS;
-
-outHaveLock:
- AsyncSocketUnlock(asock);
- return retVal;
+ return ASOCKERR_SUCCESS;
}
/*
*-----------------------------------------------------------------------------
*
- * AsyncSocketGetReceivedFd --
+ * AsyncTCPSocketGetReceivedFd --
*
* Retrieve received file descriptor from socket.
*
*-----------------------------------------------------------------------------
*/
-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;
}
/*
*-----------------------------------------------------------------------------
*
- * AsyncSocketConnectSSL --
+ * AsyncTCPSocketConnectSSL --
*
* Initialize the socket's SSL object, by calling SSL_ConnectAndVerify.
* NOTE: This call is blocking.
*-----------------------------------------------------------------------------
*/
-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();
/*
*-----------------------------------------------------------------------------
*
- * AsyncSocketAcceptSSL --
+ * AsyncTCPSocketAcceptSSL --
*
* Initialize the socket's SSL object, by calling SSL_Accept or
* SSL_AcceptWithContext.
*-----------------------------------------------------------------------------
*/
-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);
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketSslConnectCallback --
+ * AsyncTCPSocketSslConnectCallback --
*
* Poll callback to redrive an outstanding ssl connect operation.
*
*/
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
/*
*-----------------------------------------------------------------------------
*
- * AsyncSocketStartSslConnect --
+ * AsyncTCPSocketStartSslConnect --
*
* Start an asynchronous SSL connect operation.
*
*-----------------------------------------------------------------------------
*/
-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
/*
*----------------------------------------------------------------------------
*
- * AsyncSocketSslAcceptCallback --
+ * AsyncTCPSocketSslAcceptCallback --
*
* Poll callback for redrive an outstanding ssl accept operation
*
*/
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.
*
*-----------------------------------------------------------------------------
*/
-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.
*
*-----------------------------------------------------------------------------
*/
-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;
/*
*-----------------------------------------------------------------------------
*
- * 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
*-----------------------------------------------------------------------------
*/
-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.
int *outError) // OUT
{
struct sockaddr_un addr;
+ AsyncTCPSocket *asock;
memset(&addr, 0, sizeof addr);
addr.sun_family = AF_UNIX;
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