diff options
Diffstat (limited to 'src/include/microhttpd_ws.h')
-rw-r--r-- | src/include/microhttpd_ws.h | 979 |
1 files changed, 979 insertions, 0 deletions
diff --git a/src/include/microhttpd_ws.h b/src/include/microhttpd_ws.h new file mode 100644 index 00000000..915ca339 --- /dev/null +++ b/src/include/microhttpd_ws.h | |||
@@ -0,0 +1,979 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2021 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | /** | ||
20 | * @file microhttpd_ws.h | ||
21 | * @brief interface for experimental web socket extension to libmicrohttpd | ||
22 | * @author David Gausmann | ||
23 | */ | ||
24 | #ifndef MHD_MICROHTTPD_WS_H | ||
25 | #define MHD_MICROHTTPD_WS_H | ||
26 | |||
27 | |||
28 | #ifdef __cplusplus | ||
29 | extern "C" | ||
30 | { | ||
31 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
32 | } | ||
33 | #endif | ||
34 | #endif | ||
35 | |||
36 | |||
37 | /** | ||
38 | * @brief Handle for the encoding/decoding of websocket data | ||
39 | * (one stream is used per websocket) | ||
40 | * @ingroup websocket | ||
41 | */ | ||
42 | struct MHD_WebSocketStream; | ||
43 | |||
44 | /** | ||
45 | * @brief Flags for the initialization of a websocket stream | ||
46 | * `struct MHD_WebSocketStream` used by | ||
47 | * #MHD_websocket_stream_init() or | ||
48 | * #MHD_websocket_stream_init2(). | ||
49 | * @ingroup websocket | ||
50 | */ | ||
51 | enum MHD_WEBSOCKET_FLAG | ||
52 | { | ||
53 | /** | ||
54 | * The websocket is used by the server (default). | ||
55 | * Thus all outgoing payload will not be "masked". | ||
56 | * All incoming payload must be masked. | ||
57 | * This cannot be used together with #MHD_WEBSOCKET_FLAG_CLIENT | ||
58 | */ | ||
59 | MHD_WEBSOCKET_FLAG_SERVER = 0, | ||
60 | /** | ||
61 | * The websocket is used by the client | ||
62 | * (not used if you provide the server). | ||
63 | * Thus all outgoing payload will be "masked" (XOR-ed with random values). | ||
64 | * All incoming payload must be unmasked. | ||
65 | * Please note that this implementation doesn't use a strong random | ||
66 | * number generator for the mask as suggested in RFC6455 10.3, because | ||
67 | * the main intention of this implemention is the use as server | ||
68 | * with MHD, which doesn't need masking. | ||
69 | * Instead a weak random number generator is used (`rand()`). | ||
70 | * You can set the seed for the random number generator | ||
71 | * by calling #MHD_websocket_srand(). | ||
72 | * This cannot be used together with #MHD_WEBSOCKET_FLAG_SERVER | ||
73 | */ | ||
74 | MHD_WEBSOCKET_FLAG_CLIENT = 1, | ||
75 | /** | ||
76 | * You don't want to get fragmented data while decoding. | ||
77 | * Fragmented frames will be internally put together until | ||
78 | * they are complete. | ||
79 | * Whether or not data is fragmented is decided | ||
80 | * by the sender of the data during encoding. | ||
81 | * This cannot be used together with #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS | ||
82 | */ | ||
83 | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS = 0, | ||
84 | /** | ||
85 | * You want fragmented data, if it appears while decoding. | ||
86 | * You will receive the content of the fragmented frame, | ||
87 | * but if you are decoding text, you will never get an unfinished | ||
88 | * UTF-8 sequences (if the sequence appears between two fragments). | ||
89 | * Instead the text will end before the unfinished UTF-8 sequence. | ||
90 | * With the next fragment, which finishes the UTF-8 sequence, | ||
91 | * you will get the complete UTF-8 sequence. | ||
92 | * This cannot be used together with #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS | ||
93 | */ | ||
94 | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS = 2, | ||
95 | /** | ||
96 | * If the websocket stream becomes invalid during decoding due to | ||
97 | * protocol errors, a matching close frame will automatically | ||
98 | * be generated. | ||
99 | * The close frame will be returned via the parameters | ||
100 | * result and result_len of #MHD_websocket_decode() and | ||
101 | * the return value is negative | ||
102 | * (a value of `enum MHD_WEBSOCKET_STATUS`). | ||
103 | * The generated close frame must be freed by the caller | ||
104 | * with #MHD_websocket_free(). | ||
105 | */ | ||
106 | MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR = 4 | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * @brief Enum to specify the fragmenting behavior | ||
111 | * while encoding with #MHD_websocket_encode_text() or | ||
112 | * #MHD_websocket_encode_binary(). | ||
113 | * @ingroup websocket | ||
114 | */ | ||
115 | enum MHD_WEBSOCKET_FRAGMENTATION | ||
116 | { | ||
117 | /** | ||
118 | * You don't want to use fragmentation. | ||
119 | * The encoded frame consists of only one frame. | ||
120 | */ | ||
121 | MHD_WEBSOCKET_FRAGMENTATION_NONE = 0, | ||
122 | /** | ||
123 | * You want to use fragmentation. | ||
124 | * The encoded frame is the first frame of | ||
125 | * a series of data frames of the same type | ||
126 | * (text or binary). | ||
127 | * You may send control frames (ping, pong or close) | ||
128 | * between these data frames. | ||
129 | */ | ||
130 | MHD_WEBSOCKET_FRAGMENTATION_FIRST = 1, | ||
131 | /** | ||
132 | * You want to use fragmentation. | ||
133 | * The encoded frame is not the first frame of | ||
134 | * the series of data frames, but also not the last one. | ||
135 | * You may send control frames (ping, pong or close) | ||
136 | * between these data frames. | ||
137 | */ | ||
138 | MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING = 2, | ||
139 | /** | ||
140 | * You want to use fragmentation. | ||
141 | * The encoded frame is the last frame of | ||
142 | * the series of data frames, but also not the first one. | ||
143 | * After this frame, you may send all type of frames again. | ||
144 | */ | ||
145 | MHD_WEBSOCKET_FRAGMENTATION_LAST = 3 | ||
146 | }; | ||
147 | |||
148 | /** | ||
149 | * @brief Enum of the return value for almost every MHD_websocket function. | ||
150 | * Errors are negative and values equal to or above zero mean a success. | ||
151 | * Positive values are only used by #MHD_websocket_decode(). | ||
152 | * @ingroup websocket | ||
153 | */ | ||
154 | enum MHD_WEBSOCKET_STATUS | ||
155 | { | ||
156 | /** | ||
157 | * The call succeeded. | ||
158 | * For #MHD_websocket_decode() this means that no error occurred, | ||
159 | * but also no frame has been completed yet. | ||
160 | */ | ||
161 | MHD_WEBSOCKET_STATUS_OK = 0, | ||
162 | /** | ||
163 | * #MHD_websocket_decode() has decoded a text frame. | ||
164 | * The parameters result and result_len are filled with the decoded text | ||
165 | * (if any). | ||
166 | */ | ||
167 | MHD_WEBSOCKET_STATUS_TEXT_FRAME = 0x1, | ||
168 | /** | ||
169 | * #MHD_websocket_decode() has decoded a binary frame. | ||
170 | * The parameters result and result_len are filled with the decoded | ||
171 | * binary data (if any). | ||
172 | */ | ||
173 | MHD_WEBSOCKET_STATUS_BINARY_FRAME = 0x2, | ||
174 | /** | ||
175 | * #MHD_websocket_decode() has decoded a close frame. | ||
176 | * This means you must close the socket using #MHD_upgrade_action() | ||
177 | * with #MHD_UPGRADE_ACTION_CLOSE. | ||
178 | * You may respond with a close frame before closing. | ||
179 | * The parameters result and result_len are filled with | ||
180 | * the close reason (if any). | ||
181 | * The close reason starts with a two byte sequence of close code | ||
182 | * in network byte order (see `enum MHD_WEBSOCKET_CLOSEREASON`). | ||
183 | * After these two bytes a UTF-8 encoded close reason may follow. | ||
184 | * Compare with result_len to decide whether there is any close reason. | ||
185 | */ | ||
186 | MHD_WEBSOCKET_STATUS_CLOSE_FRAME = 0x8, | ||
187 | /** | ||
188 | * #MHD_websocket_decode() has decoded a ping frame. | ||
189 | * You should respond to this with a pong frame. | ||
190 | * The pong frame must contain the same binary data as | ||
191 | * the corresponding ping frame (if it had any). | ||
192 | * The parameters result and result_len are filled with | ||
193 | * the binary ping data (if any). | ||
194 | */ | ||
195 | MHD_WEBSOCKET_STATUS_PING_FRAME = 0x9, | ||
196 | /** | ||
197 | * #MHD_websocket_decode() has decoded a pong frame. | ||
198 | * You should usually only receive pong frames if you sent | ||
199 | * a ping frame before. | ||
200 | * The binary data should be equal to your ping frame and can be | ||
201 | * used to distinguish the response if you sent multiple ping frames. | ||
202 | * The parameters result and result_len are filled with | ||
203 | * the binary pong data (if any). | ||
204 | */ | ||
205 | MHD_WEBSOCKET_STATUS_PONG_FRAME = 0xA, | ||
206 | /** | ||
207 | * #MHD_websocket_decode() has decoded a text frame fragment. | ||
208 | * The parameters result and result_len are filled with the decoded text | ||
209 | * (if any). | ||
210 | * This is like #MHD_WEBSOCKET_STATUS_TEXT_FRAME, but it can only | ||
211 | * appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS during | ||
212 | * the call of #MHD_websocket_stream_init() or | ||
213 | * #MHD_websocket_stream_init2(). | ||
214 | */ | ||
215 | MHD_WEBSOCKET_STATUS_TEXT_FRAGMENT = 0x11, | ||
216 | /** | ||
217 | * #MHD_websocket_decode() has decoded a binary frame fragment. | ||
218 | * The parameters result and result_len are filled with the decoded | ||
219 | * binary data (if any). | ||
220 | * This is like #MHD_WEBSOCKET_STATUS_BINARY_FRAME, but it can only | ||
221 | * appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS during | ||
222 | * the call of #MHD_websocket_stream_init() or | ||
223 | * #MHD_websocket_stream_init2(). | ||
224 | */ | ||
225 | MHD_WEBSOCKET_STATUS_BINARY_FRAGMENT = 0x12, | ||
226 | /** | ||
227 | * #MHD_websocket_decode() has decoded the last text frame fragment. | ||
228 | * The parameters result and result_len are filled with the decoded text | ||
229 | * (if any). | ||
230 | * This is like #MHD_WEBSOCKET_STATUS_TEXT_FRAGMENT, but it appears | ||
231 | * only for the last fragment of a series of fragments. | ||
232 | * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS | ||
233 | * during the call of #MHD_websocket_stream_init() or | ||
234 | * #MHD_websocket_stream_init2(). | ||
235 | */ | ||
236 | MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT = 0x21, | ||
237 | /** | ||
238 | * #MHD_websocket_decode() has decoded the last binary frame fragment. | ||
239 | * The parameters result and result_len are filled with the decoded | ||
240 | * binary data (if any). | ||
241 | * This is like #MHD_WEBSOCKET_STATUS_BINARY_FRAGMENT, but it appears | ||
242 | * only for the last fragment of a series of fragments. | ||
243 | * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS | ||
244 | * during the call of #MHD_websocket_stream_init() or | ||
245 | * #MHD_websocket_stream_init2(). | ||
246 | */ | ||
247 | MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT = 0x22, | ||
248 | /** | ||
249 | * The call failed and the stream is invalid now for decoding. | ||
250 | * You must close the websocket now using #MHD_upgrade_action() | ||
251 | * with #MHD_UPGRADE_ACTION_CLOSE. | ||
252 | * You can send a close frame before closing. | ||
253 | * This is only used by #MHD_websocket_decode() and happens | ||
254 | * if the stream contains errors (i. e. invalid byte data). | ||
255 | */ | ||
256 | MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR = -1, | ||
257 | /** | ||
258 | * You tried to decode something, but the stream has already | ||
259 | * been marked invalid. | ||
260 | * You must close the websocket now using #MHD_upgrade_action() | ||
261 | * with #MHD_UPGRADE_ACTION_CLOSE. | ||
262 | * You can send a close frame before closing. | ||
263 | * This is only used by #MHD_websocket_decode() and happens | ||
264 | * if you call #MDM_websocket_decode() again after is | ||
265 | * has been invalidated. | ||
266 | */ | ||
267 | MHD_WEBSOCKET_STATUS_STREAM_BROKEN = -2, | ||
268 | /** | ||
269 | * A memory allocation failed. The stream remains valid. | ||
270 | * If this occurred while decoding, the decoding could be | ||
271 | * possible later if enough memory is available. | ||
272 | * This could happen while decoding if you received a too big data frame. | ||
273 | * You could try to specify max_payload_size during the call of | ||
274 | * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2() then to | ||
275 | * avoid this and close the frame instead. | ||
276 | */ | ||
277 | MHD_WEBSOCKET_STATUS_MEMORY_ERROR = -3, | ||
278 | /** | ||
279 | * You passed invalid parameters during the function call | ||
280 | * (i. e. a NULL pointer for a required parameter). | ||
281 | * The stream remains valid. | ||
282 | */ | ||
283 | MHD_WEBSOCKET_STATUS_PARAMETER_ERROR = -4, | ||
284 | /** | ||
285 | * The maximum payload size has been exceeded. | ||
286 | * If you got this return code from #MHD_websocket_decode() then | ||
287 | * the stream becomes invalid and the websocket must be closed | ||
288 | * using #MHD_upgrade_action() with #MHD_UPGRADE_ACTION_CLOSE. | ||
289 | * You can send a close frame before closing. | ||
290 | * The maximum payload size is specified during the call of | ||
291 | * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2(). | ||
292 | * This can also appear if you specified 0 as maximum payload size | ||
293 | * when the message is greater than the maximum allocatable memory size | ||
294 | * (i. e. more than 4 GB on 32 bit systems). | ||
295 | * If you got this return code from #MHD_websocket_encode_close(), | ||
296 | * #MHD_websocket_encode_ping() or #MHD_websocket_encode_pong() then | ||
297 | * you passed to much payload data. The stream remains valid then. | ||
298 | */ | ||
299 | MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED = -5, | ||
300 | /** | ||
301 | * An UTF-8 text is invalid. | ||
302 | * If you got this return code from #MHD_websocket_decode() then | ||
303 | * the stream becomes invalid and you must close the websocket | ||
304 | * using #MHD_upgrade_action() with #MHD_UPGRADE_ACTION_CLOSE. | ||
305 | * You can send a close frame before closing. | ||
306 | * If you got this from #MHD_websocket_encode_text() or | ||
307 | * #MHD_websocket_encode_close() then you passed invalid UTF-8 text. | ||
308 | * The stream remains valid then. | ||
309 | */ | ||
310 | MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR = -6 | ||
311 | }; | ||
312 | |||
313 | /** | ||
314 | * @brief Enumeration of possible close reasons for close frames. | ||
315 | * | ||
316 | * The possible values are specified in RFC 6455 7.4.1 | ||
317 | * These close reasons here are the default set specified by RFC 6455, | ||
318 | * but also other close reasons could be used. | ||
319 | * | ||
320 | * The definition is for short: | ||
321 | * 0-999 are never used (if you pass 0 in | ||
322 | * #MHD_websocket_encode_close() then no close reason is used). | ||
323 | * 1000-2999 are specified by RFC 6455. | ||
324 | * 3000-3999 are specified by libraries, etc. but must be registered by IANA. | ||
325 | * 4000-4999 are reserved for private use. | ||
326 | * | ||
327 | * @ingroup websocket | ||
328 | */ | ||
329 | enum MHD_WEBSOCKET_CLOSEREASON | ||
330 | { | ||
331 | /** | ||
332 | * This value is used as placeholder for #MHD_websocket_encode_close() | ||
333 | * to tell that you don't want to specify any reason. | ||
334 | * If you use this value then no reason text may be used. | ||
335 | * This value cannot a result of decoding, because this value | ||
336 | * is not a valid close reason for the WebSocket protocol. | ||
337 | */ | ||
338 | MHD_WEBSOCKET_CLOSEREASON_NO_REASON = 0, | ||
339 | /** | ||
340 | * You close the websocket fulfilled its purpose and shall | ||
341 | * now be closed in a normal, planned way. | ||
342 | */ | ||
343 | MHD_WEBSOCKET_CLOSEREASON_REGULAR = 1000, | ||
344 | /** | ||
345 | * You close the websocket because are shutting down the server or | ||
346 | * something similar. | ||
347 | */ | ||
348 | MHD_WEBSOCKET_CLOSEREASON_GOING_AWAY = 1001, | ||
349 | /** | ||
350 | * You close the websocket because you a protocol error occurred | ||
351 | * during decoding (i. e. invalid byte data). | ||
352 | */ | ||
353 | MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR = 1002, | ||
354 | /** | ||
355 | * You close the websocket because you received data which you don't accept. | ||
356 | * For example if you received a binary frame, | ||
357 | * but your application only expects text frames. | ||
358 | */ | ||
359 | MHD_WEBSOCKET_CLOSEREASON_UNSUPPORTED_DATATYPE = 1003, | ||
360 | /** | ||
361 | * You close the websocket because it contains malformed UTF-8. | ||
362 | * The UTF-8 validity is automatically checked by #MHD_websocket_decode(), | ||
363 | * so you don't need to check it on your own. | ||
364 | * UTF-8 is specified in RFC 3629. | ||
365 | */ | ||
366 | MHD_WEBSOCKET_CLOSEREASON_MALFORMED_UTF8 = 1007, | ||
367 | /** | ||
368 | * You close the websocket because of any reason. | ||
369 | * Usually this close reason is used if no other close reason | ||
370 | * is more specific or if you don't want to use any other close reason. | ||
371 | */ | ||
372 | MHD_WEBSOCKET_CLOSEREASON_POLICY_VIOLATED = 1008, | ||
373 | /** | ||
374 | * You close the websocket because you received a frame which is too big to process. | ||
375 | * You can specify the maximum allowed payload size during the call of | ||
376 | * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2(). | ||
377 | */ | ||
378 | MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED = 1009, | ||
379 | /** | ||
380 | * This status code can be sent by the client if it | ||
381 | * expected a specific extension, but this extension hasn't been negotiated. | ||
382 | */ | ||
383 | MHD_WEBSOCKET_CLOSEREASON_MISSING_EXTENSION = 1010, | ||
384 | /** | ||
385 | * The server closes the websocket because it encountered | ||
386 | * an unexpected condition that prevented it from fulfilling the request. | ||
387 | */ | ||
388 | MHD_WEBSOCKET_CLOSEREASON_UNEXPECTED_CONDITION = 1011 | ||
389 | }; | ||
390 | |||
391 | /** | ||
392 | * @brief Enumeration of possible UTF-8 check steps | ||
393 | * | ||
394 | * These values are used during the encoding of fragmented text frames | ||
395 | * or for error analysis while encoding text frames. | ||
396 | * Its values specify the next step of the UTF-8 check. | ||
397 | * UTF-8 sequences consist of one to four bytes. | ||
398 | * This enumeration just says how long the current UTF-8 sequence is | ||
399 | * and what is the next expected byte. | ||
400 | * | ||
401 | * @ingroup websocket | ||
402 | */ | ||
403 | enum MHD_WEBSOCKET_UTF8STEP | ||
404 | { | ||
405 | /** | ||
406 | * There is no open UTF-8 sequence. | ||
407 | * The next byte must be 0x00-0x7F or 0xC2-0xF4. | ||
408 | */ | ||
409 | MHD_WEBSOCKET_UTF8STEP_NORMAL = 0, | ||
410 | /** | ||
411 | * The second byte of a two byte UTF-8 sequence. | ||
412 | * The first byte was 0xC2-0xDF. | ||
413 | * The next byte must be 0x80-0xBF. | ||
414 | */ | ||
415 | MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 = 1, | ||
416 | /** | ||
417 | * The second byte of a three byte UTF-8 sequence. | ||
418 | * The first byte was 0xE0. | ||
419 | * The next byte must be 0xA0-0xBF. | ||
420 | */ | ||
421 | MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2 = 2, | ||
422 | /** | ||
423 | * The second byte of a three byte UTF-8 sequence. | ||
424 | * The first byte was 0xED. | ||
425 | * The next byte must by 0x80-0x9F. | ||
426 | */ | ||
427 | MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2 = 3, | ||
428 | /** | ||
429 | * The second byte of a three byte UTF-8 sequence. | ||
430 | * The first byte was 0xE1-0xEC or 0xEE-0xEF. | ||
431 | * The next byte must be 0x80-0xBF. | ||
432 | */ | ||
433 | MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2 = 4, | ||
434 | /** | ||
435 | * The third byte of a three byte UTF-8 sequence. | ||
436 | * The next byte must be 0x80-0xBF. | ||
437 | */ | ||
438 | MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2 = 5, | ||
439 | /** | ||
440 | * The second byte of a four byte UTF-8 sequence. | ||
441 | * The first byte was 0xF0. | ||
442 | * The next byte must be 0x90-0xBF. | ||
443 | */ | ||
444 | MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3 = 6, | ||
445 | /** | ||
446 | * The second byte of a four byte UTF-8 sequence. | ||
447 | * The first byte was 0xF4. | ||
448 | * The next byte must be 0x80-0x8F. | ||
449 | */ | ||
450 | MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3 = 7, | ||
451 | /** | ||
452 | * The second byte of a four byte UTF-8 sequence. | ||
453 | * The first byte was 0xF1-0xF3. | ||
454 | * The next byte must be 0x80-0xBF. | ||
455 | */ | ||
456 | MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3 = 8, | ||
457 | /** | ||
458 | * The third byte of a four byte UTF-8 sequence. | ||
459 | * The next byte must be 0x80-0xBF. | ||
460 | */ | ||
461 | MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3 = 9, | ||
462 | /** | ||
463 | * The fourth byte of a four byte UTF-8 sequence. | ||
464 | * The next byte must be 0x80-0xBF. | ||
465 | */ | ||
466 | MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3 = 10 | ||
467 | }; | ||
468 | |||
469 | /** | ||
470 | * @brief Enumeration of validity values | ||
471 | * | ||
472 | * These values are used for #MHD_websocket_stream_is_valid() | ||
473 | * and specifiy the validity status. | ||
474 | * | ||
475 | * @ingroup websocket | ||
476 | */ | ||
477 | enum MHD_WEBSOCKET_VALIDITY | ||
478 | { | ||
479 | /** | ||
480 | * The stream is invalid. | ||
481 | * It cannot be used for decoding anymore. | ||
482 | */ | ||
483 | MHD_WEBSOCKET_VALIDITY_INVALID = 0, | ||
484 | /** | ||
485 | * The stream is valid. | ||
486 | * Decoding works as expected. | ||
487 | */ | ||
488 | MHD_WEBSOCKET_VALIDITY_VALID = 1, | ||
489 | /** | ||
490 | * The stream has received a close frame and | ||
491 | * is partly invalid. | ||
492 | * You can still use the stream for decoding, | ||
493 | * but if a data frame is received an error will be reported. | ||
494 | * After a close frame has been sent, no data frames | ||
495 | * may follow from the sender of the close frame. | ||
496 | */ | ||
497 | MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES = 2 | ||
498 | }; | ||
499 | /** | ||
500 | * This method is called by many websocket | ||
501 | * functions for allocating data. | ||
502 | * By default 'malloc' is used. | ||
503 | * This can be used for operating systems like Windows | ||
504 | * where malloc, realloc and free are compiler dependent. | ||
505 | * | ||
506 | * @param len new size | ||
507 | * @return allocated memory | ||
508 | * @ingroup websocket | ||
509 | */ | ||
510 | typedef void* | ||
511 | (*MHD_WebSocketMallocCallback) (size_t len); | ||
512 | /** | ||
513 | * This method is called by many websocket | ||
514 | * functions for reallocating data. | ||
515 | * By default 'realloc' is used. | ||
516 | * This can be used for operating systems like Windows | ||
517 | * where malloc, realloc and free are compiler dependent. | ||
518 | * | ||
519 | * @param cls closure | ||
520 | * @param len new size | ||
521 | * @return reallocated memory | ||
522 | * @ingroup websocket | ||
523 | */ | ||
524 | typedef void* | ||
525 | (*MHD_WebSocketReallocCallback) (void *cls, size_t len); | ||
526 | /** | ||
527 | * This method is called by many websocket | ||
528 | * functions for freeing data. | ||
529 | * By default 'free' is used. | ||
530 | * This can be used for operating systems like Windows | ||
531 | * where malloc, realloc and free are compiler dependent. | ||
532 | * | ||
533 | * @param cls closure | ||
534 | * @ingroup websocket | ||
535 | */ | ||
536 | typedef void | ||
537 | (*MHD_WebSocketFreeCallback) (void *cls); | ||
538 | |||
539 | /** | ||
540 | * Creates the response value for the incoming 'Sec-WebSocket-Key' header. | ||
541 | * The generated value must be sent to the client as 'Sec-WebSocket-Accept' response header. | ||
542 | * | ||
543 | * @param sec_websocket_key The value of the 'Sec-WebSocket-Key' request header | ||
544 | * @param[out] sec_websocket_accept The response buffer, which will receive | ||
545 | * the generated 'Sec-WebSocket-Accept' header. | ||
546 | * This buffer must be at least 29 bytes long and | ||
547 | * will contain a terminating NUL character. | ||
548 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
549 | * Typically 0 on success or less than 0 on errors. | ||
550 | * @ingroup websocket | ||
551 | */ | ||
552 | _MHD_EXTERN int | ||
553 | MHD_websocket_create_accept (const char*sec_websocket_key, | ||
554 | char*sec_websocket_accept); | ||
555 | |||
556 | /** | ||
557 | * Creates a new websocket stream, used for decoding/encoding. | ||
558 | * | ||
559 | * @param[out] ws The websocket stream | ||
560 | * @param flags Combination of `enum MHD_WEBSOCKET_FLAG` values | ||
561 | * to modify the behavior of the websocket stream. | ||
562 | * @param max_message_size The maximum size for incoming payload | ||
563 | * data in bytes. Use 0 to allow each size. | ||
564 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
565 | * Typically 0 on success or less than 0 on errors. | ||
566 | * @ingroup websocket | ||
567 | */ | ||
568 | _MHD_EXTERN int | ||
569 | MHD_websocket_stream_init (struct MHD_WebSocketStream**ws, | ||
570 | int flags, | ||
571 | size_t max_payload_size); | ||
572 | |||
573 | /** | ||
574 | * Creates a new websocket stream, used for decoding/encoding, | ||
575 | * but with custom memory functions for malloc, realloc and free. | ||
576 | * | ||
577 | * @param[out] ws The websocket stream | ||
578 | * @param flags Combination of `enum MHD_WEBSOCKET_FLAG` values | ||
579 | * to modify the behavior of the websocket stream. | ||
580 | * @param max_message_size The maximum size for incoming payload | ||
581 | * data in bytes. Use 0 to allow each size. | ||
582 | * @param callback_malloc The callback function for 'malloc'. | ||
583 | * @param callback_realloc The callback function for 'realloc'. | ||
584 | * @param callback_free The callback function for 'free'. | ||
585 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
586 | * Typically 0 on success or less than 0 on errors. | ||
587 | * @ingroup websocket | ||
588 | */ | ||
589 | _MHD_EXTERN int | ||
590 | MHD_websocket_stream_init2 (struct MHD_WebSocketStream**ws, | ||
591 | int flags, | ||
592 | size_t max_payload_size, | ||
593 | MHD_WebSocketMallocCallback callback_malloc, | ||
594 | MHD_WebSocketReallocCallback callback_realloc, | ||
595 | MHD_WebSocketFreeCallback callback_free); | ||
596 | |||
597 | /** | ||
598 | * Frees a websocket stream | ||
599 | * | ||
600 | * @param ws The websocket stream. This value may be NULL. | ||
601 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
602 | * Typically 0 on success or less than 0 on errors. | ||
603 | * @ingroup websocket | ||
604 | */ | ||
605 | _MHD_EXTERN int | ||
606 | MHD_websocket_stream_free (struct MHD_WebSocketStream*ws); | ||
607 | |||
608 | /** | ||
609 | * Invalidates a websocket stream. | ||
610 | * After invalidation a websocket stream cannot be used for decoding anymore. | ||
611 | * Encoding is still possible. | ||
612 | * | ||
613 | * @param ws The websocket stream. | ||
614 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
615 | * Typically 0 on success or less than 0 on errors. | ||
616 | * @ingroup websocket | ||
617 | */ | ||
618 | _MHD_EXTERN int | ||
619 | MHD_websocket_stream_invalidate (struct MHD_WebSocketStream*ws); | ||
620 | |||
621 | /** | ||
622 | * Queries whether a websocket stream is valid. | ||
623 | * Invalidated websocket streams cannot be used for decoding anymore. | ||
624 | * Encoding is still possible. | ||
625 | * | ||
626 | * @param ws The websocket stream. | ||
627 | * @return A value of `enum MHD_WEBSOCKET_VALIDITY`. | ||
628 | * @ingroup websocket | ||
629 | */ | ||
630 | _MHD_EXTERN int | ||
631 | MHD_websocket_stream_is_valid (struct MHD_WebSocketStream*ws); | ||
632 | |||
633 | /** | ||
634 | * Decodes a byte sequence via this websocket stream. | ||
635 | * Decoding is done until either a frame is complete or | ||
636 | * the end of the byte sequence is reached. | ||
637 | * | ||
638 | * @param ws The websocket stream. | ||
639 | * @param streambuf The byte sequence for decoding. | ||
640 | * Typically that what you received via `recv()`. | ||
641 | * @param streambuf_len The length of the byte sequence @a streambuf | ||
642 | * @param[out] streambuf_read_len The number of bytes which has been processed | ||
643 | * by this call. This value may be less | ||
644 | * than @a streambuf_len when a frame is decoded | ||
645 | * before the end of the buffer is reached. | ||
646 | * The remaining bytes of @a buf must be passed | ||
647 | * in the following decoding. | ||
648 | * @param[out] payload This variable receives a buffer with the decoded | ||
649 | * payload data. | ||
650 | * If no decoded data is available this is NULL. | ||
651 | * When this variable is not NULL then | ||
652 | * the buffer contains always @a payload_len bytes plus | ||
653 | * one terminating NUL character. | ||
654 | * The caller must free this buffer | ||
655 | * using #MHD_websocket_free(). | ||
656 | * If you passed the flag | ||
657 | * #MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR | ||
658 | * upon creation of this websocket stream and | ||
659 | * a decoding error occurred | ||
660 | * (return value less than 0), then this | ||
661 | * buffer contains a generated close frame | ||
662 | * which must be sent via the socket to the recipient. | ||
663 | * If you passed the flag #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS | ||
664 | * upon creation of this websocket stream then | ||
665 | * this payload may only be a part of the complete message. | ||
666 | * Only complete UTF-8 sequences are returned | ||
667 | * for fragmented text frames. | ||
668 | * If necessary the UTF-8 sequence will be completed | ||
669 | * with the next text fragment. | ||
670 | * @param[out] payload_len The length of the result payload buffer in bytes. | ||
671 | * | ||
672 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
673 | * This is greater than 0 if a frame has is complete, equal to 0 if more data | ||
674 | * is needed an less than 0 on errors. | ||
675 | * @ingroup websocket | ||
676 | */ | ||
677 | _MHD_EXTERN int | ||
678 | MHD_websocket_decode (struct MHD_WebSocketStream*ws, | ||
679 | const char*streambuf, | ||
680 | size_t streambuf_len, | ||
681 | size_t*streambuf_read_len, | ||
682 | char**payload, | ||
683 | size_t*payload_len); | ||
684 | |||
685 | /** | ||
686 | * Splits the payload of of a decoded close frame. | ||
687 | * | ||
688 | * @param payload The payload of the close frame. | ||
689 | * This parameter may be NULL if @a payload_len is 0. | ||
690 | * @param payload_len The length of @a payload. | ||
691 | * @param[out] reason_code The numeric close reason. | ||
692 | * If there was no close reason, this is | ||
693 | * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON. | ||
694 | * Compare with `enum MHD_WEBSOCKET_CLOSEREASON`. | ||
695 | * This parameter is optional and can be NULL. | ||
696 | * @param[out] reason_utf8 The literal close reason. | ||
697 | * If there was no literal close reason, this is NULL. | ||
698 | * This parameter is optional and can be NULL. | ||
699 | * Please note that no memory is allocated | ||
700 | * in this function. | ||
701 | * If not NULL the returned value of this parameter | ||
702 | * points to a position in the specified @a payload. | ||
703 | * @param[out] reason_utf8_len The length of the literal close reason. | ||
704 | * If there was no literal close reason, this is 0. | ||
705 | * This parameter is optional and can be NULL. | ||
706 | * | ||
707 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
708 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
709 | * or a value less than 0 on errors. | ||
710 | * @ingroup websocket | ||
711 | */ | ||
712 | _MHD_EXTERN int | ||
713 | MHD_websocket_split_close_reason (const char*payload, | ||
714 | size_t payload_len, | ||
715 | unsigned short*reason_code, | ||
716 | const char**reason_utf8, | ||
717 | size_t*reason_utf8_len); | ||
718 | |||
719 | /** | ||
720 | * Encodes an UTF-8 encoded text into websocket text frame. | ||
721 | * | ||
722 | * @param ws The websocket stream. | ||
723 | * @param payload_utf8 The UTF-8 encoded text to send. | ||
724 | * This can be NULL if payload_utf8_len is 0. | ||
725 | * @param payload_utf8_len The length of the UTF-8 encoded text in bytes. | ||
726 | * @param fragmentation A value of `enum MHD_WEBSOCKET_FRAGMENTATION` | ||
727 | * to specifiy the fragmentation behavior. | ||
728 | * Specify MHD_WEBSOCKET_FRAGMENTATION_NONE | ||
729 | * if you don't want to use fragmentation. | ||
730 | * @param[out] frame This variable receives a buffer with the encoded frame. | ||
731 | * This is what you typically send via `send()` to the recipient. | ||
732 | * If no encoded data is available this is NULL. | ||
733 | * When this variable is not NULL then the buffer contains always | ||
734 | * @a frame_len bytes plus one terminating NUL character. | ||
735 | * The caller must free this buffer using #MHD_websocket_free(). | ||
736 | * @param[out] frame_len The length of the encoded frame in bytes. | ||
737 | * @param[out] utf8_step This parameter is required for fragmentation and | ||
738 | * can be NULL if no fragmentation is used. | ||
739 | * It contains information about the last encoded | ||
740 | * UTF-8 sequence and is required to continue a previous | ||
741 | * UTF-8 sequence when fragmentation is used. | ||
742 | * The `enum MHD_WEBSOCKET_UTF8STEP` is for this. | ||
743 | * If you start a new fragment using | ||
744 | * MHD_WEBSOCKET_FRAGMENTATION_NONE or | ||
745 | * MHD_WEBSOCKET_FRAGMENTATION_FIRST the value | ||
746 | * of this variable will be initialized | ||
747 | * to MHD_WEBSOCKET_UTF8STEP_NORMAL. | ||
748 | * | ||
749 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
750 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
751 | * or a value less than 0 on errors. | ||
752 | * @ingroup websocket | ||
753 | */ | ||
754 | _MHD_EXTERN int | ||
755 | MHD_websocket_encode_text (struct MHD_WebSocketStream*ws, | ||
756 | const char*payload_utf8, | ||
757 | size_t payload_utf8_len, | ||
758 | int fragmentation, | ||
759 | char**frame, | ||
760 | size_t*frame_len, | ||
761 | int*utf8_step); | ||
762 | |||
763 | /** | ||
764 | * Encodes a binary data into websocket binary frame. | ||
765 | * | ||
766 | * @param ws The websocket stream. | ||
767 | * @param payload The binary data to send. | ||
768 | * @param payload_len The length of the binary data in bytes. | ||
769 | * @param fragmentation A value of `enum MHD_WEBSOCKET_FRAGMENTATION` | ||
770 | * to specifiy the fragmentation behavior. | ||
771 | * Specify MHD_WEBSOCKET_FRAGMENTATION_NONE | ||
772 | * if you don't want to use fragmentation. | ||
773 | * @param[out] frame This variable receives a buffer with | ||
774 | * the encoded binary frame. | ||
775 | * This is what you typically send via `send()` | ||
776 | * to the recipient. | ||
777 | * If no encoded frame is available this is NULL. | ||
778 | * When this variable is not NULL then the allocated buffer | ||
779 | * contains always @a frame_len bytes plus one terminating | ||
780 | * NUL character. | ||
781 | * The caller must free this buffer using #MHD_websocket_free(). | ||
782 | * @param[out] frame_len The length of the result frame buffer in bytes. | ||
783 | * | ||
784 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
785 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
786 | * or a value less than 0 on errors. | ||
787 | * @ingroup websocket | ||
788 | */ | ||
789 | _MHD_EXTERN int | ||
790 | MHD_websocket_encode_binary (struct MHD_WebSocketStream*ws, | ||
791 | const char*payload, | ||
792 | size_t payload_len, | ||
793 | int fragmentation, | ||
794 | char**frame, | ||
795 | size_t*frame_len); | ||
796 | |||
797 | /** | ||
798 | * Encodes a websocket ping frame | ||
799 | * | ||
800 | * @param ws The websocket stream. | ||
801 | * @param payload The binary ping payload data to send. | ||
802 | * This may be NULL if @a payload_len is 0. | ||
803 | * @param payload_len The length of the payload data in bytes. | ||
804 | * This may not exceed 125 bytes. | ||
805 | * @param[out] frame This variable receives a buffer with the encoded ping frame data. | ||
806 | * This is what you typically send via `send()` to the recipient. | ||
807 | * If no encoded frame is available this is NULL. | ||
808 | * When this variable is not NULL then the buffer contains always | ||
809 | * @a frame_len bytes plus one terminating NUL character. | ||
810 | * The caller must free this buffer using #MHD_websocket_free(). | ||
811 | * @param[out] frame_len The length of the result frame buffer in bytes. | ||
812 | * | ||
813 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
814 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
815 | * or a value less than 0 on errors. | ||
816 | * @ingroup websocket | ||
817 | */ | ||
818 | _MHD_EXTERN int | ||
819 | MHD_websocket_encode_ping (struct MHD_WebSocketStream*ws, | ||
820 | const char*payload, | ||
821 | size_t payload_len, | ||
822 | char**frame, | ||
823 | size_t*frame_len); | ||
824 | |||
825 | /** | ||
826 | * Encodes a websocket pong frame | ||
827 | * | ||
828 | * @param ws The websocket stream. | ||
829 | * @param payload The binary pong payload data, which is typically | ||
830 | * the decoded payload from the received ping frame. | ||
831 | * This may be NULL if @a payload_len is 0. | ||
832 | * @param payload_len The length of the payload data in bytes. | ||
833 | * This may not exceed 125 bytes. | ||
834 | * @param[out] frame This variable receives a buffer with | ||
835 | * the encoded pong frame data. | ||
836 | * This is what you typically send via `send()` | ||
837 | * to the recipient. | ||
838 | * If no encoded frame is available this is NULL. | ||
839 | * When this variable is not NULL then the buffer | ||
840 | * contains always @a frame_len bytes plus one | ||
841 | * terminating NUL character. | ||
842 | * The caller must free this buffer | ||
843 | * using #MHD_websocket_free(). | ||
844 | * @param[out] frame_len The length of the result frame buffer in bytes. | ||
845 | * | ||
846 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
847 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
848 | * or a value less than 0 on errors. | ||
849 | * @ingroup websocket | ||
850 | */ | ||
851 | _MHD_EXTERN int | ||
852 | MHD_websocket_encode_pong (struct MHD_WebSocketStream*ws, | ||
853 | const char*payload, | ||
854 | size_t payload_len, | ||
855 | char**frame, | ||
856 | size_t*frame_len); | ||
857 | |||
858 | /** | ||
859 | * Encodes a websocket close frame | ||
860 | * | ||
861 | * @param ws The websocket stream. | ||
862 | * @param reason_code The reason for close. | ||
863 | * You can use `enum MHD_WEBSOCKET_CLOSEREASON` | ||
864 | * for typical reasons, | ||
865 | * but you are not limited to these values. | ||
866 | * The allowed values are specified in RFC 6455 7.4. | ||
867 | * If you don't want to enter a reason, you can specify | ||
868 | * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON then | ||
869 | * no reason is encoded. | ||
870 | * @param reason_utf8 An UTF-8 encoded text reason why the connection is closed. | ||
871 | * This may be NULL if @a reason_utf8_len is 0. | ||
872 | * This must be NULL if @a reason_code is | ||
873 | * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON (= 0). | ||
874 | * @param reason_utf8_len The length of the UTF-8 encoded text reason in bytes. | ||
875 | * This may not exceed 123 bytes. | ||
876 | * @param[out] frame This variable receives a buffer with | ||
877 | * the encoded close frame. | ||
878 | * This is what you typically send via `send()` | ||
879 | * to the recipient. | ||
880 | * If no encoded frame is available this is NULL. | ||
881 | * When this variable is not NULL then the buffer | ||
882 | * contains always @a frame_len bytes plus | ||
883 | * one terminating NUL character. | ||
884 | * The caller must free this buffer | ||
885 | * using #MHD_websocket_free(). | ||
886 | * @param[out] frame_len The length of the result frame buffer in bytes. | ||
887 | * | ||
888 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
889 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
890 | * or a value less than 0 on errors. | ||
891 | * @ingroup websocket | ||
892 | */ | ||
893 | _MHD_EXTERN int | ||
894 | MHD_websocket_encode_close (struct MHD_WebSocketStream*ws, | ||
895 | unsigned short reason_code, | ||
896 | const char*reason_utf8, | ||
897 | size_t reason_utf8_len, | ||
898 | char**frame, | ||
899 | size_t*frame_len); | ||
900 | |||
901 | /** | ||
902 | * Sets the seed for the random number generated used for | ||
903 | * the generation of masked frames (this is only used for client websockets). | ||
904 | * This seed is used for all websocket streams. | ||
905 | * Internally `srand()` is called. | ||
906 | * Please note that on some situations | ||
907 | * (where `rand()` and `srand()` are shared between your program | ||
908 | * and this library) this could cause unwanted results in your program if | ||
909 | * your program relies on a specific seed. | ||
910 | * | ||
911 | * @param seed The seed used for the initialization of | ||
912 | * the pseudo random number generator. | ||
913 | * Typically `time(NULL)` is used here to | ||
914 | * generate a seed. | ||
915 | * | ||
916 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
917 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
918 | * or a value less than 0 on errors. | ||
919 | * @ingroup websocket | ||
920 | */ | ||
921 | _MHD_EXTERN int | ||
922 | MHD_websocket_srand (unsigned long seed); | ||
923 | |||
924 | /** | ||
925 | * Allocates memory with the associated 'malloc' function | ||
926 | * of the websocket stream | ||
927 | * | ||
928 | * @param ws The websocket stream. | ||
929 | * @param len The length of the memory to allocate in bytes | ||
930 | * | ||
931 | * @return The allocated memory on success or NULL on failure. | ||
932 | * @ingroup websocket | ||
933 | */ | ||
934 | _MHD_EXTERN void* | ||
935 | MHD_websocket_malloc (struct MHD_WebSocketStream*ws, | ||
936 | size_t len); | ||
937 | |||
938 | /** | ||
939 | * Reallocates memory with the associated 'realloc' function | ||
940 | * of the websocket stream | ||
941 | * | ||
942 | * @param ws The websocket stream. | ||
943 | * @param cls The previously allocated memory or NULL | ||
944 | * @param len The new length of the memory in bytes | ||
945 | * | ||
946 | * @return The allocated memory on success or NULL on failure. | ||
947 | * If NULL is returned the previously allocated buffer | ||
948 | * remains valid. | ||
949 | * @ingroup websocket | ||
950 | */ | ||
951 | _MHD_EXTERN void* | ||
952 | MHD_websocket_realloc (struct MHD_WebSocketStream*ws, | ||
953 | void*cls, | ||
954 | size_t len); | ||
955 | |||
956 | /** | ||
957 | * Frees memory with the associated 'free' function | ||
958 | * of the websocket stream | ||
959 | * | ||
960 | * @param ws The websocket stream. | ||
961 | * @param cls The previously allocated memory or NULL | ||
962 | * | ||
963 | * @return A value of `enum MHD_WEBSOCKET_STATUS`. | ||
964 | * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success | ||
965 | * or a value less than 0 on errors. | ||
966 | * @ingroup websocket | ||
967 | */ | ||
968 | _MHD_EXTERN int | ||
969 | MHD_websocket_free (struct MHD_WebSocketStream*ws, | ||
970 | void*cls); | ||
971 | |||
972 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
973 | { | ||
974 | #endif | ||
975 | #ifdef __cplusplus | ||
976 | } | ||
977 | #endif | ||
978 | |||
979 | #endif | ||