aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2017-04-13 23:24:13 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2017-04-26 16:08:07 +0200
commit7e674cc7202abfae0dd07df8805a0dea743bf4be (patch)
treeb3351f2b72c800e4c856a7aa340915885b6184f3
parentf2995647f0f79e816c7f46033e1ec824185732b5 (diff)
Use upgrade abitlity of libmicrohttpd
Since version 0.9.52, libmicrohttpd correctly handles upgrading of connections. Leveraging that feature is a best. Change-Id: Icde686cd9a3c12dda5ee74f354086ccff435796c Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/afb-hreq.h1
-rw-r--r--src/afb-hsrv.c4
-rw-r--r--src/afb-websock.c65
3 files changed, 45 insertions, 25 deletions
diff --git a/src/afb-hreq.h b/src/afb-hreq.h
index f4c00ff2..ff394e03 100644
--- a/src/afb-hreq.h
+++ b/src/afb-hreq.h
@@ -44,7 +44,6 @@ struct afb_hreq {
struct MHD_PostProcessor *postform;
struct hreq_data *data;
struct json_object *json;
- int upgrade;
};
extern int afb_hreq_unprefix(struct afb_hreq *request, const char *prefix, size_t length);
diff --git a/src/afb-hsrv.c b/src/afb-hsrv.c
index f0866f82..87895a7b 100644
--- a/src/afb-hsrv.c
+++ b/src/afb-hsrv.c
@@ -231,8 +231,6 @@ static void end_handler(void *cls, struct MHD_Connection *connection, void **rec
hreq = *recordreq;
if (hreq) {
- if (hreq->upgrade)
- MHD_suspend_connection (connection);
afb_hreq_unref(hreq);
}
}
@@ -399,7 +397,7 @@ int afb_hsrv_start(struct afb_hsrv *hsrv, uint16_t port, unsigned int connection
const union MHD_DaemonInfo *info;
httpd = MHD_start_daemon(
- MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_TCP_FASTOPEN | MHD_USE_DEBUG | MHD_USE_SUSPEND_RESUME,
+ MHD_USE_EPOLL | MHD_ALLOW_UPGRADE | MHD_USE_TCP_FASTOPEN | MHD_USE_DEBUG | MHD_USE_SUSPEND_RESUME,
port, /* port */
new_client_handler, NULL, /* Tcp Accept call back + extra attribute */
access_handler, hsrv, /* Http Request Call back + extra attribute */
diff --git a/src/afb-websock.c b/src/afb-websock.c
index 523ad8ff..765624d9 100644
--- a/src/afb-websock.c
+++ b/src/afb-websock.c
@@ -119,15 +119,47 @@ static const struct protodef *search_proto(const struct protodef *protodefs, con
}
}
-static int check_websocket_upgrade(struct MHD_Connection *con, const struct protodef *protodefs, void *context, void **websock, struct afb_apiset *apiset)
+struct memo_websocket {
+ const struct protodef *proto;
+ struct afb_hreq *hreq;
+ struct afb_apiset *apiset;
+};
+
+static void close_websocket(void *closure)
+{
+ struct MHD_UpgradeResponseHandle *urh = closure;
+ MHD_upgrade_action (urh, MHD_UPGRADE_ACTION_CLOSE);
+}
+
+static void upgrade_to_websocket(
+ void *cls,
+ struct MHD_Connection *connection,
+ void *con_cls,
+ const char *extra_in,
+ size_t extra_in_size,
+ MHD_socket sock,
+ struct MHD_UpgradeResponseHandle *urh)
{
- const union MHD_ConnectionInfo *info;
+ struct memo_websocket *memo = cls;
+ void *ws;
+
+ ws = memo->proto->create(sock, memo->apiset, &memo->hreq->xreq.context, close_websocket, urh);
+ if (ws == NULL) {
+ /* TODO */
+ close_websocket(urh);
+ }
+ afb_hreq_unref(memo->hreq);
+ free(memo);
+}
+
+static int check_websocket_upgrade(struct MHD_Connection *con, const struct protodef *protodefs, struct afb_hreq *hreq, struct afb_apiset *apiset)
+{
+ struct memo_websocket *memo;
struct MHD_Response *response;
const char *connection, *upgrade, *key, *version, *protocols;
char acceptval[29];
int vernum;
const struct protodef *proto;
- void *ws;
/* is an upgrade to websocket ? */
upgrade = MHD_lookup_connection_value(con, MHD_HEADER_KIND, MHD_HTTP_HEADER_UPGRADE);
@@ -137,7 +169,7 @@ static int check_websocket_upgrade(struct MHD_Connection *con, const struct prot
/* is a connection for upgrade ? */
connection = MHD_lookup_connection_value(con, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONNECTION);
if (connection == NULL
- || !headerhas (connection, MHD_HTTP_HEADER_UPGRADE))
+ || !headerhas (connection, MHD_HTTP_HEADER_UPGRADE))
return 0;
/* has a key and a version ? */
@@ -166,25 +198,21 @@ static int check_websocket_upgrade(struct MHD_Connection *con, const struct prot
return 1;
}
- /* create the web socket */
- info = MHD_get_connection_info(con, MHD_CONNECTION_INFO_CONNECTION_FD);
- if (info == NULL) {
- response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
- MHD_queue_response(con, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
- MHD_destroy_response(response);
- return 1;
- }
- ws = proto->create(info->connect_fd, apiset, context, (void*)MHD_resume_connection, con);
- if (ws == NULL) {
+ /* record context */
+ memo = malloc(sizeof *memo);
+ if (memo == NULL) {
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_queue_response(con, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
MHD_destroy_response(response);
return 1;
}
+ memo->proto = proto;
+ memo->hreq = hreq;
+ memo->apiset = apiset;
/* send the accept connection */
+ response = MHD_create_response_for_upgrade(upgrade_to_websocket, memo);
make_accept_value(key, acceptval);
- 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, sec_websocket_protocol_s, proto->name);
MHD_add_response_header(response, MHD_HTTP_HEADER_CONNECTION, MHD_HTTP_HEADER_UPGRADE);
@@ -192,7 +220,6 @@ static int check_websocket_upgrade(struct MHD_Connection *con, const struct prot
MHD_queue_response(con, MHD_HTTP_SWITCHING_PROTOCOLS, response);
MHD_destroy_response(response);
- *websock = ws;
return 1;
}
@@ -203,7 +230,6 @@ static const struct protodef protodefs[] = {
int afb_websock_check_upgrade(struct afb_hreq *hreq, struct afb_apiset *apiset)
{
- void *ws;
int rc;
/* is a get ? */
@@ -211,12 +237,9 @@ int afb_websock_check_upgrade(struct afb_hreq *hreq, struct afb_apiset *apiset)
|| strcasecmp(hreq->version, MHD_HTTP_VERSION_1_1))
return 0;
- ws = NULL;
- rc = check_websocket_upgrade(hreq->connection, protodefs, &hreq->xreq.context, &ws, apiset);
+ rc = check_websocket_upgrade(hreq->connection, protodefs, hreq, apiset);
if (rc == 1) {
hreq->replied = 1;
- if (ws != NULL)
- hreq->upgrade = 1;
}
return rc;
}