Selaa lähdekoodia

Merge pull request #922 from jdetaeye/websocket_compression_client

Websocket compression client
bel2125 4 vuotta sitten
vanhempi
commit
a3bd89361c
3 muutettua tiedostoa jossa 155 lisäystä ja 31 poistoa
  1. 24 0
      include/civetweb.h
  2. 129 29
      src/civetweb.c
  3. 2 2
      src/mod_zlib.inl

+ 24 - 0
include/civetweb.h

@@ -1421,6 +1421,19 @@ mg_connect_websocket_client(const char *host,
                             mg_websocket_close_handler close_func,
                             void *user_data);
 
+CIVETWEB_API struct mg_connection *
+mg_connect_websocket_client_extensions(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,
+                                       const char *extensions);
+
 
 /* Connect to a TCP server as a client (can be used to connect to a HTTP server)
    Parameters:
@@ -1467,6 +1480,17 @@ CIVETWEB_API struct mg_connection *mg_connect_websocket_client_secure(
     mg_websocket_close_handler close_func,
     void *user_data);
 
+CIVETWEB_API struct mg_connection *
+mg_connect_websocket_client_secure_extensions(
+    const struct mg_client_options *client_options,
+    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,
+    const char *extensions);
 
 #if defined(MG_LEGACY_INTERFACE) /* 2019-11-02 */
 enum { TIMEOUT_INFINITE = -1 };

+ 129 - 29
src/civetweb.c

@@ -12937,8 +12937,8 @@ read_websocket(struct mg_connection *conn,
 							size_t inflate_buf_size_old = 0;
 							size_t inflate_buf_size =
 							    data_len
-							    * 4; // Initial guess of the inflated message
-							         // size. We double the memory when needed.
+							    * 10; // Initial guess of the inflated message
+							          // size. We double the memory when needed.
 							Bytef *inflated;
 							Bytef *new_mem;
 							conn->websocket_inflate_state.avail_in =
@@ -12962,7 +12962,7 @@ read_websocket(struct mg_connection *conn,
 									mg_cry_internal(
 									    conn,
 									    "Out of memory: Cannot allocate "
-									    "inflate buffer of %i bytes",
+									    "inflate buffer of %zu bytes",
 									    inflate_buf_size);
 									exit_by_callback = 1;
 									break;
@@ -12977,7 +12977,7 @@ read_websocket(struct mg_connection *conn,
 								    inflate(&conn->websocket_inflate_state,
 								            Z_SYNC_FLUSH);
 								if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR
-								    || ret == Z_MEM_ERROR || ret < 0) {
+								    || ret == Z_MEM_ERROR) {
 									mg_cry_internal(
 									    conn,
 									    "ZLIB inflate error: %i %s",
@@ -13150,7 +13150,7 @@ mg_websocket_write_exec(struct mg_connection *conn,
 		if (deflated == NULL) {
 			mg_cry_internal(
 			    conn,
-			    "Out of memory: Cannot allocate deflate buffer of %i bytes",
+			    "Out of memory: Cannot allocate deflate buffer of %zu bytes",
 			    deflated_size);
 			mg_unlock_connection(conn);
 			return -1;
@@ -18174,37 +18174,18 @@ mg_connect_websocket_client_impl(const struct mg_client_options *client_options,
                                  const char *origin,
                                  mg_websocket_data_handler data_func,
                                  mg_websocket_close_handler close_func,
-                                 void *user_data)
+                                 void *user_data,
+                                 const char *extensions)
 {
 	struct mg_connection *conn = NULL;
 
 #if defined(USE_WEBSOCKET)
 	struct websocket_client_thread_data *thread_data;
 	static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
-	const char *handshake_req;
 
 	const char *host = client_options->host;
 	int i;
 
-	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";
-	}
-
 #if defined(__clang__)
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wformat-nonliteral"
@@ -18230,7 +18211,68 @@ mg_connect_websocket_client_impl(const struct mg_client_options *client_options,
 		return NULL;
 	}
 
-	i = mg_printf(conn, handshake_req, path, host, magic, origin);
+	if (origin != NULL) {
+		if (extensions != NULL) {
+			i = mg_printf(conn,
+			              "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"
+			              "Sec-WebSocket-Extensions: %s\r\n"
+			              "Origin: %s\r\n"
+			              "\r\n",
+			              path,
+			              host,
+			              magic,
+			              extensions,
+			              origin);
+		} else {
+			i = mg_printf(conn,
+			              "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",
+			              path,
+			              host,
+			              magic,
+			              origin);
+		}
+	} else {
+
+		if (extensions != NULL) {
+			i = mg_printf(conn,
+			              "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"
+			              "Sec-WebSocket-Extensions: %s\r\n"
+			              "\r\n",
+			              path,
+			              host,
+			              magic,
+			              extensions);
+		} else {
+			i = mg_printf(conn,
+			              "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",
+			              path,
+			              host,
+			              magic);
+		}
+	}
 	if (i <= 0) {
 		mg_snprintf(conn,
 		            NULL, /* No truncation check for ebuf */
@@ -18356,7 +18398,8 @@ mg_connect_websocket_client(const char *host,
 	                                        origin,
 	                                        data_func,
 	                                        close_func,
-	                                        user_data);
+	                                        user_data,
+	                                        NULL);
 }
 
 
@@ -18382,9 +18425,66 @@ mg_connect_websocket_client_secure(
 	                                        origin,
 	                                        data_func,
 	                                        close_func,
-	                                        user_data);
+	                                        user_data,
+	                                        NULL);
+}
+
+struct mg_connection *
+mg_connect_websocket_client_extensions(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,
+                                       const char *extensions)
+{
+	struct mg_client_options client_options;
+	memset(&client_options, 0, sizeof(client_options));
+	client_options.host = host;
+	client_options.port = port;
+
+	return mg_connect_websocket_client_impl(&client_options,
+	                                        use_ssl,
+	                                        error_buffer,
+	                                        error_buffer_size,
+	                                        path,
+	                                        origin,
+	                                        data_func,
+	                                        close_func,
+	                                        user_data,
+	                                        extensions);
 }
 
+struct mg_connection *
+mg_connect_websocket_client_secure_extensions(
+    const struct mg_client_options *client_options,
+    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,
+    const char *extensions)
+{
+	if (!client_options) {
+		return NULL;
+	}
+	return mg_connect_websocket_client_impl(client_options,
+	                                        1,
+	                                        error_buffer,
+	                                        error_buffer_size,
+	                                        path,
+	                                        origin,
+	                                        data_func,
+	                                        close_func,
+	                                        user_data,
+	                                        extensions);
+}
 
 /* Prepare connection data structure */
 static void

+ 2 - 2
src/mod_zlib.inl

@@ -194,7 +194,7 @@ websocket_deflate_negotiate(struct mg_connection *conn)
 			} else if (!strncmp(extensions, "client_no_context_takeover", 26)) {
 				extensions += 26;
 				conn->websocket_deflate_client_no_context_takeover = 1;
-			} else if (!strncmp(extensions, "server-max-window-bits", 22)) {
+			} else if (!strncmp(extensions, "server_max_window_bits", 22)) {
 				extensions += 22;
 				if (*extensions == '=') {
 					++extensions;
@@ -218,7 +218,7 @@ websocket_deflate_negotiate(struct mg_connection *conn)
 					if (*extensions == '"')
 						++extensions;
 				}
-			} else if (!strncmp(extensions, "client-max-window-bits", 22)) {
+			} else if (!strncmp(extensions, "client_max_window_bits", 22)) {
 				extensions += 22;
 				if (*extensions == '=') {
 					++extensions;