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 * @ingroup networking
30 * @{
31 */
32
33 /** Message type values. Returned in websocket_recv_msg() */
34 #define WEBSOCKET_FLAG_FINAL 0x00000001 /**< Final frame */
35 #define WEBSOCKET_FLAG_TEXT 0x00000002 /**< Textual data */
36 #define WEBSOCKET_FLAG_BINARY 0x00000004 /**< Binary data */
37 #define WEBSOCKET_FLAG_CLOSE 0x00000008 /**< Closing connection */
38 #define WEBSOCKET_FLAG_PING 0x00000010 /**< Ping message */
39 #define WEBSOCKET_FLAG_PONG 0x00000020 /**< Pong message */
40
41 enum websocket_opcode {
42 WEBSOCKET_OPCODE_CONTINUE = 0x00,
43 WEBSOCKET_OPCODE_DATA_TEXT = 0x01,
44 WEBSOCKET_OPCODE_DATA_BINARY = 0x02,
45 WEBSOCKET_OPCODE_CLOSE = 0x08,
46 WEBSOCKET_OPCODE_PING = 0x09,
47 WEBSOCKET_OPCODE_PONG = 0x0A,
48 };
49
50 /**
51 * @typedef websocket_connect_cb_t
52 * @brief Callback called after Websocket connection is established.
53 *
54 * @param ws_sock Websocket id
55 * @param req HTTP handshake request
56 * @param user_data A valid pointer on some user data or NULL
57 *
58 * @return 0 if ok, <0 if there is an error and connection should be aborted
59 */
60 typedef int (*websocket_connect_cb_t)(int ws_sock, struct http_request *req,
61 void *user_data);
62
63 /**
64 * Websocket client connection request. This contains all the data that is
65 * needed when doing a Websocket connection request.
66 */
67 struct websocket_request {
68 /** Host of the Websocket server when doing HTTP handshakes. */
69 const char *host;
70
71 /** URL of the Websocket. */
72 const char *url;
73
74 /** User supplied callback function to call when optional headers need
75 * to be sent. This can be NULL, in which case the optional_headers
76 * field in http_request is used. The idea of this optional_headers
77 * callback is to allow user to send more HTTP header data that is
78 * practical to store in allocated memory.
79 */
80 http_header_cb_t optional_headers_cb;
81
82 /** A NULL terminated list of any optional headers that
83 * should be added to the HTTP request. May be NULL.
84 * If the optional_headers_cb is specified, then this field is ignored.
85 */
86 const char **optional_headers;
87
88 /** User supplied callback function to call when a connection is
89 * established.
90 */
91 websocket_connect_cb_t cb;
92
93 /** User supplied list of callback functions if the calling application
94 * wants to know the parsing status or the HTTP fields during the
95 * handshake. This is optional parameter and normally not needed but
96 * is useful if the caller wants to know something about
97 * the fields that the server is sending.
98 */
99 const struct http_parser_settings *http_cb;
100
101 /** User supplied buffer where HTTP connection data is stored */
102 uint8_t *tmp_buf;
103
104 /** Length of the user supplied temp buffer */
105 size_t tmp_buf_len;
106 };
107
108 /**
109 * @brief Connect to a server that provides Websocket service. The callback is
110 * called after connection is established. The returned value is a new socket
111 * descriptor that can be used to send / receive data using the BSD socket API.
112 *
113 * @param http_sock Socket id to the server. Note that this socket is used to do
114 * HTTP handshakes etc. The actual Websocket connectivity is done via the
115 * returned websocket id. Note that the http_sock must not be closed
116 * after this function returns as it is used to deliver the Websocket
117 * packets to the Websocket server.
118 * @param req Websocket request. User should allocate and fill the request
119 * data.
120 * @param timeout Max timeout to wait for the connection. The timeout value is
121 * in milliseconds. Value SYS_FOREVER_MS means to wait forever.
122 * @param user_data User specified data that is passed to the callback.
123 *
124 * @return Websocket id to be used when sending/receiving Websocket data.
125 */
126 int websocket_connect(int http_sock, struct websocket_request *req,
127 int32_t timeout, void *user_data);
128
129 /**
130 * @brief Send websocket msg to peer.
131 *
132 * @details The function will automatically add websocket header to the
133 * message.
134 *
135 * @param ws_sock Websocket id returned by websocket_connect().
136 * @param payload Websocket data to send.
137 * @param payload_len Length of the data to be sent.
138 * @param opcode Operation code (text, binary, ping, pong, close)
139 * @param mask Mask the data, see RFC 6455 for details
140 * @param final Is this final message for this message send. If final == false,
141 * then the first message must have valid opcode and subsequent messages
142 * must have opcode WEBSOCKET_OPCODE_CONTINUE. If final == true and this
143 * is the only message, then opcode should have proper opcode (text or
144 * binary) set.
145 * @param timeout How long to try to send the message. The value is in
146 * milliseconds. Value SYS_FOREVER_MS means to wait forever.
147 *
148 * @return <0 if error, >=0 amount of bytes sent
149 */
150 int websocket_send_msg(int ws_sock, const uint8_t *payload, size_t payload_len,
151 enum websocket_opcode opcode, bool mask, bool final,
152 int32_t timeout);
153
154 /**
155 * @brief Receive websocket msg from peer.
156 *
157 * @details The function will automatically remove websocket header from the
158 * message.
159 *
160 * @param ws_sock Websocket id returned by websocket_connect().
161 * @param buf Buffer where websocket data is read.
162 * @param buf_len Length of the data buffer.
163 * @param message_type Type of the message.
164 * @param remaining How much there is data left in the message after this read.
165 * @param timeout How long to try to receive the message.
166 * The value is in milliseconds. Value SYS_FOREVER_MS means to wait
167 * forever.
168 *
169 * @retval >=0 amount of bytes received.
170 * @retval -EAGAIN on timeout.
171 * @retval -ENOTCONN on socket close.
172 * @retval -errno other negative errno value in case of failure.
173 */
174 int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len,
175 uint32_t *message_type, uint64_t *remaining,
176 int32_t timeout);
177
178 /**
179 * @brief Close websocket.
180 *
181 * @details One must call websocket_connect() after this call to re-establish
182 * the connection.
183 *
184 * @param ws_sock Websocket id returned by websocket_connect().
185 */
186 int websocket_disconnect(int ws_sock);
187
188 #if defined(CONFIG_WEBSOCKET_CLIENT)
189 void websocket_init(void);
190 #else
websocket_init(void)191 static inline void websocket_init(void)
192 {
193 }
194 #endif
195
196 #ifdef __cplusplus
197 }
198 #endif
199
200 /**
201 * @}
202 */
203
204 #endif /* ZEPHYR_INCLUDE_NET_WEBSOCKET_H_ */
205