/** @file @brief Websocket private header This is not to be included by the application. */ /* * Copyright (c) 2019 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #define WS_SHA1_OUTPUT_LEN 20 /* Min Websocket header length */ #define MIN_HEADER_LEN 2 /* Max Websocket header length */ #define MAX_HEADER_LEN 14 /* From RFC 6455 chapter 4.2.2 */ #define WS_MAGIC "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" /** * Websocket parser states */ enum websocket_parser_state { WEBSOCKET_PARSER_STATE_OPCODE, WEBSOCKET_PARSER_STATE_LENGTH, WEBSOCKET_PARSER_STATE_EXT_LEN, WEBSOCKET_PARSER_STATE_MASK, WEBSOCKET_PARSER_STATE_PAYLOAD, }; /** * Description of external buffers for payload and receiving */ struct websocket_buffer { /* external buffer */ uint8_t *buf; /* size of external buffer */ size_t size; /* data length in external buffer */ size_t count; }; /** * Websocket connection information */ __net_socket struct websocket_context { union { /** User data. */ void *user_data; /** This is used during HTTP handshake to verify that the * peer sent proper Sec-WebSocket-Accept key. */ uint8_t *sec_accept_key; }; /** Reference count. */ atomic_t refcount; /** Internal lock for protecting this context from multiple access. */ struct k_mutex lock; /* The socket number is valid only after HTTP handshake is done * so we can share the memory for these. */ union { /** HTTP parser settings for the application usage */ const struct http_parser_settings *http_cb; /** The Websocket socket id. If data is sent via this socket, it * will automatically add Websocket headers etc into the data. */ int sock; }; /** Buffer for receiving from TCP socket. * This buffer used for HTTP handshakes and Websocket packet parser. * User must provide the actual buffer where the data are * stored temporarily. */ struct websocket_buffer recv_buf; /** The real TCP socket to use when sending Websocket data to peer. */ int real_sock; /** Websocket connection masking value */ uint32_t masking_value; /** Message length */ uint64_t message_len; /** Message type */ uint32_t message_type; /** Parser remaining length in current state */ uint64_t parser_remaining; /** Parser state */ enum websocket_parser_state parser_state; /** Is the message masked */ uint8_t masked : 1; /** Did we receive Sec-WebSocket-Accept: field */ uint8_t sec_accept_present : 1; /** Is Sec-WebSocket-Accept field correct */ uint8_t sec_accept_ok : 1; /** Did we receive all from peer during HTTP handshake */ uint8_t all_received : 1; }; #if defined(CONFIG_NET_TEST) /** * Websocket unit test does not use socket layer but feeds * the data directly here when testing this function. */ struct test_data { /** pointer to data "tx" buffer */ uint8_t *input_buf; /** "tx" buffer data length */ size_t input_len; /** "tx" buffer read (recv) position */ size_t input_pos; /** external test context */ struct websocket_context *ctx; }; #endif /* CONFIG_NET_TEST */ /** * @brief Disconnect the Websocket. * * @param sock Websocket id returned by websocket_connect() call. * * @return 0 if ok, <0 if error */ int websocket_disconnect(int sock); /** * @typedef websocket_context_cb_t * @brief Callback used while iterating over websocket contexts * * @param context A valid pointer on current websocket context * @param user_data A valid pointer on some user data or NULL */ typedef void (*websocket_context_cb_t)(struct websocket_context *ctx, void *user_data); /** * @brief Iterate over websocket context. This is mainly used by net-shell * to show information about websockets. * * @param cb Websocket context callback * @param user_data Caller specific data. */ void websocket_context_foreach(websocket_context_cb_t cb, void *user_data);