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; }
int ringqInsertcA(ringq_t *rq, char c) { a_assert(rq); a_assert(rq->buflen == (rq->endbuf - rq->buf)); if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { return -1; } if (rq->servp <= rq->buf) { rq->servp = rq->endbuf; } *--rq->servp = (unsigned char) c; return 0; }
int ringqPutcA(ringq_t *rq, char c) { a_assert(rq); a_assert(rq->buflen == (rq->endbuf - rq->buf)); if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { return -1; } *rq->endp++ = (unsigned char) c; if (rq->endp >= rq->endbuf) { rq->endp = rq->buf; } return 0; }
int ringqInsertc(ringq_t *rq, char_t c) { char_t *cp; a_assert(rq); a_assert(rq->buflen == (rq->endbuf - rq->buf)); if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) { return -1; } if (rq->servp <= rq->buf) { rq->servp = rq->endbuf; } cp = (char_t*) rq->servp; *--cp = (char_t) c; rq->servp = (unsigned char *) cp; return 0; }
int ringqPutc(ringq_t *rq, char_t c) { char_t *cp; a_assert(rq); a_assert(rq->buflen == (rq->endbuf - rq->buf)); if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) { return -1; } cp = (char_t*) rq->endp; *cp++ = (char_t) c; rq->endp = (unsigned char *) cp; if (rq->endp >= rq->endbuf) { rq->endp = rq->buf; } return 0; }
int socketRead(int sid, char *buf, int bufsize) { socket_t *sp; ringq_t *rq; int len, room, errCode, bytesRead; a_assert(buf); a_assert(bufsize > 0); if ((sp = socketPtr(sid)) == NULL) { return -1; } if (sp->flags & SOCKET_EOF) { return 0; } rq = &sp->inBuf; for (bytesRead = 0; bufsize > 0; ) { len = min(ringqLen(rq), bufsize); if (len <= 0) { /* * if blocking mode and already have data, exit now or it may block * forever. */ if ((sp->flags & SOCKET_BLOCK) && (bytesRead > 0)) { break; } /* * This flush is critical for readers of datagram packets. If the * buffer is not big enough to read the whole datagram in one hit, * the recvfrom call will fail. */ ringqFlush(rq); room = ringqPutBlkMax(rq); len = socketGetInput(sid, (char *) rq->endp, room, &errCode); if (len < 0) { if (errCode == EWOULDBLOCK) { if ((sp->flags & SOCKET_BLOCK) && (bytesRead == 0)) { continue; } if (bytesRead >= 0) { return bytesRead; } } return -1; } else if (len == 0) { /* * If bytesRead is 0, this is EOF since socketRead should never * be called unless there is data yet to be read. Set the flag. * Then pass back the number of bytes read. */ if (bytesRead == 0) { sp->flags |= SOCKET_EOF; } return bytesRead; } ringqPutBlkAdj(rq, len); len = min(len, bufsize); } memcpy(&buf[bytesRead], rq->servp, len); ringqGetBlkAdj(rq, len); bufsize -= len; bytesRead += len; } return bytesRead; }