From e781c842836720cdaf208ec57347c2e2722ce252 Mon Sep 17 00:00:00 2001 From: JCash Date: Tue, 25 Aug 2020 14:25:29 +0200 Subject: [PATCH] first embryo --- .gitignore | 5 +- example/example.script | 30 - examples/assets/button.gui | 144 + examples/assets/fonts/example.font | 3 + examples/assets/images/green_button08.png | Bin 0 -> 267 bytes examples/assets/ui.atlas | 6 + .../websocket.collection | 6 +- examples/websocket.gui | 724 ++++ examples/websocket.gui_script | 120 + game.project | 7 +- myextension/ext.manifest | 2 - myextension/src/myextension.cpp | 112 - websocket/ext.manifest | 8 + websocket/include/wslay/config.h | 10 + websocket/include/wslay/wslay.h | 772 ++++ websocket/include/wslay/wslay_event.h | 142 + websocket/include/wslay/wslay_frame.h | 76 + websocket/include/wslay/wslay_net.h | 54 + websocket/include/wslay/wslay_queue.h | 53 + websocket/include/wslay/wslay_stack.h | 50 + websocket/include/wslay/wslayver.h | 31 + websocket/src/connection_pool.h | 174 + websocket/src/dns.h | 93 + websocket/src/mbedtls/base64.h | 98 + websocket/src/mbedtls/config.h | 3551 +++++++++++++++++ websocket/src/script_util.cpp | 79 + websocket/src/script_util.h | 12 + websocket/src/socket.h | 570 +++ websocket/src/uri.h | 85 + websocket/src/websocket.cpp | 1056 +++++ websocket/src/wslay/wslay_event.c | 1027 +++++ websocket/src/wslay/wslay_frame.c | 340 ++ websocket/src/wslay/wslay_net.c | 36 + websocket/src/wslay/wslay_queue.c | 117 + websocket/src/wslay/wslay_stack.c | 86 + 35 files changed, 9528 insertions(+), 151 deletions(-) delete mode 100644 example/example.script create mode 100644 examples/assets/button.gui create mode 100644 examples/assets/fonts/example.font create mode 100755 examples/assets/images/green_button08.png create mode 100644 examples/assets/ui.atlas rename example/example.collection => examples/websocket.collection (83%) mode change 100755 => 100644 create mode 100644 examples/websocket.gui create mode 100644 examples/websocket.gui_script delete mode 100644 myextension/ext.manifest delete mode 100644 myextension/src/myextension.cpp create mode 100644 websocket/ext.manifest create mode 100644 websocket/include/wslay/config.h create mode 100644 websocket/include/wslay/wslay.h create mode 100644 websocket/include/wslay/wslay_event.h create mode 100644 websocket/include/wslay/wslay_frame.h create mode 100644 websocket/include/wslay/wslay_net.h create mode 100644 websocket/include/wslay/wslay_queue.h create mode 100644 websocket/include/wslay/wslay_stack.h create mode 100644 websocket/include/wslay/wslayver.h create mode 100644 websocket/src/connection_pool.h create mode 100644 websocket/src/dns.h create mode 100644 websocket/src/mbedtls/base64.h create mode 100644 websocket/src/mbedtls/config.h create mode 100644 websocket/src/script_util.cpp create mode 100644 websocket/src/script_util.h create mode 100644 websocket/src/socket.h create mode 100644 websocket/src/uri.h create mode 100644 websocket/src/websocket.cpp create mode 100644 websocket/src/wslay/wslay_event.c create mode 100644 websocket/src/wslay/wslay_frame.c create mode 100644 websocket/src/wslay/wslay_net.c create mode 100644 websocket/src/wslay/wslay_queue.c create mode 100644 websocket/src/wslay/wslay_stack.c diff --git a/.gitignore b/.gitignore index a32d29f..2b43067 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,7 @@ Thumbs.db *.pyc .project .cproject -builtins \ No newline at end of file +builtins +lws_source +lws_build +*.profraw \ No newline at end of file diff --git a/example/example.script b/example/example.script deleted file mode 100644 index 53b4483..0000000 --- a/example/example.script +++ /dev/null @@ -1,30 +0,0 @@ -function init(self) - local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - local reverse_s = myextension.reverse(s) - print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba -end - -function final(self) - -- Add finalization code here - -- Remove this function if not needed -end - -function update(self, dt) - -- Add update code here - -- Remove this function if not needed -end - -function on_message(self, message_id, message, sender) - -- Add message-handling code here - -- Remove this function if not needed -end - -function on_input(self, action_id, action) - -- Add input-handling code here - -- Remove this function if not needed -end - -function on_reload(self) - -- Add reload-handling code here - -- Remove this function if not needed -end diff --git a/examples/assets/button.gui b/examples/assets/button.gui new file mode 100644 index 0000000..daf8d2e --- /dev/null +++ b/examples/assets/button.gui @@ -0,0 +1,144 @@ +script: "" +fonts { + name: "example" + font: "/examples/assets/fonts/example.font" +} +textures { + name: "ui" + texture: "/examples/assets/ui.atlas" +} +background_color { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 200.0 + y: 45.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "ui/green_button08" + id: "button" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + layer: "below" + inherit_alpha: true + slice9 { + x: 8.0 + y: 8.0 + z: 8.0 + w: 8.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 200.0 + y: 40.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "FOOBAR" + font: "example" + id: "label" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + adjust_mode: ADJUST_MODE_FIT + line_break: false + parent: "button" + layer: "text" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 1.0 + shadow_alpha: 1.0 + template_node_child: false + text_leading: 1.0 + text_tracking: 0.0 +} +layers { + name: "below" +} +layers { + name: "text" +} +layers { + name: "above" +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT +max_nodes: 512 diff --git a/examples/assets/fonts/example.font b/examples/assets/fonts/example.font new file mode 100644 index 0000000..4929518 --- /dev/null +++ b/examples/assets/fonts/example.font @@ -0,0 +1,3 @@ +font: "/builtins/fonts/vera_mo_bd.ttf" +material: "/builtins/fonts/font.material" +size: 15 diff --git a/examples/assets/images/green_button08.png b/examples/assets/images/green_button08.png new file mode 100755 index 0000000000000000000000000000000000000000..b9d40d0fb748191734b16fcbbb62237bfe22e995 GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^hCr;#!3-n~!ivuUDW?FR5LX}_x85ppon`D=i@5a` z(d*3O)>{HaV%M9;tT&I}XjOLFzxGO4$Ag5XThYZQd`r&x6dd(R+-y^P*1Pp?Z0)ts zANQ(sfu?Yk1o;Is%(vfvKmPpt_4#K@SKI}P=6Sj}hEy=Vy=LCTWGKRNaoY5%J-h!0 ze$ - -static int Reverse(lua_State* L) -{ - // The number of expected items to be on the Lua stack - // once this struct goes out of scope - DM_LUA_STACK_CHECK(L, 1); - - // Check and get parameter string from stack - char* str = (char*)luaL_checkstring(L, 1); - - // Reverse the string - int len = strlen(str); - for(int i = 0; i < len / 2; i++) { - const char a = str[i]; - const char b = str[len - i - 1]; - str[i] = b; - str[len - i - 1] = a; - } - - // Put the reverse string on the stack - lua_pushstring(L, str); - - // Return 1 item - return 1; -} - -// Functions exposed to Lua -static const luaL_reg Module_methods[] = -{ - {"reverse", Reverse}, - {0, 0} -}; - -static void LuaInit(lua_State* L) -{ - int top = lua_gettop(L); - - // Register lua names - luaL_register(L, MODULE_NAME, Module_methods); - - lua_pop(L, 1); - assert(top == lua_gettop(L)); -} - -dmExtension::Result AppInitializeMyExtension(dmExtension::AppParams* params) -{ - dmLogInfo("AppInitializeMyExtension\n"); - return dmExtension::RESULT_OK; -} - -dmExtension::Result InitializeMyExtension(dmExtension::Params* params) -{ - // Init Lua - LuaInit(params->m_L); - dmLogInfo("Registered %s Extension\n", MODULE_NAME); - return dmExtension::RESULT_OK; -} - -dmExtension::Result AppFinalizeMyExtension(dmExtension::AppParams* params) -{ - dmLogInfo("AppFinalizeMyExtension\n"); - return dmExtension::RESULT_OK; -} - -dmExtension::Result FinalizeMyExtension(dmExtension::Params* params) -{ - dmLogInfo("FinalizeMyExtension\n"); - return dmExtension::RESULT_OK; -} - -dmExtension::Result OnUpdateMyExtension(dmExtension::Params* params) -{ - dmLogInfo("OnUpdateMyExtension\n"); - return dmExtension::RESULT_OK; -} - -void OnEventMyExtension(dmExtension::Params* params, const dmExtension::Event* event) -{ - switch(event->m_Event) - { - case dmExtension::EVENT_ID_ACTIVATEAPP: - dmLogInfo("OnEventMyExtension - EVENT_ID_ACTIVATEAPP\n"); - break; - case dmExtension::EVENT_ID_DEACTIVATEAPP: - dmLogInfo("OnEventMyExtension - EVENT_ID_DEACTIVATEAPP\n"); - break; - case dmExtension::EVENT_ID_ICONIFYAPP: - dmLogInfo("OnEventMyExtension - EVENT_ID_ICONIFYAPP\n"); - break; - case dmExtension::EVENT_ID_DEICONIFYAPP: - dmLogInfo("OnEventMyExtension - EVENT_ID_DEICONIFYAPP\n"); - break; - default: - dmLogWarning("OnEventMyExtension - Unknown event id\n"); - break; - } -} - -// Defold SDK uses a macro for setting up extension entry points: -// -// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final) - -// MyExtension is the C++ symbol that holds all relevant extension data. -// It must match the name field in the `ext.manifest` -DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, OnUpdateMyExtension, OnEventMyExtension, FinalizeMyExtension) diff --git a/websocket/ext.manifest b/websocket/ext.manifest new file mode 100644 index 0000000..90dbe3f --- /dev/null +++ b/websocket/ext.manifest @@ -0,0 +1,8 @@ +# C++ symbol in your extension +name: "Websocket" + +platforms: + common: + context: + includes: ["upload/websocket/include/wslay"] + defines: ["FOO"] diff --git a/websocket/include/wslay/config.h b/websocket/include/wslay/config.h new file mode 100644 index 0000000..242cefa --- /dev/null +++ b/websocket/include/wslay/config.h @@ -0,0 +1,10 @@ +/* This configuration file is used only by CMake build system. */ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAVE_ARPA_INET_H +#define HAVE_NETINET_IN_H +/* #undef HAVE_WINSOCK2_H */ +/* #undef WORDS_BIGENDIAN */ + +#endif /* CONFIG_H */ diff --git a/websocket/include/wslay/wslay.h b/websocket/include/wslay/wslay.h new file mode 100644 index 0000000..2fde81a --- /dev/null +++ b/websocket/include/wslay/wslay.h @@ -0,0 +1,772 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAY_H +#define WSLAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + +/* + * wslay/wslayver.h is generated from wslay/wslayver.h.in by + * configure. The projects which do not use autotools can set + * WSLAY_VERSION macro from outside to avoid to generating wslayver.h + */ +#ifndef WSLAY_VERSION +# include +#endif /* WSLAY_VERSION */ + +enum wslay_error { + WSLAY_ERR_WANT_READ = -100, + WSLAY_ERR_WANT_WRITE = -101, + WSLAY_ERR_PROTO = -200, + WSLAY_ERR_INVALID_ARGUMENT = -300, + WSLAY_ERR_INVALID_CALLBACK = -301, + WSLAY_ERR_NO_MORE_MSG = -302, + WSLAY_ERR_CALLBACK_FAILURE = -400, + WSLAY_ERR_WOULDBLOCK = -401, + WSLAY_ERR_NOMEM = -500 +}; + +/* + * Status codes defined in RFC6455 + */ +enum wslay_status_code { + WSLAY_CODE_NORMAL_CLOSURE = 1000, + WSLAY_CODE_GOING_AWAY = 1001, + WSLAY_CODE_PROTOCOL_ERROR = 1002, + WSLAY_CODE_UNSUPPORTED_DATA = 1003, + WSLAY_CODE_NO_STATUS_RCVD = 1005, + WSLAY_CODE_ABNORMAL_CLOSURE = 1006, + WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA = 1007, + WSLAY_CODE_POLICY_VIOLATION = 1008, + WSLAY_CODE_MESSAGE_TOO_BIG = 1009, + WSLAY_CODE_MANDATORY_EXT = 1010, + WSLAY_CODE_INTERNAL_SERVER_ERROR = 1011, + WSLAY_CODE_TLS_HANDSHAKE = 1015 +}; + +enum wslay_io_flags { + /* + * There is more data to send. + */ + WSLAY_MSG_MORE = 1 +}; + +/* + * Callback function used by wslay_frame_send() function when it needs + * to send data. The implementation of this function must send at most + * len bytes of data in data. flags is the bitwise OR of zero or more + * of the following flag: + * + * WSLAY_MSG_MORE + * There is more data to send + * + * It provides some hints to tune performance and behaviour. user_data + * is one given in wslay_frame_context_init() function. The + * implementation of this function must return the number of bytes + * sent. If there is an error, return -1. The return value 0 is also + * treated an error by the library. + */ +typedef ssize_t (*wslay_frame_send_callback)(const uint8_t *data, size_t len, + int flags, void *user_data); +/* + * Callback function used by wslay_frame_recv() function when it needs + * more data. The implementation of this function must fill at most + * len bytes of data into buf. The memory area of buf is allocated by + * library and not be freed by the application code. flags is always 0 + * in this version. user_data is one given in + * wslay_frame_context_init() function. The implementation of this + * function must return the number of bytes filled. If there is an + * error, return -1. The return value 0 is also treated an error by + * the library. + */ +typedef ssize_t (*wslay_frame_recv_callback)(uint8_t *buf, size_t len, + int flags, void *user_data); +/* + * Callback function used by wslay_frame_send() function when it needs + * new mask key. The implementation of this function must write + * exactly len bytes of mask key to buf. user_data is one given in + * wslay_frame_context_init() function. The implementation of this + * function return 0 on success. If there is an error, return -1. + */ +typedef int (*wslay_frame_genmask_callback)(uint8_t *buf, size_t len, + void *user_data); + +struct wslay_frame_callbacks { + wslay_frame_send_callback send_callback; + wslay_frame_recv_callback recv_callback; + wslay_frame_genmask_callback genmask_callback; +}; + +/* + * The opcode defined in RFC6455. + */ +enum wslay_opcode { + WSLAY_CONTINUATION_FRAME = 0x0u, + WSLAY_TEXT_FRAME = 0x1u, + WSLAY_BINARY_FRAME = 0x2u, + WSLAY_CONNECTION_CLOSE = 0x8u, + WSLAY_PING = 0x9u, + WSLAY_PONG = 0xau +}; + +/* + * Macro that returns 1 if opcode is control frame opcode, otherwise + * returns 0. + */ +#define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1) + +/* + * Macros that represent and return reserved bits: RSV1, RSV2, RSV3. + * These macros assume that rsv is constructed by ((RSV1 << 2) | + * (RSV2 << 1) | RSV3) + */ +#define WSLAY_RSV_NONE ((uint8_t) 0) +#define WSLAY_RSV1_BIT (((uint8_t) 1) << 2) +#define WSLAY_RSV2_BIT (((uint8_t) 1) << 1) +#define WSLAY_RSV3_BIT (((uint8_t) 1) << 0) + +#define wslay_get_rsv1(rsv) ((rsv >> 2) & 1) +#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1) +#define wslay_get_rsv3(rsv) (rsv & 1) + +struct wslay_frame_iocb { + /* 1 for fragmented final frame, 0 for otherwise */ + uint8_t fin; + /* + * reserved 3 bits. rsv = ((RSV1 << 2) | (RSV << 1) | RSV3). + * RFC6455 requires 0 unless extensions are negotiated. + */ + uint8_t rsv; + /* 4 bit opcode */ + uint8_t opcode; + /* payload length [0, 2**63-1] */ + uint64_t payload_length; + /* 1 for masked frame, 0 for unmasked */ + uint8_t mask; + /* part of payload data */ + const uint8_t *data; + /* bytes of data defined above */ + size_t data_length; +}; + +struct wslay_frame_context; +typedef struct wslay_frame_context *wslay_frame_context_ptr; + +/* + * Initializes ctx using given callbacks and user_data. This function + * allocates memory for struct wslay_frame_context and stores the + * result to *ctx. The callback functions specified in callbacks are + * copied to ctx. user_data is stored in ctx and it will be passed to + * callback functions. When the user code finished using ctx, it must + * call wslay_frame_context_free to deallocate memory. + */ +int wslay_frame_context_init(wslay_frame_context_ptr *ctx, + const struct wslay_frame_callbacks *callbacks, + void *user_data); + +/* + * Deallocates memory pointed by ctx. + */ +void wslay_frame_context_free(wslay_frame_context_ptr ctx); + +/* + * Send WebSocket frame specified in iocb. ctx must be initialized + * using wslay_frame_context_init() function. iocb->fin must be 1 if + * this is a fin frame, otherwise 0. iocb->rsv is reserved bits. + * iocb->opcode must be the opcode of this frame. iocb->mask must be + * 1 if this is masked frame, otherwise 0. iocb->payload_length is + * the payload_length of this frame. iocb->data must point to the + * payload data to be sent. iocb->data_length must be the length of + * the data. This function calls send_callback function if it needs + * to send bytes. This function calls gen_mask_callback function if + * it needs new mask key. This function returns the number of payload + * bytes sent. Please note that it does not include any number of + * header bytes. If it cannot send any single bytes of payload, it + * returns WSLAY_ERR_WANT_WRITE. If the library detects error in iocb, + * this function returns WSLAY_ERR_INVALID_ARGUMENT. If callback + * functions report a failure, this function returns + * WSLAY_ERR_INVALID_CALLBACK. This function does not always send all + * given data in iocb. If there are remaining data to be sent, adjust + * data and data_length in iocb accordingly and call this function + * again. + */ +ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb); + +/* + * Receives WebSocket frame and stores it in iocb. This function + * returns the number of payload bytes received. This does not + * include header bytes. In this case, iocb will be populated as + * follows: iocb->fin is 1 if received frame is fin frame, otherwise + * 0. iocb->rsv is reserved bits of received frame. iocb->opcode is + * opcode of received frame. iocb->mask is 1 if received frame is + * masked, otherwise 0. iocb->payload_length is the payload length of + * received frame. iocb->data is pointed to the buffer containing + * received payload data. This buffer is allocated by the library and + * must be read-only. iocb->data_length is the number of payload + * bytes recieved. This function calls recv_callback if it needs to + * receive additional bytes. If it cannot receive any single bytes of + * payload, it returns WSLAY_ERR_WANT_READ. If the library detects + * protocol violation in a received frame, this function returns + * WSLAY_ERR_PROTO. If callback functions report a failure, this + * function returns WSLAY_ERR_INVALID_CALLBACK. This function does + * not always receive whole frame in a single call. If there are + * remaining data to be received, call this function again. This + * function ensures frame alignment. + */ +ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb); + +struct wslay_event_context; +/* Pointer to the event-based API context */ +typedef struct wslay_event_context *wslay_event_context_ptr; + +struct wslay_event_on_msg_recv_arg { + /* reserved bits: rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3 */ + uint8_t rsv; + /* opcode */ + uint8_t opcode; + /* received message */ + const uint8_t *msg; + /* message length */ + size_t msg_length; + /* + * Status code iff opcode == WSLAY_CONNECTION_CLOSE. If no status + * code is included in the close control frame, it is set to 0. + */ + uint16_t status_code; +}; + +/* + * Callback function invoked by wslay_event_recv() when a message is + * completely received. + */ +typedef void (*wslay_event_on_msg_recv_callback) +(wslay_event_context_ptr ctx, + const struct wslay_event_on_msg_recv_arg *arg, void *user_data); + +struct wslay_event_on_frame_recv_start_arg { + /* fin bit; 1 for final frame, or 0. */ + uint8_t fin; + /* reserved bits: rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3 */ + uint8_t rsv; + /* opcode of the frame */ + uint8_t opcode; + /* payload length of ths frame */ + uint64_t payload_length; +}; + +/* + * Callback function invoked by wslay_event_recv() when a new frame + * starts to be received. This callback function is only invoked once + * for each frame. + */ +typedef void (*wslay_event_on_frame_recv_start_callback) +(wslay_event_context_ptr ctx, + const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data); + +struct wslay_event_on_frame_recv_chunk_arg { + /* chunk of payload data */ + const uint8_t *data; + /* length of data */ + size_t data_length; +}; + +/* + * Callback function invoked by wslay_event_recv() when a chunk of + * frame payload is received. + */ +typedef void (*wslay_event_on_frame_recv_chunk_callback) +(wslay_event_context_ptr ctx, + const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data); + +/* + * Callback function invoked by wslay_event_recv() when a frame is + * completely received. + */ +typedef void (*wslay_event_on_frame_recv_end_callback) +(wslay_event_context_ptr ctx, void *user_data); + +/* + * Callback function invoked by wslay_event_recv() when it wants to + * receive more data from peer. The implementation of this callback + * function must read data at most len bytes from peer and store them + * in buf and return the number of bytes read. flags is always 0 in + * this version. + * + * If there is an error, return -1 and set error code + * WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). Wslay + * event-based API on the whole assumes non-blocking I/O. If the cause + * of error is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK + * instead. This is important because it tells wslay_event_recv() to + * stop receiving further data and return. + */ +typedef ssize_t (*wslay_event_recv_callback)(wslay_event_context_ptr ctx, + uint8_t *buf, size_t len, + int flags, void *user_data); + +/* + * Callback function invoked by wslay_event_send() when it wants to + * send more data to peer. The implementation of this callback + * function must send data at most len bytes to peer and return the + * number of bytes sent. flags is the bitwise OR of zero or more of + * the following flag: + * + * WSLAY_MSG_MORE + * There is more data to send + * + * It provides some hints to tune performance and behaviour. + * + * If there is an error, return -1 and set error code + * WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). Wslay + * event-based API on the whole assumes non-blocking I/O. If the cause + * of error is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK + * instead. This is important because it tells wslay_event_send() to + * stop sending data and return. + */ +typedef ssize_t (*wslay_event_send_callback)(wslay_event_context_ptr ctx, + const uint8_t *data, size_t len, + int flags, void *user_data); + +/* + * Callback function invoked by wslay_event_send() when it wants new + * mask key. As described in RFC6455, only the traffic from WebSocket + * client is masked, so this callback function is only needed if an + * event-based API is initialized for WebSocket client use. + */ +typedef int (*wslay_event_genmask_callback)(wslay_event_context_ptr ctx, + uint8_t *buf, size_t len, + void *user_data); + +struct wslay_event_callbacks { + wslay_event_recv_callback recv_callback; + wslay_event_send_callback send_callback; + wslay_event_genmask_callback genmask_callback; + wslay_event_on_frame_recv_start_callback on_frame_recv_start_callback; + wslay_event_on_frame_recv_chunk_callback on_frame_recv_chunk_callback; + wslay_event_on_frame_recv_end_callback on_frame_recv_end_callback; + wslay_event_on_msg_recv_callback on_msg_recv_callback; +}; + +/* + * Initializes ctx as WebSocket Server. user_data is an arbitrary + * pointer, which is directly passed to each callback functions as + * user_data argument. + * + * On success, returns 0. On error, returns one of following negative + * values: + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_context_server_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, void *user_data); + +/* + * Initializes ctx as WebSocket client. user_data is an arbitrary + * pointer, which is directly passed to each callback functions as + * user_data argument. + * + * On success, returns 0. On error, returns one of following negative + * values: + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_context_client_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, void *user_data); + +/* + * Releases allocated resources for ctx. + */ +void wslay_event_context_free(wslay_event_context_ptr ctx); + +/* + * Sets a bit mask of allowed reserved bits. + * Currently only permitted values are WSLAY_RSV1_BIT to allow PMCE + * extension (see RFC-7692) or WSLAY_RSV_NONE to disable. + * + * Default: WSLAY_RSV_NONE + */ +void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv); + +/* + * Enables or disables buffering of an entire message for non-control + * frames. If val is 0, buffering is enabled. Otherwise, buffering is + * disabled. If wslay_event_on_msg_recv_callback is invoked when + * buffering is disabled, the msg_length member of struct + * wslay_event_on_msg_recv_arg is set to 0. + * + * The control frames are always buffered regardless of this function call. + * + * This function must not be used after the first invocation of + * wslay_event_recv() function. + */ +void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val); + +/* + * Sets maximum length of a message that can be received. The length + * of message is checked by wslay_event_recv() function. If the length + * of a message is larger than this value, reading operation is + * disabled (same effect with wslay_event_shutdown_read() call) and + * close control frame with WSLAY_CODE_MESSAGE_TOO_BIG is queued. If + * buffering for non-control frames is disabled, the library checks + * each frame payload length and does not check length of entire + * message. + * + * The default value is (1u << 31)-1. + */ +void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, + uint64_t val); + +/* + * Sets callbacks to ctx. The callbacks previouly set by this function + * or wslay_event_context_server_init() or + * wslay_event_context_client_init() are replaced with callbacks. + */ +void wslay_event_config_set_callbacks +(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks); + +/* + * Receives messages from peer. When receiving + * messages, it uses wslay_event_recv_callback function. Single call + * of this function receives multiple messages until + * wslay_event_recv_callback function sets error code + * WSLAY_ERR_WOULDBLOCK. + * + * When close control frame is received, this function automatically + * queues close control frame. Also this function calls + * wslay_event_set_read_enabled() with second argument 0 to disable + * further read from peer. + * + * When ping control frame is received, this function automatically + * queues pong control frame. + * + * In case of a fatal errror which leads to negative return code, this + * function calls wslay_event_set_read_enabled() with second argument + * 0 to disable further read from peer. + * + * wslay_event_recv() returns 0 if it succeeds, or one of the + * following negative error codes: + * + * WSLAY_ERR_CALLBACK_FAILURE + * User defined callback function is failed. + * + * WSLAY_ERR_NOMEM + * Out of memory. + * + * When negative error code is returned, application must not make any + * further call of wslay_event_recv() and must close WebSocket + * connection. + */ +int wslay_event_recv(wslay_event_context_ptr ctx); + +/* + * Sends queued messages to peer. When sending a + * message, it uses wslay_event_send_callback function. Single call of + * wslay_event_send() sends multiple messages until + * wslay_event_send_callback sets error code WSLAY_ERR_WOULDBLOCK. + * + * If ctx is initialized for WebSocket client use, wslay_event_send() + * uses wslay_event_genmask_callback to get new mask key. + * + * When a message queued using wslay_event_queue_fragmented_msg() is + * sent, wslay_event_send() invokes + * wslay_event_fragmented_msg_callback for that message. + * + * After close control frame is sent, this function calls + * wslay_event_set_write_enabled() with second argument 0 to disable + * further transmission to peer. + * + * If there are any pending messages, wslay_event_want_write() returns + * 1, otherwise returns 0. + * + * In case of a fatal errror which leads to negative return code, this + * function calls wslay_event_set_write_enabled() with second argument + * 0 to disable further transmission to peer. + * + * wslay_event_send() returns 0 if it succeeds, or one of the + * following negative error codes: + * + * WSLAY_ERR_CALLBACK_FAILURE + * User defined callback function is failed. + * + * WSLAY_ERR_NOMEM + * Out of memory. + * + * When negative error code is returned, application must not make any + * further call of wslay_event_send() and must close WebSocket + * connection. + */ +int wslay_event_send(wslay_event_context_ptr ctx); + +struct wslay_event_msg { + uint8_t opcode; + const uint8_t *msg; + size_t msg_length; +}; + +/* + * Queues message specified in arg. + * + * This function supports both control and non-control messages and + * the given message is sent without fragmentation. If fragmentation + * is needed, use wslay_event_queue_fragmented_msg() function instead. + * + * This function just queues a message and does not send + * it. wslay_event_send() function call sends these queued messages. + * + * wslay_event_queue_msg() returns 0 if it succeeds, or returns the + * following negative error codes: + * + * WSLAY_ERR_NO_MORE_MSG + * Could not queue given message. The one of possible reason is that + * close control frame has been queued/sent and no further queueing + * message is not allowed. + * + * WSLAY_ERR_INVALID_ARGUMENT + * The given message is invalid. + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_queue_msg(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg); + +/* + * Extended version of wslay_event_queue_msg which allows to set reserved bits. + */ +int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg, uint8_t rsv); + +/* + * Specify "source" to generate message. + */ +union wslay_event_msg_source { + int fd; + void *data; +}; + +/* + * Callback function called by wslay_event_send() to read message data + * from source. The implementation of + * wslay_event_fragmented_msg_callback must store at most len bytes of + * data to buf and return the number of stored bytes. If all data is + * read (i.e., EOF), set *eof to 1. If no data can be generated at the + * moment, return 0. If there is an error, return -1 and set error + * code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). + */ +typedef ssize_t (*wslay_event_fragmented_msg_callback) +(wslay_event_context_ptr ctx, + uint8_t *buf, size_t len, const union wslay_event_msg_source *source, + int *eof, void *user_data); + +struct wslay_event_fragmented_msg { + /* opcode */ + uint8_t opcode; + /* "source" to generate message data */ + union wslay_event_msg_source source; + /* Callback function to read message data from source. */ + wslay_event_fragmented_msg_callback read_callback; +}; + +/* + * Queues a fragmented message specified in arg. + * + * This function supports non-control messages only. For control frames, + * use wslay_event_queue_msg() or wslay_event_queue_close(). + * + * This function just queues a message and does not send + * it. wslay_event_send() function call sends these queued messages. + * + * wslay_event_queue_fragmented_msg() returns 0 if it succeeds, or + * returns the following negative error codes: + * + * WSLAY_ERR_NO_MORE_MSG + * Could not queue given message. The one of possible reason is that + * close control frame has been queued/sent and no further queueing + * message is not allowed. + * + * WSLAY_ERR_INVALID_ARGUMENT + * The given message is invalid. + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_queue_fragmented_msg +(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg); + +/* + * Extended version of wslay_event_queue_fragmented_msg which allows to set + * reserved bits. + */ +int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_fragmented_msg *arg, uint8_t rsv); + +/* + * Queues close control frame. This function is provided just for + * convenience. wslay_event_queue_msg() can queue a close control + * frame as well. status_code is the status code of close control + * frame. reason is the close reason encoded in UTF-8. reason_length + * is the length of reason in bytes. reason_length must be less than + * 123 bytes. + * + * If status_code is 0, reason and reason_length is not used and close + * control frame with zero-length payload will be queued. + * + * This function just queues a message and does not send + * it. wslay_event_send() function call sends these queued messages. + * + * wslay_event_queue_close() returns 0 if it succeeds, or returns the + * following negative error codes: + * + * WSLAY_ERR_NO_MORE_MSG + * Could not queue given message. The one of possible reason is that + * close control frame has been queued/sent and no further queueing + * message is not allowed. + * + * WSLAY_ERR_INVALID_ARGUMENT + * The given message is invalid. + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_queue_close(wslay_event_context_ptr ctx, + uint16_t status_code, + const uint8_t *reason, size_t reason_length); + +/* + * Sets error code to tell the library there is an error. This + * function is typically used in user defined callback functions. See + * the description of callback function to know which error code + * should be used. + */ +void wslay_event_set_error(wslay_event_context_ptr ctx, int val); + +/* + * Query whehter the library want to read more data from peer. + * + * wslay_event_want_read() returns 1 if the library want to read more + * data from peer, or returns 0. + */ +int wslay_event_want_read(wslay_event_context_ptr ctx); + +/* + * Query whehter the library want to send more data to peer. + * + * wslay_event_want_write() returns 1 if the library want to send more + * data to peer, or returns 0. + */ +int wslay_event_want_write(wslay_event_context_ptr ctx); + +/* + * Prevents the event-based API context from reading any further data + * from peer. + * + * This function may be used with wslay_event_queue_close() if the + * application detects error in the data received and wants to fail + * WebSocket connection. + */ +void wslay_event_shutdown_read(wslay_event_context_ptr ctx); + +/* + * Prevents the event-based API context from sending any further data + * to peer. + */ +void wslay_event_shutdown_write(wslay_event_context_ptr ctx); + +/* + * Returns 1 if the event-based API context allows read operation, or + * return 0. + * + * After wslay_event_shutdown_read() is called, + * wslay_event_get_read_enabled() returns 0. + */ +int wslay_event_get_read_enabled(wslay_event_context_ptr ctx); + +/* + * Returns 1 if the event-based API context allows write operation, or + * return 0. + * + * After wslay_event_shutdown_write() is called, + * wslay_event_get_write_enabled() returns 0. + */ +int wslay_event_get_write_enabled(wslay_event_context_ptr ctx); + +/* + * Returns 1 if a close control frame has been received from peer, or + * returns 0. + */ +int wslay_event_get_close_received(wslay_event_context_ptr ctx); + +/* + * Returns 1 if a close control frame has been sent to peer, or + * returns 0. + */ +int wslay_event_get_close_sent(wslay_event_context_ptr ctx); + +/* + * Returns status code received in close control frame. If no close + * control frame has not been received, returns + * WSLAY_CODE_ABNORMAL_CLOSURE. If received close control frame has no + * status code, returns WSLAY_CODE_NO_STATUS_RCVD. + */ +uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx); + +/* + * Returns status code sent in close control frame. If no close + * control frame has not been sent, returns + * WSLAY_CODE_ABNORMAL_CLOSURE. If sent close control frame has no + * status code, returns WSLAY_CODE_NO_STATUS_RCVD. + */ +uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx); + +/* + * Returns the number of queued messages. + */ +size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx); + +/* + * Returns the sum of queued message length. It only counts the + * message length queued using wslay_event_queue_msg() or + * wslay_event_queue_close(). + */ +size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* WSLAY_H */ diff --git a/websocket/include/wslay/wslay_event.h b/websocket/include/wslay/wslay_event.h new file mode 100644 index 0000000..36feb90 --- /dev/null +++ b/websocket/include/wslay/wslay_event.h @@ -0,0 +1,142 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAY_EVENT_H +#define WSLAY_EVENT_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +struct wslay_stack; +struct wslay_queue; + +struct wslay_event_byte_chunk { + uint8_t *data; + size_t data_length; +}; + +struct wslay_event_imsg { + uint8_t fin; + uint8_t rsv; + uint8_t opcode; + uint32_t utf8state; + struct wslay_queue *chunks; + size_t msg_length; +}; + +enum wslay_event_msg_type { + WSLAY_NON_FRAGMENTED, + WSLAY_FRAGMENTED +}; + +struct wslay_event_omsg { + uint8_t fin; + uint8_t opcode; + uint8_t rsv; + enum wslay_event_msg_type type; + + uint8_t *data; + size_t data_length; + + union wslay_event_msg_source source; + wslay_event_fragmented_msg_callback read_callback; +}; + +struct wslay_event_frame_user_data { + wslay_event_context_ptr ctx; + void *user_data; +}; + +enum wslay_event_close_status { + WSLAY_CLOSE_RECEIVED = 1 << 0, + WSLAY_CLOSE_QUEUED = 1 << 1, + WSLAY_CLOSE_SENT = 1 << 2 +}; + +enum wslay_event_config { + WSLAY_CONFIG_NO_BUFFERING = 1 << 0 +}; + +struct wslay_event_context { + /* config status, bitwise OR of enum wslay_event_config values*/ + uint32_t config; + /* maximum message length that can be received */ + uint64_t max_recv_msg_length; + /* 1 if initialized for server, otherwise 0 */ + uint8_t server; + /* bitwise OR of enum wslay_event_close_status values */ + uint8_t close_status; + /* status code in received close control frame */ + uint16_t status_code_recv; + /* status code in sent close control frame */ + uint16_t status_code_sent; + wslay_frame_context_ptr frame_ctx; + /* 1 if reading is enabled, otherwise 0. Upon receiving close + control frame this value set to 0. If any errors in read + operation will also set this value to 0. */ + uint8_t read_enabled; + /* 1 if writing is enabled, otherwise 0 Upon completing sending + close control frame, this value set to 0. If any errors in write + opration will also set this value to 0. */ + uint8_t write_enabled; + /* imsg buffer to allow interleaved control frame between + non-control frames. */ + struct wslay_event_imsg imsgs[2]; + /* Pointer to imsgs to indicate current used buffer. */ + struct wslay_event_imsg *imsg; + /* payload length of frame currently being received. */ + uint64_t ipayloadlen; + /* next byte offset of payload currently being received. */ + uint64_t ipayloadoff; + /* error value set by user callback */ + int error; + /* Pointer to the message currently being sent. NULL if no message + is currently sent. */ + struct wslay_event_omsg *omsg; + /* Queue for non-control frames */ + struct wslay_queue/**/ *send_queue; + /* Queue for control frames */ + struct wslay_queue/**/ *send_ctrl_queue; + /* Size of send_queue + size of send_ctrl_queue */ + size_t queued_msg_count; + /* The sum of message length in send_queue */ + size_t queued_msg_length; + /* Buffer used for fragmented messages */ + uint8_t obuf[4096]; + uint8_t *obuflimit; + uint8_t *obufmark; + /* payload length of frame currently being sent. */ + uint64_t opayloadlen; + /* next byte offset of payload currently being sent. */ + uint64_t opayloadoff; + struct wslay_event_callbacks callbacks; + struct wslay_event_frame_user_data frame_user_data; + void *user_data; + uint8_t allowed_rsv_bits; +}; + +#endif /* WSLAY_EVENT_H */ diff --git a/websocket/include/wslay/wslay_frame.h b/websocket/include/wslay/wslay_frame.h new file mode 100644 index 0000000..6a75858 --- /dev/null +++ b/websocket/include/wslay/wslay_frame.h @@ -0,0 +1,76 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAY_FRAME_H +#define WSLAY_FRAME_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +enum wslay_frame_state { + PREP_HEADER, + SEND_HEADER, + SEND_PAYLOAD, + RECV_HEADER1, + RECV_PAYLOADLEN, + RECV_EXT_PAYLOADLEN, + RECV_MASKKEY, + RECV_PAYLOAD +}; + +struct wslay_frame_opcode_memo { + uint8_t fin; + uint8_t opcode; + uint8_t rsv; +}; + +struct wslay_frame_context { + uint8_t ibuf[4096]; + uint8_t *ibufmark; + uint8_t *ibuflimit; + struct wslay_frame_opcode_memo iom; + uint64_t ipayloadlen; + uint64_t ipayloadoff; + uint8_t imask; + uint8_t imaskkey[4]; + enum wslay_frame_state istate; + size_t ireqread; + + uint8_t oheader[14]; + uint8_t *oheadermark; + uint8_t *oheaderlimit; + uint64_t opayloadlen; + uint64_t opayloadoff; + uint8_t omask; + uint8_t omaskkey[4]; + enum wslay_frame_state ostate; + + struct wslay_frame_callbacks callbacks; + void *user_data; +}; + +#endif /* WSLAY_FRAME_H */ diff --git a/websocket/include/wslay/wslay_net.h b/websocket/include/wslay/wslay_net.h new file mode 100644 index 0000000..2310870 --- /dev/null +++ b/websocket/include/wslay/wslay_net.h @@ -0,0 +1,54 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAY_NET_H +#define WSLAY_NET_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include + +#ifdef HAVE_ARPA_INET_H +# include +#endif /* HAVE_ARPA_INET_H */ +#ifdef HAVE_NETINET_IN_H +# include +#endif /* HAVE_NETINET_IN_H */ +/* For Mingw build */ +#ifdef HAVE_WINSOCK2_H +# include +#endif /* HAVE_WINSOCK2_H */ + +#ifdef WORDS_BIGENDIAN +# define ntoh64(x) (x) +# define hton64(x) (x) +#else /* !WORDS_BIGENDIAN */ +uint64_t wslay_byteswap64(uint64_t x); +# define ntoh64(x) wslay_byteswap64(x) +# define hton64(x) wslay_byteswap64(x) +#endif /* !WORDS_BIGENDIAN */ + +#endif /* WSLAY_NET_H */ diff --git a/websocket/include/wslay/wslay_queue.h b/websocket/include/wslay/wslay_queue.h new file mode 100644 index 0000000..55e78a0 --- /dev/null +++ b/websocket/include/wslay/wslay_queue.h @@ -0,0 +1,53 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAY_QUEUE_H +#define WSLAY_QUEUE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +struct wslay_queue_cell { + void *data; + struct wslay_queue_cell *next; +}; + +struct wslay_queue { + struct wslay_queue_cell *top; + struct wslay_queue_cell *tail; +}; + +struct wslay_queue* wslay_queue_new(void); +void wslay_queue_free(struct wslay_queue *queue); +int wslay_queue_push(struct wslay_queue *queue, void *data); +int wslay_queue_push_front(struct wslay_queue *queue, void *data); +void wslay_queue_pop(struct wslay_queue *queue); +void* wslay_queue_top(struct wslay_queue *queue); +void* wslay_queue_tail(struct wslay_queue *queue); +int wslay_queue_empty(struct wslay_queue *queue); + +#endif /* WSLAY_QUEUE_H */ diff --git a/websocket/include/wslay/wslay_stack.h b/websocket/include/wslay/wslay_stack.h new file mode 100644 index 0000000..16e4e96 --- /dev/null +++ b/websocket/include/wslay/wslay_stack.h @@ -0,0 +1,50 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAY_STACK_H +#define WSLAY_STACK_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +struct wslay_stack_cell { + void *data; + struct wslay_stack_cell *next; +}; + +struct wslay_stack { + struct wslay_stack_cell *top; +}; + +struct wslay_stack* wslay_stack_new(); +void wslay_stack_free(struct wslay_stack *stack); +int wslay_stack_push(struct wslay_stack *stack, void *data); +void wslay_stack_pop(struct wslay_stack *stack); +void* wslay_stack_top(struct wslay_stack *stack); +int wslay_stack_empty(struct wslay_stack *stack); + +#endif /* WSLAY_STACK_H */ diff --git a/websocket/include/wslay/wslayver.h b/websocket/include/wslay/wslayver.h new file mode 100644 index 0000000..e153b07 --- /dev/null +++ b/websocket/include/wslay/wslayver.h @@ -0,0 +1,31 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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. + */ +#ifndef WSLAYVER_H +#define WSLAYVER_H + +/* Version number of wslay release */ +#define WSLAY_VERSION "1.0.1-DEV" + +#endif /* WSLAYVER_H */ diff --git a/websocket/src/connection_pool.h b/websocket/src/connection_pool.h new file mode 100644 index 0000000..dd033b9 --- /dev/null +++ b/websocket/src/connection_pool.h @@ -0,0 +1,174 @@ +// Copyright 2020 The Defold Foundation +// Licensed under the Defold License version 1.0 (the "License"); you may not use +// this file except in compliance with the License. +// +// You may obtain a copy of the License, together with FAQs at +// https://www.defold.com/license +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef DMSDK_CONNECTION_POOL +#define DMSDK_CONNECTION_POOL + +#include +#include +#include + +/** + * Connection pooling + */ +namespace dmConnectionPool +{ + /** + * Connection pool handle + */ + typedef struct ConnectionPool* HPool; + + /** + * Connection handle + */ + typedef uint32_t HConnection; + + /** + * Result codes + */ + enum Result + { + RESULT_OK = 0, //!< RESULT_OK + RESULT_OUT_OF_RESOURCES = -1,//!< RESULT_OUT_OF_RESOURCES + RESULT_SOCKET_ERROR = -2, //!< RESULT_SOCKET_ERROR + RESULT_HANDSHAKE_FAILED = -3,//!< RESULT_HANDSHAKE_FAILED + RESULT_SHUT_DOWN = -4, // + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/websocket/src/mbedtls/config.h b/websocket/src/mbedtls/config.h new file mode 100644 index 0000000..41b85ee --- /dev/null +++ b/websocket/src/mbedtls/config.h @@ -0,0 +1,3551 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +//#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +//#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT + * and MBEDTLS_ECDH_LEGACY_CONTEXT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDH_LEGACY_CONTEXT + * + * Use a backward compatible ECDH context. + * + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + * + * Define this macro if you enable MBEDTLS_ECP_RESTARTABLE or if you + * want to access ECDH context fields directly. Otherwise you should + * comment out this macro definition. + * + * This option has no effect if #MBEDTLS_ECDH_C is not enabled. + * + * \note This configuration option is experimental. Future versions of the + * library may modify the way the ECDH context layout is configured + * and may modify the layout of the new context type. + */ +#define MBEDTLS_ECDH_LEGACY_CONTEXT + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +//#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_PSA_CRYPTO_SPM + * + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure + * Partition Manager) integration which separates the code into two parts: a + * NSPE (Non-Secure Process Environment) and an SPE (Secure Process + * Environment). + * + * Module: library/psa_crypto.c + * Requires: MBEDTLS_PSA_CRYPTO_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SPM + +/** + * \def MBEDTLS_PSA_INJECT_ENTROPY + * + * Enable support for entropy injection at first boot. This feature is + * required on systems that do not have a built-in entropy source (TRNG). + * This feature is currently not supported on systems that have a built-in + * entropy source. + * + * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED + * + */ +//#define MBEDTLS_PSA_INJECT_ENTROPY + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_DTLS_CONNECTION_ID + * + * Enable support for the DTLS Connection ID extension + * (version draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) + * which allows to identify DTLS connections across changes + * in the underlying transport. + * + * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`, + * `mbedtls_ssl_get_peer_cid()` and `mbedtls_ssl_conf_cid()`. + * See the corresponding documentation for more information. + * + * \warning The Connection ID extension is still in draft state. + * We make no stability promises for the availability + * or the shape of the API controlled by this option. + * + * The maximum lengths of outgoing and incoming CIDs can be configured + * through the options + * - MBEDTLS_SSL_CID_OUT_LEN_MAX + * - MBEDTLS_SSL_CID_IN_LEN_MAX. + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Uncomment to enable the Connection ID extension. + */ +//#define MBEDTLS_SSL_DTLS_CONNECTION_ID + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * + * This option controls the availability of the API mbedtls_ssl_get_peer_cert() + * giving access to the peer's certificate after completion of the handshake. + * + * Unless you need mbedtls_ssl_peer_cert() in your application, it is + * recommended to disable this option for reduced RAM usage. + * + * \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still + * defined, but always returns \c NULL. + * + * \note This option has no influence on the protection against the + * triple handshake attack. Even if it is disabled, Mbed TLS will + * still ensure that certificates do not change during renegotiation, + * for exaple by keeping a hash of the peer's certificate. + * + * Comment this macro to disable storing the peer's certificate + * after the handshake. + */ +#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_USE_PSA_CRYPTO + * + * Make the X.509 and TLS library use PSA for cryptographic operations, and + * enable new APIs for using keys handled by PSA Crypto. + * + * \note Development of this option is currently in progress, and parts + * of the X.509 and TLS modules are not ported to PSA yet. However, these parts + * will still continue to work as usual, so enabling this option should not + * break backwards compatibility. + * + * \warning The PSA Crypto API is in beta stage. While you're welcome to + * experiment using it, incompatible API changes are still possible, and some + * parts may not have reached the same quality as the rest of Mbed TLS yet. + * + * \warning This option enables new Mbed TLS APIs that are dependent on the + * PSA Crypto API, so can't come with the same stability guarantees as the + * rest of the Mbed TLS APIs. You're welcome to experiment with them, but for + * now, access to these APIs is opt-in (via enabling the present option), in + * order to clearly differentiate them from the stable Mbed TLS APIs. + * + * Requires: MBEDTLS_PSA_CRYPTO_C. + * + * Uncomment this to enable internal use of PSA Crypto and new associated APIs. + */ +//#define MBEDTLS_USE_PSA_CRYPTO + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +//#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + * + * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()` + * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure + * the set of trusted certificates through a callback instead of a linked + * list. + * + * This is useful for example in environments where a large number of trusted + * certificates is present and storing them in a linked list isn't efficient + * enough, or when the set of trusted certificates changes frequently. + * + * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and + * `mbedtls_ssl_conf_ca_cb()` for more information. + * + * Uncomment to enable trusted certificate callbacks. + */ +//#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_PSA_CRYPTO_C + * + * Enable the Platform Security Architecture cryptography API. + * + * \warning The PSA Crypto API is still beta status. While you're welcome to + * experiment using it, incompatible API changes are still possible, and some + * parts may not have reached the same quality as the rest of Mbed TLS yet. + * + * Module: crypto/library/psa_crypto.c + * + * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_C + +/** + * \def MBEDTLS_PSA_CRYPTO_STORAGE_C + * + * Enable the Platform Security Architecture persistent key storage. + * + * Module: crypto/library/psa_crypto_storage.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, + * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of + * the PSA ITS interface + */ +//#define MBEDTLS_PSA_CRYPTO_STORAGE_C + +/** + * \def MBEDTLS_PSA_ITS_FILE_C + * + * Enable the emulation of the Platform Security Architecture + * Internal Trusted Storage (PSA ITS) over files. + * + * Module: crypto/library/psa_its_file.c + * + * Requires: MBEDTLS_FS_IO + * + */ +//#define MBEDTLS_PSA_ITS_FILE_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +//#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +//#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_CID_IN_LEN_MAX + * + * The maximum length of CIDs used for incoming DTLS messages. + * + */ +//#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 + +/** \def MBEDTLS_SSL_CID_OUT_LEN_MAX + * + * The maximum length of CIDs used for outgoing DTLS messages. + * + */ +//#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 + +/** \def MBEDTLS_SSL_CID_PADDING_GRANULARITY + * + * This option controls the use of record plaintext padding + * when using the Connection ID extension in DTLS 1.2. + * + * The padding will always be chosen so that the length of the + * padded plaintext is a multiple of the value of this option. + * + * Note: A value of \c 1 means that no padding will be used + * for outgoing records. + * + * Note: On systems lacking division instructions, + * a power of two should be preferred. + * + */ +//#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/websocket/src/script_util.cpp b/websocket/src/script_util.cpp new file mode 100644 index 0000000..2568f62 --- /dev/null +++ b/websocket/src/script_util.cpp @@ -0,0 +1,79 @@ +#include "script_util.h" + +namespace dmWebsocket { + +bool luaL_checkbool(lua_State *L, int numArg) +{ + bool b = false; + if (lua_isboolean(L, numArg)) + { + b = lua_toboolean(L, numArg); + } + else + { + luaL_typerror(L, numArg, lua_typename(L, LUA_TBOOLEAN)); + } + return b; +} + +bool luaL_checkboold(lua_State *L, int numArg, int def) +{ + int type = lua_type(L, numArg); + if (type != LUA_TNONE && type != LUA_TNIL) + { + return luaL_checkbool(L, numArg); + } + return def; +} + +lua_Number luaL_checknumberd(lua_State *L, int numArg, lua_Number def) +{ + int type = lua_type(L, numArg); + if (type != LUA_TNONE && type != LUA_TNIL) + { + return luaL_checknumber(L, numArg); + } + return def; +} + +char* luaL_checkstringd(lua_State *L, int numArg, const char* def) +{ + int type = lua_type(L, numArg); + if (type != LUA_TNONE && type != LUA_TNIL) + { + return (char*)luaL_checkstring(L, numArg); + } + return (char*)def; +} + +lua_Number luaL_checktable_number(lua_State *L, int numArg, const char* field, lua_Number def) +{ + lua_Number result = def; + if(lua_istable(L, numArg)) + { + lua_getfield(L, numArg, field); + if(!lua_isnil(L, -1)) + { + result = luaL_checknumber(L, -1); + } + lua_pop(L, 1); + } + return result; +} + +char* luaL_checktable_string(lua_State *L, int numArg, const char* field, char* def) +{ + char* result = def; + if(lua_istable(L, numArg)) + { + lua_getfield(L, numArg, field); + if(!lua_isnil(L, -1)) + { + result = (char*)luaL_checkstring(L, -1); + } + lua_pop(L, 1); + } + return result; +} + +} // namespace \ No newline at end of file diff --git a/websocket/src/script_util.h b/websocket/src/script_util.h new file mode 100644 index 0000000..5d825a0 --- /dev/null +++ b/websocket/src/script_util.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace dmWebsocket { + bool luaL_checkbool(lua_State *L, int numArg); + bool luaL_checkboold(lua_State *L, int numArg, int def); + lua_Number luaL_checknumberd(lua_State *L, int numArg, lua_Number def); + char* luaL_checkstringd(lua_State *L, int numArg, const char* def); + lua_Number luaL_checktable_number(lua_State *L, int numArg, const char* field, lua_Number def); + char* luaL_checktable_string(lua_State *L, int numArg, const char* field, char* def); +} // namespace \ No newline at end of file diff --git a/websocket/src/socket.h b/websocket/src/socket.h new file mode 100644 index 0000000..a86cede --- /dev/null +++ b/websocket/src/socket.h @@ -0,0 +1,570 @@ +// Copyright 2020 The Defold Foundation +// Licensed under the Defold License version 1.0 (the "License"); you may not use +// this file except in compliance with the License. +// +// You may obtain a copy of the License, together with FAQs at +// https://www.defold.com/license +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef DM_SOCKET_H +#define DM_SOCKET_H + +#include +#include // memset, memcmp + +#if defined(__linux__) || defined(__MACH__) || defined(ANDROID) || defined(__EMSCRIPTEN__) || defined(__NX__) +#include +#elif defined(_WIN32) +#include +#else +#error "Unsupported platform" +#endif + +/** + * Socket abstraction + * @note For Recv* and Send* function ETIMEDOUT is translated to EWOULDBLOCK + * on win32 for compatibility with BSD sockets. + */ +namespace dmSocket +{ + struct Selector + { + fd_set m_FdSets[3]; + int m_Nfds; + Selector(); + }; + + /** + * Socket result + */ + enum Result + { + RESULT_OK = 0, //!< RESULT_OK + + RESULT_ACCES = -1, //!< RESULT_ACCES + RESULT_AFNOSUPPORT = -2, //!< RESULT_AFNOSUPPORT + RESULT_WOULDBLOCK = -3, //!< RESULT_WOULDBLOCK + RESULT_BADF = -4, //!< RESULT_BADF + RESULT_CONNRESET = -5, //!< RESULT_CONNRESET + RESULT_DESTADDRREQ = -6, //!< RESULT_DESTADDRREQ + RESULT_FAULT = -7, //!< RESULT_FAULT + RESULT_HOSTUNREACH = -8, //!< RESULT_HOSTUNREACH + RESULT_INTR = -9, //!< RESULT_INTR + RESULT_INVAL = -10, //!< RESULT_INVAL + RESULT_ISCONN = -11, //!< RESULT_ISCONN + RESULT_MFILE = -12, //!< RESULT_MFILE + RESULT_MSGSIZE = -13, //!< RESULT_MSGSIZE + RESULT_NETDOWN = -14, //!< RESULT_NETDOWN + RESULT_NETUNREACH = -15, //!< RESULT_NETUNREACH + //RESULT_NFILE = -16, + RESULT_NOBUFS = -17, //!< RESULT_NOBUFS + //RESULT_NOENT = -18, + //RESULT_NOMEM = -19, + RESULT_NOTCONN = -20, //!< RESULT_NOTCONN + //RESULT_NOTDIR = -21, + RESULT_NOTSOCK = -22, //!< RESULT_NOTSOCK + RESULT_OPNOTSUPP = -23, //!< RESULT_OPNOTSUPP + RESULT_PIPE = -24, //!< RESULT_PIPE + RESULT_PROTONOSUPPORT = -25, //!< RESULT_PROTONOSUPPORT + RESULT_PROTOTYPE = -26, //!< RESULT_PROTOTYPE + RESULT_TIMEDOUT = -27, //!< RESULT_TIMEDOUT + + RESULT_ADDRNOTAVAIL = -28, //!< RESULT_ADDRNOTAVAIL + RESULT_CONNREFUSED = -29, //!< RESULT_CONNREFUSED + RESULT_ADDRINUSE = -30, //!< RESULT_ADDRINUSE + RESULT_CONNABORTED = -31, //!< RESULT_CONNABORTED + RESULT_INPROGRESS = -32, //!< RESULT_INPROGRESS + + // gethostbyname errors + RESULT_HOST_NOT_FOUND = -100, //!< RESULT_HOST_NOT_FOUND + RESULT_TRY_AGAIN = -101, //!< RESULT_TRY_AGAIN + RESULT_NO_RECOVERY = -102, //!< RESULT_NO_RECOVERY + RESULT_NO_DATA = -103, //!< RESULT_NO_DATA + + RESULT_UNKNOWN = -1000,//!< RESULT_UNKNOWN + }; + + /** + * Socket handle + * @note Use INVALID_SOCKET_HANDLE instead of zero for unset values. This is an exception + * from all other handles. + */ + typedef int Socket; + + enum SelectorKind + { + SELECTOR_KIND_READ = 0, + SELECTOR_KIND_WRITE = 1, + SELECTOR_KIND_EXCEPT = 2, + }; + + enum Flags + { + FLAGS_UP = (1 << 0), + FLAGS_RUNNING = (1 << 1), + FLAGS_INET = (1 << 2), + FLAGS_LINK = (1 << 3), + }; + + /** + * Invalid socket handle + */ + const Socket INVALID_SOCKET_HANDLE = 0xffffffff; + + /** + * Domain type + */ + enum Domain + { + DOMAIN_MISSING, //!< DOMAIN_MISSING + DOMAIN_IPV4, //!< DOMAIN_IPV4 + DOMAIN_IPV6, //!< DOMAIN_IPV6 + DOMAIN_UNKNOWN, //!< DOMAIN_UNKNOWN + }; + + /** + * Socket type + */ + enum Type + { + TYPE_STREAM, //!< TYPE_STREAM + TYPE_DGRAM, //!< TYPE_DGRAM + }; + + /** + * Network protocol + */ + enum Protocol + { + PROTOCOL_TCP, //!< PROTOCOL_TCP + PROTOCOL_UDP, //!< PROTOCOL_UDP + }; + + /** + * Socket shutdown type + */ + enum ShutdownType + { + SHUTDOWNTYPE_READ, + SHUTDOWNTYPE_WRITE, + SHUTDOWNTYPE_READWRITE, + }; + + /** + * Network address + * Network addresses were previously represented as an uint32_t, but in + * order to support IPv6 the internal representation was changed to a + * struct. + */ + struct Address + { + + Address() { + m_family = dmSocket::DOMAIN_MISSING; + memset(m_address, 0x0, sizeof(m_address)); + } + + Domain m_family; + uint32_t m_address[4]; + }; + + /** + * Comparison operators for dmSocket::Address (network address). + * These operators are required since network code was initially designed + * with the assumption that addresses were stored as uint32_t (IPv4), and + * thus sortable. + */ + inline bool operator==(const Address& lhs, const Address& rhs) + { + return memcmp(lhs.m_address, rhs.m_address, sizeof(lhs.m_address)) == 0; + } + + inline bool operator< (const Address& lhs, const Address& rhs) + { + return memcmp(lhs.m_address, rhs.m_address, sizeof(lhs.m_address)) < 0; + } + + inline bool operator!=(const Address& lhs, const Address& rhs) { return !operator==(lhs,rhs); } + inline bool operator> (const Address& lhs, const Address& rhs) { return operator< (rhs,lhs); } + inline bool operator<=(const Address& lhs, const Address& rhs) { return !operator> (lhs,rhs); } + inline bool operator>=(const Address& lhs, const Address& rhs) { return !operator< (lhs,rhs); } + + struct IfAddr + { + char m_Name[128]; + uint32_t m_Flags; + Address m_Address; + uint8_t m_MacAddress[6]; + }; + + /** + * Initialize socket system. Network initialization is required on some platforms. + * @return RESULT_OK on success + */ + Result Initialize(); + + /** + * Finalize socket system. + * @return RESULT_OK on success + */ + Result Finalize(); + + /** + * Create a new socket. Corresponds to BSD socket function socket(). + * @note SIGPIPE is disabled on applicable platforms. This has the implication + * that Receive can return zero bytes when the connection is closed by remote peer. + * @param type Soccket type + * @param protocol Protocol + * @param socket Pointer to created socket + * @return RESULT_OK on succcess + */ + Result New(Domain domain, Type type, enum Protocol protocol, Socket* socket); + + /** + * Delete a socket. Corresponds to BSD socket function close() + * @param socket Socket to close + * @return RESULT_OK on success + */ + Result Delete(Socket socket); + + /** + * Get underlying file descriptor + * @param socket socket to get fd for + * @return file-descriptor + */ + int GetFD(Socket socket); + + /** + * Set reuse socket address option on socket. Socket option SO_REUSEADDR on most platforms + * @param socket Socket to set reuse address to + * @param reuse True if reuse + * @return RESULT_OK on success + */ + Result SetReuseAddress(Socket socket, bool reuse); + + + /** + * Set broadcast address option on socket. Socket option SO_BROADCAST on most platforms. + * @param socket Socket to set reuse address to + * @param broadcast True if broadcast + * @return RESULT_OK on success + */ + Result SetBroadcast(Socket socket, bool broadcast); + + /** + * Set blocking option on a socket + * @param socket Socket to set blocking on + * @param blocking True to block + * @return RESULT_OK on success + */ + Result SetBlocking(Socket socket, bool blocking); + + /** + * Set TCP_NODELAY on socket + * @param socket Socket to set TCP_NODELAY on + * @param no_delay True for no delay + * @return RESULT_OK on success + */ + Result SetNoDelay(Socket socket, bool no_delay); + + /** + * Set socket send timeout + * @note Timeout resolution might be in milliseconds, e.g. windows. Use values + * larger than or equal to 1000. + * @param socket socket + * @param timeout timeout in microseconds + * @return RESULT_OK on success + */ + Result SetSendTimeout(Socket socket, uint64_t timeout); + + /** + * Set socket receive timeout + * @note Timeout resolution might be in milliseconds, e.g. windows. Use values + * larger than or equal to 1000 + * @param socket socket + * @param timeout timeout in microseconds + * @return RESULT_OK on success + */ + Result SetReceiveTimeout(Socket socket, uint64_t timeout); + + /** + * Add multicast membership + * @param socket socket to add membership on + * @param multi_addr multicast address + * @param interface_addr interface address + * @param ttl multicast package time to live + * @return RESULT_OK + */ + Result AddMembership(Socket socket, Address multi_addr, Address interface_addr, int ttl); + + /** + * Set address for outgoing multicast datagrams + * @param socket socket to set multicast address for + * @param address address of network interface to use + * @return RESULT_OK + */ + Result SetMulticastIf(Socket socket, Address address); + + /** + * Accept a connection on a socket + * @param socket Socket to accept connections on + * @param address Result address parameter + * @param accept_socket Pointer to accepted socket (result) + * @return RESULT_OK on success + */ + Result Accept(Socket socket, Address* address, Socket* accept_socket); + + /** + * Bind a name to a socket + * @param socket Socket to bind name to + * @param address Address to bind + * @param port Port to bind to + * @return RESULT_OK on success + */ + Result Bind(Socket socket, Address address, int port); + + /** + * Initiate a connection on a socket + * @param socket Socket to initiate connection on + * @param address Address to connect to + * @param port Port to connect to + * @return RESULT_OK on success + */ + Result Connect(Socket socket, Address address, int port); + + /** + * Listen for connections on a socket + * @param socket Socket to listen on + * @param backlog Maximum length for the queue of pending connections + * @return RESULT_OK on success + */ + Result Listen(Socket socket, int backlog); + + /** + * Shutdown part of a socket connection + * @param socket Socket to shutdown connection ow + * @param how Shutdown type + * @return RESULT_OK on success + */ + Result Shutdown(Socket socket, ShutdownType how); + + /** + * Send a message on a socket + * @param socket Socket to send a message on + * @param buffer Buffer to send + * @param length Length of buffer to send + * @param sent_bytes Number of bytes sent (result) + * @return RESULT_OK on success + */ + Result Send(Socket socket, const void* buffer, int length, int* sent_bytes); + + /** + * Send a message to a specific address + * @param socket Socket to send a message on + * @param buffer Buffer to send + * @param length Length of buffer to send + * @param sent_bytes Number of bytes sent (result) + * @param to_addr To address + * @param to_port From addres + * @return RESULT_OK on success + */ + Result SendTo(Socket socket, const void* buffer, int length, int* sent_bytes, Address to_addr, uint16_t to_port); + + /** + * Receive data on a socket + * @param socket Socket to receive data on + * @param buffer Buffer to receive to + * @param length Receive buffer length + * @param received_bytes Number of received bytes (result) + * @return RESULT_OK on success + */ + Result Receive(Socket socket, void* buffer, int length, int* received_bytes); + + /** + * Receive from socket + * @param socket Socket to receive data on + * @param buffer Buffer to receive to + * @param length Receive buffer length + * @param received_bytes Number of received bytes (result) + * @param from_addr From address (result) + * @param from_port To address (result) + * @return RESULT_OK on success + */ + Result ReceiveFrom(Socket socket, void* buffer, int length, int* received_bytes, + Address* from_addr, uint16_t* from_port); + + + /** + * Get name, address and port for socket + * @param socket Socket to get name for + * @param address Address (result) + * @param port Socket (result) + * @return RESULT_OK on success + */ + Result GetName(Socket socket, Address*address, uint16_t* port); + + /** + * Get local hostname + * @param hostname hostname buffer + * @param hostname_length hostname buffer length + * @return RESULT_OK on success + */ + Result GetHostname(char* hostname, int hostname_length); + + /** + * Get first local IP address + * The function tries to determine the local IP address. If several + * IP addresses are available only a single is returned + * @note This function might fallback to 127.0.0.1 if no adapter is found + * Sometimes it might be appropriate to run this function periodically + * @param address address result + * @return RESULT_OK on success + */ + Result GetLocalAddress(Address* address); + + /** + * Get address from ip string + * @param address IP-string + * @return Address + */ + Address AddressFromIPString(const char* address); + + /** + * Convert address to ip string + * @param address address to convert + * @return IP string. The caller is responsible to free the string using free() + */ + char* AddressToIPString(Address address); + + /** + * Get host by name. + * @param name Hostname to resolve + * @param address Host address result + * @param ipv4 Whether or not to search for IPv4 addresses + * @param ipv6 Whether or not to search for IPv6 addresses + * @return RESULT_OK on success + */ + Result GetHostByName(const char* name, Address* address, bool ipv4 = true, bool ipv6 = true); + + /** + * Get information about network adapters (loopback devices are not included) + * @note Make sure that addresses is large enough. If too small + * the result is capped. + * @param addresses array of if-addresses + * @param addresses_count count + * @param count actual count + */ + void GetIfAddresses(IfAddr* addresses, uint32_t addresses_count, uint32_t* count); + + /** + * Convert result value to string + * @param result Result to convert + * @return Result as string + */ + const char* ResultToString(Result result); + + /** + * Converts a native result (error) to dmSocket::Result + * Also logs the error + * @param filename the file that calls this function + * @param line the line number of this call + * @param r the native result + * @return Result + */ + Result NativeToResult(const char* filename, int line, int r); + + /** + * Check if a network address is empty (all zeroes). + * @param address The address to check + * @return True if the address is empty, false otherwise + */ + bool Empty(Address address); + + /** + * Return a pointer to the IPv4 buffer of address. + * @note Make sure the address family of address is actually AF_INET before + * attempting to retrieve the IPv4 buffer, otherwise an assert will trigger. + * @param address Pointer to the address containing the buffer + * @return Pointer to the buffer that holds the IPv4 address + */ + uint32_t* IPv4(Address* address); + + /** + * Return a pointer to the IPv6 buffer of address. + * @note Make sure the address family of address is actually AF_INET6 before + * attempting to retrieve the IPv6 buffer, otherwise an assert will trigger. + * @param address Pointer to the address containing the buffer + * @return Pointer to the buffer that holds the IPv6 address + */ + uint32_t* IPv6(Address* address); + + /** + * Checks if a socket was created for IPv4 (AF_INET). + * @param socket The socket to check + * @return True if the socket was created for IPv4 communication, false otherwise + */ + bool IsSocketIPv4(Socket socket); + + /** + * Checks if a socket was created for IPv6 (AF_INET6). + * @param socket The socket to check + * @return True if the socket was created for IPv6 communication, false otherwise + */ + bool IsSocketIPv6(Socket socket); + + /** + * Calculate the number of bits that differs between address a and b. + * @note This is used for the Hamming Distance. + * @param a The first address to compare + * @param b The second address to compare + * @return Number of bits that differs between a and b + */ + uint32_t BitDifference(Address a, Address b); + + struct Selector; + + /** + * Clear selector for socket. Similar to FD_CLR + * @param selector Selector + * @param selector_kind Kind to clear + * @param socket Socket to clear + */ + void SelectorClear(Selector* selector, SelectorKind selector_kind, Socket socket); + + /** + * Set selector for socket. Similar to FD_SET + * @param selector Selector + * @param selector_kind Kind to clear + * @param socket Socket to set + */ + void SelectorSet(Selector* selector, SelectorKind selector_kind, Socket socket); + + /** + * Check if selector is set. Similar to FD_ISSET + * @param selector Selector + * @param selector_kind Selector kind + * @param socket Socket to check for + * @return True if set. + */ + bool SelectorIsSet(Selector* selector, SelectorKind selector_kind, Socket socket); + + /** + * Clear selector (all kinds). Similar to FD_ZERO + * @param selector Selector + */ + void SelectorZero(Selector* selector); + + /** + * Select for pending data + * @param selector Selector + * @param timeout Timeout. For blocking pass -1 + * @return RESULT_OK on success + */ + Result Select(Selector* selector, int32_t timeout); +} + +#endif // DM_SOCKET_H diff --git a/websocket/src/uri.h b/websocket/src/uri.h new file mode 100644 index 0000000..09e90d9 --- /dev/null +++ b/websocket/src/uri.h @@ -0,0 +1,85 @@ +// Copyright 2020 The Defold Foundation +// Licensed under the Defold License version 1.0 (the "License"); you may not use +// this file except in compliance with the License. +// +// You may obtain a copy of the License, together with FAQs at +// https://www.defold.com/license +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef DM_URI_H +#define DM_URI_H + +namespace dmURI +{ + /** + * URI parsing result + */ + enum Result + { + RESULT_OK,//!< RESULT_OK + }; + + const uint32_t MAX_SCHEME_LEN = 8; + const uint32_t MAX_LOCATION_LEN = 64; + const uint32_t MAX_PATH_LEN = 2048; + // Maximum length of an URI + // scheme :// location / path + const uint32_t MAX_URI_LEN = MAX_SCHEME_LEN + 3 + MAX_LOCATION_LEN + 1 + MAX_PATH_LEN; + + + /** + * URI parsing result parts + */ + struct Parts + { + /// Scheme parts, eg http + char m_Scheme[MAX_SCHEME_LEN]; + + /// Location part, eg foo.com:80 + char m_Location[MAX_LOCATION_LEN]; + + /// Hostname part of location, eg foo.com + char m_Hostname[MAX_LOCATION_LEN]; + + /// Port part of location, eg 80. -1 if not present + int m_Port; + + /// Path part, eg index.html + // Increased from 512 to 2048 (DEF-3410). 2048 seems like a reasonable + // number based on the following SO answer: https://stackoverflow.com/a/417184/1266551 + char m_Path[MAX_PATH_LEN]; + }; + + /** + * Parse URI and split in three parts. (scheme, location, path) + * @note This is a simplified URI parser and does not conform to rfc2396. + * Missing features are: parameters, query, fragment part of URI and support for escaped sequences + * @note For http m_Port is set to 80 if not specified in uri. + * @param uri URI to parse + * @param parts Result + * @return RESULT_OK on success + */ + Result Parse(const char* uri, Parts* parts); + + /** + * Performs URL encoding of the supplied buffer + * @param src String to encode + * @param dst Encoded string + * @param dst_size size of the provided out buffer + */ + void Encode(const char* src, char* dst, uint32_t dst_size); + + /** + * Undoes URL decoding on a buffer. + * @note The output will never be larger than the input. + * @param src Input + * @param dst Decoded output + */ + void Decode(const char* src, char* dst); +} + +#endif // DM_URI_H diff --git a/websocket/src/websocket.cpp b/websocket/src/websocket.cpp new file mode 100644 index 0000000..df3e318 --- /dev/null +++ b/websocket/src/websocket.cpp @@ -0,0 +1,1056 @@ +// More info on websockets +// https://tools.ietf.org/html/rfc6455 + +#define LIB_NAME "Websocket" +#define MODULE_NAME "websocket" + +// include the Defold SDK +#include + +#include + +#include "connection_pool.h" +#include "socket.h" +#include "dns.h" +#include "uri.h" + +#include "script_util.h" + +extern "C" int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen ); +extern "C" int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen ); + +namespace dmCrypt +{ + void HashSha1(const uint8_t* buf, uint32_t buflen, uint8_t* digest); +} + +namespace dmWebsocket { + +enum State +{ + STATE_CONNECTING, + STATE_HANDSHAKE, + STATE_CONNECTED, + STATE_DISCONNECTED, +}; + +enum Result +{ + RESULT_OK, + RESULT_FAIL_WSLAY_INIT, + RESULT_NOT_CONNECTED, + RESULT_HANDSHAKE_FAILED, +}; + +enum Event +{ + EVENT_CONNECTED, + EVENT_DISCONNECTED, + EVENT_MESSAGE, +}; + +struct WebsocketConnection +{ + char m_Key[16]; + wslay_event_context_ptr m_Ctx; + dmURI::Parts m_Url; + dmConnectionPool::HConnection m_Connection; + dmSocket::Socket m_Socket; + State m_State; + uint32_t m_SSL:1; + char* m_Response; + int m_ResponseSize; + uint32_t m_ResponseCapacity; + dmScript::LuaCallbackInfo* m_Callback; + Result m_Status; +}; + +struct WebsocketContext +{ + uint64_t m_BufferSize; + int m_Timeout; + dmArray m_Connections; + dmConnectionPool::HPool m_Pool; + dmDNS::HChannel m_Channel; + uint32_t m_Initialized:1; +} g_Websocket; + + +static void HandleCallback(WebsocketConnection* conn, int event, const uint8_t* msg, size_t msg_len); + + +#define WS_SENDALL(s) \ + sock_res = Send(conn, s, strlen(s), 0);\ + if (sock_res != dmSocket::RESULT_OK)\ + {\ + return sock_res;\ + }\ + +static void debugPrintBuffer(const char* s, size_t len) +{ + for (int i = 0; i < len; ++i) + { + const char* p = s + i; + if (*p == '\r') { + printf("\\r"); + } + else if (*p == '\n') { + printf("\\n\n"); + } + else if (*p == '\t') { + printf("\t"); + } + else { + printf("%c", *p); + } + } +} + +static dmSocket::Result Send(WebsocketConnection* conn, const char* buffer, int length, int* out_sent_bytes) +{ + // if (response->m_SSLConnection != 0) { + // int r = 0; + // while( ( r = mbedtls_ssl_write(response->m_SSLConnection, (const uint8_t*) buffer, length) ) < 0 ) + // { + // if (r == MBEDTLS_ERR_SSL_WANT_WRITE || + // r == MBEDTLS_ERR_SSL_WANT_READ) { + // return dmSocket::RESULT_TRY_AGAIN; + // } + + // if (r < 0) { + // return SSLToSocket(r); + // } + // } + + // // In order to mimic the http code path, we return the same error number + // if( (r == length) && HasRequestTimedOut(response->m_Client) ) + // { + // return dmSocket::RESULT_WOULDBLOCK; + // } + + // if (r != length) { + // return SSLToSocket(r); + // } + + // return dmSocket::RESULT_OK; + // } else { + int total_sent_bytes = 0; + int sent_bytes = 0; + + while (total_sent_bytes < length) { + + dmSocket::Result r = dmSocket::Send(conn->m_Socket, buffer + total_sent_bytes, length - total_sent_bytes, &sent_bytes); + +debugPrintBuffer(buffer + total_sent_bytes, sent_bytes); + + if( r == dmSocket::RESULT_WOULDBLOCK ) + { + r = dmSocket::RESULT_TRY_AGAIN; + } + // if( (r == dmSocket::RESULT_OK || r == dmSocket::RESULT_TRY_AGAIN) && HasRequestTimedOut(response->m_Client) ) + // { + // r = dmSocket::RESULT_WOULDBLOCK; + // } + + if (r == dmSocket::RESULT_TRY_AGAIN) + continue; + + if (r != dmSocket::RESULT_OK) { + return r; + } + + total_sent_bytes += sent_bytes; + } + if (out_sent_bytes) + *out_sent_bytes = total_sent_bytes; + return dmSocket::RESULT_OK; +// } +} + +static dmSocket::Result Receive(WebsocketConnection* conn, void* buffer, int length, int* received_bytes) +{ + // if (response->m_SSLConnection != 0) { + + // int ret = 0; + // do + // { + // memset(buffer, 0, length); + // ret = mbedtls_ssl_read( response->m_SSLConnection, (unsigned char*)buffer, length-1 ); + + // if( ret == MBEDTLS_ERR_SSL_WANT_READ || + // ret == MBEDTLS_ERR_SSL_WANT_WRITE || + // ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + // { + // continue; + // } + + // if (HasRequestTimedOut(response->m_Client)) { + // return dmSocket::RESULT_WOULDBLOCK; + // } + + // if( ret <= 0 ) + // { + // return SSLToSocket(ret); + // } + + // ((uint8_t*)buffer)[ret] = 0; + + // *received_bytes = ret; + // return dmSocket::RESULT_OK; + // } + // while( 1 ); + // } else { + return dmSocket::Receive(conn->m_Socket, buffer, length, received_bytes); + //} +} + +static void CreateKey(char key[16]) +{ + // TODO: Create proper key + for (int i = 0; i < 16; ++i) + { + key[i] = (char)i; + } +} + +static void printHex(const uint8_t* data, size_t len) +{ + for (int i = 0; i < 16; ++i) + { + printf("%x", data[i]); + } +} + + +static dmSocket::Result SendClientHandshake(WebsocketConnection* conn) +{ + printf("SendClientHandshake\n"); + + CreateKey(conn->m_Key); + printf("DBG: CreateKey: '"); + printHex((const uint8_t*)conn->m_Key, 16); + printf("'\n"); + + char encoded_key[32]; + size_t encoded_key_len = 0; + mbedtls_base64_encode((unsigned char*)encoded_key, sizeof(encoded_key), &encoded_key_len, (const unsigned char*)conn->m_Key, sizeof(conn->m_Key)); + + printf("DBG: encoded: '%s'\n", encoded_key); + + char port[8] = ""; + if (!(conn->m_Url.m_Port == 80 || conn->m_Url.m_Port == 443)) + dmSnPrintf(port, sizeof(port), ":%d", conn->m_Url.m_Port); + + dmSocket::Result sock_res = dmSocket::RESULT_OK; + WS_SENDALL("GET /"); + WS_SENDALL(conn->m_Url.m_Path); + WS_SENDALL(" HTTP/1.1\r\n"); + WS_SENDALL("Host: "); + WS_SENDALL(conn->m_Url.m_Hostname); + WS_SENDALL(port); + WS_SENDALL("\r\n"); + WS_SENDALL("Upgrade: websocket\r\n"); + WS_SENDALL("Connection: Upgrade\r\n"); + WS_SENDALL("Sec-WebSocket-Key: "); + WS_SENDALL(encoded_key); + WS_SENDALL("\r\n"); + WS_SENDALL("Sec-WebSocket-Version: 13\r\n"); + + // Add custom protocols + + // Add custom headers + + WS_SENDALL("\r\n"); + + // String request = "GET " + p_path + " HTTP/1.1\r\n"; + // request += "Host: " + p_host + port + "\r\n"; + // request += "Upgrade: websocket\r\n"; + // request += "Connection: Upgrade\r\n"; + // request += "Sec-WebSocket-Key: " + _key + "\r\n"; + // request += "Sec-WebSocket-Version: 13\r\n"; + // if (p_protocols.size() > 0) { + // request += "Sec-WebSocket-Protocol: "; + // for (int i = 0; i < p_protocols.size(); i++) { + // if (i != 0) { + // request += ","; + // } + // request += p_protocols[i]; + // } + // request += "\r\n"; + // } + // for (int i = 0; i < p_custom_headers.size(); i++) { + // request += p_custom_headers[i] + "\r\n"; + // } + // request += "\r\n"; + + //dmSocket::SetNoDelay(conn->m_Socket, true); + return sock_res; +} + +static Result VerifyHeaders(WebsocketConnection* conn) +{ + char* r = conn->m_Response; + + printf("SERVER RESPONSE:\n%s\n", r); + + const char* http_version_and_status_protocol = "HTTP/1.1 101"; // optionally "Web Socket Protocol Handshake" + if (strstr(r, http_version_and_status_protocol) != r) { + dmLogError("Missing: '%s'", http_version_and_status_protocol); + return RESULT_HANDSHAKE_FAILED; + } + r = strstr(r, "\r\n") + 2; + + + bool upgraded = false; + bool valid_key = false; + const char* protocol = ""; + + // Sec-WebSocket-Protocol + + // parse he + while (r) + { + // Tokenize the each header line: "Key: Value\r\n" + const char* key = r; + r = strchr(r, ':'); + *r = 0; + ++r; + const char* value = r; + while(*value == ' ') + ++value; + r = strstr(r, "\r\n"); + *r = 0; + r += 2; + + printf("KEY: '%s', VALUE: '%s'\n", key, value); + + if (strcmp(key, "Connection") == 0 && strcmp(value, "Upgrade") == 0) + upgraded = true; + else if (strcmp(key, "Sec-WebSocket-Accept") == 0) + { + const char* magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // as per the rfc document on page 7 (https://tools.ietf.org/html/rfc6455) + + uint8_t client_key[64]; + size_t client_key_len = 0; + mbedtls_base64_encode((unsigned char*)client_key, sizeof(client_key), &client_key_len, (const unsigned char*)conn->m_Key, sizeof(conn->m_Key)); + memcpy(client_key + client_key_len, magic, strlen(magic)); + client_key_len += strlen(magic); + client_key[client_key_len] = 0; + + uint8_t client_key_sha1[20]; + dmCrypt::HashSha1(client_key, client_key_len, client_key_sha1); + + mbedtls_base64_encode((unsigned char*)client_key, sizeof(client_key), &client_key_len, client_key_sha1, sizeof(client_key_sha1)); + client_key[client_key_len] = 0; + + if (strcmp(value, (const char*)client_key) == 0) + valid_key = true; + + printf("DBG: CLIENT KEY+MAGIC: '%s'\n", client_key); + } + + if (strcmp(r, "\r\n") == 0) + break; + } + + return (upgraded && valid_key) ? RESULT_OK : RESULT_HANDSHAKE_FAILED; +} + +static Result ReceiveHeaders(WebsocketConnection* conn) +{ + while (1) + { + int max_to_recv = (int)(g_Websocket.m_BufferSize - 1) - conn->m_ResponseSize; // allow for a terminating null character + + if (max_to_recv <= 0) + { + dmLogError("Receive buffer full"); + return RESULT_HANDSHAKE_FAILED; + } + + int recv_bytes = 0; + dmSocket::Result r = Receive(conn, conn->m_Response + conn->m_ResponseSize, max_to_recv, &recv_bytes); + + if( r == dmSocket::RESULT_WOULDBLOCK ) + { + r = dmSocket::RESULT_TRY_AGAIN; + } + + if (r == dmSocket::RESULT_TRY_AGAIN) + continue; + + if (r != dmSocket::RESULT_OK) + { + dmLogError("Receive error: %s", dmSocket::ResultToString(r)); + return RESULT_HANDSHAKE_FAILED; + } + +debugPrintBuffer(conn->m_Response + conn->m_ResponseSize, recv_bytes); + + conn->m_ResponseSize += recv_bytes; + + // NOTE: We have an extra byte for null-termination so no buffer overrun here. + conn->m_Response[conn->m_ResponseSize] = '\0'; + + // Check if the end of the response has arrived + if (conn->m_ResponseSize >= 4 && strcmp(conn->m_Response + conn->m_ResponseSize - 4, "\r\n\r\n") == 0) + { + return RESULT_OK; + } + + if (r == 0) + { + dmLogError("Failed to parse headers:\n%s", conn->m_Response); + return RESULT_HANDSHAKE_FAILED; + } + } +} + +static ssize_t WSL_RecvCallback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, int flags, void *user_data) +{ + WebsocketConnection* conn = (WebsocketConnection*)user_data; + + // struct Session *session = (struct Session*)user_data; + // ssize_t r; + // while((r = recv(session->fd, buf, len, 0)) == -1 && errno == EINTR); + // if(r == -1) { + // if(errno == EAGAIN || errno == EWOULDBLOCK) { + // wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + // } else { + // wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + // } + // } else if(r == 0) { + // /* Unexpected EOF is also treated as an error */ + // wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + // r = -1; + // } + // return r; + + int r = -1; // received bytes if >=0, error if < 0 + + dmSocket::Result socket_result = Receive(conn, buf, len, &r); + + if (dmSocket::RESULT_OK == socket_result && r == 0) + socket_result = dmSocket::RESULT_WOULDBLOCK; + + if (dmSocket::RESULT_OK != socket_result) + { + if (socket_result == dmSocket::RESULT_WOULDBLOCK || socket_result == dmSocket::RESULT_TRY_AGAIN) { + wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + } + else + wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + return -1; + } + return r; +} + +static ssize_t WSL_SendCallback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data) +{ + WebsocketConnection* conn = (WebsocketConnection*)user_data; + + // struct Session *session = (struct Session*)user_data; + // ssize_t r; + + // int sflags = 0; + // // #ifdef MSG_MORE + // // if(flags & WSLAY_MSG_MORE) { + // // sflags |= MSG_MORE; + // // } + // // #endif // MSG_MORE + // while((r = send(session->fd, data, len, sflags)) == -1 && errno == EINTR); + // if(r == -1) { + // if(errno == EAGAIN || errno == EWOULDBLOCK) { + // wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + // } else { + // wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + // } + // } + // return r; + + int sent_bytes = 0; + dmSocket::Result socket_result = Send(conn, (const char*)data, len, &sent_bytes); + + // dmSocket::Result socket_result; + // int r = -1; // sent bytes if >=0, error if < 0 + + // do { + // socket_result = dmSocket::Send(conn->m_Socket, data, len, &r); + // } + // while (r == -1 && socket_result == dmSocket::RESULT_INTR); + + if (socket_result != dmSocket::RESULT_OK) + { + if (socket_result == dmSocket::RESULT_WOULDBLOCK || socket_result == dmSocket::RESULT_TRY_AGAIN) + wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + else + wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + return -1; + } + return (ssize_t)sent_bytes; +} + +// Error WSLPeer::parse_message(const wslay_event_on_msg_recv_arg *arg) { +// uint8_t is_string = 0; +// if (arg->opcode == WSLAY_TEXT_FRAME) { +// is_string = 1; +// } else if (arg->opcode == WSLAY_CONNECTION_CLOSE) { +// close_code = arg->status_code; +// size_t len = arg->msg_length; +// close_reason = ""; +// if (len > 2 /* first 2 bytes = close code */) { +// close_reason.parse_utf8((char *)arg->msg + 2, len - 2); +// } +// if (!wslay_event_get_close_sent(_data->ctx)) { +// if (_data->is_server) { +// WSLServer *helper = (WSLServer *)_data->obj; +// helper->_on_close_request(_data->id, close_code, close_reason); +// } else { +// WSLClient *helper = (WSLClient *)_data->obj; +// helper->_on_close_request(close_code, close_reason); +// } +// } +// return ERR_FILE_EOF; +// } else if (arg->opcode != WSLAY_BINARY_FRAME) { +// // Ping or pong +// return ERR_SKIP; +// } +// _in_buffer.write_packet(arg->msg, arg->msg_length, &is_string); +// return OK; +// } + +static void WSL_OnMsgRecvCallback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data) +{ + WebsocketConnection* conn = (WebsocketConnection*)user_data; + if (arg->opcode == WSLAY_TEXT_FRAME || arg->opcode == WSLAY_BINARY_FRAME) + { + HandleCallback(conn, EVENT_MESSAGE, arg->msg, arg->msg_length); + } else if (arg->opcode == WSLAY_CONNECTION_CLOSE) + { + // TODO: Store the reason + + // close_code = arg->status_code; +// size_t len = arg->msg_length; +// close_reason = ""; +// if (len > 2 /* first 2 bytes = close code */) { +// close_reason.parse_utf8((char *)arg->msg + 2, len - 2); +// } +// if (!wslay_event_get_close_sent(_data->ctx)) { +// if (_data->is_server) { +// WSLServer *helper = (WSLServer *)_data->obj; +// helper->_on_close_request(_data->id, close_code, close_reason); +// } else { +// WSLClient *helper = (WSLClient *)_data->obj; +// helper->_on_close_request(close_code, close_reason); +// } +// } + } +} + +static int WSL_GenmaskCallback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, void *user_data) { + // RandomNumberGenerator rng; + // // TODO maybe use crypto in the future? + // rng.set_seed(OS::get_singleton()->get_unix_time()); + // for (unsigned int i = 0; i < len; i++) { + // buf[i] = (uint8_t)rng.randi_range(0, 255); + // } + // return 0; + + // TODO: Create a random mask + for (unsigned int i = 0; i < len; i++) { + buf[i] = (uint8_t)(i & 0xFF); + } + return 0; +} + +// *************************************************************************************************** +// LUA functions + + // struct wslay_event_msg msg; // Should I use fragmented? + // msg.opcode = write_mode == WRITE_MODE_TEXT ? WSLAY_TEXT_FRAME : WSLAY_BINARY_FRAME; + // msg.msg = p_buffer; + // msg.msg_length = p_buffer_size; + + // wslay_event_queue_msg(_data->ctx, &msg); + // if (wslay_event_send(_data->ctx) < 0) { + // close_now(); + // return FAILED; + // } + +const struct wslay_event_callbacks g_WslCallbacks = { + WSL_RecvCallback, + WSL_SendCallback, + WSL_GenmaskCallback, + NULL, + NULL, + NULL, + WSL_OnMsgRecvCallback +}; + + +static WebsocketConnection* WSL_CreateConnection() +{ + WebsocketConnection* conn = (WebsocketConnection*)malloc(sizeof(WebsocketConnection)); + memset(conn, 0, sizeof(WebsocketConnection)); + conn->m_ResponseCapacity = g_Websocket.m_BufferSize; + conn->m_Response = (char*)malloc(conn->m_ResponseCapacity); + return conn; +} + +static void WSL_DestroyConnection(WebsocketConnection* conn) +{ + if (conn->m_State == STATE_CONNECTED) + wslay_event_context_free(conn->m_Ctx); + + if (conn->m_Callback) + dmScript::DestroyCallback(conn->m_Callback); + + if (conn->m_Connection) + dmConnectionPool::Close(g_Websocket.m_Pool, conn->m_Connection); + + free((void*)conn->m_Response); + free((void*)conn); +} + +static void WSL_CloseConnection(WebsocketConnection* conn) +{ + // we want it to send this message in the polling + if (conn->m_State == STATE_CONNECTED) { + const char* reason = "Client wants to close"; + wslay_event_queue_close(conn->m_Ctx, 0, (const uint8_t*)reason, strlen(reason)); + } + else + conn->m_State = STATE_DISCONNECTED; +} + + +static Result WSL_OpenConnection(WebsocketConnection* conn, const char* url) +{ + dmURI::Parts uri; + dmURI::Parse(url, &conn->m_Url); + + if (strcmp(conn->m_Url.m_Scheme, "https") == 0) + strcpy(conn->m_Url.m_Scheme, "wss"); + + conn->m_SSL = strcmp(conn->m_Url.m_Scheme, "wss") == 0 ? 1 : 0; + + conn->m_State = STATE_CONNECTING; + // dmSocket::Result socket_result; + // dmConnectionPool::Result pool_result = dmConnectionPool::Dial(g_Websocket.m_Pool, conn->m_Url.m_Hostname, conn->m_Url.m_Port, g_Websocket.m_Channel, conn->m_SSL, g_Websocket.m_Timeout, &conn->m_Connection, &socket_result); + // if (dmConnectionPool::RESULT_OK != pool_result) + // { + // return RESULT_NOT_CONNECTED; + // } + + // conn->m_Socket = dmConnectionPool::GetSocket(g_Websocket.m_Pool, conn->m_Connection); + + // conn->m_State = STATE_HANDSHAKE; + // socket_result = SendClientHandshake(conn); + // if (dmSocket::RESULT_OK != socket_result) + // { + // return RESULT_HANDSHAKE_FAILED; + // } + + // Result result = ReceiveHeaders(conn); + // if (RESULT_OK != result) + // { + // dmLogError("Failed receiving Handshake headers"); + // return result; + // } + + // result = VerifyHeaders(conn); + // if (RESULT_OK != result) + // { + // dmLogError("Failed verifying handshake headers:\n%s\n\n", conn->m_Response); + // return result; + // } + + // // Handshake complete, time to + + // // Currently only supports client implementation + // int ret = -1; + // ret = wslay_event_context_client_init(&conn->m_Ctx, &g_WslCallbacks, conn); + // if (ret == 0) + // wslay_event_config_set_max_recv_msg_length(conn->m_Ctx, g_Websocket.m_BufferSize); + // if (ret != 0) + // { + // return RESULT_FAIL_WSLAY_INIT; + // } + + // conn->m_State = STATE_CONNECTED; + + return RESULT_OK; +} + +static int FindConnection(WebsocketConnection* conn) +{ + for (int i = 0; i < g_Websocket.m_Connections.Size(); ++i ) + { + if (g_Websocket.m_Connections[i] == conn) + return i; + } + return -1; +} + +/*# +* +*/ +static int WSL_Lua_Connect(lua_State* L) +{ + DM_LUA_STACK_CHECK(L, 2); + + if (!g_Websocket.m_Initialized) + return DM_LUA_ERROR("The web socket module isn't initialized"); + + const char* url = luaL_checkstring(L, 1); + + WebsocketConnection* conn = WSL_CreateConnection(); + Result result = WSL_OpenConnection(conn, url); + if (RESULT_OK != result) + { + WSL_CloseConnection(conn); + WSL_DestroyConnection(conn); + + char msg[256]; + + switch (result) + { + case RESULT_FAIL_WSLAY_INIT: dmSnPrintf(msg, sizeof(msg), "Failed to initialize websocket context for %s", url); break; + case RESULT_NOT_CONNECTED: dmSnPrintf(msg, sizeof(msg), "Failed to connect to %s", url); break; + default: dmSnPrintf(msg, sizeof(msg), "Failed to create websocket for %s", url); break; + } + + lua_pushnil(L); + lua_pushstring(L, msg); + return 2; + } + + // long playedTime = luaL_checktable_number(L, 2, "playedTime", -1); + // long progressValue = luaL_checktable_number(L, 2, "progressValue", -1); + // char *description = luaL_checktable_string(L, 2, "description", NULL); + // char *coverImage = luaL_checktable_string(L, 2, "coverImage", NULL); + + conn->m_Callback = dmScript::CreateCallback(L, 3); + + if (g_Websocket.m_Connections.Full()) + g_Websocket.m_Connections.OffsetCapacity(2); + g_Websocket.m_Connections.Push(conn); + + lua_pushlightuserdata(L, conn); + lua_pushnil(L); + return 2; +} + +static int WSL_Lua_Disconnect(lua_State* L) +{ + DM_LUA_STACK_CHECK(L, 0); + + if (!g_Websocket.m_Initialized) + return DM_LUA_ERROR("The web socket module isn't initialized"); + + if (!lua_islightuserdata(L, 1)) + return DM_LUA_ERROR("The first argument must be a valid connection!"); + + WebsocketConnection* conn = (WebsocketConnection*)lua_touserdata(L, 1); + + int i = FindConnection(conn); + if (i != -1) + { + WSL_CloseConnection(conn); + } + return 0; +} + +static int WSL_Lua_Send(lua_State* L) +{ + DM_LUA_STACK_CHECK(L, 0); + + if (!g_Websocket.m_Initialized) + return DM_LUA_ERROR("The web socket module isn't initialized"); + + if (!lua_islightuserdata(L, 1)) + return DM_LUA_ERROR("The first argument must be a valid connection!"); + + WebsocketConnection* conn = (WebsocketConnection*)lua_touserdata(L, 1); + + int i = FindConnection(conn); + if (i == -1) + return DM_LUA_ERROR("Invalid connection"); + + if (conn->m_State != STATE_CONNECTED) + return DM_LUA_ERROR("Connection isn't connected"); + + size_t string_length = 0; + const char* string = luaL_checklstring(L, 2, &string_length); + + int write_mode = WSLAY_BINARY_FRAME; // WSLAY_TEXT_FRAME + + struct wslay_event_msg msg; + msg.opcode = write_mode; + msg.msg = (const uint8_t*)string; + msg.msg_length = string_length; + + wslay_event_queue_msg(conn->m_Ctx, &msg); // it makes a copy of the data + + return 0; +} + +static void HandleCallback(WebsocketConnection* conn, int event, const uint8_t* msg, size_t msg_len) +{ + if (!dmScript::IsCallbackValid(conn->m_Callback)) + return; + + lua_State* L = dmScript::GetCallbackLuaContext(conn->m_Callback); + DM_LUA_STACK_CHECK(L, 0) + + if (!dmScript::SetupCallback(conn->m_Callback)) + { + dmLogError("Failed to setup callback"); + return; + } + + lua_pushlightuserdata(L, conn); + + lua_newtable(L); + + lua_pushinteger(L, event); + lua_setfield(L, -2, "event"); + + lua_pushinteger(L, conn->m_Status); + lua_setfield(L, -2, "status"); + + if (conn->m_Status != RESULT_OK) + { + //lua_pushstring(L, conn->m_ErrorMessage); + lua_pushstring(L, "TODO: Some error"); + lua_setfield(L, -2, "error"); + } + + if (msg != 0) { + lua_pushlstring(L, (const char*)msg, msg_len); + lua_setfield(L, -2, "message"); + } + + dmScript::PCall(L, 3, 0); + + dmScript::TeardownCallback(conn->m_Callback); +} + +#define WSLAY_CASE(_X) case _X: return #_X; + +static const char* WSL_ResultToString(int err) +{ + switch(err) { + WSLAY_CASE(WSLAY_ERR_WANT_READ); + WSLAY_CASE(WSLAY_ERR_WANT_WRITE); + WSLAY_CASE(WSLAY_ERR_PROTO); + WSLAY_CASE(WSLAY_ERR_INVALID_ARGUMENT); + WSLAY_CASE(WSLAY_ERR_INVALID_CALLBACK); + WSLAY_CASE(WSLAY_ERR_NO_MORE_MSG); + WSLAY_CASE(WSLAY_ERR_CALLBACK_FAILURE); + WSLAY_CASE(WSLAY_ERR_WOULDBLOCK); + WSLAY_CASE(WSLAY_ERR_NOMEM); + default: return "Unknown error"; + }; +} + +#undef WSLAY_CASE + +// *************************************************************************************************** +// Life cycle functions + +// Functions exposed to Lua +static const luaL_reg Websocket_module_methods[] = +{ + {"connect", WSL_Lua_Connect}, + {"disconnect", WSL_Lua_Disconnect}, + {"send", WSL_Lua_Send}, + {0, 0} +}; + +static void LuaInit(lua_State* L) +{ + int top = lua_gettop(L); + + // Register lua names + luaL_register(L, MODULE_NAME, Websocket_module_methods); + +#define SETCONSTANT(name, val) \ + lua_pushnumber(L, (lua_Number) val); \ + lua_setfield(L, -2, #name); + + SETCONSTANT(EVENT_CONNECTED, EVENT_CONNECTED); + SETCONSTANT(EVENT_DISCONNECTED, EVENT_DISCONNECTED); + SETCONSTANT(EVENT_MESSAGE, EVENT_MESSAGE); + +#undef SETCONSTANT + + lua_pop(L, 1); + assert(top == lua_gettop(L)); +} + +static dmExtension::Result WebsocketAppInitialize(dmExtension::AppParams* params) +{ + g_Websocket.m_BufferSize = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.buffer_size", 64 * 1024); + g_Websocket.m_Timeout = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.socket_timeout", 250 * 1000); + g_Websocket.m_Connections.SetCapacity(4); + g_Websocket.m_Channel = 0; + g_Websocket.m_Pool = 0; + + dmConnectionPool::Params pool_params; + pool_params.m_MaxConnections = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.max_connections", 2); + dmConnectionPool::Result result = dmConnectionPool::New(&pool_params, &g_Websocket.m_Pool); + + if (dmConnectionPool::RESULT_OK != result) + { + dmLogError("Failed to create connection pool: %d", result); + } + + dmDNS::Result dns_result = dmDNS::NewChannel(&g_Websocket.m_Channel); + + if (dmDNS::RESULT_OK != dns_result) + { + dmLogError("Failed to create connection pool: %s", dmDNS::ResultToString(dns_result)); + } + + g_Websocket.m_Initialized = 1; + if (g_Websocket.m_Channel == 0 || g_Websocket.m_Pool == 0) + { + if (g_Websocket.m_Channel) + dmDNS::DeleteChannel(g_Websocket.m_Channel); + if (g_Websocket.m_Pool) + dmConnectionPool::Delete(g_Websocket.m_Pool); + + g_Websocket.m_Initialized = 0; + } + + return dmExtension::RESULT_OK; +} + +static dmExtension::Result WebsocketInitialize(dmExtension::Params* params) +{ + if (!g_Websocket.m_Initialized) + return dmExtension::RESULT_OK; + + LuaInit(params->m_L); + dmLogInfo("Registered %s extension\n", MODULE_NAME); + + return dmExtension::RESULT_OK; +} + +static dmExtension::Result WebsocketAppFinalize(dmExtension::AppParams* params) +{ + return dmExtension::RESULT_OK; +} + +static dmExtension::Result WebsocketFinalize(dmExtension::Params* params) +{ + return dmExtension::RESULT_OK; +} + +static dmExtension::Result WebsocketOnUpdate(dmExtension::Params* params) +{ + uint32_t size = g_Websocket.m_Connections.Size(); + +#define CLOSE_CONN(MSG, ...) \ + dmLogError(MSG, __VA_ARGS__); \ + WSL_CloseConnection(conn); + + for (uint32_t i = 0; i < size; ++i) + { + WebsocketConnection* conn = g_Websocket.m_Connections[i]; + + if (STATE_DISCONNECTED == conn->m_State) + { + HandleCallback(conn, EVENT_DISCONNECTED, 0, 0); + + g_Websocket.m_Connections.EraseSwap(i); + --i; + --size; + WSL_DestroyConnection(conn); + } + else if (STATE_CONNECTED == conn->m_State) + { + int err = 0; + if ((err = wslay_event_recv(conn->m_Ctx)) != 0 || (err = wslay_event_send(conn->m_Ctx)) != 0) { + dmLogError("Websocket poll error: %s from %s", WSL_ResultToString(err), conn->m_Url.m_Hostname); + } + + if ((wslay_event_get_close_sent(conn->m_Ctx) && wslay_event_get_close_received(conn->m_Ctx))) { + CLOSE_CONN("Websocket received close event for %s", conn->m_Url.m_Hostname); + conn->m_State = STATE_DISCONNECTED; + continue; + } + } + else if (STATE_HANDSHAKE == conn->m_State) + { + // TODO: Split up this state into three? + // e.g. STATE_HANDSHAKE_SEND, STATE_HANDSHAKE_RECEIVE, STATE_HANDSHAKE_VERIFY + + dmSocket::Result socket_result = SendClientHandshake(conn); + if (dmSocket::RESULT_OK != socket_result) + { + CLOSE_CONN("Failed sending handshake: %s", dmSocket::ResultToString(socket_result)); + continue; + } + + Result result = ReceiveHeaders(conn); + if (RESULT_OK != result) + { + CLOSE_CONN("Failed receiving handshake headers. %d", result); + continue; + } + + result = VerifyHeaders(conn); + if (RESULT_OK != result) + { + CLOSE_CONN("Failed verifying handshake headers:\n%s\n\n", conn->m_Response); + continue; + } + + // Currently only supports client implementation + int ret = -1; + ret = wslay_event_context_client_init(&conn->m_Ctx, &g_WslCallbacks, conn); + if (ret == 0) + wslay_event_config_set_max_recv_msg_length(conn->m_Ctx, g_Websocket.m_BufferSize); + if (ret != 0) + { + CLOSE_CONN("Failed initializing wslay: %s", WSL_ResultToString(ret)); + continue; + } + + if (conn->m_Socket) { + dmSocket::SetNoDelay(conn->m_Socket, true); + dmSocket::SetBlocking(conn->m_Socket, false); + dmSocket::SetReceiveTimeout(conn->m_Socket, 500); + } + + conn->m_Response[0] = 0; + conn->m_ResponseSize = 0; + conn->m_State = STATE_CONNECTED; + + HandleCallback(conn, EVENT_CONNECTED, 0, 0); + } + else if (STATE_CONNECTING == conn->m_State) + { + // wait for it to finish + dmSocket::Result socket_result; + dmConnectionPool::Result pool_result = dmConnectionPool::Dial(g_Websocket.m_Pool, conn->m_Url.m_Hostname, conn->m_Url.m_Port, g_Websocket.m_Channel, conn->m_SSL, g_Websocket.m_Timeout, &conn->m_Connection, &socket_result); + if (dmConnectionPool::RESULT_OK != pool_result) + { + CLOSE_CONN("Failed to open connection: %s", dmSocket::ResultToString(socket_result)); + continue; + } + + conn->m_Socket = dmConnectionPool::GetSocket(g_Websocket.m_Pool, conn->m_Connection); + conn->m_State = STATE_HANDSHAKE; + } + } + + return dmExtension::RESULT_OK; +} + +} // dmWebsocket + +DM_DECLARE_EXTENSION(Websocket, LIB_NAME, dmWebsocket::WebsocketAppInitialize, dmWebsocket::WebsocketAppFinalize, dmWebsocket::WebsocketInitialize, dmWebsocket::WebsocketOnUpdate, 0, dmWebsocket::WebsocketFinalize) + diff --git a/websocket/src/wslay/wslay_event.c b/websocket/src/wslay/wslay_event.c new file mode 100644 index 0000000..4aa407a --- /dev/null +++ b/websocket/src/wslay/wslay_event.c @@ -0,0 +1,1027 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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 "wslay_event.h" + +#include +#include +#include + +#include "wslay_queue.h" +#include "wslay_frame.h" +#include "wslay_net.h" +/* Start of utf8 dfa */ +/* Copyright (c) 2008-2010 Bjoern Hoehrmann + * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + * + * Copyright (c) 2008-2009 Bjoern Hoehrmann + * + * 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. + */ +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 12 + +static const uint8_t utf8d[] = { + /* + * The first part of the table maps bytes to character classes that + * to reduce the size of the transition table and create bitmasks. + */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + /* + * The second part is a transition table that maps a combination + * of a state of the automaton and a character class to a state. + */ + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; + +static uint32_t +decode(uint32_t* state, uint32_t* codep, uint32_t byte) { + uint32_t type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +/* End of utf8 dfa */ + +static ssize_t wslay_event_frame_recv_callback(uint8_t *buf, size_t len, + int flags, void *user_data) +{ + struct wslay_event_frame_user_data *e = + (struct wslay_event_frame_user_data*)user_data; + return e->ctx->callbacks.recv_callback(e->ctx, buf, len, flags, e->user_data); +} + +static ssize_t wslay_event_frame_send_callback(const uint8_t *data, size_t len, + int flags, void *user_data) +{ + struct wslay_event_frame_user_data *e = + (struct wslay_event_frame_user_data*)user_data; + return e->ctx->callbacks.send_callback(e->ctx, data, len, flags, + e->user_data); +} + +static int wslay_event_frame_genmask_callback(uint8_t *buf, size_t len, + void *user_data) +{ + struct wslay_event_frame_user_data *e = + (struct wslay_event_frame_user_data*)user_data; + return e->ctx->callbacks.genmask_callback(e->ctx, buf, len, e->user_data); +} + +static int wslay_event_byte_chunk_init +(struct wslay_event_byte_chunk **chunk, size_t len) +{ + *chunk = (struct wslay_event_byte_chunk*)malloc + (sizeof(struct wslay_event_byte_chunk)); + if(*chunk == NULL) { + return WSLAY_ERR_NOMEM; + } + memset(*chunk, 0, sizeof(struct wslay_event_byte_chunk)); + if(len) { + (*chunk)->data = (uint8_t*)malloc(len); + if((*chunk)->data == NULL) { + free(*chunk); + return WSLAY_ERR_NOMEM; + } + (*chunk)->data_length = len; + } + return 0; +} + +static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) +{ + if(!c) { + return; + } + free(c->data); + free(c); +} + +static void wslay_event_byte_chunk_copy(struct wslay_event_byte_chunk *c, + size_t off, + const uint8_t *data, size_t data_length) +{ + memcpy(c->data+off, data, data_length); +} + +static void wslay_event_imsg_set(struct wslay_event_imsg *m, + uint8_t fin, uint8_t rsv, uint8_t opcode) +{ + m->fin = fin; + m->rsv = rsv; + m->opcode = opcode; + m->msg_length = 0; +} + +static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) +{ + if(!m->chunks) { + return; + } + while(!wslay_queue_empty(m->chunks)) { + wslay_event_byte_chunk_free((struct wslay_event_byte_chunk*)wslay_queue_top(m->chunks)); + wslay_queue_pop(m->chunks); + } +} + +static void wslay_event_imsg_reset(struct wslay_event_imsg *m) +{ + m->opcode = 0xffu; + m->utf8state = UTF8_ACCEPT; + wslay_event_imsg_chunks_free(m); +} + +static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, size_t len) +{ + if(len == 0) { + return 0; + } else { + int r; + struct wslay_event_byte_chunk *chunk; + if((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) { + return r; + } + if((r = wslay_queue_push(m->chunks, chunk)) != 0) { + return r; + } + m->msg_length += len; + return 0; + } +} + +static int wslay_event_omsg_non_fragmented_init +(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, + const uint8_t *msg, size_t msg_length) +{ + *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); + if(!*m) { + return WSLAY_ERR_NOMEM; + } + memset(*m, 0, sizeof(struct wslay_event_omsg)); + (*m)->fin = 1; + (*m)->opcode = opcode; + (*m)->rsv = rsv; + (*m)->type = WSLAY_NON_FRAGMENTED; + if(msg_length) { + (*m)->data = (uint8_t*)malloc(msg_length); + if(!(*m)->data) { + free(*m); + return WSLAY_ERR_NOMEM; + } + memcpy((*m)->data, msg, msg_length); + (*m)->data_length = msg_length; + } + return 0; +} + +static int wslay_event_omsg_fragmented_init +(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, + const union wslay_event_msg_source source, + wslay_event_fragmented_msg_callback read_callback) +{ + *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); + if(!*m) { + return WSLAY_ERR_NOMEM; + } + memset(*m, 0, sizeof(struct wslay_event_omsg)); + (*m)->opcode = opcode; + (*m)->rsv = rsv; + (*m)->type = WSLAY_FRAGMENTED; + (*m)->source = source; + (*m)->read_callback = read_callback; + return 0; +} + +static void wslay_event_omsg_free(struct wslay_event_omsg *m) +{ + if(!m) { + return; + } + free(m->data); + free(m); +} + +static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len) +{ + if(len == 0) { + return NULL; + } else { + size_t off = 0; + uint8_t *buf = (uint8_t*)malloc(len); + if(!buf) { + return NULL; + } + while(!wslay_queue_empty(queue)) { + struct wslay_event_byte_chunk *chunk = (struct wslay_event_byte_chunk *)wslay_queue_top(queue); + memcpy(buf+off, chunk->data, chunk->data_length); + off += chunk->data_length; + wslay_event_byte_chunk_free(chunk); + wslay_queue_pop(queue); + assert(off <= len); + } + assert(len == off); + return buf; + } +} + +static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) +{ + return ctx->write_enabled && (ctx->close_status & WSLAY_CLOSE_QUEUED) == 0; +} + +int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, + const uint8_t *reason, size_t reason_length) +{ + if(!wslay_event_is_msg_queueable(ctx)) { + return WSLAY_ERR_NO_MORE_MSG; + } else if(reason_length > 123) { + return WSLAY_ERR_INVALID_ARGUMENT; + } else { + uint8_t msg[128]; + size_t msg_length; + struct wslay_event_msg arg; + uint16_t ncode; + int r; + if(status_code == 0) { + msg_length = 0; + } else { + ncode = htons(status_code); + memcpy(msg, &ncode, 2); + if(reason_length) { + memcpy(msg+2, reason, reason_length); + } + msg_length = reason_length+2; + } + arg.opcode = WSLAY_CONNECTION_CLOSE; + arg.msg = msg; + arg.msg_length = msg_length; + r = wslay_event_queue_msg(ctx, &arg); + if(r == 0) { + ctx->close_status |= WSLAY_CLOSE_QUEUED; + } + return r; + } +} + +static int wslay_event_queue_close_wrapper +(wslay_event_context_ptr ctx, uint16_t status_code, + const uint8_t *reason, size_t reason_length) +{ + int r; + ctx->read_enabled = 0; + if((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) && + r != WSLAY_ERR_NO_MORE_MSG) { + return r; + } + return 0; +} + +static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, uint8_t rsv) +{ + return ((rsv & ~ctx->allowed_rsv_bits) == 0); +} + +int wslay_event_queue_msg(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg) +{ + return wslay_event_queue_msg_ex(ctx, arg, WSLAY_RSV_NONE); +} + +int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg, uint8_t rsv) +{ + int r; + struct wslay_event_omsg *omsg; + if(!wslay_event_is_msg_queueable(ctx)) { + return WSLAY_ERR_NO_MORE_MSG; + } + /* RSV1 is not allowed for control frames */ + if((wslay_is_ctrl_frame(arg->opcode) && + (arg->msg_length > 125 || wslay_get_rsv1(rsv))) + || !wslay_event_verify_rsv_bits(ctx, rsv)) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if((r = wslay_event_omsg_non_fragmented_init + (&omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) { + return r; + } + if(wslay_is_ctrl_frame(arg->opcode)) { + if((r = wslay_queue_push(ctx->send_ctrl_queue, omsg)) != 0) { + return r; + } + } else { + if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { + return r; + } + } + ++ctx->queued_msg_count; + ctx->queued_msg_length += arg->msg_length; + return 0; +} + +int wslay_event_queue_fragmented_msg +(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) +{ + return wslay_event_queue_fragmented_msg_ex(ctx, arg, WSLAY_RSV_NONE); +} + +int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_fragmented_msg *arg, uint8_t rsv) +{ + int r; + struct wslay_event_omsg *omsg; + if(!wslay_event_is_msg_queueable(ctx)) { + return WSLAY_ERR_NO_MORE_MSG; + } + if(wslay_is_ctrl_frame(arg->opcode) || + !wslay_event_verify_rsv_bits(ctx, rsv)) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if((r = wslay_event_omsg_fragmented_init + (&omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) { + return r; + } + if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { + return r; + } + ++ctx->queued_msg_count; + return 0; +} + +void wslay_event_config_set_callbacks +(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks) +{ + ctx->callbacks = *callbacks; +} + +static int wslay_event_context_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) +{ + int i, r; + struct wslay_frame_callbacks frame_callbacks = { + wslay_event_frame_send_callback, + wslay_event_frame_recv_callback, + wslay_event_frame_genmask_callback + }; + *ctx = (wslay_event_context_ptr)malloc(sizeof(struct wslay_event_context)); + if(!*ctx) { + return WSLAY_ERR_NOMEM; + } + memset(*ctx, 0, sizeof(struct wslay_event_context)); + wslay_event_config_set_callbacks(*ctx, callbacks); + (*ctx)->user_data = user_data; + (*ctx)->frame_user_data.ctx = *ctx; + (*ctx)->frame_user_data.user_data = user_data; + if((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, + &(*ctx)->frame_user_data)) != 0) { + wslay_event_context_free(*ctx); + return r; + } + (*ctx)->read_enabled = (*ctx)->write_enabled = 1; + (*ctx)->send_queue = wslay_queue_new(); + if(!(*ctx)->send_queue) { + wslay_event_context_free(*ctx); + return WSLAY_ERR_NOMEM; + } + (*ctx)->send_ctrl_queue = wslay_queue_new(); + if(!(*ctx)->send_ctrl_queue) { + wslay_event_context_free(*ctx); + return WSLAY_ERR_NOMEM; + } + (*ctx)->queued_msg_count = 0; + (*ctx)->queued_msg_length = 0; + for(i = 0; i < 2; ++i) { + wslay_event_imsg_reset(&(*ctx)->imsgs[i]); + (*ctx)->imsgs[i].chunks = wslay_queue_new(); + if(!(*ctx)->imsgs[i].chunks) { + wslay_event_context_free(*ctx); + return WSLAY_ERR_NOMEM; + } + } + (*ctx)->imsg = &(*ctx)->imsgs[0]; + (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf; + (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE; + (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE; + (*ctx)->max_recv_msg_length = (1u << 31)-1; + return 0; +} + +int wslay_event_context_server_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) +{ + int r; + if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + return r; + } + (*ctx)->server = 1; + return 0; +} + +int wslay_event_context_client_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) +{ + int r; + if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + return r; + } + (*ctx)->server = 0; + return 0; +} + +void wslay_event_context_free(wslay_event_context_ptr ctx) +{ + int i; + if(!ctx) { + return; + } + for(i = 0; i < 2; ++i) { + wslay_event_imsg_chunks_free(&ctx->imsgs[i]); + wslay_queue_free(ctx->imsgs[i].chunks); + } + if(ctx->send_queue) { + while(!wslay_queue_empty(ctx->send_queue)) { + wslay_event_omsg_free((struct wslay_event_omsg *)wslay_queue_top(ctx->send_queue)); + wslay_queue_pop(ctx->send_queue); + } + wslay_queue_free(ctx->send_queue); + } + if(ctx->send_ctrl_queue) { + while(!wslay_queue_empty(ctx->send_ctrl_queue)) { + wslay_event_omsg_free((struct wslay_event_omsg *)wslay_queue_top(ctx->send_ctrl_queue)); + wslay_queue_pop(ctx->send_ctrl_queue); + } + wslay_queue_free(ctx->send_ctrl_queue); + } + wslay_frame_context_free(ctx->frame_ctx); + wslay_event_omsg_free(ctx->omsg); + free(ctx); +} + +static void wslay_event_call_on_frame_recv_start_callback +(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) +{ + if(ctx->callbacks.on_frame_recv_start_callback) { + struct wslay_event_on_frame_recv_start_arg arg; + arg.fin = iocb->fin; + arg.rsv = iocb->rsv; + arg.opcode = iocb->opcode; + arg.payload_length = iocb->payload_length; + ctx->callbacks.on_frame_recv_start_callback(ctx, &arg, ctx->user_data); + } +} + +static void wslay_event_call_on_frame_recv_chunk_callback +(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) +{ + if(ctx->callbacks.on_frame_recv_chunk_callback) { + struct wslay_event_on_frame_recv_chunk_arg arg; + arg.data = iocb->data; + arg.data_length = iocb->data_length; + ctx->callbacks.on_frame_recv_chunk_callback(ctx, &arg, ctx->user_data); + } +} + +static void wslay_event_call_on_frame_recv_end_callback +(wslay_event_context_ptr ctx) +{ + if(ctx->callbacks.on_frame_recv_end_callback) { + ctx->callbacks.on_frame_recv_end_callback(ctx, ctx->user_data); + } +} + +static int wslay_event_is_valid_status_code(uint16_t status_code) +{ + return (1000 <= status_code && status_code <= 1011 && + status_code != 1004 && status_code != 1005 && status_code != 1006) || + (3000 <= status_code && status_code <= 4999); +} + +static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) +{ + return (ctx->config & WSLAY_CONFIG_NO_BUFFERING) > 0; +} + +int wslay_event_recv(wslay_event_context_ptr ctx) +{ + struct wslay_frame_iocb iocb; + ssize_t r; + while(ctx->read_enabled) { + memset(&iocb, 0, sizeof(iocb)); + r = wslay_frame_recv(ctx->frame_ctx, &iocb); + if(r >= 0) { + int new_frame = 0; + /* RSV1 is not allowed on control and continuation frames */ + if((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) || + (wslay_get_rsv1(iocb.rsv) && (wslay_is_ctrl_frame(iocb.opcode) || + iocb.opcode == WSLAY_CONTINUATION_FRAME)) || + (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + if(ctx->imsg->opcode == 0xffu) { + if(iocb.opcode == WSLAY_TEXT_FRAME || + iocb.opcode == WSLAY_BINARY_FRAME || + iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || + iocb.opcode == WSLAY_PONG) { + wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); + new_frame = 1; + } else { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + } else if(ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) { + if(iocb.opcode == WSLAY_CONTINUATION_FRAME) { + ctx->imsg->fin = iocb.fin; + } else if(iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || + iocb.opcode == WSLAY_PONG) { + ctx->imsg = &ctx->imsgs[1]; + wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); + } else { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + new_frame = 1; + } + if(new_frame) { + if(ctx->imsg->msg_length+iocb.payload_length > + ctx->max_recv_msg_length) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) { + return r; + } + break; + } + ctx->ipayloadlen = iocb.payload_length; + wslay_event_call_on_frame_recv_start_callback(ctx, &iocb); + if(!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + if((r = wslay_event_imsg_append_chunk(ctx->imsg, + iocb.payload_length)) != 0) { + ctx->read_enabled = 0; + return r; + } + } + } + /* If RSV1 bit is set then it is too early for utf-8 validation */ + if((!wslay_get_rsv1(ctx->imsg->rsv) && + ctx->imsg->opcode == WSLAY_TEXT_FRAME) || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + size_t i; + if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + i = 2; + } else { + i = 0; + } + for(; i < iocb.data_length; ++i) { + uint32_t codep; + if(decode(&ctx->imsg->utf8state, &codep, + iocb.data[i]) == UTF8_REJECT) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { + return r; + } + break; + } + } + } + if(ctx->imsg->utf8state == UTF8_REJECT) { + break; + } + wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb); + if(iocb.data_length > 0) { + if(!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + struct wslay_event_byte_chunk *chunk; + chunk = (struct wslay_event_byte_chunk *)wslay_queue_tail(ctx->imsg->chunks); + wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, + iocb.data, iocb.data_length); + } + ctx->ipayloadoff += iocb.data_length; + } + if(ctx->ipayloadoff == ctx->ipayloadlen) { + if(ctx->imsg->fin && + (ctx->imsg->opcode == WSLAY_TEXT_FRAME || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && + ctx->imsg->utf8state != UTF8_ACCEPT) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { + return r; + } + break; + } + wslay_event_call_on_frame_recv_end_callback(ctx); + if(ctx->imsg->fin) { + if(ctx->callbacks.on_msg_recv_callback || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || + ctx->imsg->opcode == WSLAY_PING) { + struct wslay_event_on_msg_recv_arg arg; + uint16_t status_code = 0; + uint8_t *msg = NULL; + size_t msg_length = 0; + if(!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + msg = wslay_event_flatten_queue(ctx->imsg->chunks, + ctx->imsg->msg_length); + if(ctx->imsg->msg_length && !msg) { + ctx->read_enabled = 0; + return WSLAY_ERR_NOMEM; + } + msg_length = ctx->imsg->msg_length; + } + if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + const uint8_t *reason; + size_t reason_length; + if(ctx->imsg->msg_length >= 2) { + memcpy(&status_code, msg, 2); + status_code = ntohs(status_code); + if(!wslay_event_is_valid_status_code(status_code)) { + free(msg); + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + reason = msg+2; + reason_length = ctx->imsg->msg_length-2; + } else { + reason = NULL; + reason_length = 0; + } + ctx->close_status |= WSLAY_CLOSE_RECEIVED; + ctx->status_code_recv = + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + if((r = wslay_event_queue_close_wrapper + (ctx, status_code, reason, reason_length)) != 0) { + free(msg); + return r; + } + } else if(ctx->imsg->opcode == WSLAY_PING) { + struct wslay_event_msg pong_arg; + pong_arg.opcode = WSLAY_PONG; + pong_arg.msg = msg; + pong_arg.msg_length = ctx->imsg->msg_length; + if((r = wslay_event_queue_msg(ctx, &pong_arg)) && + r != WSLAY_ERR_NO_MORE_MSG) { + ctx->read_enabled = 0; + free(msg); + return r; + } + } + if(ctx->callbacks.on_msg_recv_callback) { + arg.rsv = ctx->imsg->rsv; + arg.opcode = ctx->imsg->opcode; + arg.msg = msg; + arg.msg_length = msg_length; + arg.status_code = status_code; + ctx->error = 0; + ctx->callbacks.on_msg_recv_callback(ctx, &arg, ctx->user_data); + } + free(msg); + } + wslay_event_imsg_reset(ctx->imsg); + if(ctx->imsg == &ctx->imsgs[1]) { + ctx->imsg = &ctx->imsgs[0]; + } + } + ctx->ipayloadlen = ctx->ipayloadoff = 0; + } + } else { + if(r != WSLAY_ERR_WANT_READ || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + if((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) { + return r; + } + return WSLAY_ERR_CALLBACK_FAILURE; + } + break; + } + } + return 0; +} + +static void wslay_event_on_non_fragmented_msg_popped +(wslay_event_context_ptr ctx) +{ + ctx->omsg->fin = 1; + ctx->opayloadlen = ctx->omsg->data_length; + ctx->opayloadoff = 0; +} + +static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop +(wslay_event_context_ptr ctx) +{ + /* + * If Close control frame is queued, we don't send any control frame + * other than Close. + */ + if(ctx->close_status & WSLAY_CLOSE_QUEUED) { + while(!wslay_queue_empty(ctx->send_ctrl_queue)) { + struct wslay_event_omsg *msg = (struct wslay_event_omsg *)wslay_queue_top(ctx->send_ctrl_queue); + wslay_queue_pop(ctx->send_ctrl_queue); + if(msg->opcode == WSLAY_CONNECTION_CLOSE) { + return msg; + } else { + wslay_event_omsg_free(msg); + } + } + return NULL; + } else { + struct wslay_event_omsg *msg = (struct wslay_event_omsg *)wslay_queue_top(ctx->send_ctrl_queue); + wslay_queue_pop(ctx->send_ctrl_queue); + return msg; + } +} + +int wslay_event_send(wslay_event_context_ptr ctx) +{ + struct wslay_frame_iocb iocb; + ssize_t r; + while(ctx->write_enabled && + (!wslay_queue_empty(ctx->send_queue) || + !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg)) { + if(!ctx->omsg) { + if(wslay_queue_empty(ctx->send_ctrl_queue)) { + ctx->omsg = (struct wslay_event_omsg *)wslay_queue_top(ctx->send_queue); + wslay_queue_pop(ctx->send_queue); + } else { + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if(ctx->omsg == NULL) { + break; + } + } + if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + wslay_event_on_non_fragmented_msg_popped(ctx); + } + } else if(!wslay_is_ctrl_frame(ctx->omsg->opcode) && + ctx->frame_ctx->ostate == PREP_HEADER && + !wslay_queue_empty(ctx->send_ctrl_queue)) { + if((r = wslay_queue_push_front(ctx->send_queue, ctx->omsg)) != 0) { + ctx->write_enabled = 0; + return r; + } + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if(ctx->omsg == NULL) { + break; + } + /* ctrl message has WSLAY_NON_FRAGMENTED */ + wslay_event_on_non_fragmented_msg_popped(ctx); + } + if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; + iocb.mask = ctx->server^1; + iocb.data = ctx->omsg->data+ctx->opayloadoff; + iocb.data_length = ctx->opayloadlen-ctx->opayloadoff; + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_send(ctx->frame_ctx, &iocb); + if(r >= 0) { + ctx->opayloadoff += r; + if(ctx->opayloadoff == ctx->opayloadlen) { + --ctx->queued_msg_count; + ctx->queued_msg_length -= ctx->omsg->data_length; + if(ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { + uint16_t status_code = 0; + ctx->write_enabled = 0; + ctx->close_status |= WSLAY_CLOSE_SENT; + if(ctx->omsg->data_length >= 2) { + memcpy(&status_code, ctx->omsg->data, 2); + status_code = ntohs(status_code); + } + ctx->status_code_sent = + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + } + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + break; + } + } else { + if(r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + break; + } + } else { + if(ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { + int eof = 0; + r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), + &ctx->omsg->source, + &eof, ctx->user_data); + if(r == 0 && eof == 0) { + break; + } else if(r < 0) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + ctx->obuflimit = ctx->obuf+r; + if(eof) { + ctx->omsg->fin = 1; + } + ctx->opayloadlen = r; + ctx->opayloadoff = 0; + } + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = ctx->omsg->fin; + iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; + iocb.mask = ctx->server ? 0 : 1; + iocb.data = ctx->obufmark; + iocb.data_length = ctx->obuflimit-ctx->obufmark; + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_send(ctx->frame_ctx, &iocb); + if(r >= 0) { + ctx->obufmark += r; + if(ctx->obufmark == ctx->obuflimit) { + ctx->obufmark = ctx->obuflimit = ctx->obuf; + if(ctx->omsg->fin) { + --ctx->queued_msg_count; + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME; + /* RSV1 is not set on continuation frames */ + ctx->omsg->rsv = ctx->omsg->rsv & ~WSLAY_RSV1_BIT; + } + } else { + break; + } + } else { + if(r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && + ctx->error != 0)) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + break; + } + } + } + return 0; +} + +void wslay_event_set_error(wslay_event_context_ptr ctx, int val) +{ + ctx->error = val; +} + +int wslay_event_want_read(wslay_event_context_ptr ctx) +{ + return ctx->read_enabled; +} + +int wslay_event_want_write(wslay_event_context_ptr ctx) +{ + return ctx->write_enabled && + (!wslay_queue_empty(ctx->send_queue) || + !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg); +} + +void wslay_event_shutdown_read(wslay_event_context_ptr ctx) +{ + ctx->read_enabled = 0; +} + +void wslay_event_shutdown_write(wslay_event_context_ptr ctx) +{ + ctx->write_enabled = 0; +} + +int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) +{ + return ctx->read_enabled; +} + +int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) +{ + return ctx->write_enabled; +} + +int wslay_event_get_close_received(wslay_event_context_ptr ctx) +{ + return (ctx->close_status & WSLAY_CLOSE_RECEIVED) > 0; +} + +int wslay_event_get_close_sent(wslay_event_context_ptr ctx) +{ + return (ctx->close_status & WSLAY_CLOSE_SENT) > 0; +} + +void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv) +{ + /* We currently only allow WSLAY_RSV1_BIT or WSLAY_RSV_NONE */ + ctx->allowed_rsv_bits = rsv & WSLAY_RSV1_BIT; +} + +void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) +{ + if(val) { + ctx->config |= WSLAY_CONFIG_NO_BUFFERING; + } else { + ctx->config &= ~WSLAY_CONFIG_NO_BUFFERING; + } +} + +void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, + uint64_t val) +{ + ctx->max_recv_msg_length = val; +} + +uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) +{ + return ctx->status_code_recv; +} + +uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) +{ + return ctx->status_code_sent; +} + +size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) +{ + return ctx->queued_msg_count; +} + +size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) +{ + return ctx->queued_msg_length; +} diff --git a/websocket/src/wslay/wslay_frame.c b/websocket/src/wslay/wslay_frame.c new file mode 100644 index 0000000..445e750 --- /dev/null +++ b/websocket/src/wslay/wslay_frame.c @@ -0,0 +1,340 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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 "wslay_frame.h" + +#include +#include +#include + +#include "wslay_net.h" + +#define wslay_min(A, B) (((A) < (B)) ? (A) : (B)) + +int wslay_frame_context_init(wslay_frame_context_ptr *ctx, + const struct wslay_frame_callbacks *callbacks, + void *user_data) +{ + *ctx = (wslay_frame_context_ptr)malloc(sizeof(struct wslay_frame_context)); + if(*ctx == NULL) { + return -1; + } + memset(*ctx, 0, sizeof(struct wslay_frame_context)); + (*ctx)->istate = RECV_HEADER1; + (*ctx)->ireqread = 2; + (*ctx)->ostate = PREP_HEADER; + (*ctx)->user_data = user_data; + (*ctx)->ibufmark = (*ctx)->ibuflimit = (*ctx)->ibuf; + (*ctx)->callbacks = *callbacks; + return 0; +} + +void wslay_frame_context_free(wslay_frame_context_ptr ctx) +{ + free(ctx); +} + +ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb) +{ + if(iocb->data_length > iocb->payload_length) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if(ctx->ostate == PREP_HEADER) { + uint8_t *hdptr = ctx->oheader; + memset(ctx->oheader, 0, sizeof(ctx->oheader)); + *hdptr |= (iocb->fin << 7) & 0x80u; + *hdptr |= (iocb->rsv << 4) & 0x70u; + *hdptr |= iocb->opcode & 0xfu; + ++hdptr; + *hdptr |= (iocb->mask << 7) & 0x80u; + if(wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if(iocb->payload_length < 126) { + *hdptr |= iocb->payload_length; + ++hdptr; + } else if(iocb->payload_length < (1 << 16)) { + uint16_t len = htons(iocb->payload_length); + *hdptr |= 126; + ++hdptr; + memcpy(hdptr, &len, 2); + hdptr += 2; + } else if(iocb->payload_length < (1ull << 63)) { + uint64_t len = hton64(iocb->payload_length); + *hdptr |= 127; + ++hdptr; + memcpy(hdptr, &len, 8); + hdptr += 8; + } else { + /* Too large payload length */ + return WSLAY_ERR_INVALID_ARGUMENT; + } + if(iocb->mask) { + if(ctx->callbacks.genmask_callback(ctx->omaskkey, 4, + ctx->user_data) != 0) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->omask = 1; + memcpy(hdptr, ctx->omaskkey, 4); + hdptr += 4; + } + } + ctx->ostate = SEND_HEADER; + ctx->oheadermark = ctx->oheader; + ctx->oheaderlimit = hdptr; + ctx->opayloadlen = iocb->payload_length; + ctx->opayloadoff = 0; + } + if(ctx->ostate == SEND_HEADER) { + ptrdiff_t len = ctx->oheaderlimit-ctx->oheadermark; + ssize_t r; + int flags = 0; + if(iocb->data_length > 0) { + flags |= WSLAY_MSG_MORE; + }; + r = ctx->callbacks.send_callback(ctx->oheadermark, len, flags, + ctx->user_data); + if(r > 0) { + if(r > len) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->oheadermark += r; + if(ctx->oheadermark == ctx->oheaderlimit) { + ctx->ostate = SEND_PAYLOAD; + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + if(ctx->ostate == SEND_PAYLOAD) { + size_t totallen = 0; + if(iocb->data_length > 0) { + if(ctx->omask) { + uint8_t temp[4096]; + const uint8_t *datamark = iocb->data, + *datalimit = iocb->data+iocb->data_length; + while(datamark < datalimit) { + size_t datalen = datalimit - datamark; + const uint8_t *writelimit = datamark+ + wslay_min(sizeof(temp), datalen); + size_t writelen = writelimit-datamark; + ssize_t r; + size_t i; + for(i = 0; i < writelen; ++i) { + temp[i] = datamark[i]^ctx->omaskkey[(ctx->opayloadoff+i)%4]; + } + r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data); + if(r > 0) { + if((size_t)r > writelen) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + datamark += r; + ctx->opayloadoff += r; + totallen += r; + } + } else { + if(totallen > 0) { + break; + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + } + } else { + ssize_t r; + r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0, + ctx->user_data); + if(r > 0) { + if((size_t)r > iocb->data_length) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->opayloadoff += r; + totallen = r; + } + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + } + if(ctx->opayloadoff == ctx->opayloadlen) { + ctx->ostate = PREP_HEADER; + } + return totallen; + } + return WSLAY_ERR_INVALID_ARGUMENT; +} + +static void wslay_shift_ibuf(wslay_frame_context_ptr ctx) +{ + ptrdiff_t len = ctx->ibuflimit-ctx->ibufmark; + memmove(ctx->ibuf, ctx->ibufmark, len); + ctx->ibuflimit = ctx->ibuf+len; + ctx->ibufmark = ctx->ibuf; +} + +static ssize_t wslay_recv(wslay_frame_context_ptr ctx) +{ + ssize_t r; + if(ctx->ibufmark != ctx->ibuf) { + wslay_shift_ibuf(ctx); + } + r = ctx->callbacks.recv_callback + (ctx->ibuflimit, ctx->ibuf+sizeof(ctx->ibuf)-ctx->ibuflimit, + 0, ctx->user_data); + if(r > 0) { + ctx->ibuflimit += r; + } else { + r = WSLAY_ERR_WANT_READ; + } + return r; +} + +#define WSLAY_AVAIL_IBUF(ctx) ((size_t)(ctx->ibuflimit - ctx->ibufmark)) + +ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb) +{ + ssize_t r; + if(ctx->istate == RECV_HEADER1) { + uint8_t fin, opcode, rsv, payloadlen; + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + } + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + return WSLAY_ERR_WANT_READ; + } + fin = (ctx->ibufmark[0] >> 7) & 1; + rsv = (ctx->ibufmark[0] >> 4) & 7; + opcode = ctx->ibufmark[0] & 0xfu; + ctx->iom.opcode = opcode; + ctx->iom.fin = fin; + ctx->iom.rsv = rsv; + ++ctx->ibufmark; + ctx->imask = (ctx->ibufmark[0] >> 7) & 1; + payloadlen = ctx->ibufmark[0] & 0x7fu; + ++ctx->ibufmark; + if(wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) { + return WSLAY_ERR_PROTO; + } + if(payloadlen == 126) { + ctx->istate = RECV_EXT_PAYLOADLEN; + ctx->ireqread = 2; + } else if(payloadlen == 127) { + ctx->istate = RECV_EXT_PAYLOADLEN; + ctx->ireqread = 8; + } else { + ctx->ipayloadlen = payloadlen; + ctx->ipayloadoff = 0; + if(ctx->imask) { + ctx->istate = RECV_MASKKEY; + ctx->ireqread = 4; + } else { + ctx->istate = RECV_PAYLOAD; + } + } + } + if(ctx->istate == RECV_EXT_PAYLOADLEN) { + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + return WSLAY_ERR_WANT_READ; + } + } + ctx->ipayloadlen = 0; + ctx->ipayloadoff = 0; + memcpy((uint8_t*)&ctx->ipayloadlen+(8-ctx->ireqread), + ctx->ibufmark, ctx->ireqread); + ctx->ipayloadlen = ntoh64(ctx->ipayloadlen); + ctx->ibufmark += ctx->ireqread; + if(ctx->ireqread == 8) { + if(ctx->ipayloadlen < (1 << 16) || + ctx->ipayloadlen & (1ull << 63)) { + return WSLAY_ERR_PROTO; + } + } else if(ctx->ipayloadlen < 126) { + return WSLAY_ERR_PROTO; + } + if(ctx->imask) { + ctx->istate = RECV_MASKKEY; + ctx->ireqread = 4; + } else { + ctx->istate = RECV_PAYLOAD; + } + } + if(ctx->istate == RECV_MASKKEY) { + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + return WSLAY_ERR_WANT_READ; + } + } + memcpy(ctx->imaskkey, ctx->ibufmark, 4); + ctx->ibufmark += 4; + ctx->istate = RECV_PAYLOAD; + } + if(ctx->istate == RECV_PAYLOAD) { + uint8_t *readlimit, *readmark; + uint64_t rempayloadlen = ctx->ipayloadlen-ctx->ipayloadoff; + if(WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + } + readmark = ctx->ibufmark; + readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen ? + ctx->ibuflimit : ctx->ibufmark+rempayloadlen; + if(ctx->imask) { + for(; ctx->ibufmark != readlimit; + ++ctx->ibufmark, ++ctx->ipayloadoff) { + ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4]; + } + } else { + ctx->ibufmark = readlimit; + ctx->ipayloadoff += readlimit-readmark; + } + iocb->fin = ctx->iom.fin; + iocb->rsv = ctx->iom.rsv; + iocb->opcode = ctx->iom.opcode; + iocb->payload_length = ctx->ipayloadlen; + iocb->mask = ctx->imask; + iocb->data = readmark; + iocb->data_length = ctx->ibufmark-readmark; + if(ctx->ipayloadlen == ctx->ipayloadoff) { + ctx->istate = RECV_HEADER1; + ctx->ireqread = 2; + } + return iocb->data_length; + } + return WSLAY_ERR_INVALID_ARGUMENT; +} diff --git a/websocket/src/wslay/wslay_net.c b/websocket/src/wslay/wslay_net.c new file mode 100644 index 0000000..d3867c2 --- /dev/null +++ b/websocket/src/wslay/wslay_net.c @@ -0,0 +1,36 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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 "wslay_net.h" + +#ifndef WORDS_BIGENDIAN + +uint64_t wslay_byteswap64(uint64_t x) +{ + uint64_t u = ntohl(x & 0xffffffffllu); + uint64_t l = ntohl(x >> 32); + return (u << 32) | l; +} + +#endif /* !WORDS_BIGENDIAN */ diff --git a/websocket/src/wslay/wslay_queue.c b/websocket/src/wslay/wslay_queue.c new file mode 100644 index 0000000..8d26696 --- /dev/null +++ b/websocket/src/wslay/wslay_queue.c @@ -0,0 +1,117 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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 "wslay_queue.h" + +#include +#include + +struct wslay_queue* wslay_queue_new(void) +{ + struct wslay_queue *queue = (struct wslay_queue*)malloc + (sizeof(struct wslay_queue)); + if(!queue) { + return NULL; + } + queue->top = queue->tail = NULL; + return queue; +} + +void wslay_queue_free(struct wslay_queue *queue) +{ + if(!queue) { + return; + } else { + struct wslay_queue_cell *p = queue->top; + while(p) { + struct wslay_queue_cell *next = p->next; + free(p); + p = next; + } + free(queue); + } +} + +int wslay_queue_push(struct wslay_queue *queue, void *data) +{ + struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc + (sizeof(struct wslay_queue_cell)); + if(!new_cell) { + return WSLAY_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = NULL; + if(queue->tail) { + queue->tail->next = new_cell; + queue->tail = new_cell; + + } else { + queue->top = queue->tail = new_cell; + } + return 0; +} + +int wslay_queue_push_front(struct wslay_queue *queue, void *data) +{ + struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc + (sizeof(struct wslay_queue_cell)); + if(!new_cell) { + return WSLAY_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = queue->top; + queue->top = new_cell; + if(!queue->tail) { + queue->tail = queue->top; + } + return 0; +} + +void wslay_queue_pop(struct wslay_queue *queue) +{ + struct wslay_queue_cell *top = queue->top; + assert(top); + queue->top = top->next; + if(top == queue->tail) { + queue->tail = NULL; + } + free(top); +} + +void* wslay_queue_top(struct wslay_queue *queue) +{ + assert(queue->top); + return queue->top->data; +} + +void* wslay_queue_tail(struct wslay_queue *queue) +{ + assert(queue->tail); + return queue->tail->data; +} + +int wslay_queue_empty(struct wslay_queue *queue) +{ + return queue->top == NULL; +} diff --git a/websocket/src/wslay/wslay_stack.c b/websocket/src/wslay/wslay_stack.c new file mode 100644 index 0000000..0e05d74 --- /dev/null +++ b/websocket/src/wslay/wslay_stack.c @@ -0,0 +1,86 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * 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 "wslay_stack.h" + +#include +#include + +struct wslay_stack* wslay_stack_new() +{ + struct wslay_stack *stack = (struct wslay_stack*)malloc + (sizeof(struct wslay_stack)); + if(!stack) { + return NULL; + } + stack->top = NULL; + return stack; +} + +void wslay_stack_free(struct wslay_stack *stack) +{ + struct wslay_stack_cell *p; + if(!stack) { + return; + } + p = stack->top; + while(p) { + struct wslay_stack_cell *next = p->next; + free(p); + p = next; + } + free(stack); +} + +int wslay_stack_push(struct wslay_stack *stack, void *data) +{ + struct wslay_stack_cell *new_cell = (struct wslay_stack_cell*)malloc + (sizeof(struct wslay_stack_cell)); + if(!new_cell) { + return WSLAY_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = stack->top; + stack->top = new_cell; + return 0; +} + +void wslay_stack_pop(struct wslay_stack *stack) +{ + struct wslay_stack_cell *top = stack->top; + assert(top); + stack->top = top->next; + free(top); +} + +void* wslay_stack_top(struct wslay_stack *stack) +{ + assert(stack->top); + return stack->top->data; +} + +int wslay_stack_empty(struct wslay_stack *stack) +{ + return stack->top == NULL; +}