static int BSslHandleAsync(SslBindCtx *pCtx, int iCode, int iDefError, int iTimeo) { int iError, iResult = 0; SYS_fd_set FdSet; if ((iError = SSL_get_error(pCtx->pSSL, iCode)) != SSL_ERROR_NONE) { SYS_FD_ZERO(&FdSet); SYS_FD_SET(pCtx->SockFD, &FdSet); if (iError == SSL_ERROR_WANT_READ) { if (SysSelect((long) pCtx->SockFD + 1, &FdSet, NULL, NULL, iTimeo) < 0) return ErrGetErrorCode(); iResult = 1; } else if (iError == SSL_ERROR_WANT_WRITE) { if (SysSelect((long) pCtx->SockFD + 1, NULL, &FdSet, NULL, iTimeo) < 0) return ErrGetErrorCode(); iResult = 1; } else { ErrSetErrorCode(iDefError); iResult = iDefError; } } return iResult; }
enum MqErrorE pIoSelect ( struct MqIoS * const io, enum MqIoSelectE const typ, struct timeval * const timeout ) { // set in GenericCreateSocket or in PipeCreate -> SysConnect need this register MQ_SOCK const sock = *io->sockP; fd_set *fds, *readfds = NULL, *writefds = NULL; if (sock < 0) return MQ_CONTINUE; // nothing found fds = &io->fdset; // build fds FD_SET (sock, fds); // compose switch (typ) { case MQ_SELECT_RECV: readfds = fds; break; case MQ_SELECT_SEND: writefds = fds; break; } // do the select MqErrorReturn (SysSelect (io->context, (sock+1), readfds, writefds, timeout)); }
enum MqErrorE SysSend ( struct MqS * const context, MQ_SOCK hdl, MQ_BIN buf, MQ_SIZE numBytes, int flags, MQ_TIME_T timeout ) { MQ_SIZE ldata = 0; MQ_INT trycount = (MQ_INT) (timeout*100); // send data from buf do { ldata = send (hdl, (const MQ_buf_T) buf, numBytes, flags); //printLV("numBytes<%d>, hdl<%d>, ldata<%d>\n", numBytes, hdl, ldata); // check for errors if (unlikely (ldata == -1)) { //printLV("ERROR sock<%i>, numBytes<%i>, errnum<%i>, str<%s>\n", hdl, numBytes, sSysGetErrorNum, strerror(errno)); switch (sSysGetErrorNum) { case WIN32_WSA (EWOULDBLOCK): { // waiting for "send" is buggy -> just use 0.01 sec and try send again on "timeout" (MQ_CONTINUE) struct timeval tv = {(long) 0L, 10000L}; fd_set fds; if (trycount <= 0) return MqErrorDbV (MQ_ERROR_TIMEOUT, timeout); // now wait until the socket become send-able FD_ZERO(&fds); FD_SET(hdl, &fds); switch (SysSelect (context, (hdl+1), NULL, &fds, &tv)) { case MQ_OK: break; case MQ_CONTINUE: trycount -= 1; continue; // with "do" loop case MQ_ERROR: pIoCloseSocket (__func__, context->link.io); return MqErrorStack (context); } ldata = 0; break; } case WIN32_WSA (ECONNRESET): case WIN32_WSA (EBADF): { pIoCloseSocket (__func__, context->link.io); return pErrorSetExitWithCheck (context); } default: pIoCloseSocket (__func__, context->link.io); return sSysMqErrorMsg (context, __func__, "send"); } } buf += ldata; numBytes -= ldata; } while (numBytes > 0); return MQ_OK; }
enum MqErrorE SysRecv ( struct MqS * const context, MQ_SOCK const hdl, MQ_BIN buf, MQ_SIZE numBytes, MQ_SIZE * const newSize, MQ_TIME_T timeout ) { int const flags = 0; register MQ_SIZE ldata = 0; *newSize = 0; // recv data in buf do { ldata = recv (hdl, (MQ_buf_T) buf, numBytes, flags); // check for errors if (unlikely (ldata <= 0)) { if (ldata == -1) { //MqDLogV(context,0,"ERROR sock<%i>, numBytes<%i>, str<%s>\n", hdl, numBytes, strerror(errno)); switch (sSysGetErrorNum) { case WIN32_WSA (EWOULDBLOCK): { struct timeval tv = {(long)timeout, 0L}; fd_set fds; FD_ZERO(&fds); FD_SET(hdl, &fds); // now wait until the socket become recv-able switch (SysSelect (context, (hdl+1), &fds, NULL, &tv)) { case MQ_OK: break; case MQ_CONTINUE: return MqErrorDbV (MQ_ERROR_TIMEOUT, timeout); case MQ_ERROR: pIoCloseSocket (__func__, context->link.io); return MqErrorStack(context); } ldata = 0; break; } case WIN32_WSA (ECONNRESET): case WIN32_WSA (EBADF): { pIoCloseSocket (__func__, context->link.io); return pErrorSetExitWithCheck (context); } default: pIoCloseSocket (__func__, context->link.io); return sSysMqErrorMsg (context, __func__, "recv"); } } else if (ldata == 0) { pIoCloseSocket (__func__, context->link.io); return pErrorSetExitWithCheck (context); } } buf += ldata; numBytes -= ldata; *newSize += ldata; } while (numBytes > 0); return MQ_OK; }
enum MqErrorE SysSelect ( struct MqS * const context, int n, fd_set * readfds, fd_set * writefds, struct timeval const * const timeout ) { int ret; struct timeval tv = *timeout; sSysSetErrorNum(0); ret = MqSysSelect (n, (void*)readfds, (void*)writefds, NULL, &tv); switch (ret) { case 0: return MQ_CONTINUE; // timeout case SOCKET_ERROR: switch (sSysGetErrorNum) { /* #ifdef MQ_IS_WIN32 case WIN32_WSA (ENOTSOCK): M0 MqSysSleep(context,1); return MQ_CONTINUE; case WIN32_WSA (EFAULT): M1 MqSysSleep(context,1); return MQ_CONTINUE; #endif */ case WIN32_WSA (EINTR): return MQ_CONTINUE; //case WIN32_WSA (ENOTSOCK): //case WIN32_WSA (EFAULT): case WIN32_WSA (EBADF): { // check all sockets's to get the bad one MQ_SOCK i; int num=0; fd_set fd_test, *fds = NULL, *read_test = NULL, *write_test = NULL; struct timeval timeout = {0L,0L}; struct MqS const * sockmq = NULL; MQ_SOCK sock=-1; // read or write ? if (readfds != NULL) { read_test = &fd_test; fds = readfds; } else { write_test = &fd_test; fds = writefds; } // get the number of sockets for (i=0;i<n;i++) { if (FD_ISSET(i,fds)) { num++; sock = i; //printI(sock) } } // only one socket? if (num == 1) { sockmq = pIoGetMsgqueFromSocket(context->link.io,sock); if (sockmq == NULL) { return sSysMqErrorMsg (context, __func__, "select"); } else if (sockmq == context) { pIoCloseSocket (__func__, context->link.io); return pErrorSetExitWithCheck (context); } else { pIoCloseSocket (__func__, sockmq->link.io); return MQ_CONTINUE; } } // ok, more than one socket check every socket for (i=0;i<n;i++) { if (!FD_ISSET(i,fds)) continue; FD_ZERO (&fd_test); FD_SET (i, &fd_test); if (MqErrorCheckI (SysSelect(context,i+1,read_test,write_test,&timeout))) { return MQ_ERROR; } } return MQ_CONTINUE; } default: return sSysMqErrorMsg (context, __func__, "select"); } } return MQ_OK; }