Line data Source code
1 1 : /** @file 2 : * @brief Websocket API 3 : * 4 : * An API for applications to setup websocket connections 5 : */ 6 : 7 : /* 8 : * Copyright (c) 2019 Intel Corporation 9 : * 10 : * SPDX-License-Identifier: Apache-2.0 11 : */ 12 : 13 : #ifndef ZEPHYR_INCLUDE_NET_WEBSOCKET_H_ 14 : #define ZEPHYR_INCLUDE_NET_WEBSOCKET_H_ 15 : 16 : #include <zephyr/kernel.h> 17 : 18 : #include <zephyr/net/net_ip.h> 19 : #include <zephyr/net/http/parser.h> 20 : #include <zephyr/net/http/client.h> 21 : 22 : #ifdef __cplusplus 23 : extern "C" { 24 : #endif 25 : 26 : /** 27 : * @brief Websocket API 28 : * @defgroup websocket Websocket API 29 : * @since 1.12 30 : * @version 0.1.0 31 : * @ingroup networking 32 : * @{ 33 : */ 34 : 35 : /** Message type values. Returned in websocket_recv_msg() */ 36 1 : #define WEBSOCKET_FLAG_FINAL 0x00000001 /**< Final frame */ 37 1 : #define WEBSOCKET_FLAG_TEXT 0x00000002 /**< Textual data */ 38 1 : #define WEBSOCKET_FLAG_BINARY 0x00000004 /**< Binary data */ 39 1 : #define WEBSOCKET_FLAG_CLOSE 0x00000008 /**< Closing connection */ 40 1 : #define WEBSOCKET_FLAG_PING 0x00000010 /**< Ping message */ 41 1 : #define WEBSOCKET_FLAG_PONG 0x00000020 /**< Pong message */ 42 : 43 : /** @brief Websocket option codes */ 44 1 : enum websocket_opcode { 45 : WEBSOCKET_OPCODE_CONTINUE = 0x00, /**< Message continues */ 46 : WEBSOCKET_OPCODE_DATA_TEXT = 0x01, /**< Textual data */ 47 : WEBSOCKET_OPCODE_DATA_BINARY = 0x02, /**< Binary data */ 48 : WEBSOCKET_OPCODE_CLOSE = 0x08, /**< Closing connection */ 49 : WEBSOCKET_OPCODE_PING = 0x09, /**< Ping message */ 50 : WEBSOCKET_OPCODE_PONG = 0x0A, /**< Pong message */ 51 : }; 52 : 53 : /** 54 : * @typedef websocket_connect_cb_t 55 : * @brief Callback called after Websocket connection is established. 56 : * 57 : * @param ws_sock Websocket id 58 : * @param req HTTP handshake request 59 : * @param user_data A valid pointer on some user data or NULL 60 : * 61 : * @return 0 if ok, <0 if there is an error and connection should be aborted 62 : */ 63 1 : typedef int (*websocket_connect_cb_t)(int ws_sock, struct http_request *req, 64 : void *user_data); 65 : 66 : /** 67 : * Websocket client connection request. This contains all the data that is 68 : * needed when doing a Websocket connection request. 69 : */ 70 1 : struct websocket_request { 71 : /** Host of the Websocket server when doing HTTP handshakes. */ 72 1 : const char *host; 73 : 74 : /** URL of the Websocket. */ 75 1 : const char *url; 76 : 77 : /** User supplied callback function to call when optional headers need 78 : * to be sent. This can be NULL, in which case the optional_headers 79 : * field in http_request is used. The idea of this optional_headers 80 : * callback is to allow user to send more HTTP header data that is 81 : * practical to store in allocated memory. 82 : */ 83 1 : http_header_cb_t optional_headers_cb; 84 : 85 : /** A NULL terminated list of any optional headers that 86 : * should be added to the HTTP request. May be NULL. 87 : * If the optional_headers_cb is specified, then this field is ignored. 88 : */ 89 1 : const char **optional_headers; 90 : 91 : /** User supplied callback function to call when a connection is 92 : * established. 93 : */ 94 1 : websocket_connect_cb_t cb; 95 : 96 : /** User supplied list of callback functions if the calling application 97 : * wants to know the parsing status or the HTTP fields during the 98 : * handshake. This is optional parameter and normally not needed but 99 : * is useful if the caller wants to know something about 100 : * the fields that the server is sending. 101 : */ 102 1 : const struct http_parser_settings *http_cb; 103 : 104 : /** User supplied buffer where HTTP connection data is stored */ 105 1 : uint8_t *tmp_buf; 106 : 107 : /** Length of the user supplied temp buffer */ 108 1 : size_t tmp_buf_len; 109 : }; 110 : 111 : /** 112 : * @brief Connect to a server that provides Websocket service. The callback is 113 : * called after connection is established. The returned value is a new socket 114 : * descriptor that can be used to send / receive data using the BSD socket API. 115 : * 116 : * @param http_sock Socket id to the server. Note that this socket is used to do 117 : * HTTP handshakes etc. The actual Websocket connectivity is done via the 118 : * returned websocket id. Note that the http_sock must not be closed 119 : * after this function returns as it is used to deliver the Websocket 120 : * packets to the Websocket server. 121 : * @param req Websocket request. User should allocate and fill the request 122 : * data. 123 : * @param timeout Max timeout to wait for the connection. The timeout value is 124 : * in milliseconds. Value SYS_FOREVER_MS means to wait forever. 125 : * @param user_data User specified data that is passed to the callback. 126 : * 127 : * @return Websocket id to be used when sending/receiving Websocket data. 128 : */ 129 1 : int websocket_connect(int http_sock, struct websocket_request *req, 130 : int32_t timeout, void *user_data); 131 : 132 : /** 133 : * @brief Send websocket msg to peer. 134 : * 135 : * @details The function will automatically add websocket header to the 136 : * message. 137 : * 138 : * @param ws_sock Websocket id returned by websocket_connect(). 139 : * @param payload Websocket data to send. 140 : * @param payload_len Length of the data to be sent. 141 : * @param opcode Operation code (text, binary, ping, pong, close) 142 : * @param mask Mask the data, see RFC 6455 for details 143 : * @param final Is this final message for this message send. If final == false, 144 : * then the first message must have valid opcode and subsequent messages 145 : * must have opcode WEBSOCKET_OPCODE_CONTINUE. If final == true and this 146 : * is the only message, then opcode should have proper opcode (text or 147 : * binary) set. 148 : * @param timeout How long to try to send the message. The value is in 149 : * milliseconds. Value SYS_FOREVER_MS means to wait forever. 150 : * 151 : * @return <0 if error, >=0 amount of bytes sent 152 : */ 153 1 : int websocket_send_msg(int ws_sock, const uint8_t *payload, size_t payload_len, 154 : enum websocket_opcode opcode, bool mask, bool final, 155 : int32_t timeout); 156 : 157 : /** 158 : * @brief Receive websocket msg from peer. 159 : * 160 : * @details The function will automatically remove websocket header from the 161 : * message. 162 : * 163 : * @param ws_sock Websocket id returned by websocket_connect(). 164 : * @param buf Buffer where websocket data is read. 165 : * @param buf_len Length of the data buffer. 166 : * @param message_type Type of the message. 167 : * @param remaining How much there is data left in the message after this read. 168 : * @param timeout How long to try to receive the message. 169 : * The value is in milliseconds. Value SYS_FOREVER_MS means to wait 170 : * forever. 171 : * 172 : * @retval >=0 amount of bytes received. 173 : * @retval -EAGAIN on timeout. 174 : * @retval -ENOTCONN on socket close. 175 : * @retval -errno other negative errno value in case of failure. 176 : */ 177 1 : int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len, 178 : uint32_t *message_type, uint64_t *remaining, 179 : int32_t timeout); 180 : 181 : /** 182 : * @brief Close websocket. 183 : * 184 : * @details One must call websocket_connect() after this call to re-establish 185 : * the connection. 186 : * 187 : * @param ws_sock Websocket id returned by websocket_connect(). 188 : * 189 : * @return <0 if error, 0 the connection was closed successfully 190 : */ 191 1 : int websocket_disconnect(int ws_sock); 192 : 193 : /** 194 : * @brief Register a socket as websocket. This is called by HTTP server 195 : * when a connection is upgraded to a websocket connection. 196 : * 197 : * @param http_sock Underlying socket connection socket. 198 : * @param recv_buf Temporary receive buffer for websocket parsing. This must 199 : * point to a memory area that is valid for the duration of the whole 200 : * websocket session. 201 : * @param recv_buf_len Length of the temporary receive buffer. 202 : * 203 : * @return <0 if error, >=0 the actual websocket to be used by application 204 : */ 205 1 : int websocket_register(int http_sock, uint8_t *recv_buf, size_t recv_buf_len); 206 : 207 : /** 208 : * @brief Unregister a websocket. This is called when we no longer need 209 : * the underlying "real" socket. This will close first the websocket 210 : * and then the original socket. 211 : * 212 : * @param ws_sock Websocket connection socket. 213 : * 214 : * @return <0 if error, 0 the websocket connection is now fully closed 215 : */ 216 1 : int websocket_unregister(int ws_sock); 217 : 218 : /** @cond INTERNAL_HIDDEN */ 219 : 220 : #if defined(CONFIG_WEBSOCKET_CLIENT) 221 : void websocket_init(void); 222 : #else 223 : static inline void websocket_init(void) 224 : { 225 : } 226 : #endif 227 : 228 : /** @endcond */ 229 : 230 : #ifdef __cplusplus 231 : } 232 : #endif 233 : 234 : /** 235 : * @} 236 : */ 237 : 238 : #endif /* ZEPHYR_INCLUDE_NET_WEBSOCKET_H_ */