bool ustream_write_pending(struct ustream *s) { struct ustream_buf *buf = s->w.head; int wr = 0, len; if (s->write_error) return false; while (buf && s->w.data_bytes) { struct ustream_buf *next = buf->next; int maxlen = buf->tail - buf->data; len = s->write(s, buf->data, maxlen, !!buf->next); if (len < 0) { ustream_write_error(s); break; } if (len == 0) break; wr += len; s->w.data_bytes -= len; if (len < maxlen) { buf->data += len; break; } ustream_free_buf(&s->w, buf); buf = next; } if (s->notify_write) s->notify_write(s, wr); if (s->eof && wr && !s->w.data_bytes) ustream_state_change(s); return !s->w.data_bytes; }
static bool __ustream_fd_poll(struct ustream_fd *sf, unsigned int events) { struct ustream *s = &sf->stream; bool more = false; if (events & ULOOP_READ) ustream_fd_read_pending(sf, &more); if (events & ULOOP_WRITE) { bool no_more = ustream_write_pending(s); if (no_more) ustream_fd_set_uloop(s, false); } if (sf->fd.error && !s->write_error) { ustream_state_change(s); s->write_error = true; ustream_fd_set_uloop(s, false); } return more; }
static void ustream_fd_read_pending(struct ustream_fd *sf, bool *more) { struct ustream *s = &sf->stream; int buflen = 0; ssize_t len; char *buf; do { if (s->read_blocked) break; buf = ustream_reserve(s, 1, &buflen); if (!buf) break; len = read(sf->fd.fd, buf, buflen); if (len < 0) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == ENOTCONN) return; len = 0; } if (!len) { if (!s->eof) ustream_state_change(s); s->eof = true; ustream_fd_set_uloop(s, false); return; } ustream_fill_read(s, len); *more = true; } while (1); }
static void ustream_write_error(struct ustream *s) { if (!s->write_error) ustream_state_change(s); s->write_error = true; }