summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/lib/websocket.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-07-24 09:54:23 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-07-24 09:54:44 +0000
commit836b47cb7e99a977c5a23b059ca1d0b5065d310e (patch)
tree1604da8f482d02effa033c94a84be42bc0c848c3 /web/server/h2o/libh2o/lib/websocket.c
parentReleasing debian version 1.44.3-2. (diff)
downloadnetdata-836b47cb7e99a977c5a23b059ca1d0b5065d310e.tar.xz
netdata-836b47cb7e99a977c5a23b059ca1d0b5065d310e.zip
Merging upstream version 1.46.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'web/server/h2o/libh2o/lib/websocket.c')
-rw-r--r--web/server/h2o/libh2o/lib/websocket.c238
1 files changed, 0 insertions, 238 deletions
diff --git a/web/server/h2o/libh2o/lib/websocket.c b/web/server/h2o/libh2o/lib/websocket.c
deleted file mode 100644
index 2886acda6..000000000
--- a/web/server/h2o/libh2o/lib/websocket.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2014 DeNA Co., Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <openssl/sha.h>
-#include "h2o/websocket.h"
-
-#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
-static void create_accept_key(char *dst, const char *client_key)
-{
- uint8_t sha1buf[20], key_src[60];
-
- memcpy(key_src, client_key, 24);
- memcpy(key_src + 24, WS_GUID, 36);
- SHA1(key_src, sizeof(key_src), sha1buf);
- h2o_base64_encode(dst, sha1buf, sizeof(sha1buf), 0);
- dst[28] = '\0';
-}
-
-static void on_close(h2o_websocket_conn_t *conn)
-{
- (*conn->cb)(conn, NULL);
-}
-
-static void on_recv(h2o_socket_t *sock, const char *err)
-{
- h2o_websocket_conn_t *conn = sock->data;
-
- if (err != NULL) {
- on_close(conn);
- return;
- }
- h2o_websocket_proceed(conn);
-}
-
-static void on_write_complete(h2o_socket_t *sock, const char *err)
-{
- h2o_websocket_conn_t *conn = sock->data;
-
- if (err != NULL) {
- on_close(conn);
- return;
- }
- h2o_websocket_proceed(conn);
-}
-
-static ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, int flags, void *_conn)
-{
- h2o_websocket_conn_t *conn = _conn;
-
- /* return WOULDBLOCK if no data */
- if (conn->sock->input->size == 0) {
- wslay_event_set_error(conn->ws_ctx, WSLAY_ERR_WOULDBLOCK);
- return -1;
- }
-
- if (conn->sock->input->size < len)
- len = conn->sock->input->size;
- memcpy(buf, conn->sock->input->bytes, len);
- h2o_buffer_consume(&conn->sock->input, len);
- return len;
-}
-
-static ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *_conn)
-{
- h2o_websocket_conn_t *conn = _conn;
- h2o_iovec_t buf;
-
- /* return WOULDBLOCK if pending (TODO: queue fixed number of chunks, instead of only one) */
- if (h2o_socket_is_writing(conn->sock)) {
- wslay_event_set_error(conn->ws_ctx, WSLAY_ERR_WOULDBLOCK);
- return -1;
- }
-
- /* copy data */
- conn->_write_buf = h2o_mem_realloc(conn->_write_buf, len);
- memcpy(conn->_write_buf, data, len);
-
- /* write */
- buf.base = conn->_write_buf;
- buf.len = len;
- h2o_socket_write(conn->sock, &buf, 1, on_write_complete);
-
- return len;
-}
-
-static void on_msg_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *_conn)
-{
- h2o_websocket_conn_t *conn = _conn;
- (*conn->cb)(conn, arg);
-}
-
-static void on_complete(void *user_data, h2o_socket_t *sock, size_t reqsize)
-{
- h2o_websocket_conn_t *conn = user_data;
-
- /* close the connection on error */
- if (sock == NULL) {
- (*conn->cb)(conn, NULL);
- return;
- }
-
- conn->sock = sock;
- sock->data = conn;
- h2o_buffer_consume(&sock->input, reqsize);
- h2o_websocket_proceed(conn);
-}
-
-h2o_websocket_conn_t *h2o_upgrade_to_websocket(h2o_req_t *req, const char *client_key, void *data, h2o_websocket_msg_callback cb)
-{
- h2o_websocket_conn_t *conn = h2o_mem_alloc(sizeof(*conn));
- char accept_key[29];
-
- /* only for http1 connection */
- assert(req->version < 0x200);
-
- /* setup the context */
- memset(conn, 0, sizeof(*conn));
- // conn->sock = sock; set by on_complete
- conn->ws_callbacks.recv_callback = recv_callback;
- conn->ws_callbacks.send_callback = send_callback;
- conn->ws_callbacks.on_msg_recv_callback = on_msg_callback;
- conn->data = data;
- conn->cb = cb;
-
- wslay_event_context_server_init(&conn->ws_ctx, &conn->ws_callbacks, conn);
-
- /* build response */
- create_accept_key(accept_key, client_key);
- req->res.status = 101;
- req->res.reason = "Switching Protocols";
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("websocket"));
- h2o_add_header_by_str(&req->pool, &req->res.headers, H2O_STRLIT("sec-websocket-accept"), 0, NULL, accept_key,
- strlen(accept_key));
-
- /* send */
- h2o_http1_upgrade(req, NULL, 0, on_complete, conn);
-
- return conn;
-}
-
-int h2o_is_websocket_handshake(h2o_req_t *req, const char **ws_client_key)
-{
- ssize_t key_header_index;
-
- *ws_client_key = NULL;
-
- /* method */
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("GET"))) {
- /* ok */
- } else {
- return 0;
- }
-
- /* upgrade header */
- if (req->upgrade.base != NULL && h2o_lcstris(req->upgrade.base, req->upgrade.len, H2O_STRLIT("websocket"))) {
- /* ok */
- } else {
- return 0;
- }
- /* sec-websocket-key header */
- if ((key_header_index = h2o_find_header_by_str(&req->headers, H2O_STRLIT("sec-websocket-key"), -1)) != -1) {
- if (req->headers.entries[key_header_index].value.len != 24) {
- return -1;
- }
- } else {
- return 0;
- }
-
- *ws_client_key = req->headers.entries[key_header_index].value.base;
- return 0;
-}
-
-void h2o_websocket_close(h2o_websocket_conn_t *conn)
-{
- if (conn->sock != NULL)
- h2o_socket_close(conn->sock);
- free(conn->_write_buf);
- wslay_event_context_free(conn->ws_ctx);
- free(conn);
-}
-
-void h2o_websocket_proceed(h2o_websocket_conn_t *conn)
-{
- int handled;
-
- /* run the loop until getting to a point where no more progress can be achieved */
- do {
- handled = 0;
- if (!h2o_socket_is_writing(conn->sock) && wslay_event_want_write(conn->ws_ctx)) {
- if (wslay_event_send(conn->ws_ctx) != 0) {
- goto Close;
- }
- handled = 1;
- }
- if (conn->sock->input->size != 0 && wslay_event_want_read(conn->ws_ctx)) {
- if (wslay_event_recv(conn->ws_ctx) != 0) {
- goto Close;
- }
- handled = 1;
- }
- } while (handled);
-
- if (wslay_event_want_read(conn->ws_ctx)) {
- h2o_socket_read_start(conn->sock, on_recv);
- } else if (h2o_socket_is_writing(conn->sock) || wslay_event_want_write(conn->ws_ctx)) {
- h2o_socket_read_stop(conn->sock);
- } else {
- /* nothing is going on... close the socket */
- goto Close;
- }
-
- return;
-
-Close:
- on_close(conn);
-}