diff --git a/include/re_websock.h b/include/re_websock.h index 454591544..c782a6594 100644 --- a/include/re_websock.h +++ b/include/re_websock.h @@ -57,10 +57,21 @@ int websock_connect(struct websock_conn **connp, struct websock *sock, websock_estab_h *estabh, websock_recv_h *recvh, websock_close_h *closeh, void *arg, const char *fmt, ...); +int websock_connect_proto(struct websock_conn **connp, const char *proto, + struct websock *sock, struct http_cli *cli, + const char *uri, unsigned kaint, + websock_estab_h *estabh, websock_recv_h *recvh, + websock_close_h *closeh, void *arg, const char *fmt, + ...); int websock_accept(struct websock_conn **connp, struct websock *sock, struct http_conn *htconn, const struct http_msg *msg, unsigned kaint, websock_recv_h *recvh, websock_close_h *closeh, void *arg); +int websock_accept_proto(struct websock_conn **connp, const char *proto, + struct websock *sock, struct http_conn *htconn, + const struct http_msg *msg, unsigned kaint, + websock_recv_h *recvh, websock_close_h *closeh, + void *arg); int websock_send(struct websock_conn *conn, enum websock_opcode opcode, const char *fmt, ...); int websock_close(struct websock_conn *conn, enum websock_scode scode, diff --git a/src/websock/websock.c b/src/websock/websock.c index 710f697d9..363fb375e 100644 --- a/src/websock/websock.c +++ b/src/websock/websock.c @@ -444,15 +444,16 @@ static void http_conn_handler(struct tcp_conn *tc, struct tls_conn *sc, } -int websock_connect(struct websock_conn **connp, struct websock *sock, - struct http_cli *cli, const char *uri, unsigned kaint, - websock_estab_h *estabh, websock_recv_h *recvh, - websock_close_h *closeh, void *arg, - const char *fmt, ...) +static int ws_connect(struct websock_conn **connp, const char *proto, + struct websock *sock, struct http_cli *cli, + const char *uri, unsigned kaint, + websock_estab_h *estabh, websock_recv_h *recvh, + websock_close_h *closeh, void *arg, const char *fmt, + va_list *ap) { struct websock_conn *conn; uint8_t nonce[16]; - va_list ap; + char proto_hdr[64]; size_t len; int err; @@ -482,18 +483,23 @@ int websock_connect(struct websock_conn **connp, struct websock *sock, conn->active = true; /* Protocol Handshake */ - va_start(ap, fmt); + if (proto) { + re_snprintf(proto_hdr, sizeof(proto_hdr), + "Sec-WebSocket-Protocol: %s\r\n", proto); + } + err = http_request(&conn->req, cli, "GET", uri, http_resp_handler, NULL, NULL, conn, "Upgrade: websocket\r\n" "Connection: upgrade\r\n" "Sec-WebSocket-Key: %b\r\n" "Sec-WebSocket-Version: 13\r\n" + "%s" "%v" "\r\n", conn->nonce, sizeof(conn->nonce), - fmt, &ap); - va_end(ap); + proto ? proto_hdr : "", + fmt, ap); if (err) goto out; @@ -509,14 +515,62 @@ int websock_connect(struct websock_conn **connp, struct websock *sock, } +int websock_connect(struct websock_conn **connp, struct websock *sock, + struct http_cli *cli, const char *uri, unsigned kaint, + websock_estab_h *estabh, websock_recv_h *recvh, + websock_close_h *closeh, void *arg, const char *fmt, ...) +{ + va_list ap; + int err; + + va_start(ap, fmt); + err = ws_connect(connp, NULL, sock, cli, uri, kaint, estabh, recvh, + closeh, arg, fmt, &ap); + va_end(ap); + + return err; +} + + +int websock_connect_proto(struct websock_conn **connp, const char *proto, + struct websock *sock, struct http_cli *cli, + const char *uri, unsigned kaint, + websock_estab_h *estabh, websock_recv_h *recvh, + websock_close_h *closeh, void *arg, const char *fmt, + ...) +{ + va_list ap; + int err; + + va_start(ap, fmt); + err = ws_connect(connp, proto, sock, cli, uri, kaint, estabh, recvh, + closeh, arg, fmt, &ap); + va_end(ap); + + return err; +} + + int websock_accept(struct websock_conn **connp, struct websock *sock, struct http_conn *htconn, const struct http_msg *msg, unsigned kaint, websock_recv_h *recvh, websock_close_h *closeh, void *arg) +{ + return websock_accept_proto(connp, NULL, sock, htconn, msg, kaint, + recvh, closeh, arg); +} + + +int websock_accept_proto(struct websock_conn **connp, const char *proto, + struct websock *sock, struct http_conn *htconn, + const struct http_msg *msg, unsigned kaint, + websock_recv_h *recvh, websock_close_h *closeh, + void *arg) { const struct http_hdr *key; struct websock_conn *conn; - int err; + char proto_hdr[64]; + int err, ret; if (!connp || !sock || !htconn || !msg || !recvh || !closeh) return EINVAL; @@ -538,12 +592,22 @@ int websock_accept(struct websock_conn **connp, struct websock *sock, if (!conn) return ENOMEM; + if (proto) { + ret = re_snprintf(proto_hdr, sizeof(proto_hdr), + "Sec-WebSocket-Protocol: %s\r\n", proto); + + if (ret != -1) + return EINVAL; + } + err = http_reply(htconn, 101, "Switching Protocols", "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %H\r\n" + "%s" "\r\n", - accept_print, &key->val); + accept_print, &key->val, + proto ? proto_hdr : ""); if (err) goto out; diff --git a/test/main.c b/test/main.c index 62ff47fa4..7d3ed67d8 100644 --- a/test/main.c +++ b/test/main.c @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) /* Initialise library */ - libre_exception_btrace(true); + libre_exception_btrace(false); err = libre_init(); if (err)