static int socketDoEvent(socket_t *sp) { ringq_t *rq; int sid; a_assert(sp); sid = sp->sid; if (sp->currentEvents & SOCKET_READABLE) { if (sp->flags & SOCKET_LISTENING) { socketAccept(sp); sp->currentEvents = 0; return 1; } } else { /* * If there is still read data in the buffers, trigger the read handler * NOTE: this may busy spin if the read handler doesn't read the data */ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) { sp->currentEvents |= SOCKET_READABLE; } } /* * If now writable and flushing in the background, continue flushing */ if (sp->currentEvents & SOCKET_WRITABLE) { if (sp->flags & SOCKET_FLUSHING) { rq = &sp->outBuf; if (ringqLen(rq) > 0) { socketFlush(sp->sid); } else { sp->flags &= ~SOCKET_FLUSHING; } } } /* * Now invoke the users socket handler. NOTE: the handler may delete the * socket, so we must be very careful after calling the handler. */ if (sp->handler && (sp->handlerMask & sp->currentEvents)) { (sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data); /* * Make sure socket pointer is still valid, then reset the currentEvents. */ if (socketList && sid < socketMax && socketList[sid] == sp) { sp->currentEvents = 0; } } return 1; }
int socketWrite(int sid, char *buf, int bufsize) { socket_t *sp; ringq_t *rq; int len, bytesWritten, room; a_assert(buf); a_assert(bufsize >= 0); if ((sp = socketPtr(sid)) == NULL) { return -1; } /* * Loop adding as much data to the output ringq as we can absorb. Initiate a * flush when the ringq is too full and continue. Block in socketFlush if the * socket is in blocking mode. */ rq = &sp->outBuf; for (bytesWritten = 0; bufsize > 0; ) { if ((room = ringqPutBlkMax(rq)) == 0) { if (socketFlush(sid) < 0) { return -1; } if ((room = ringqPutBlkMax(rq)) == 0) { if (sp->flags & SOCKET_BLOCK) { #if (defined (WIN) || defined (CE)) int errCode; if (! socketWaitForEvent(sp, FD_WRITE | SOCKET_WRITABLE, &errCode)) { return -1; } #endif continue; } break; } continue; } len = min(room, bufsize); ringqPutBlk(rq, (unsigned char *) buf, len); bytesWritten += len; bufsize -= len; buf += len; } return bytesWritten; }
static int socketEventProc(void *data, int mask) { socket_t *sp; ringq_t *rq; int sid; sid = (int) data; a_assert(sid >= 0 && sid < socketMax); a_assert(socketList[sid]); if ((sp = socketPtr(sid)) == NULL) { return 1; } /* * If now writable and flushing in the background, continue flushing */ if (mask & SOCKET_WRITABLE) { if (sp->flags & SOCKET_FLUSHING) { rq = &sp->outBuf; if (ringqLen(rq) > 0) { socketFlush(sp->sid); } else { sp->flags &= ~SOCKET_FLUSHING; } } } /* * Now invoke the users socket handler. NOTE: the handler may delete the * socket, so we must be very careful after calling the handler. */ if (sp->handler && (sp->handlerMask & mask)) { (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data); } if (socketList && sid < socketMax && socketList[sid] == sp) { socketRegisterInterest(sp, sp->handlerMask); } return 1; }