/*
- * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Copyright (C) 2016-2019 "IoT.bzh"
* Author: José Bollo <jose.bollo@iot.bzh>
*
* Licensed under the Apache License, Version 2.0 (the "License");
#include <stdarg.h>
#include <poll.h>
-#include <systemd/sd-event.h>
-
#include "websock.h"
#include "afb-ws.h"
-
-#include "afb-common.h"
+#include "fdev.h"
/*
* declaration of the websock interface for afb-ws
const struct afb_ws_itf *itf; /* the callback interface */
void *closure; /* closure when calling the callbacks */
struct websock *ws; /* the websock handler */
- sd_event_source *evsrc; /* the event source for the socket */
+ struct fdev *fdev; /* the fdev for the socket */
struct buf buffer; /* the last read fragment */
};
struct websock *wsi = ws->ws;
if (wsi != NULL) {
ws->ws = NULL;
- sd_event_source_unref(ws->evsrc);
- ws->evsrc = NULL;
+ fdev_unref(ws->fdev);
websock_destroy(wsi);
free(ws->buffer.buffer);
ws->state = waiting;
}
}
-static int io_event_callback(sd_event_source *src, int fd, uint32_t revents, void *ws)
+static void fdevcb(void *ws, uint32_t revents, struct fdev *fdev)
{
if ((revents & EPOLLIN) != 0)
aws_on_readable(ws);
if ((revents & EPOLLHUP) != 0)
afb_ws_hangup(ws);
- return 0;
}
/*
*
* Returns the handle for the afb_ws created or NULL on error.
*/
-struct afb_ws *afb_ws_create(struct sd_event *eloop, int fd, const struct afb_ws_itf *itf, void *closure)
+struct afb_ws *afb_ws_create(struct fdev *fdev, const struct afb_ws_itf *itf, void *closure)
{
- int rc;
struct afb_ws *result;
- assert(fd >= 0);
+ assert(fdev);
/* allocation */
result = malloc(sizeof * result);
goto error;
/* init */
- result->fd = fd;
+ result->fdev = fdev;
+ result->fd = fdev_fd(fdev);
result->state = waiting;
result->itf = itf;
result->closure = closure;
if (result->ws == NULL)
goto error2;
- /* creates the evsrc */
- rc = sd_event_add_io(eloop, &result->evsrc, result->fd, EPOLLIN, io_event_callback, result);
- if (rc < 0) {
- errno = -rc;
- goto error3;
- }
+ /* finalize */
+ fdev_set_events(fdev, EPOLLIN);
+ fdev_set_callback(fdev, fdevcb, result);
return result;
-error3:
- websock_destroy(result->ws);
error2:
free(result);
error:
+ fdev_unref(fdev);
return NULL;
}
*/
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);
}
}