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);
ssize_t sz;
char *buffer;
- if (size != 0) {
+ if (size != 0 || ws->buffer.buffer == NULL) {
buffer = realloc(ws->buffer.buffer, ws->buffer.size + size + 1);
if (buffer == NULL)
return 0;
ws->buffer.buffer = buffer;
- do {
+ while (size != 0) {
sz = websock_read(ws->ws, &buffer[ws->buffer.size], size);
if (sz < 0) {
if (errno != EAGAIN)
return 0;
pfd.fd = ws->fd;
pfd.events = POLLIN;
- poll(&pfd, 1, 10);
+ poll(&pfd, 1, 10); /* TODO: make fully asynchronous websockets */
} else {
ws->buffer.size += (size_t)sz;
size -= (size_t)sz;
}
- } while (size != 0);
+ }
}
return 1;
}
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);
}
}
}
/*
- * Callback when 'close' command received from 'ws' with 'code' and 'size'.
+ * Callback when 'continue' command received from 'ws' with 'code' and 'size'.
*/
static void aws_on_continue(struct afb_ws *ws, int last, size_t size)
{