aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd_ws/mhd_websocket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd_ws/mhd_websocket.c')
-rw-r--r--src/microhttpd_ws/mhd_websocket.c587
1 files changed, 478 insertions, 109 deletions
diff --git a/src/microhttpd_ws/mhd_websocket.c b/src/microhttpd_ws/mhd_websocket.c
index ea1a5bda..da787f7d 100644
--- a/src/microhttpd_ws/mhd_websocket.c
+++ b/src/microhttpd_ws/mhd_websocket.c
@@ -36,6 +36,10 @@ struct MHD_WebSocketStream
36 MHD_WebSocketReallocCallback realloc; 36 MHD_WebSocketReallocCallback realloc;
37 /* The function pointer to free for payload (can be used to use different memory management) */ 37 /* The function pointer to free for payload (can be used to use different memory management) */
38 MHD_WebSocketFreeCallback free; 38 MHD_WebSocketFreeCallback free;
39 /* A closure for the random number generator (only used for client mode; usually not required) */
40 void* cls_rng;
41 /* The random number generator (only used for client mode; usually not required) */
42 MHD_WebSocketRandomNumberGenerator rng;
39 /* The flags specified upon initialization. It may alter the behavior of decoding/encoding */ 43 /* The flags specified upon initialization. It may alter the behavior of decoding/encoding */
40 int flags; 44 int flags;
41 /* The current step for the decoder. 0 means start of a frame. */ 45 /* The current step for the decoder. 0 means start of a frame. */
@@ -122,13 +126,6 @@ enum MHD_WebSocket_UTF8Result
122 MHD_WebSocket_UTF8Result_Incomplete = 2 126 MHD_WebSocket_UTF8Result_Incomplete = 2
123}; 127};
124 128
125#define htonll(x) \
126 ((1 == htonl (1)) ? (x) : ((uint64_t) htonl ((x) & 0xFFFFFFFF) << 32) \
127 | htonl ((x) >> 32))
128#define ntohll(x) \
129 ((1 == ntohl (1)) ? (x) : ((uint64_t) ntohl ((x) & 0xFFFFFFFF) << 32) \
130 | ntohl ((x) >> 32))
131
132static void 129static void
133MHD_websocket_copy_payload (char*dst, 130MHD_websocket_copy_payload (char*dst,
134 const char*src, 131 const char*src,
@@ -142,12 +139,12 @@ MHD_websocket_check_utf8 (const char*buf,
142 int*utf8_step, 139 int*utf8_step,
143 size_t*buf_offset); 140 size_t*buf_offset);
144 141
145static int 142static enum MHD_WEBSOCKET_STATUS
146MHD_websocket_decode_header_complete (struct MHD_WebSocketStream*ws, 143MHD_websocket_decode_header_complete (struct MHD_WebSocketStream*ws,
147 char**payload, 144 char**payload,
148 size_t*payload_len); 145 size_t*payload_len);
149 146
150static int 147static enum MHD_WEBSOCKET_STATUS
151MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws, 148MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
152 char**payload, 149 char**payload,
153 size_t*payload_len); 150 size_t*payload_len);
@@ -158,7 +155,7 @@ static char
158MHD_websocket_encode_overhead_size (struct MHD_WebSocketStream *ws, 155MHD_websocket_encode_overhead_size (struct MHD_WebSocketStream *ws,
159 size_t payload_len); 156 size_t payload_len);
160 157
161static int 158static enum MHD_WEBSOCKET_STATUS
162MHD_websocket_encode_data (struct MHD_WebSocketStream*ws, 159MHD_websocket_encode_data (struct MHD_WebSocketStream*ws,
163 const char*payload, 160 const char*payload,
164 size_t payload_len, 161 size_t payload_len,
@@ -167,7 +164,7 @@ MHD_websocket_encode_data (struct MHD_WebSocketStream*ws,
167 size_t*frame_len, 164 size_t*frame_len,
168 char opcode); 165 char opcode);
169 166
170static int 167static enum MHD_WEBSOCKET_STATUS
171MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws, 168MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws,
172 const char*payload, 169 const char*payload,
173 size_t payload_len, 170 size_t payload_len,
@@ -176,35 +173,338 @@ MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws,
176 char opcode); 173 char opcode);
177 174
178static uint32_t 175static uint32_t
179MHD_websocket_generate_mask (); 176MHD_websocket_generate_mask (struct MHD_WebSocketStream*ws);
177
178static uint16_t
179MHD_htons (uint16_t value);
180
181static uint64_t
182MHD_htonll (uint64_t value);
183
184
185/**
186 * Checks whether the HTTP version is 1.1 or above.
187 */
188_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
189MHD_websocket_check_http_version (const char* http_version)
190{
191 /* validate parameters */
192 if (NULL == http_version)
193 {
194 /* Like with the other check routines, */
195 /* NULL is threated as "value not given" and not as parameter error */
196 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
197 }
198
199 /* Check whether the version has a valid format */
200 /* RFC 1945 3.1: The format must be "HTTP/x.x" where x is */
201 /* any digit and must appear at least once */
202 if ('H' != http_version[0] ||
203 'T' != http_version[1] ||
204 'T' != http_version[2] ||
205 'P' != http_version[3] ||
206 '/' != http_version[4])
207 {
208 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
209 }
210
211 /* Find the major and minor part of the version */
212 /* RFC 1945 3.1: Both numbers must be threated as separate integers. */
213 /* Leading zeros must be ignored and both integers may have multiple digits */
214 const char* major = NULL;
215 const char* dot = NULL;
216 size_t i = 5;
217 for (;;)
218 {
219 char c = http_version[i];
220 if ('0' <= c && '9' >= c)
221 {
222 if (NULL == major ||
223 (http_version + i == major + 1 && '0' == *major) )
224 {
225 major = http_version + i;
226 }
227 ++i;
228 }
229 else if ('.' == http_version[i])
230 {
231 dot = http_version + i;
232 ++i;
233 break;
234 }
235 else
236 {
237 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
238 }
239 }
240 const char* minor = NULL;
241 const char* end = NULL;
242 for (;;)
243 {
244 char c = http_version[i];
245 if ('0' <= c && '9' >= c)
246 {
247 if (NULL == minor ||
248 (http_version + i == minor + 1 && '0' == *minor) )
249 {
250 minor = http_version + i;
251 }
252 ++i;
253 }
254 else if (0 == c)
255 {
256 end = http_version + i;
257 break;
258 }
259 else
260 {
261 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
262 }
263 }
264 if (NULL == major || NULL == dot || NULL == minor || NULL == end)
265 {
266 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
267 }
268 if (2 <= dot - major || '2' <= *major ||
269 ('1' == *major && (2 <= end - minor || '1' <= *minor)) )
270 {
271 return MHD_WEBSOCKET_STATUS_OK;
272 }
273
274 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
275}
276
277
278/**
279 * Checks whether the "Connection" request header has the 'Upgrade' token.
280 */
281_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
282MHD_websocket_check_connection_header (const char* connection_header)
283{
284 /* validate parameters */
285 if (NULL == connection_header)
286 {
287 /* To be compatible with the return value */
288 /* of MHD_lookup_connection_value, */
289 /* NULL is threated as "value not given" and not as parameter error */
290 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
291 }
292
293 /* Check whether the Connection includes an Upgrade token */
294 /* RFC 7230 6.1: Multiple tokens may appear. */
295 /* RFC 7230 3.2.6: Tokens are comma separated */
296 const char* token_start = NULL;
297 const char* token_end = NULL;
298 for(size_t i = 0; ; ++i)
299 {
300 char c = connection_header[i];
301
302 /* RFC 7230 3.2.6: The list of allowed characters is a token is: */
303 /* "!" / "#" / "$" / "%" / "&" / "'" / "*" / */
304 /* "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" */
305 /* DIGIT / ALPHA */
306 if ('!' == c || '#' == c || '$' == c || '%' == c ||
307 '&' == c || '\'' == c || '*' == c ||
308 '+' == c || '-' == c || '.' == c || '^' == c ||
309 '_' == c || '`' == c || '|' == c || '~' == c ||
310 ('0' <= c && '9' >= c) ||
311 ('A' <= c && 'Z' >= c) || ('a' <= c && 'z' >= c) )
312 {
313 /* This is a valid token character */
314 if (NULL == token_start)
315 {
316 token_start = connection_header + i;
317 }
318 token_end = connection_header + i + 1;
319 }
320 else if (' ' == c || '\t' == c)
321 {
322 /* White-spaces around tokens will be ignored */
323 }
324 else if (',' == c || 0 == c)
325 {
326 /* Check the token (case-insensitive) */
327 if (NULL != token_start)
328 {
329 if ( 7 == (token_end - token_start) )
330 {
331 if ( ('U' == token_start[0] || 'u' == token_start[0]) &&
332 ('P' == token_start[1] || 'p' == token_start[1]) &&
333 ('G' == token_start[2] || 'g' == token_start[2]) &&
334 ('R' == token_start[3] || 'r' == token_start[3]) &&
335 ('A' == token_start[4] || 'a' == token_start[4]) &&
336 ('D' == token_start[5] || 'd' == token_start[5]) &&
337 ('E' == token_start[6] || 'e' == token_start[6]) )
338 {
339 /* The token equals to "Upgrade" */
340 return MHD_WEBSOCKET_STATUS_OK;
341 }
342 }
343 }
344 if (0 == c)
345 {
346 break;
347 }
348 token_start = NULL;
349 token_end = NULL;
350 }
351 else
352 {
353 /* RFC 7230 3.2.6: Other characters are not allowed */
354 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
355 }
356 }
357 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
358}
359
360
361/**
362 * Checks whether the "Upgrade" request header has the "websocket" keyword.
363 */
364_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
365MHD_websocket_check_upgrade_header (const char* upgrade_header)
366{
367 /* validate parameters */
368 if (NULL == upgrade_header)
369 {
370 /* To be compatible with the return value */
371 /* of MHD_lookup_connection_value, */
372 /* NULL is threated as "value not given" and not as parameter error */
373 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
374 }
375
376 /* Check whether the Connection includes an Upgrade token */
377 /* RFC 7230 6.1: Multiple tokens may appear. */
378 /* RFC 7230 3.2.6: Tokens are comma separated */
379 const char* keyword_start = NULL;
380 const char* keyword_end = NULL;
381 for(size_t i = 0; ; ++i)
382 {
383 char c = upgrade_header[i];
384
385 /* RFC 7230 3.2.6: The list of allowed characters is a token is: */
386 /* "!" / "#" / "$" / "%" / "&" / "'" / "*" / */
387 /* "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" */
388 /* DIGIT / ALPHA */
389 /* We also allow "/" here as the sub-delimiter for the protocol version */
390 if ('!' == c || '#' == c || '$' == c || '%' == c ||
391 '&' == c || '\'' == c || '*' == c ||
392 '+' == c || '-' == c || '.' == c || '^' == c ||
393 '_' == c || '`' == c || '|' == c || '~' == c ||
394 '/' == c ||
395 ('0' <= c && '9' >= c) ||
396 ('A' <= c && 'Z' >= c) || ('a' <= c && 'z' >= c) )
397 {
398 /* This is a valid token character */
399 if (NULL == keyword_start)
400 {
401 keyword_start = upgrade_header + i;
402 }
403 keyword_end = upgrade_header + i + 1;
404 }
405 else if (' ' == c || '\t' == c)
406 {
407 /* White-spaces around tokens will be ignored */
408 }
409 else if (',' == c || 0 == c)
410 {
411 /* Check the token (case-insensitive) */
412 if (NULL != keyword_start)
413 {
414 if ( 9 == (keyword_end - keyword_start) )
415 {
416 if ( ('W' == keyword_start[0] || 'w' == keyword_start[0]) &&
417 ('E' == keyword_start[1] || 'e' == keyword_start[1]) &&
418 ('B' == keyword_start[2] || 'b' == keyword_start[2]) &&
419 ('S' == keyword_start[3] || 's' == keyword_start[3]) &&
420 ('O' == keyword_start[4] || 'o' == keyword_start[4]) &&
421 ('C' == keyword_start[5] || 'c' == keyword_start[5]) &&
422 ('K' == keyword_start[6] || 'k' == keyword_start[6]) &&
423 ('E' == keyword_start[7] || 'e' == keyword_start[7]) &&
424 ('T' == keyword_start[8] || 't' == keyword_start[8]) )
425 {
426 /* The keyword equals to "websocket" */
427 return MHD_WEBSOCKET_STATUS_OK;
428 }
429 }
430 }
431 if (0 == c)
432 {
433 break;
434 }
435 keyword_start = NULL;
436 keyword_end = NULL;
437 }
438 else
439 {
440 /* RFC 7230 3.2.6: Other characters are not allowed */
441 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
442 }
443 }
444 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
445}
446
447
448/**
449 * Checks whether the "Sec-WebSocket-Version" request header
450 * equals to "13"
451 */
452_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
453MHD_websocket_check_version_header (const char* version_header)
454{
455 /* validate parameters */
456 if (NULL == version_header)
457 {
458 /* To be compatible with the return value */
459 /* of MHD_lookup_connection_value, */
460 /* NULL is threated as "value not given" and not as parameter error */
461 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
462 }
463
464 if ('1' == version_header[0] &&
465 '3' == version_header[1] &&
466 0 == version_header[2])
467 {
468 /* The version equals to "13" */
469 return MHD_WEBSOCKET_STATUS_OK;
470 }
471 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
472}
473
180 474
181/** 475/**
182 * Creates the response for the Sec-WebSocket-Accept header 476 * Creates the response for the Sec-WebSocket-Accept header
183 */ 477 */
184_MHD_EXTERN int 478_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
185MHD_websocket_create_accept (const char*sec_websocket_key, 479MHD_websocket_create_accept_header (const char*sec_websocket_key,
186 char*sec_websocket_accept) 480 char*sec_websocket_accept)
187{ 481{
188 /* initialize output variables for errors cases */ 482 /* initialize output variables for errors cases */
189 if (NULL != sec_websocket_accept) 483 if (NULL != sec_websocket_accept)
190 *sec_websocket_accept = 0; 484 *sec_websocket_accept = 0;
191 485
192 /* validate parameters */ 486 /* validate parameters */
193 if ((NULL == sec_websocket_key) || 487 if (NULL == sec_websocket_accept)
194 (NULL == sec_websocket_accept) )
195 { 488 {
196 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; 489 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR;
197 } 490 }
491 if (NULL == sec_websocket_key)
492 {
493 /* NULL is not a parameter error, */
494 /* because MHD_lookup_connection_value returns NULL */
495 /* if the header wasn't found */
496 return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER;
497 }
198 498
199 /* build SHA1 hash of the given key and the UUID appended */ 499 /* build SHA1 hash of the given key and the UUID appended */
200 char sha1[20]; 500 char sha1[20];
201 const char*suffix = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 501 const char*suffix = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
202 int length = (int) strlen (sec_websocket_key); 502 int length = (int) strlen (sec_websocket_key);
203 struct sha1_ctx ctx; 503 struct sha1_ctx ctx;
204 sha1_init_ctx (&ctx); 504 MHD_SHA1_init (&ctx);
205 sha1_process_bytes (sec_websocket_key, length, &ctx); 505 MHD_SHA1_update (&ctx, (const uint8_t*) sec_websocket_key, length);
206 sha1_process_bytes (suffix, 36, &ctx); 506 MHD_SHA1_update (&ctx, (const uint8_t*) suffix, 36);
207 sha1_finish_ctx (&ctx, sha1); 507 MHD_SHA1_finish (&ctx, (uint8_t*) sha1);
208 508
209 /* base64 encode that SHA1 hash */ 509 /* base64 encode that SHA1 hash */
210 /* (simple algorithm here; SHA1 has always 20 bytes, */ 510 /* (simple algorithm here; SHA1 has always 20 bytes, */
@@ -234,7 +534,7 @@ MHD_websocket_create_accept (const char*sec_websocket_key,
234/** 534/**
235 * Initializes a new websocket stream 535 * Initializes a new websocket stream
236 */ 536 */
237_MHD_EXTERN int 537_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
238MHD_websocket_stream_init (struct MHD_WebSocketStream**ws, 538MHD_websocket_stream_init (struct MHD_WebSocketStream**ws,
239 int flags, 539 int flags,
240 size_t max_payload_size) 540 size_t max_payload_size)
@@ -244,7 +544,9 @@ MHD_websocket_stream_init (struct MHD_WebSocketStream**ws,
244 max_payload_size, 544 max_payload_size,
245 malloc, 545 malloc,
246 realloc, 546 realloc,
247 free); 547 free,
548 NULL,
549 NULL);
248} 550}
249 551
250 552
@@ -252,13 +554,15 @@ MHD_websocket_stream_init (struct MHD_WebSocketStream**ws,
252 * Initializes a new websocket stream with 554 * Initializes a new websocket stream with
253 * additional parameters for allocation functions 555 * additional parameters for allocation functions
254 */ 556 */
255_MHD_EXTERN int 557_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
256MHD_websocket_stream_init2 (struct MHD_WebSocketStream**ws, 558MHD_websocket_stream_init2 (struct MHD_WebSocketStream**ws,
257 int flags, 559 int flags,
258 size_t max_payload_size, 560 size_t max_payload_size,
259 MHD_WebSocketMallocCallback callback_malloc, 561 MHD_WebSocketMallocCallback callback_malloc,
260 MHD_WebSocketReallocCallback callback_realloc, 562 MHD_WebSocketReallocCallback callback_realloc,
261 MHD_WebSocketFreeCallback callback_free) 563 MHD_WebSocketFreeCallback callback_free,
564 void* cls_rng,
565 MHD_WebSocketRandomNumberGenerator callback_rng)
262{ 566{
263 /* initialize output variables for errors cases */ 567 /* initialize output variables for errors cases */
264 if (NULL != ws) 568 if (NULL != ws)
@@ -270,7 +574,9 @@ MHD_websocket_stream_init2 (struct MHD_WebSocketStream**ws,
270 ((uint64_t) 0x7FFFFFFFFFFFFFFF < max_payload_size) || 574 ((uint64_t) 0x7FFFFFFFFFFFFFFF < max_payload_size) ||
271 (NULL == callback_malloc) || 575 (NULL == callback_malloc) ||
272 (NULL == callback_realloc) || 576 (NULL == callback_realloc) ||
273 (NULL == callback_free) ) 577 (NULL == callback_free) ||
578 ((0 != (flags & MHD_WEBSOCKET_FLAG_CLIENT)) &&
579 (NULL == callback_rng)))
274 { 580 {
275 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; 581 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR;
276 } 582 }
@@ -288,6 +594,8 @@ MHD_websocket_stream_init2 (struct MHD_WebSocketStream**ws,
288 ws_->malloc = callback_malloc; 594 ws_->malloc = callback_malloc;
289 ws_->realloc = callback_realloc; 595 ws_->realloc = callback_realloc;
290 ws_->free = callback_free; 596 ws_->free = callback_free;
597 ws_->cls_rng = cls_rng;
598 ws_->rng = callback_rng;
291 ws_->validity = MHD_WEBSOCKET_VALIDITY_VALID; 599 ws_->validity = MHD_WEBSOCKET_VALIDITY_VALID;
292 600
293 /* return stream */ 601 /* return stream */
@@ -300,7 +608,7 @@ MHD_websocket_stream_init2 (struct MHD_WebSocketStream**ws,
300/** 608/**
301 * Frees a previously allocated websocket stream 609 * Frees a previously allocated websocket stream
302 */ 610 */
303_MHD_EXTERN int 611_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
304MHD_websocket_stream_free (struct MHD_WebSocketStream*ws) 612MHD_websocket_stream_free (struct MHD_WebSocketStream*ws)
305{ 613{
306 /* validate parameters */ 614 /* validate parameters */
@@ -323,7 +631,7 @@ MHD_websocket_stream_free (struct MHD_WebSocketStream*ws)
323/** 631/**
324 * Invalidates a websocket stream (no more decoding possible) 632 * Invalidates a websocket stream (no more decoding possible)
325 */ 633 */
326_MHD_EXTERN int 634_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
327MHD_websocket_stream_invalidate (struct MHD_WebSocketStream*ws) 635MHD_websocket_stream_invalidate (struct MHD_WebSocketStream*ws)
328{ 636{
329 /* validate parameters */ 637 /* validate parameters */
@@ -340,7 +648,7 @@ MHD_websocket_stream_invalidate (struct MHD_WebSocketStream*ws)
340/** 648/**
341 * Returns whether a websocket stream is valid 649 * Returns whether a websocket stream is valid
342 */ 650 */
343_MHD_EXTERN int 651_MHD_EXTERN enum MHD_WEBSOCKET_VALIDITY
344MHD_websocket_stream_is_valid (struct MHD_WebSocketStream*ws) 652MHD_websocket_stream_is_valid (struct MHD_WebSocketStream*ws)
345{ 653{
346 /* validate parameters */ 654 /* validate parameters */
@@ -354,7 +662,7 @@ MHD_websocket_stream_is_valid (struct MHD_WebSocketStream*ws)
354/** 662/**
355 * Decodes incoming data to a websocket frame 663 * Decodes incoming data to a websocket frame
356 */ 664 */
357_MHD_EXTERN int 665_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
358MHD_websocket_decode (struct MHD_WebSocketStream*ws, 666MHD_websocket_decode (struct MHD_WebSocketStream*ws,
359 const char*streambuf, 667 const char*streambuf,
360 size_t streambuf_len, 668 size_t streambuf_len,
@@ -372,7 +680,7 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
372 680
373 /* validate parameters */ 681 /* validate parameters */
374 if ((NULL == ws) || 682 if ((NULL == ws) ||
375 (NULL == streambuf) && (0 != streambuf_len) || 683 ((NULL == streambuf) && (0 != streambuf_len)) ||
376 (NULL == streambuf_read_len) || 684 (NULL == streambuf_read_len) ||
377 (NULL == payload) || 685 (NULL == payload) ||
378 (NULL == payload_len) ) 686 (NULL == payload_len) )
@@ -657,8 +965,8 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
657 else 965 else
658 { 966 {
659 size_t size = (size_t) frame_len; 967 size_t size = (size_t) frame_len;
660 if ((SIZE_MAX < size) || ws->max_payload_size && 968 if ((SIZE_MAX < size) ||
661 (ws->max_payload_size < size) ) 969 (ws->max_payload_size && (ws->max_payload_size < size)) )
662 { 970 {
663 /* RFC 6455 7.4.1 1009: If the message is too big to process, we may close the connection */ 971 /* RFC 6455 7.4.1 1009: If the message is too big to process, we may close the connection */
664 ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; 972 ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID;
@@ -713,8 +1021,7 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
713 case MHD_WebSocket_DecodeStep_Length2of2: 1021 case MHD_WebSocket_DecodeStep_Length2of2:
714 { 1022 {
715 ws->frame_header [ws->frame_header_size++] = streambuf [current++]; 1023 ws->frame_header [ws->frame_header_size++] = streambuf [current++];
716 size_t size = (size_t) htons (*((unsigned 1024 size_t size = (size_t) MHD_htons (*((uint16_t*) &ws->frame_header [2]));
717 short*) &ws->frame_header [2]));
718 if (125 >= size) 1025 if (125 >= size)
719 { 1026 {
720 /* RFC 6455 5.2 Payload length: The minimal number of bytes */ 1027 /* RFC 6455 5.2 Payload length: The minimal number of bytes */
@@ -733,8 +1040,8 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
733 *streambuf_read_len = current; 1040 *streambuf_read_len = current;
734 return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; 1041 return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR;
735 } 1042 }
736 if ((SIZE_MAX < size) || ws->max_payload_size && (ws->max_payload_size < 1043 if ((SIZE_MAX < size) ||
737 size) ) 1044 (ws->max_payload_size && (ws->max_payload_size < size)) )
738 { 1045 {
739 /* RFC 6455 7.4.1 1009: If the message is too big to process, */ 1046 /* RFC 6455 7.4.1 1009: If the message is too big to process, */
740 /* we may close the connection */ 1047 /* we may close the connection */
@@ -771,7 +1078,7 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
771 case MHD_WebSocket_DecodeStep_Length8of8: 1078 case MHD_WebSocket_DecodeStep_Length8of8:
772 { 1079 {
773 ws->frame_header [ws->frame_header_size++] = streambuf [current++]; 1080 ws->frame_header [ws->frame_header_size++] = streambuf [current++];
774 uint64_t size = htonll (*((uint64_t*) &ws->frame_header [2])); 1081 uint64_t size = MHD_htonll (*((uint64_t*) &ws->frame_header [2]));
775 if (0x7fffffffffffffff < size) 1082 if (0x7fffffffffffffff < size)
776 { 1083 {
777 /* RFC 6455 5.2 frame-payload-length-63: The length may */ 1084 /* RFC 6455 5.2 frame-payload-length-63: The length may */
@@ -809,8 +1116,8 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
809 *streambuf_read_len = current; 1116 *streambuf_read_len = current;
810 return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; 1117 return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR;
811 } 1118 }
812 if ((SIZE_MAX < size) || ws->max_payload_size && (ws->max_payload_size < 1119 if ((SIZE_MAX < size) ||
813 size) ) 1120 (ws->max_payload_size && (ws->max_payload_size < size)) )
814 { 1121 {
815 /* RFC 6455 7.4.1 1009: If the message is too big to process, */ 1122 /* RFC 6455 7.4.1 1009: If the message is too big to process, */
816 /* we may close the connection */ 1123 /* we may close the connection */
@@ -893,13 +1200,13 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
893 & 0x03)); 1200 & 0x03));
894 current += bytes_to_take; 1201 current += bytes_to_take;
895 ws->payload_index += bytes_to_take; 1202 ws->payload_index += bytes_to_take;
896 if ((MHD_WebSocket_DecodeStep_PayloadOfDataFrame == 1203 if (((MHD_WebSocket_DecodeStep_PayloadOfDataFrame ==
897 ws->decode_step) && 1204 ws->decode_step) &&
898 (MHD_WebSocket_Opcode_Text == ws->data_type) || 1205 (MHD_WebSocket_Opcode_Text == ws->data_type)) ||
899 (MHD_WebSocket_DecodeStep_PayloadOfControlFrame == 1206 ((MHD_WebSocket_DecodeStep_PayloadOfControlFrame ==
900 ws->decode_step) && 1207 ws->decode_step) &&
901 (MHD_WebSocket_Opcode_Close == (ws->frame_header [0] & 0x0f)) && 1208 (MHD_WebSocket_Opcode_Close == (ws->frame_header [0] & 0x0f)) &&
902 (2 < ws->payload_index) ) 1209 (2 < ws->payload_index)) )
903 { 1210 {
904 /* RFC 6455 8.1: We need to check the UTF-8 validity */ 1211 /* RFC 6455 8.1: We need to check the UTF-8 validity */
905 int utf8_step; 1212 int utf8_step;
@@ -1016,7 +1323,7 @@ MHD_websocket_decode (struct MHD_WebSocketStream*ws,
1016} 1323}
1017 1324
1018 1325
1019static int 1326static enum MHD_WEBSOCKET_STATUS
1020MHD_websocket_decode_header_complete (struct MHD_WebSocketStream*ws, 1327MHD_websocket_decode_header_complete (struct MHD_WebSocketStream*ws,
1021 char**payload, 1328 char**payload,
1022 size_t*payload_len) 1329 size_t*payload_len)
@@ -1119,13 +1426,15 @@ MHD_websocket_decode_header_complete (struct MHD_WebSocketStream*ws,
1119} 1426}
1120 1427
1121 1428
1122static int 1429static enum MHD_WEBSOCKET_STATUS
1123MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws, 1430MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
1124 char**payload, 1431 char**payload,
1125 size_t*payload_len) 1432 size_t*payload_len)
1126{ 1433{
1127 /* all payload data of the current frame has been received */ 1434 /* all payload data of the current frame has been received */
1128 char is_fin = ws->frame_header [0] & 0x80; 1435 char is_continue = MHD_WebSocket_Opcode_Continuation ==
1436 (ws->frame_header [0] & 0x0F);
1437 char is_fin = ws->frame_header [0] & 0x80;
1129 if (0 != is_fin) 1438 if (0 != is_fin)
1130 { 1439 {
1131 /* the frame is complete */ 1440 /* the frame is complete */
@@ -1134,9 +1443,9 @@ MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
1134 /* data frame */ 1443 /* data frame */
1135 char data_type = ws->data_type; 1444 char data_type = ws->data_type;
1136 if ((0 != (ws->flags & MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS)) && 1445 if ((0 != (ws->flags & MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS)) &&
1137 (MHD_WebSocket_Opcode_Continuation == (ws->frame_header [0] & 0x0F))) 1446 (0 != is_continue))
1138 { 1447 {
1139 data_type |= 0x20; /* mark as last fragment */ 1448 data_type |= 0x40; /* mark as last fragment */
1140 } 1449 }
1141 *payload = ws->data_payload; 1450 *payload = ws->data_payload;
1142 *payload_len = ws->data_payload_size; 1451 *payload_len = ws->data_payload_size;
@@ -1170,7 +1479,7 @@ MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
1170 { 1479 {
1171 /* the last UTF-8 sequence is incomplete, so we keep the start of 1480 /* the last UTF-8 sequence is incomplete, so we keep the start of
1172 that and only return the part before */ 1481 that and only return the part before */
1173 size_t given_utf8; 1482 size_t given_utf8 = 0;
1174 switch (ws->data_utf8_step) 1483 switch (ws->data_utf8_step)
1175 { 1484 {
1176 /* one byte given */ 1485 /* one byte given */
@@ -1220,7 +1529,10 @@ MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
1220 ws->decode_step = MHD_WebSocket_DecodeStep_Start; 1529 ws->decode_step = MHD_WebSocket_DecodeStep_Start;
1221 ws->payload_index = 0; 1530 ws->payload_index = 0;
1222 ws->frame_header_size = 0; 1531 ws->frame_header_size = 0;
1223 return ws->data_type | 0x10; /* mark as fragment */ 1532 if (0 != is_continue)
1533 return ws->data_type | 0x20; /* mark as middle fragment */
1534 else
1535 return ws->data_type | 0x10; /* mark as first fragment */
1224 } 1536 }
1225 else 1537 else
1226 { 1538 {
@@ -1233,7 +1545,10 @@ MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
1233 ws->decode_step = MHD_WebSocket_DecodeStep_Start; 1545 ws->decode_step = MHD_WebSocket_DecodeStep_Start;
1234 ws->payload_index = 0; 1546 ws->payload_index = 0;
1235 ws->frame_header_size = 0; 1547 ws->frame_header_size = 0;
1236 return ws->data_type | 0x10; /* mark as fragment */ 1548 if (0 != is_continue)
1549 return ws->data_type | 0x20; /* mark as middle fragment */
1550 else
1551 return ws->data_type | 0x10; /* mark as first fragment */
1237 } 1552 }
1238 } 1553 }
1239 else 1554 else
@@ -1251,7 +1566,7 @@ MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream*ws,
1251/** 1566/**
1252 * Splits the received close reason 1567 * Splits the received close reason
1253 */ 1568 */
1254_MHD_EXTERN int 1569_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
1255MHD_websocket_split_close_reason (const char*payload, 1570MHD_websocket_split_close_reason (const char*payload,
1256 size_t payload_len, 1571 size_t payload_len,
1257 unsigned short*reason_code, 1572 unsigned short*reason_code,
@@ -1283,7 +1598,7 @@ MHD_websocket_split_close_reason (const char*payload,
1283 else 1598 else
1284 { 1599 {
1285 if (NULL != reason_code) 1600 if (NULL != reason_code)
1286 *reason_code = htons (*((unsigned short*) payload)); 1601 *reason_code = MHD_htons (*((uint16_t*) payload));
1287 } 1602 }
1288 1603
1289 /* decode reason text */ 1604 /* decode reason text */
@@ -1309,7 +1624,7 @@ MHD_websocket_split_close_reason (const char*payload,
1309/** 1624/**
1310 * Encodes a text into a websocket text frame 1625 * Encodes a text into a websocket text frame
1311 */ 1626 */
1312_MHD_EXTERN int 1627_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
1313MHD_websocket_encode_text (struct MHD_WebSocketStream*ws, 1628MHD_websocket_encode_text (struct MHD_WebSocketStream*ws,
1314 const char*payload_utf8, 1629 const char*payload_utf8,
1315 size_t payload_utf8_len, 1630 size_t payload_utf8_len,
@@ -1333,13 +1648,13 @@ MHD_websocket_encode_text (struct MHD_WebSocketStream*ws,
1333 1648
1334 /* validate parameters */ 1649 /* validate parameters */
1335 if ((NULL == ws) || 1650 if ((NULL == ws) ||
1336 (0 != payload_utf8_len) && (NULL == payload_utf8) || 1651 ((0 != payload_utf8_len) && (NULL == payload_utf8)) ||
1337 (NULL == frame) || 1652 (NULL == frame) ||
1338 (NULL == frame_len) || 1653 (NULL == frame_len) ||
1339 (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) || 1654 (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) ||
1340 (MHD_WEBSOCKET_FRAGMENTATION_LAST < fragmentation) || 1655 (MHD_WEBSOCKET_FRAGMENTATION_LAST < fragmentation) ||
1341 (MHD_WEBSOCKET_FRAGMENTATION_NONE != fragmentation) && (NULL == 1656 ((MHD_WEBSOCKET_FRAGMENTATION_NONE != fragmentation) &&
1342 utf8_step) ) 1657 (NULL == utf8_step)) )
1343 { 1658 {
1344 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; 1659 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR;
1345 } 1660 }
@@ -1356,8 +1671,8 @@ MHD_websocket_encode_text (struct MHD_WebSocketStream*ws,
1356 utf8_step, 1671 utf8_step,
1357 NULL); 1672 NULL);
1358 if ((MHD_WebSocket_UTF8Result_Invalid == utf8_result) || 1673 if ((MHD_WebSocket_UTF8Result_Invalid == utf8_result) ||
1359 (MHD_WebSocket_UTF8Result_Incomplete == utf8_result) && 1674 ((MHD_WebSocket_UTF8Result_Incomplete == utf8_result) &&
1360 (MHD_WEBSOCKET_FRAGMENTATION_NONE == fragmentation) ) 1675 (MHD_WEBSOCKET_FRAGMENTATION_NONE == fragmentation)) )
1361 { 1676 {
1362 return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; 1677 return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR;
1363 } 1678 }
@@ -1376,7 +1691,7 @@ MHD_websocket_encode_text (struct MHD_WebSocketStream*ws,
1376/** 1691/**
1377 * Encodes binary data into a websocket binary frame 1692 * Encodes binary data into a websocket binary frame
1378 */ 1693 */
1379_MHD_EXTERN int 1694_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
1380MHD_websocket_encode_binary (struct MHD_WebSocketStream*ws, 1695MHD_websocket_encode_binary (struct MHD_WebSocketStream*ws,
1381 const char*payload, 1696 const char*payload,
1382 size_t payload_len, 1697 size_t payload_len,
@@ -1392,7 +1707,7 @@ MHD_websocket_encode_binary (struct MHD_WebSocketStream*ws,
1392 1707
1393 /* validate parameters */ 1708 /* validate parameters */
1394 if ((NULL == ws) || 1709 if ((NULL == ws) ||
1395 (0 != payload_len) && (NULL == payload) || 1710 ((0 != payload_len) && (NULL == payload)) ||
1396 (NULL == frame) || 1711 (NULL == frame) ||
1397 (NULL == frame_len) || 1712 (NULL == frame_len) ||
1398 (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) || 1713 (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) ||
@@ -1420,7 +1735,7 @@ MHD_websocket_encode_binary (struct MHD_WebSocketStream*ws,
1420/** 1735/**
1421 * Internal function for encoding text/binary data into a websocket frame 1736 * Internal function for encoding text/binary data into a websocket frame
1422 */ 1737 */
1423static int 1738static enum MHD_WEBSOCKET_STATUS
1424MHD_websocket_encode_data (struct MHD_WebSocketStream*ws, 1739MHD_websocket_encode_data (struct MHD_WebSocketStream*ws,
1425 const char*payload, 1740 const char*payload,
1426 size_t payload_len, 1741 size_t payload_len,
@@ -1433,7 +1748,7 @@ MHD_websocket_encode_data (struct MHD_WebSocketStream*ws,
1433 char is_masked = MHD_websocket_encode_is_masked (ws); 1748 char is_masked = MHD_websocket_encode_is_masked (ws);
1434 size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); 1749 size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len);
1435 size_t total_len = overhead_len + payload_len; 1750 size_t total_len = overhead_len + payload_len;
1436 uint32_t mask = 0 != is_masked ? MHD_websocket_generate_mask () : 0; 1751 uint32_t mask = 0 != is_masked ? MHD_websocket_generate_mask (ws) : 0;
1437 1752
1438 /* allocate memory */ 1753 /* allocate memory */
1439 char*result = ws->malloc (total_len + 1); 1754 char*result = ws->malloc (total_len + 1);
@@ -1468,13 +1783,13 @@ MHD_websocket_encode_data (struct MHD_WebSocketStream*ws,
1468 else if (65536 > payload_len) 1783 else if (65536 > payload_len)
1469 { 1784 {
1470 *(result++) = is_masked | 126; 1785 *(result++) = is_masked | 126;
1471 *((unsigned short *) result) = htons ((unsigned short) payload_len); 1786 *((uint16_t *) result) = MHD_htons ((uint16_t) payload_len);
1472 result += 2; 1787 result += 2;
1473 } 1788 }
1474 else 1789 else
1475 { 1790 {
1476 *(result++) = is_masked | 127; 1791 *(result++) = is_masked | 127;
1477 *((uint64_t *) result) = htonll ((uint64_t) payload_len); 1792 *((uint64_t *) result) = MHD_htonll ((uint64_t) payload_len);
1478 result += 8; 1793 result += 8;
1479 1794
1480 } 1795 }
@@ -1505,7 +1820,7 @@ MHD_websocket_encode_data (struct MHD_WebSocketStream*ws,
1505/** 1820/**
1506 * Encodes a websocket ping frame 1821 * Encodes a websocket ping frame
1507 */ 1822 */
1508_MHD_EXTERN int 1823_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
1509MHD_websocket_encode_ping (struct MHD_WebSocketStream*ws, 1824MHD_websocket_encode_ping (struct MHD_WebSocketStream*ws,
1510 const char*payload, 1825 const char*payload,
1511 size_t payload_len, 1826 size_t payload_len,
@@ -1525,7 +1840,7 @@ MHD_websocket_encode_ping (struct MHD_WebSocketStream*ws,
1525/** 1840/**
1526 * Encodes a websocket pong frame 1841 * Encodes a websocket pong frame
1527 */ 1842 */
1528_MHD_EXTERN int 1843_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
1529MHD_websocket_encode_pong (struct MHD_WebSocketStream*ws, 1844MHD_websocket_encode_pong (struct MHD_WebSocketStream*ws,
1530 const char*payload, 1845 const char*payload,
1531 size_t payload_len, 1846 size_t payload_len,
@@ -1545,7 +1860,7 @@ MHD_websocket_encode_pong (struct MHD_WebSocketStream*ws,
1545/** 1860/**
1546 * Internal function for encoding ping/pong frames 1861 * Internal function for encoding ping/pong frames
1547 */ 1862 */
1548static int 1863static enum MHD_WEBSOCKET_STATUS
1549MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws, 1864MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws,
1550 const char*payload, 1865 const char*payload,
1551 size_t payload_len, 1866 size_t payload_len,
@@ -1561,7 +1876,7 @@ MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws,
1561 1876
1562 /* validate the parameters */ 1877 /* validate the parameters */
1563 if ((NULL == ws) || 1878 if ((NULL == ws) ||
1564 (0 != payload_len) && (NULL == payload) || 1879 ((0 != payload_len) && (NULL == payload)) ||
1565 (NULL == frame) || 1880 (NULL == frame) ||
1566 (NULL == frame_len) ) 1881 (NULL == frame_len) )
1567 { 1882 {
@@ -1576,7 +1891,7 @@ MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws,
1576 char is_masked = MHD_websocket_encode_is_masked (ws); 1891 char is_masked = MHD_websocket_encode_is_masked (ws);
1577 size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); 1892 size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len);
1578 size_t total_len = overhead_len + payload_len; 1893 size_t total_len = overhead_len + payload_len;
1579 uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask () : 0; 1894 uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask (ws) : 0;
1580 1895
1581 /* allocate memory */ 1896 /* allocate memory */
1582 char*result = ws->malloc (total_len + 1); 1897 char*result = ws->malloc (total_len + 1);
@@ -1618,7 +1933,7 @@ MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream*ws,
1618/** 1933/**
1619 * Encodes a websocket close frame 1934 * Encodes a websocket close frame
1620 */ 1935 */
1621_MHD_EXTERN int 1936_MHD_EXTERN enum MHD_WEBSOCKET_STATUS
1622MHD_websocket_encode_close (struct MHD_WebSocketStream*ws, 1937MHD_websocket_encode_close (struct MHD_WebSocketStream*ws,
1623 unsigned short reason_code, 1938 unsigned short reason_code,
1624 const char*reason_utf8, 1939 const char*reason_utf8,
@@ -1634,13 +1949,13 @@ MHD_websocket_encode_close (struct MHD_WebSocketStream*ws,
1634 1949
1635 /* validate the parameters */ 1950 /* validate the parameters */
1636 if ((NULL == ws) || 1951 if ((NULL == ws) ||
1637 (0 != reason_utf8_len) && (NULL == reason_utf8) || 1952 ((0 != reason_utf8_len) && (NULL == reason_utf8)) ||
1638 (NULL == frame) || 1953 (NULL == frame) ||
1639 (NULL == frame_len) || 1954 (NULL == frame_len) ||
1640 (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) && (1000 > 1955 ((MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) &&
1641 reason_code) || 1956 (1000 > reason_code)) ||
1642 (0 != reason_utf8_len) && (MHD_WEBSOCKET_CLOSEREASON_NO_REASON == 1957 ((0 != reason_utf8_len) &&
1643 reason_code) ) 1958 (MHD_WEBSOCKET_CLOSEREASON_NO_REASON == reason_code)) )
1644 { 1959 {
1645 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; 1960 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR;
1646 } 1961 }
@@ -1668,7 +1983,7 @@ MHD_websocket_encode_close (struct MHD_WebSocketStream*ws,
1668 2 + reason_utf8_len : 0); 1983 2 + reason_utf8_len : 0);
1669 size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); 1984 size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len);
1670 size_t total_len = overhead_len + payload_len; 1985 size_t total_len = overhead_len + payload_len;
1671 uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask () : 0; 1986 uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask (ws) : 0;
1672 1987
1673 /* allocate memory */ 1988 /* allocate memory */
1674 char*result = ws->malloc (total_len + 1); 1989 char*result = ws->malloc (total_len + 1);
@@ -1697,7 +2012,7 @@ MHD_websocket_encode_close (struct MHD_WebSocketStream*ws,
1697 if (0 != reason_code) 2012 if (0 != reason_code)
1698 { 2013 {
1699 /* close reason code */ 2014 /* close reason code */
1700 unsigned short reason_code_nb = htons (reason_code); 2015 uint16_t reason_code_nb = MHD_htons (reason_code);
1701 MHD_websocket_copy_payload (result, 2016 MHD_websocket_copy_payload (result,
1702 (const char*) &reason_code_nb, 2017 (const char*) &reason_code_nb,
1703 2, 2018 2,
@@ -1815,8 +2130,8 @@ MHD_websocket_check_utf8 (const char*buf,
1815 /* RFC 3629 4: three byte UTF-8 sequence, but the second byte must be 0x80-0x9F */ 2130 /* RFC 3629 4: three byte UTF-8 sequence, but the second byte must be 0x80-0x9F */
1816 utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2; 2131 utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2;
1817 } 2132 }
1818 else if ((0xE1 <= character) && (0xEC >= character) || 2133 else if (((0xE1 <= character) && (0xEC >= character)) ||
1819 (0xEE <= character) && (0xEF >= character) ) 2134 ((0xEE <= character) && (0xEF >= character)) )
1820 { 2135 {
1821 /* RFC 3629 4: three byte UTF-8 sequence, both tail bytes must be 0x80-0xBF */ 2136 /* RFC 3629 4: three byte UTF-8 sequence, both tail bytes must be 0x80-0xBF */
1822 utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2; 2137 utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2;
@@ -1991,30 +2306,32 @@ MHD_websocket_check_utf8 (const char*buf,
1991 2306
1992 2307
1993/** 2308/**
1994 * Calls srand in the scope of MHD to set the seed
1995 * for the random number generator used for masking.
1996 */
1997_MHD_EXTERN int
1998MHD_websocket_srand (unsigned long seed)
1999{
2000 srand (seed);
2001
2002 return MHD_WEBSOCKET_STATUS_OK;
2003}
2004
2005
2006/**
2007 * Generates a mask for masking by calling 2309 * Generates a mask for masking by calling
2008 * a random number generator. 2310 * a random number generator.
2009 */ 2311 */
2010static uint32_t 2312static uint32_t
2011MHD_websocket_generate_mask () 2313MHD_websocket_generate_mask (struct MHD_WebSocketStream*ws)
2012{ 2314{
2013 unsigned char mask_[4]; 2315 unsigned char mask_[4];
2014 mask_ [0] = (unsigned char) (rand () & 0xFF); 2316 if (NULL != ws->rng)
2015 mask_ [1] = (unsigned char) (rand () & 0xFF); 2317 {
2016 mask_ [2] = (unsigned char) (rand () & 0xFF); 2318 size_t offset = 0;
2017 mask_ [3] = (unsigned char) (rand () & 0xFF); 2319 while (offset < 4)
2320 {
2321 size_t encoded = ws->rng (ws->cls_rng,
2322 mask_ + offset,
2323 4 - offset);
2324 offset += encoded;
2325 }
2326 }
2327 else
2328 {
2329 /* this case should never happen */
2330 mask_ [0] = 0;
2331 mask_ [1] = 0;
2332 mask_ [2] = 0;
2333 mask_ [3] = 0;
2334 }
2018 2335
2019 return *((uint32_t *) mask_); 2336 return *((uint32_t *) mask_);
2020} 2337}
@@ -2024,15 +2341,15 @@ MHD_websocket_generate_mask ()
2024 * Calls the malloc function associated with the websocket steam 2341 * Calls the malloc function associated with the websocket steam
2025 */ 2342 */
2026_MHD_EXTERN void* 2343_MHD_EXTERN void*
2027MHD_websocket_malloc (struct MHD_WebSocketStream*ws, 2344MHD_websocket_malloc (struct MHD_WebSocketStream* ws,
2028 size_t len) 2345 size_t buf_len)
2029{ 2346{
2030 if (NULL == ws) 2347 if (NULL == ws)
2031 { 2348 {
2032 return NULL; 2349 return NULL;
2033 } 2350 }
2034 2351
2035 return ws->malloc (len); 2352 return ws->malloc (buf_len);
2036} 2353}
2037 2354
2038 2355
@@ -2040,16 +2357,16 @@ MHD_websocket_malloc (struct MHD_WebSocketStream*ws,
2040 * Calls the realloc function associated with the websocket steam 2357 * Calls the realloc function associated with the websocket steam
2041 */ 2358 */
2042_MHD_EXTERN void* 2359_MHD_EXTERN void*
2043MHD_websocket_realloc (struct MHD_WebSocketStream*ws, 2360MHD_websocket_realloc (struct MHD_WebSocketStream* ws,
2044 void*cls, 2361 void* buf,
2045 size_t len) 2362 size_t new_buf_len)
2046{ 2363{
2047 if (NULL == ws) 2364 if (NULL == ws)
2048 { 2365 {
2049 return NULL; 2366 return NULL;
2050 } 2367 }
2051 2368
2052 return ws->realloc (cls, len); 2369 return ws->realloc (buf, new_buf_len);
2053} 2370}
2054 2371
2055 2372
@@ -2057,15 +2374,67 @@ MHD_websocket_realloc (struct MHD_WebSocketStream*ws,
2057 * Calls the free function associated with the websocket steam 2374 * Calls the free function associated with the websocket steam
2058 */ 2375 */
2059_MHD_EXTERN int 2376_MHD_EXTERN int
2060MHD_websocket_free (struct MHD_WebSocketStream*ws, 2377MHD_websocket_free (struct MHD_WebSocketStream* ws,
2061 void*cls) 2378 void* buf)
2062{ 2379{
2063 if (NULL == ws) 2380 if (NULL == ws)
2064 { 2381 {
2065 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; 2382 return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR;
2066 } 2383 }
2067 2384
2068 ws->free (cls); 2385 ws->free (buf);
2069 2386
2070 return MHD_WEBSOCKET_STATUS_OK; 2387 return MHD_WEBSOCKET_STATUS_OK;
2071} 2388}
2389
2390/**
2391 * Converts a 16 bit value into network byte order (MSB first)
2392 * in dependence of the host system
2393 */
2394static uint16_t
2395MHD_htons (uint16_t value)
2396{
2397 uint16_t endian = 0x0001;
2398
2399 if (((char *) &endian)[0] == 0x01)
2400 {
2401 /* least significant byte first */
2402 ((char *) &endian)[0] = ((char *) &value)[1];
2403 ((char *) &endian)[1] = ((char *) &value)[0];
2404 return endian;
2405 }
2406 else
2407 {
2408 /* most significant byte first */
2409 return value;
2410 }
2411}
2412
2413/**
2414 * Converts a 64 bit value into network byte order (MSB first)
2415 * in dependence of the host system
2416 */
2417static uint64_t
2418MHD_htonll (uint64_t value)
2419{
2420 uint64_t endian = 0x0000000000000001;
2421
2422 if (((char *) &endian)[0] == 0x01)
2423 {
2424 /* least significant byte first */
2425 ((char *) &endian)[0] = ((char *) &value)[7];
2426 ((char *) &endian)[1] = ((char *) &value)[6];
2427 ((char *) &endian)[2] = ((char *) &value)[5];
2428 ((char *) &endian)[3] = ((char *) &value)[4];
2429 ((char *) &endian)[4] = ((char *) &value)[3];
2430 ((char *) &endian)[5] = ((char *) &value)[2];
2431 ((char *) &endian)[6] = ((char *) &value)[1];
2432 ((char *) &endian)[7] = ((char *) &value)[0];
2433 return endian;
2434 }
2435 else
2436 {
2437 /* most significant byte first */
2438 return value;
2439 }
2440}