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_ */
|