From 1b4ea06e92e55cdc631a3dc7514c751d3924af05 Mon Sep 17 00:00:00 2001 From: Lammert Bies Date: Wed, 16 Nov 2016 16:30:20 +0100 Subject: [PATCH] Moved mg_connect_websocket_client to own file --- Makefile | 1 + src/httplib_connect_websocket_client.c | 138 +++++++++++++++++++++++++ src/libhttp.c | 103 ------------------ 3 files changed, 139 insertions(+), 103 deletions(-) create mode 100644 src/httplib_connect_websocket_client.c diff --git a/Makefile b/Makefile index a90ef6ff..8f065f9c 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,7 @@ BUILD_DIRS = $(BUILD_DIR) $(BUILD_DIR)/src $(BUILD_DIR)/resources LIB_SOURCES = src/libhttp.c \ src/httplib_accept_new_connection.c \ src/httplib_check_feature.c \ + src/httplib_connect_websocket_client.c \ src/httplib_consume_socket.c \ src/httplib_free_context.c \ src/httplib_get_response_code_text.c \ diff --git a/src/httplib_connect_websocket_client.c b/src/httplib_connect_websocket_client.c new file mode 100644 index 00000000..27c6a42e --- /dev/null +++ b/src/httplib_connect_websocket_client.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2016 Lammert Bies + * Copyright (c) 2013-2016 the Civetweb developers + * Copyright (c) 2004-2013 Sergey Lyubka + * + * 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 "libhttp-private.h" + + + +/* + * struct mg_connection *mg_connect_websocket_client(); + * + * The function mg_connect_websocket_client() connects as a client to a + * websocket on another server. If this succeeds a connection pointer is + * returned, otherwise NULL. + */ + +struct mg_connection *mg_connect_websocket_client(const char *host, + int port, + int use_ssl, + char *error_buffer, + size_t error_buffer_size, + const char *path, + const char *origin, + mg_websocket_data_handler data_func, + mg_websocket_close_handler close_func, + void *user_data) +{ + struct mg_connection *conn = NULL; + +#if defined(USE_WEBSOCKET) + struct mg_context *newctx = NULL; + struct websocket_client_thread_data *thread_data; + static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw=="; + static const char *handshake_req; + + if (origin != NULL) { + handshake_req = "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Origin: %s\r\n" + "\r\n"; + } else { + handshake_req = "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + "\r\n"; + } + + /* Establish the client connection and request upgrade */ + conn = mg_download(host, port, use_ssl, error_buffer, error_buffer_size, handshake_req, path, host, magic, origin); + + /* Connection object will be null if something goes wrong */ + if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) { + if (!*error_buffer) { + /* if there is a connection, but it did not return 101, + * error_buffer is not yet set */ + XX_httplib_snprintf(conn, NULL, error_buffer, error_buffer_size, "Unexpected server reply"); + } + if (conn != NULL) { + XX_httplib_free(conn); + conn = NULL; + } + return conn; + } + + /* For client connections, mg_context is fake. Since we need to set a + * callback function, we need to create a copy and modify it. */ + newctx = (struct mg_context *)XX_httplib_malloc(sizeof(struct mg_context)); + memcpy(newctx, conn->ctx, sizeof(struct mg_context)); + newctx->user_data = user_data; + newctx->context_type = 2; /* client context type */ + newctx->cfg_worker_threads = 1; /* one worker thread will be created */ + newctx->workerthreadids = + (pthread_t *)XX_httplib_calloc(newctx->cfg_worker_threads, sizeof(pthread_t)); + conn->ctx = newctx; + thread_data = (struct websocket_client_thread_data *) + XX_httplib_calloc(sizeof(struct websocket_client_thread_data), 1); + thread_data->conn = conn; + thread_data->data_handler = data_func; + thread_data->close_handler = close_func; + thread_data->callback_data = NULL; + + /* Start a thread to read the websocket client connection + * This thread will automatically stop when mg_disconnect is + * called on the client connection */ + if (mg_start_thread_with_id(websocket_client_thread, (void *)thread_data, newctx->workerthreadids) != 0) { + + XX_httplib_free((void *)thread_data); + XX_httplib_free((void *)newctx->workerthreadids); + XX_httplib_free((void *)newctx); + XX_httplib_free((void *)conn); + conn = NULL; + } +#else + /* Appease "unused parameter" warnings */ + (void)host; + (void)port; + (void)use_ssl; + (void)error_buffer; + (void)error_buffer_size; + (void)path; + (void)origin; + (void)user_data; + (void)data_func; + (void)close_func; +#endif + + return conn; + +} /* mg_connect_websocket_client */ diff --git a/src/libhttp.c b/src/libhttp.c index 12c028aa..3b2800c5 100644 --- a/src/libhttp.c +++ b/src/libhttp.c @@ -9900,106 +9900,3 @@ websocket_client_thread(void *data) #endif /* _WIN32 */ } #endif - - -struct mg_connection * -mg_connect_websocket_client(const char *host, - int port, - int use_ssl, - char *error_buffer, - size_t error_buffer_size, - const char *path, - const char *origin, - mg_websocket_data_handler data_func, - mg_websocket_close_handler close_func, - void *user_data) -{ - struct mg_connection *conn = NULL; - -#if defined(USE_WEBSOCKET) - struct mg_context *newctx = NULL; - struct websocket_client_thread_data *thread_data; - static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw=="; - static const char *handshake_req; - - if (origin != NULL) { - handshake_req = "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key: %s\r\n" - "Sec-WebSocket-Version: 13\r\n" - "Origin: %s\r\n" - "\r\n"; - } else { - handshake_req = "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key: %s\r\n" - "Sec-WebSocket-Version: 13\r\n" - "\r\n"; - } - - /* Establish the client connection and request upgrade */ - conn = mg_download(host, port, use_ssl, error_buffer, error_buffer_size, handshake_req, path, host, magic, origin); - - /* Connection object will be null if something goes wrong */ - if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) { - if (!*error_buffer) { - /* if there is a connection, but it did not return 101, - * error_buffer is not yet set */ - XX_httplib_snprintf(conn, NULL, error_buffer, error_buffer_size, "Unexpected server reply"); - } - if (conn != NULL) { - XX_httplib_free(conn); - conn = NULL; - } - return conn; - } - - /* For client connections, mg_context is fake. Since we need to set a - * callback function, we need to create a copy and modify it. */ - newctx = (struct mg_context *)XX_httplib_malloc(sizeof(struct mg_context)); - memcpy(newctx, conn->ctx, sizeof(struct mg_context)); - newctx->user_data = user_data; - newctx->context_type = 2; /* client context type */ - newctx->cfg_worker_threads = 1; /* one worker thread will be created */ - newctx->workerthreadids = - (pthread_t *)XX_httplib_calloc(newctx->cfg_worker_threads, sizeof(pthread_t)); - conn->ctx = newctx; - thread_data = (struct websocket_client_thread_data *) - XX_httplib_calloc(sizeof(struct websocket_client_thread_data), 1); - thread_data->conn = conn; - thread_data->data_handler = data_func; - thread_data->close_handler = close_func; - thread_data->callback_data = NULL; - - /* Start a thread to read the websocket client connection - * This thread will automatically stop when mg_disconnect is - * called on the client connection */ - if (mg_start_thread_with_id(websocket_client_thread, - (void *)thread_data, - newctx->workerthreadids) != 0) { - XX_httplib_free((void *)thread_data); - XX_httplib_free((void *)newctx->workerthreadids); - XX_httplib_free((void *)newctx); - XX_httplib_free((void *)conn); - conn = NULL; - } -#else - /* Appease "unused parameter" warnings */ - (void)host; - (void)port; - (void)use_ssl; - (void)error_buffer; - (void)error_buffer_size; - (void)path; - (void)origin; - (void)user_data; - (void)data_func; - (void)close_func; -#endif - - return conn; -}