* (default is NULL: no callback)
*
* Results:
- * None.
+ * ASOCKERR_SUCCESS or ASOCKERR_*.
*
* Side effects:
* None.
*----------------------------------------------------------------------------
*/
-void
+int
AsyncSocket_SetCloseOptions(AsyncSocket *asock, // IN
int flushEnabledMaxWaitMsec, // IN
AsyncSocketCloseFn closeCb) // IN
{
+ int ret;
if (VALID(asock, setCloseOptions)) {
AsyncSocketLock(asock);
- VT(asock)->setCloseOptions(asock, flushEnabledMaxWaitMsec, closeCb);
+ ret = VT(asock)->setCloseOptions(asock, flushEnabledMaxWaitMsec, closeCb);
AsyncSocketUnlock(asock);
+ } else {
+ ret = ASOCKERR_INVAL;
}
+ return ret;
}
* unless requested by the client.
*
* Result
- * None
+ * ASOCKERR_SUCCESS or ASOCKERR_*
*
* Side-effects
* See description above.
*-----------------------------------------------------------------------------
*/
-void
+int
AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, // IN
Bool enable) // IN
{
+ int ret;
if (VALID(asock, setSendLowLatencyMode)) {
AsyncSocketLock(asock);
- VT(asock)->setSendLowLatencyMode(asock, enable);
+ ret = VT(asock)->setSendLowLatencyMode(asock, enable);
AsyncSocketUnlock(asock);
+ } else {
+ ret = ASOCKERR_INVAL;
}
+ return ret;
}
* after the sslConnectFn callback is called.
*
* Results:
- * None.
- * Error is always reported using the callback supplied. Detailed SSL
- * verification error can be retrieved from verifyParam structure.
+ * ASOCKERR_SUCCESS indicates we have started async connect.
+ * ASOCKERR_* indicates a failure to start the connect.
+ *
+ * Errors during asynchronous processing is reported using the
+ * callback supplied. Detailed SSL verification error can be
+ * retrieved from verifyParam structure.
*
* Side effects:
* None.
*-----------------------------------------------------------------------------
*/
-void
+int
AsyncSocket_StartSslConnect(AsyncSocket *asock, // IN
SSLVerifyParam *verifyParam, // IN/OPT
void *sslCtx, // IN
AsyncSocketSslConnectFn sslConnectFn, // IN
void *clientData) // IN
{
+ int ret;
if (VALID(asock, startSslConnect)) {
AsyncSocketLock(asock);
- VT(asock)->startSslConnect(asock, verifyParam, sslCtx, sslConnectFn,
- clientData);
+ ret = VT(asock)->startSslConnect(asock, verifyParam, sslCtx, sslConnectFn,
+ clientData);
AsyncSocketUnlock(asock);
+ } else {
+ ret = ASOCKERR_INVAL;
}
+ return ret;
}
* or an error occurs.
*
* Results:
- * None.
- * Error is always reported using the callback supplied.
+ * ASOCKERR_SUCCESS indicates we have started async accept.
+ * ASOCKERR_* indicates a failure to start the accept.
+ *
+ * Errors during asynchronous processing are reported using the
+ * callback supplied.
*
* Side effects:
* None.
*-----------------------------------------------------------------------------
*/
-void
+int
AsyncSocket_StartSslAccept(AsyncSocket *asock, // IN
void *sslCtx, // IN
AsyncSocketSslAcceptFn sslAcceptFn, // IN
void *clientData) // IN
{
+ int ret;
if (VALID(asock, startSslAccept)) {
AsyncSocketLock(asock);
- VT(asock)->startSslAccept(asock, sslCtx, sslAcceptFn, clientData);
+ ret = VT(asock)->startSslAccept(asock, sslCtx, sslAcceptFn, clientData);
AsyncSocketUnlock(asock);
+ } else {
+ ret = ASOCKERR_INVAL;
}
+ return ret;
}
* function.
*
* Results:
- * None.
+ * ASOCKERR_*.
*
* Side effects:
* None.
*----------------------------------------------------------------------------
*/
-void
+int
AsyncSocket_CancelCbForClose(AsyncSocket *asock) // IN:
{
+ int ret;
if (VALID(asock, cancelCbForClose)) {
AsyncSocketLock(asock);
- VT(asock)->cancelCbForClose(asock);
+ ret = VT(asock)->cancelCbForClose(asock);
AsyncSocketUnlock(asock);
+ } else {
+ ret = ASOCKERR_INVAL;
}
+ return ret;
}
int (*setTCPTimeouts)(AsyncSocket *asock, int keepIdle, int keepIntvl,
int keepCnt);
Bool (*setBufferSizes)(AsyncSocket *asock, int sendSz, int recvSz);
- void (*setSendLowLatencyMode)(AsyncSocket *asock, Bool enable);
- void (*setCloseOptions)(AsyncSocket *asock, int flushEnabledMaxWaitMsec,
+ int (*setSendLowLatencyMode)(AsyncSocket *asock, Bool enable);
+ int (*setCloseOptions)(AsyncSocket *asock, int flushEnabledMaxWaitMsec,
AsyncSocketCloseFn closeCb);
Bool (*connectSSL)(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam,
void *sslContext);
- void (*startSslConnect)(AsyncSocket *asock,
+ int (*startSslConnect)(AsyncSocket *asock,
struct _SSLVerifyParam *verifyParam, void *sslCtx,
AsyncSocketSslConnectFn sslConnectFn,
void *clientData);
Bool (*acceptSSL)(AsyncSocket *asock, void *sslCtx);
- void (*startSslAccept)(AsyncSocket *asock, void *sslCtx,
+ int (*startSslAccept)(AsyncSocket *asock, void *sslCtx,
AsyncSocketSslAcceptFn sslAcceptFn,
void *clientData);
int (*flush)(AsyncSocket *asock, int timeoutMS);
int (*close)(AsyncSocket *asock);
int (*cancelRecv)(AsyncSocket *asock, int *partialRecvd, void **recvBuf,
void **recvFn, Bool cancelOnSend);
- void (*cancelCbForClose)(AsyncSocket *asock);
+ int (*cancelCbForClose)(AsyncSocket *asock);
int (*getLocalVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port);
int (*getRemoteVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port);
int (*getWebSocketError)(AsyncSocket *asock);
Bool sendCbRT;
Bool sendBufFull;
Bool sendLowLatency;
- Bool inLowLatencySendCb;
+ int inLowLatencySendCb;
Bool sslConnected;
int keepIntvl, int keepCnt);
static Bool AsyncTCPSocketSetBufferSizes(AsyncSocket *asock,
int sendSz, int recvSz);
-static void AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *asock,
+static int 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,
+static int AsyncTCPSocketStartSslConnect(AsyncSocket *asock,
+ SSLVerifyParam *verifyParam,
+ void *sslCtx,
+ AsyncSocketSslConnectFn sslConnectFn,
void *clientData);
+static Bool AsyncTCPSocketAcceptSSL(AsyncSocket *asock, void *sslCtx);
+static int AsyncTCPSocketStartSslAccept(AsyncSocket *asock, void *sslCtx,
+ AsyncSocketSslAcceptFn sslAcceptFn,
+ void *clientData);
static int AsyncTCPSocketFlush(AsyncSocket *asock, int timeoutMS);
static void AsyncTCPSocketCancelRecvCb(AsyncTCPSocket *asock);
static int AsyncTCPSocketCancelRecv(AsyncSocket *asock, int *partialRecvd,
void **recvBuf, void **recvFn,
Bool cancelOnSend);
-static void AsyncTCPSocketCancelCbForClose(AsyncSocket *asock);
+static int 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,
+static int AsyncTCPSocketSetCloseOptions(AsyncSocket *asock,
int flushEnabledMaxWaitMsec,
AsyncSocketCloseFn closeCb);
static void AsyncTCPSocketDestroy(AsyncSocket *s);
LOG(2, ("%s: sending %d bytes\n", __FUNCTION__, len));
ASSERT(AsyncTCPSocketIsLocked(asock));
- ASSERT(!asock->inLowLatencySendCb);
+
+ /*
+ * In low-latency mode, we want to guard against recursive calls to
+ * Send from within the send callback, as these have the capacity
+ * to blow up the stack. However some operations generate implicit
+ * sends (such as Close on a websocket) seem like they should be
+ * legal from the send callback. So, allow a small degree of
+ * recursive use of the send callback to accomodate these internal
+ * paths.
+ */
+ ASSERT(asock->inLowLatencySendCb < 2);
if (AsyncTCPSocketGetState(asock) != AsyncSocketConnected) {
TCPSOCKWARN(asock, ("send called but state is not connected!\n"));
* callback to be invoked prior to the call to
* AsyncTCPSocket_Send() returning.
*/
- asock->inLowLatencySendCb = TRUE;
+ asock->inLowLatencySendCb++;
asock->internalSendFn((void *)asock);
- asock->inLowLatencySendCb = FALSE;
+ asock->inLowLatencySendCb--;
} else {
#ifdef _WIN32
/*
AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN
{
int recvd;
- int needed;
int sysErr = 0;
int result;
- int pending = 0;
ASSERT(AsyncTCPSocketIsLocked(s));
ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnected);
* (e.g. aioMgr wait function), then FillRecvBuffer can be potentially be
* called twice for the same receive event.
*/
-
- needed = s->base.recvLen - s->base.recvPos;
- if (!s->base.recvBuf && needed == 0) {
+ if (!s->base.recvBuf) {
+ ASSERT(s->base.recvLen == s->base.recvPos);
return ASOCKERR_SUCCESS;
}
- ASSERT(needed > 0);
-
AsyncTCPSocketAddRef(s);
/*
s->inRecvLoop = TRUE;
- do {
+ while (TRUE) {
+ int needed = s->base.recvLen - s->base.recvPos;
+
+ ASSERT(needed > 0);
/*
* Try to read the remaining bytes to complete the current recv request.
*/
-
if (s->passFd.expected) {
int fd;
s->sslConnected = TRUE;
s->base.recvPos += recvd;
if (AsyncSocketCheckAndDispatchRecv(&s->base, &result)) {
- goto exit;
+ break;
}
} else if (recvd == 0) {
TCPSOCKLG0(s, ("recv detected client closed connection\n"));
* of connection by peer (via the error handler callback).
*/
result = ASOCKERR_REMOTE_DISCONNECT;
- goto exit;
+ break;
} else if ((sysErr = ASOCK_LASTERROR()) == ASOCK_EWOULDBLOCK) {
TCPSOCKLOG(4, s, ("recv would block\n"));
+ result = ASOCKERR_SUCCESS;
break;
} else {
TCPSOCKLG0(s, ("recv error %d: %s\n", sysErr,
- Err_Errno2String(sysErr)));
+ Err_Errno2String(sysErr)));
s->genericErrno = sysErr;
result = ASOCKERR_GENERIC;
- goto exit;
+ break;
}
+ }
- /*
- * At this point, s->recvFoo have been updated to point to the
- * next chained Recv buffer. By default we're done at this
- * point, but we may want to continue if the SSL socket has data
- * buffered in userspace already (SSL_Pending).
- */
-
- needed = s->base.recvLen - s->base.recvPos;
- ASSERT(needed > 0);
-
- pending = SSL_Pending(s->sslSock);
- needed = MIN(needed, pending);
-
- } while (needed);
-
- /*
- * Reach this point only when previous SSL_Pending returns 0 or
- * error is ASOCK_EWOULDBLOCK
- */
-
- ASSERT(pending == 0 || sysErr == ASOCK_EWOULDBLOCK);
-
- /*
- * Both a spurious wakeup and receiving any data even if it wasn't enough
- * to fire the callback are both success. We were ready and now
- * presumably we aren't ready anymore.
- */
-
- result = ASOCKERR_SUCCESS;
-
-exit:
s->inRecvLoop = FALSE;
AsyncTCPSocketRelease(s);
-
return result;
}
* socket is closed.
*
* Results:
- * None.
+ * ASOCKERR_*.
*
* Side effects:
* Unregisters send/recv Poll callbacks, and fires the send
*----------------------------------------------------------------------------
*/
-static void
+static int
AsyncTCPSocketCancelCbForClose(AsyncSocket *base) // IN:
{
AsyncTCPSocket *asock = TCPSocket(base);
free(cur);
}
AsyncTCPSocketRelease(asock);
+ return ASOCKERR_SUCCESS;
}
* (default is NULL: no callback)
*
* Results:
- * None.
+ * ASOCKERR_*.
*
* Side effects:
* None.
*----------------------------------------------------------------------------
*/
-static void
+static int
AsyncTCPSocketSetCloseOptions(AsyncSocket *base, // IN
int flushEnabledMaxWaitMsec, // IN
AsyncSocketCloseFn closeCb) // IN
asock->flushEnabledMaxWaitMsec = flushEnabledMaxWaitMsec;
asock->closeCb = closeCb;
VERIFY(closeCb == NULL);
+ return ASOCKERR_SUCCESS;
}
* set to zero.
*
* Results:
- * None.
- * Error is always reported using the callback supplied.
+ * ASOCKERR_SUCCESS or ASOCKERR_*.
+ * Errors during async processing are reported using the callback supplied.
*
* Side effects:
* None.
*-----------------------------------------------------------------------------
*/
-static void
+static int
AsyncTCPSocketStartSslConnect(AsyncSocket *base, // IN
SSLVerifyParam *verifyParam, // IN/OPT
void *sslCtx, // IN
if (asock->sslConnectFn || asock->sslAcceptFn) {
TCPSOCKWARN(asock, ("An SSL operation was already initiated.\n"));
- return;
+ return ASOCKERR_GENERIC;
}
ok = SSL_SetupConnectAndVerifyWithContext(asock->sslSock, verifyParam,
if (!ok) {
/* Something went wrong already */
(*sslConnectFn)(FALSE, BaseSocket(asock), clientData);
- return;
+ return ASOCKERR_GENERIC;
}
asock->sslConnectFn = sslConnectFn;
asock->clientData = clientData;
AsyncTCPSocketSslConnectCallback(asock);
+ return ASOCKERR_SUCCESS;
#else
- NOT_IMPLEMENTED();
+ return ASOCKERR_INVAL;
#endif
}
* not have to include the openssl header. This is in sync with
* SSL_AcceptWithContext(), where the sslCtx param is typed as void *
* Results:
- * None.
- * Error is always reported using the callback supplied.
+ * ASOCKERR_SUCCESS or ASOCKERR_*.
+ * Errors during async processing reported using the callback supplied.
*
* Side effects:
* None.
*-----------------------------------------------------------------------------
*/
-static void
+static int
AsyncTCPSocketStartSslAccept(AsyncSocket *base, // IN
void *sslCtx, // IN
AsyncSocketSslAcceptFn sslAcceptFn, // IN
if (asock->sslAcceptFn || asock->sslConnectFn) {
TCPSOCKWARN(asock, ("An SSL operation was already initiated.\n"));
- return;
+ return ASOCKERR_GENERIC;
}
ok = SSL_SetupAcceptWithContext(asock->sslSock, sslCtx);
if (!ok) {
/* Something went wrong already */
(*sslAcceptFn)(FALSE, BaseSocket(asock), clientData);
- return;
+ return ASOCKERR_GENERIC;
}
asock->sslAcceptFn = sslAcceptFn;
asock->clientData = clientData;
AsyncTCPSocketSslAcceptCallback(asock);
+ return ASOCKERR_SUCCESS;
}
* unless requested by the client.
*
* Result
- * None
+ * ASOCKERR_*
*
* Side-effects
* See description above.
*-----------------------------------------------------------------------------
*/
-static void
+static int
AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *base, // IN
Bool enable) // IN
{
AsyncTCPSocket *asock = TCPSocket(base);
asock->sendLowLatency = enable;
+ return ASOCKERR_SUCCESS;
}
Bool AsyncSocket_ConnectSSL(AsyncSocket *asock,
struct _SSLVerifyParam *verifyParam,
void *sslContext);
-void AsyncSocket_StartSslConnect(AsyncSocket *asock,
- struct _SSLVerifyParam *verifyParam,
- void *sslCtx,
- AsyncSocketSslConnectFn sslConnectFn,
- void *clientData);
-
-Bool AsyncSocket_AcceptSSL(AsyncSocket *asock, void *sslCtx);
-void AsyncSocket_StartSslAccept(AsyncSocket *asock,
+int AsyncSocket_StartSslConnect(AsyncSocket *asock,
+ struct _SSLVerifyParam *verifyParam,
void *sslCtx,
- AsyncSocketSslAcceptFn sslAcceptFn,
+ AsyncSocketSslConnectFn sslConnectFn,
void *clientData);
+Bool AsyncSocket_AcceptSSL(AsyncSocket *asock, void *sslCtx);
+int AsyncSocket_StartSslAccept(AsyncSocket *asock,
+ void *sslCtx,
+ AsyncSocketSslAcceptFn sslAcceptFn,
+ void *clientData);
+
/*
* Create a new AsyncSocket from an existing socket
*/
/*
* Unregister asynchronous send and recv from poll
*/
-void AsyncSocket_CancelCbForClose(AsyncSocket *asock);
+int AsyncSocket_CancelCbForClose(AsyncSocket *asock);
/*
* Set the error handler to invoke on I/O errors (default is to close the
/*
* Set optional AsyncSocket_Close() behaviors.
*/
-void AsyncSocket_SetCloseOptions(AsyncSocket *asock,
- int flushEnabledMaxWaitMsec,
- AsyncSocketCloseFn closeCb);
+int AsyncSocket_SetCloseOptions(AsyncSocket *asock,
+ int flushEnabledMaxWaitMsec,
+ AsyncSocketCloseFn closeCb);
/*
* Close the connection and destroy the asock.
/*
* Set low-latency mode for sends:
*/
-void AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, Bool enable);
+int AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, Bool enable);
/*
* Get negotiated websocket protocol