static inline struct buf aws_pick_buffer(struct afb_ws *ws)
{
struct buf result = ws->buffer;
+ if (result.buffer)
+ result.buffer[result.size] = 0;
ws->buffer.buffer = NULL;
ws->buffer.size = 0;
return result;
}
+/*
+ * Clear the current buffer
+ */
+static inline void aws_clear_buffer(struct afb_ws *ws)
+{
+ ws->buffer.size = 0;
+}
+
/*
* Disconnect the websocket 'ws' and calls on_hangup if
* 'call_on_hangup' is not null.
sd_event_source_unref(ws->evsrc);
ws->evsrc = NULL;
websock_destroy(wsi);
- free(aws_pick_buffer(ws).buffer);
+ free(ws->buffer.buffer);
ws->state = waiting;
if (call_on_hangup && ws->itf->on_hangup)
ws->itf->on_hangup(ws->closure);
*/
static ssize_t aws_writev(struct afb_ws *ws, const struct iovec *iov, int iovcnt)
{
- ssize_t rc;
+ int i;
+ ssize_t rc, sz, dsz;
+ struct iovec *iov2;
+ struct pollfd pfd;
+
+ /* compute the size */
+ dsz = 0;
+ i = 0;
+ while (i < iovcnt) {
+ dsz += iov[i++].iov_len;
+ if (dsz < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ if (dsz == 0)
+ return 0;
+
+ /* write the data */
+ iov2 = (struct iovec*)iov;
+ sz = dsz;
for (;;) {
- rc = writev(ws->fd, iov, iovcnt);
- if (rc == -1) {
+ rc = writev(ws->fd, iov2, iovcnt);
+ if (rc < 0) {
if (errno == EINTR)
continue;
- else if (errno == EAGAIN) {
- struct pollfd pfd;
- pfd.fd = ws->fd;
- pfd.events = POLLOUT;
- poll(&pfd, 1, 10);
- continue;
+ if (errno != EAGAIN)
+ return -1;
+ } else {
+ dsz -= rc;
+ if (dsz == 0)
+ return sz;
+
+ i = 0;
+ while (rc >= (ssize_t)iov2[i].iov_len)
+ rc -= (ssize_t)iov2[i++].iov_len;
+
+ iovcnt -= i;
+ if (iov2 != iov)
+ iov2 += i;
+ else {
+ iov += i;
+ iov2 = alloca(iovcnt * sizeof *iov2);
+ for (i = 0 ; i < iovcnt ; i++)
+ iov2[i] = iov[i];
}
+ iov2->iov_base += rc;
+ iov2->iov_len -= rc;
}
- return rc;
+ pfd.fd = ws->fd;
+ pfd.events = POLLOUT;
+ poll(&pfd, 1, 10);
}
}
struct buf b;
ws->state = waiting;
- free(aws_pick_buffer(ws).buffer);
+ aws_clear_buffer(ws);
if (ws->itf->on_close == NULL) {
websock_drop(ws->ws);
afb_ws_hangup(ws);
static void aws_drop_error(struct afb_ws *ws, uint16_t code)
{
ws->state = waiting;
- free(aws_pick_buffer(ws).buffer);
+ aws_clear_buffer(ws);
websock_drop(ws->ws);
websock_error(ws->ws, code, NULL, 0);
}
istxt = ws->state == reading_text;
ws->state = waiting;
b = aws_pick_buffer(ws);
- b.buffer[b.size] = 0;
(istxt ? ws->itf->on_text : ws->itf->on_binary)(ws->closure, b.buffer, b.size);
}
}