- response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
- MHD_add_response_header (response, sec_websocket_accept_s, acceptval);
- MHD_add_response_header (response, MHD_HTTP_HEADER_CONNECTION, MHD_HTTP_HEADER_UPGRADE);
- MHD_add_response_header (response, MHD_HTTP_HEADER_UPGRADE, websocket_s);
- MHD_queue_response (hreq->connection, MHD_HTTP_SWITCHING_PROTOCOLS, response);
- MHD_destroy_response (response);
-
- *later = 0;
- return 1;
-}
-
-/**************** WebSocket handling ****************************/
-
-static ssize_t aws_writev(struct afb_websock *ws, const struct iovec *iov, int iovcnt);
-static ssize_t aws_readv(struct afb_websock *ws, const struct iovec *iov, int iovcnt);
-static void aws_disconnect(struct afb_websock *ws);
-static void aws_on_close(struct afb_websock *ws, uint16_t code, size_t size);
-static void aws_on_content(struct afb_websock *ws, int last, size_t size);
-static void aws_on_readable(struct afb_websock *ws);
-
-static struct websock_itf aws_itf = {
- .writev = (void*)aws_writev,
- .readv = (void*)aws_readv,
- .disconnect = (void*)aws_disconnect,
-
- .on_ping = NULL,
- .on_pong = NULL,
- .on_close = (void*)aws_on_close,
- .on_text = (void*)aws_on_content,
- .on_binary = (void*)aws_on_content,
- .on_continue = (void*)aws_on_content
-};
-
-struct afb_wsreq
-{
- struct afb_websock *aws;
- struct afb_wsreq *next;
- struct json_object *id;
- struct json_object *name;
- struct json_object *token;
- struct json_object *request;
-};
-
-struct afb_websock
-{
- int fd;
- struct MHD_Connection *connection;
- struct websock *ws;
- struct upoll *up;
- struct AFB_clientCtx *context;
- struct json_tokener *tokener;
- struct afb_wsreq *requests;
-};
-
-static struct afb_arg wsreq_get(struct afb_wsreq *wsreq, const char *name);
-static void wsreq_iterate(struct afb_wsreq *wsreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure);
-static void wsreq_fail(struct afb_wsreq *wsreq, const char *status, const char *info);
-static void wsreq_success(struct afb_wsreq *wsreq, struct json_object *obj, const char *info);
-static int wsreq_session_create(struct afb_wsreq *wsreq);
-static int wsreq_session_check(struct afb_wsreq *wsreq, int refresh);
-static void wsreq_session_close(struct afb_wsreq *wsreq);
-
-static const struct afb_req_itf wsreq_itf = {
- .get = (void*)wsreq_get,
- .iterate = (void*)wsreq_iterate,
- .fail = (void*)wsreq_fail,
- .success = (void*)wsreq_success,
- .session_create = (void*)wsreq_session_create,
- .session_check = (void*)wsreq_session_check,
- .session_close = (void*)wsreq_session_close
-};
-
-struct afb_websock *afb_websock_create(struct afb_hreq *hreq)
-{
- int fd;
- struct afb_websock *result;
-
- fd = MHD_get_connection_info(hreq->connection,
- MHD_CONNECTION_INFO_CONNECTION_FD)->connect_fd;
- fd = dup(fd);
- if (fd < 0)
- return NULL;
-
- result = malloc(sizeof * result);
- if (result == NULL)
- goto error;
-
- result->connection = hreq->connection;
- result->fd = fd;
- result->context = ctxClientGet(afb_hreq_context(hreq));
- if (result->context == NULL)
- goto error2;
-
- result->tokener = json_tokener_new();
- if (result->tokener == NULL)
- goto error2;
-
- result->ws = websock_create(&aws_itf, result);
- if (result->ws == NULL)
- goto error3;
-
- result->up = upoll_open(result->fd, result);
- if (result->up == NULL)
- goto error4;
-
- upoll_on_readable(result->up, (void*)aws_on_readable);
- upoll_on_hangup(result->up, (void*)aws_disconnect);
- return result;
-error4:
- websock_destroy(result->ws);
-error3:
- json_tokener_free(result->tokener);
-error2:
- free(result);
-error:
- close(fd);
- return NULL;
-}
-
-static ssize_t aws_writev(struct afb_websock *ws, const struct iovec *iov, int iovcnt)
-{
- ssize_t rc;
- do {
- rc = writev(ws->fd, iov, iovcnt);
- } while(rc == -1 && errno == EINTR);
- return rc;
-}
-
-static ssize_t aws_readv(struct afb_websock *ws, const struct iovec *iov, int iovcnt)
-{
- ssize_t rc;
- do {
- rc = readv(ws->fd, iov, iovcnt);
- } while(rc == -1 && errno == EINTR);
- return rc;
-}
-
-static void aws_disconnect(struct afb_websock *ws)
-{
- upoll_close(ws->up);
- websock_destroy(ws->ws);
- close(ws->fd);
- MHD_resume_connection (ws->connection);
- ctxClientPut(ws->context);
- json_tokener_free(ws->tokener);
- free(ws);
-}