From 1dc4816d2bd7ec212d78754988cd2475c8cd2332 Mon Sep 17 00:00:00 2001 From: Lammert Bies Date: Sat, 10 Dec 2016 17:05:55 +0100 Subject: [PATCH] Moved websocket_client_write to own file --- Makefile | 1 + src/httplib_websocket_client_write.c | 97 ++++++++++++++++++++++++++++ src/libhttp-private.h | 1 + src/libhttp.c | 54 ++-------------- 4 files changed, 104 insertions(+), 49 deletions(-) create mode 100644 src/httplib_websocket_client_write.c diff --git a/Makefile b/Makefile index 37c4cac9..7c670bfe 100644 --- a/Makefile +++ b/Makefile @@ -102,6 +102,7 @@ LIB_SOURCES = src/libhttp.c \ src/httplib_uninitialize_ssl.c \ src/httplib_version.c \ src/httplib_websocket_client_thread.c \ + src/httplib_websocket_client_write.c \ src/httplib_worker_thread.c \ src/md5.c LIB_INLINE = src/mod_lua.inl src/md5.inl diff --git a/src/httplib_websocket_client_write.c b/src/httplib_websocket_client_write.c new file mode 100644 index 00000000..b81fcb89 --- /dev/null +++ b/src/httplib_websocket_client_write.c @@ -0,0 +1,97 @@ +/* + * 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" + + + +#if defined(USE_WEBSOCKET) + +static void mask_data( const char *in, size_t in_len, uint32_t masking_key, char *out ); + + + +/* + * int mg_websocket_client_write( struct mg_connection *conn, int opcode, const char *data, size_t dataLen ); + * + * The function mg_websocket_client_write() is used to write as a client to a + * websocket server. + */ + +int mg_websocket_client_write( struct mg_connection *conn, int opcode, const char *data, size_t dataLen ) { + + int retval = -1; + char *masked_data = XX_httplib_malloc(((dataLen + 7) / 4) * 4); + uint32_t masking_key = (uint32_t)XX_httplib_get_random(); + + if (masked_data == NULL) { + /* Return -1 in an error case */ + mg_cry(conn, "Cannot allocate buffer for masked websocket response: Out of memory"); + return -1; + } + + mask_data(data, dataLen, masking_key, masked_data); + + retval = XX_httplib_websocket_write_exec( conn, opcode, masked_data, dataLen, masking_key ); + XX_httplib_free(masked_data); + + return retval; + +} /* mg_websocket_client_write */ + + + +/* + * static void mask_data( const char *in, size_t in_len, uint32_t masking_key, char *out ); + * + * The function mask_data() is used to mask data when writing data over a + * websocket client connection. + */ + +static void mask_data( const char *in, size_t in_len, uint32_t masking_key, char *out ) { + + size_t i = 0; + + i = 0; + if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) { + /* Convert in 32 bit words, if data is 4 byte aligned */ + while (i < (in_len - 3)) { + *(uint32_t *)(void *)(out + i) = *(uint32_t *)(void *)(in + i) ^ masking_key; + i += 4; + } + } + if (i != in_len) { + /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/ + while (i < in_len) { + *(uint8_t *)(void *)(out + i) = *(uint8_t *)(void *)(in + i) ^ *(((uint8_t *)&masking_key) + (i % 4)); + i++; + } + } + +} /* mask_data */ + + +#endif /* !USE_WEBSOCKET */ diff --git a/src/libhttp-private.h b/src/libhttp-private.h index 0f48924b..f6cb94d9 100644 --- a/src/libhttp-private.h +++ b/src/libhttp-private.h @@ -931,6 +931,7 @@ const char * XX_httplib_suggest_connection_header( const struct mg_connection * void XX_httplib_tls_dtor( void *key ); void XX_httplib_uninitialize_ssl( struct mg_context *ctx ); int XX_httplib_vprintf( struct mg_connection *conn, const char *fmt, va_list ap ); +int XX_httplib_websocket_write_exec( struct mg_connection *conn, int opcode, const char *data, size_t dataLen, uint32_t masking_key ); diff --git a/src/libhttp.c b/src/libhttp.c index 1451a675..dc861197 100644 --- a/src/libhttp.c +++ b/src/libhttp.c @@ -6954,7 +6954,7 @@ void XX_httplib_read_websocket( struct mg_connection *conn, mg_websocket_data_ha } /* XX_httplib_read_websocket */ -static int mg_websocket_write_exec(struct mg_connection *conn, int opcode, const char *data, size_t dataLen, uint32_t masking_key) { +int XX_httplib_websocket_write_exec( struct mg_connection *conn, int opcode, const char *data, size_t dataLen, uint32_t masking_key ) { unsigned char header[14]; size_t headerLen = 1; @@ -7003,57 +7003,13 @@ static int mg_websocket_write_exec(struct mg_connection *conn, int opcode, const mg_unlock_connection(conn); return retval; -} -int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t dataLen) { +} /* XX_httplib_websocket_write_exec */ - return mg_websocket_write_exec(conn, opcode, data, dataLen, 0); +int mg_websocket_write( struct mg_connection *conn, int opcode, const char *data, size_t dataLen ) { + + return XX_httplib_websocket_write_exec( conn, opcode, data, dataLen, 0 ); } /* mg_websocket_write */ - -static void mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out) { - - size_t i = 0; - - i = 0; - if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) { - /* Convert in 32 bit words, if data is 4 byte aligned */ - while (i < (in_len - 3)) { - *(uint32_t *)(void *)(out + i) = *(uint32_t *)(void *)(in + i) ^ masking_key; - i += 4; - } - } - if (i != in_len) { - /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/ - while (i < in_len) { - *(uint8_t *)(void *)(out + i) = *(uint8_t *)(void *)(in + i) ^ *(((uint8_t *)&masking_key) + (i % 4)); - i++; - } - } - -} /* mask_data */ - - -int mg_websocket_client_write(struct mg_connection *conn, int opcode, const char *data, size_t dataLen) { - - int retval = -1; - char *masked_data = (char *)XX_httplib_malloc(((dataLen + 7) / 4) * 4); - uint32_t masking_key = (uint32_t)XX_httplib_get_random(); - - if (masked_data == NULL) { - /* Return -1 in an error case */ - mg_cry(conn, "Cannot allocate buffer for masked websocket response: Out of memory"); - return -1; - } - - mask_data(data, dataLen, masking_key, masked_data); - - retval = mg_websocket_write_exec( conn, opcode, masked_data, dataLen, masking_key ); - XX_httplib_free(masked_data); - - return retval; - -} /* mg_websocket_client_write */ - #endif /* !USE_WEBSOCKET */