WebSocket.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (c) 2018, 2020 Wind River Systems, Inc. and others. All Rights Reserved.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  * https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  * http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  * Keith Holman - initial implementation and documentation
15  * Ian Craggs - use memory tracking
16  * Ian Craggs - fix for one MQTT packet spread over >1 ws frame
17  *******************************************************************************/
18 
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <string.h>
22 // for timeout process in WebSocket_proxy_connect()
23 #include <time.h>
24 #if defined(_WIN32) || defined(_WIN64)
25 #include <windows.h>
26 #else
27 #include <unistd.h>
28 #endif
29 
30 #include "WebSocket.h"
31 
32 #include "Base64.h"
33 #include "Log.h"
34 #include "SHA1.h"
35 #include "LinkedList.h"
36 #include "MQTTProtocolOut.h"
37 #include "SocketBuffer.h"
38 #include "StackTrace.h"
39 
40 #if defined(__MINGW32__)
41 #define htonll __builtin_bswap64
42 #define ntohll __builtin_bswap64
43 #endif
44 
45 #if defined(__linux__)
46 # include <endian.h>
47 #elif defined(__APPLE__)
48 # include <libkern/OSByteOrder.h>
49 # define htobe16(x) OSSwapHostToBigInt16(x)
50 # define htobe32(x) OSSwapHostToBigInt32(x)
51 # define htobe64(x) OSSwapHostToBigInt64(x)
52 # define be16toh(x) OSSwapBigToHostInt16(x)
53 # define be32toh(x) OSSwapBigToHostInt32(x)
54 # define be64toh(x) OSSwapBigToHostInt64(x)
55 #elif defined(__FreeBSD__) || defined(__NetBSD__)
56 # include <sys/endian.h>
57 #elif defined(_WIN32) || defined(_WIN64)
58 # pragma comment(lib, "rpcrt4.lib")
59 # include <rpc.h>
60 # define strncasecmp(s1,s2,c) _strnicmp(s1,s2,c)
61 # define htonll(x) _byteswap_uint64(x)
62 # define ntohll(x) _byteswap_uint64(x)
63 
64 # if BYTE_ORDER == LITTLE_ENDIAN
65 # define htobe16(x) htons(x)
66 # define htobe32(x) htonl(x)
67 # define htobe64(x) htonll(x)
68 # define be16toh(x) ntohs(x)
69 # define be32toh(x) ntohl(x)
70 # define be64toh(x) ntohll(x)
71 # elif BYTE_ORDER == BIG_ENDIAN
72 # define htobe16(x) (x)
73 # define htobe32(x) (x)
74 # define htobe64(x) (x)
75 # define be16toh(x) (x)
76 # define be32toh(x) (x)
77 # define be64toh(x) (x)
78 # else
79 # error "unknown endian"
80 # endif
81  /* For Microsoft Visual Studio < 2015 */
82 # if defined(_MSC_VER) && _MSC_VER < 1900
83 # define snprintf _snprintf
84 # endif
85 #endif
86 
87 #if defined(OPENSSL)
88 #include "SSLSocket.h"
89 #include <openssl/rand.h>
90 #endif /* defined(OPENSSL) */
91 #include "Socket.h"
92 
93 #define HTTP_PROTOCOL(x) x ? "https" : "http"
94 
95 #if !(defined(_WIN32) || defined(_WIN64))
96 #if defined(LIBUUID)
97 #include <uuid/uuid.h>
98 #else /* if defined(USE_LIBUUID) */
99 #include <limits.h>
100 #include <stdlib.h>
101 #include <time.h>
102 
104 typedef unsigned char uuid_t[16];
105 
111 {
112 #if defined(OPENSSL)
113  int rc = RAND_bytes( out, sizeof(uuid_t));
114  if ( !rc )
115 #endif /* defined (OPENSSL) */
116  {
117  /* very insecure, but generates a random uuid */
118  int i;
119  srand(time(NULL));
120  for ( i = 0; i < 16; ++i )
121  out[i] = (unsigned char)(rand() % UCHAR_MAX);
122  out[6] = (out[6] & 0x0f) | 0x40;
123  out[8] = (out[8] & 0x3F) | 0x80;
124  }
125 }
126 
128 void uuid_unparse( uuid_t uu, char *out )
129 {
130  int i;
131  for ( i = 0; i < 16; ++i )
132  {
133  if ( i == 4 || i == 6 || i == 8 || i == 10 )
134  {
135  *out = '-';
136  ++out;
137  }
138  out += sprintf( out, "%02x", uu[i] );
139  }
140  *out = '\0';
141 }
142 #endif /* else if defined(LIBUUID) */
143 #endif /* if !(defined(_WIN32) || defined(_WIN64)) */
144 
145 #include "Heap.h"
146 
148 struct ws_frame
149 {
150  size_t len;
151  size_t pos;
152 };
153 
155 struct ws_frame *last_frame = NULL;
156 
158 static List* in_frames = NULL;
159 
160 static char * frame_buffer = NULL;
161 static size_t frame_buffer_len = 0;
162 static size_t frame_buffer_index = 0;
163 static size_t frame_buffer_data_len = 0;
164 
165 /* static function declarations */
166 static const char *WebSocket_strcasefind(
167  const char *buf, const char *str, size_t len);
168 
169 static char *WebSocket_getRawSocketData(
170  networkHandles *net, size_t bytes, size_t* actual_len, int* rc);
171 
172 static void WebSocket_rewindData( void );
173 
174 static void WebSocket_pong(
175  networkHandles *net, char *app_data, size_t app_data_len);
176 
177 static int WebSocket_receiveFrame(networkHandles *net, size_t *actual_len);
178 
179 
195 size_t WebSocket_calculateFrameHeaderSize(networkHandles *net, int mask_data, size_t data_len)
196 {
197  int ret = 0;
198  if ( net && net->websocket )
199  {
200  if ( data_len < 126u)
201  ret = 2; /* header 2 bytes */
202  else if ( data_len < 65536u )
203  ret = 4; /* for extra 2-bytes for payload length */
204  else if ( data_len < 0xFFFFFFFFFFFFFFFF )
205  ret = 10; /* for extra 8-bytes for payload length */
206  if ( mask_data & 0x1 )
207  ret += sizeof(uint32_t); /* for mask */
208  }
209  return ret;
210 }
211 
212 
231 struct frameData {
232  char* wsbuf0;
233  size_t wsbuf0len;
234 };
235 
236 static struct frameData WebSocket_buildFrame(networkHandles* net, int opcode, int mask_data,
237  char** pbuf0, size_t* pbuf0len, PacketBuffers* bufs)
238 {
239  int buf_len = 0u;
240  struct frameData rc;
241  int new_mask = 0;
242 
243  FUNC_ENTRY;
244  memset(&rc, '\0', sizeof(rc));
245  if ( net->websocket )
246  {
247  size_t ws_header_size = 0u;
248  size_t data_len = 0L;
249  int i;
250 
251  /* Calculate total length of MQTT buffers */
252  data_len = *pbuf0len;
253  for (i = 0; i < bufs->count; ++i)
254  data_len += bufs->buflens[i];
255 
256  /* add space for websocket frame header */
257  ws_header_size = WebSocket_calculateFrameHeaderSize(net, mask_data, data_len);
258  if (*pbuf0)
259  {
260  rc.wsbuf0len = *pbuf0len + ws_header_size;
261  rc.wsbuf0 = malloc(rc.wsbuf0len);
262  if (rc.wsbuf0 == NULL)
263  goto exit;
264  memcpy(&rc.wsbuf0[ws_header_size], *pbuf0, *pbuf0len);
265  }
266  else
267  {
268  rc.wsbuf0 = malloc(ws_header_size);
269  if (rc.wsbuf0 == NULL)
270  goto exit;
271  rc.wsbuf0len = ws_header_size;
272  }
273 
274  if (mask_data && (bufs->mask[0] == 0))
275  {
276  /* generate mask, since we are a client */
277 #if defined(OPENSSL)
278  RAND_bytes(&bufs->mask[0], sizeof(bufs->mask));
279 #else /* if defined(OPENSSL) */
280  bufs->mask[0] = (rand() % UINT8_MAX);
281  bufs->mask[1] = (rand() % UINT8_MAX);
282  bufs->mask[2] = (rand() % UINT8_MAX);
283  bufs->mask[3] = (rand() % UINT8_MAX);
284 #endif /* else if defined(OPENSSL) */
285  new_mask = 1;
286  }
287 
288  /* 1st byte */
289  rc.wsbuf0[buf_len] = (char)(1 << 7); /* final flag */
290  /* 3 bits reserved for negotiation of protocol */
291  rc.wsbuf0[buf_len] |= (char)(opcode & 0x0F); /* op code */
292  ++buf_len;
293 
294  /* 2nd byte */
295  rc.wsbuf0[buf_len] = (char)((mask_data & 0x1) << 7); /* masking bit */
296 
297  /* payload length */
298  if ( data_len < 126u )
299  rc.wsbuf0[buf_len++] |= data_len & 0x7F;
300 
301  /* 3rd byte & 4th bytes - extended payload length */
302  else if ( data_len < 65536u )
303  {
304  uint16_t len = htobe16((uint16_t)data_len);
305  rc.wsbuf0[buf_len++] |= (126u & 0x7F);
306  memcpy( &rc.wsbuf0[buf_len], &len, 2u );
307  buf_len += 2;
308  }
309  else if ( data_len < 0xFFFFFFFFFFFFFFFF )
310  {
311  uint64_t len = htobe64((uint64_t)data_len);
312  rc.wsbuf0[buf_len++] |= (127u & 0x7F);
313  memcpy( &rc.wsbuf0[buf_len], &len, 8 );
314  buf_len += 8;
315  }
316  else
317  {
318  Log(TRACE_PROTOCOL, 1, "Data too large for websocket frame" );
319  buf_len = -1;
320  }
321 
322  if (mask_data)
323  {
324  size_t idx = 0u;
325 
326  /* copy masking key into ws header */
327  memcpy( &rc.wsbuf0[buf_len], &bufs->mask, sizeof(uint32_t));
328  buf_len += sizeof(uint32_t);
329 
330  /* mask packet fixed header */
331  for (i = (int)ws_header_size; i < (int)rc.wsbuf0len; ++i, ++idx)
332  rc.wsbuf0[i] ^= bufs->mask[idx % 4];
333 
334  /* variable data buffers */
335  for (i = 0; i < bufs->count; ++i)
336  {
337  size_t j;
338 
339  if (new_mask == 0 && (i == 2 || i == bufs->count-1))
340  /* topic (2) and payload (last) buffers are already masked */
341  break;
342  for ( j = 0u; j < bufs->buflens[i]; ++j, ++idx )
343  {
344  bufs->buffers[i][j] ^= bufs->mask[idx % 4];
345  }
346  }
347  }
348  }
349 exit:
350  FUNC_EXIT_RC(buf_len);
351  return rc;
352 }
353 
354 
355 static void WebSocket_unmaskData(size_t idx, PacketBuffers* bufs)
356 {
357  int i;
358 
359  FUNC_ENTRY;
360  for (i = 0; i < bufs->count; ++i)
361  {
362  size_t j;
363  for (j = 0u; j < bufs->buflens[i]; ++j, ++idx)
364  bufs->buffers[i][j] ^= bufs->mask[idx % 4];
365  }
366  /* show that the mask has been removed */
367  bufs->mask[0] = bufs->mask[1] = bufs->mask[2] = bufs->mask[3] = 0;
368  FUNC_EXIT;
369 }
370 
371 
383 int WebSocket_connect( networkHandles *net, const char *uri)
384 {
385  int rc;
386  char *buf = NULL;
387  char *headers_buf = NULL;
388  const MQTTClient_nameValue *headers = net->httpHeaders;
389  int i, buf_len = 0;
390  int headers_buf_len = 0;
391  size_t hostname_len;
392  int port = 80;
393  const char *topic = NULL;
394 #if defined(_WIN32) || defined(_WIN64)
395  UUID uuid;
396 #else /* if defined(_WIN32) || defined(_WIN64) */
397  uuid_t uuid;
398 #endif /* else if defined(_WIN32) || defined(_WIN64) */
399 
400  FUNC_ENTRY;
401  /* Generate UUID */
402  if (net->websocket_key == NULL)
403  net->websocket_key = malloc(25u);
404  else
405  net->websocket_key = realloc(net->websocket_key, 25u);
406  if (net->websocket_key == NULL)
407  {
408  rc = PAHO_MEMORY_ERROR;
409  goto exit;
410  }
411 #if defined(_WIN32) || defined(_WIN64)
412  ZeroMemory( &uuid, sizeof(UUID) );
413  UuidCreate( &uuid );
414  Base64_encode( net->websocket_key, 25u, (const b64_data_t*)&uuid, sizeof(UUID) );
415 #else /* if defined(_WIN32) || defined(_WIN64) */
416  uuid_generate( uuid );
417  Base64_encode( net->websocket_key, 25u, uuid, sizeof(uuid_t) );
418 #endif /* else if defined(_WIN32) || defined(_WIN64) */
419 
420  hostname_len = MQTTProtocol_addressPort(uri, &port, &topic, WS_DEFAULT_PORT);
421 
422  /* if no topic, use default */
423  if ( !topic )
424  topic = "/mqtt";
425 
426  if ( headers )
427  {
428  char *headers_buf_cur = NULL;
429  while ( headers->name != NULL && headers->value != NULL )
430  {
431  headers_buf_len += (int)(strlen(headers->name) + strlen(headers->value) + 4);
432  headers++;
433  }
434  headers_buf_len++;
435 
436  if ((headers_buf = malloc(headers_buf_len)) == NULL)
437  {
438  rc = PAHO_MEMORY_ERROR;
439  goto exit;
440  }
441  headers = net->httpHeaders;
442  headers_buf_cur = headers_buf;
443 
444  while ( headers->name != NULL && headers->value != NULL )
445  {
446  headers_buf_cur += sprintf(headers_buf_cur, "%s: %s\r\n", headers->name, headers->value);
447  headers++;
448  }
449  *headers_buf_cur = '\0';
450  }
451 
452  for ( i = 0; i < 2; ++i )
453  {
454  buf_len = snprintf( buf, (size_t)buf_len,
455  "GET %s HTTP/1.1\r\n"
456  "Host: %.*s:%d\r\n"
457  "Upgrade: websocket\r\n"
458  "Connection: Upgrade\r\n"
459  "Origin: %s://%.*s:%d\r\n"
460  "Sec-WebSocket-Key: %s\r\n"
461  "Sec-WebSocket-Version: 13\r\n"
462  "Sec-WebSocket-Protocol: mqtt\r\n"
463  "%s"
464  "\r\n", topic,
465  (int)hostname_len, uri, port,
466 #if defined(OPENSSL)
467  HTTP_PROTOCOL(net->ssl),
468 #else
469  HTTP_PROTOCOL(0),
470 #endif
471 
472  (int)hostname_len, uri, port,
473  net->websocket_key,
474  headers_buf ? headers_buf : "");
475 
476  if ( i == 0 && buf_len > 0 )
477  {
478  ++buf_len; /* need 1 extra byte for ending '\0' */
479  if ((buf = malloc( buf_len )) == NULL)
480  {
481  rc = PAHO_MEMORY_ERROR;
482  goto exit;
483  }
484  }
485  }
486 
487  if (headers_buf)
488  free( headers_buf );
489 
490  if ( buf )
491  {
492  PacketBuffers nulbufs = {0, NULL, NULL, NULL, {0, 0, 0, 0}};
493 
494 #if defined(OPENSSL)
495  if (net->ssl)
496  SSLSocket_putdatas(net->ssl, net->socket, buf, buf_len, nulbufs);
497  else
498 #endif
499  Socket_putdatas(net->socket, buf, buf_len, nulbufs);
500  free( buf );
501  rc = 1;
502  }
503  else
504  {
505  free(net->websocket_key);
506  net->websocket_key = NULL;
507  rc = SOCKET_ERROR;
508  }
509 exit:
510  FUNC_EXIT_RC(rc);
511  return rc;
512 }
513 
521 void WebSocket_close(networkHandles *net, int status_code, const char *reason)
522 {
523  struct frameData fd;
524  PacketBuffers nulbufs = {0, NULL, NULL, NULL, {0, 0, 0, 0}};
525 
526  FUNC_ENTRY;
527  if ( net->websocket )
528  {
529  char *buf0;
530  size_t buf0len = sizeof(uint16_t);
531  uint16_t status_code_be;
532  const int mask_data = 1; /* all frames from client must be masked */
533 
534  if ( status_code < WebSocket_CLOSE_NORMAL ||
535  status_code > WebSocket_CLOSE_TLS_FAIL )
536  status_code = WebSocket_CLOSE_GOING_AWAY;
537 
538  if ( reason )
539  buf0len += strlen(reason);
540 
541  buf0 = malloc(buf0len);
542  if ( !buf0 )
543  goto exit;
544 
545  /* encode status code */
546  status_code_be = htobe16((uint16_t)status_code);
547  memcpy(buf0, &status_code_be, sizeof(uint16_t));
548 
549  /* encode reason, if provided */
550  if ( reason )
551  strcpy( &buf0[sizeof(uint16_t)], reason );
552 
553  fd = WebSocket_buildFrame( net, WebSocket_OP_CLOSE, mask_data, &buf0, &buf0len, &nulbufs);
554 
555 #if defined(OPENSSL)
556  if (net->ssl)
557  SSLSocket_putdatas(net->ssl, net->socket, fd.wsbuf0, fd.wsbuf0len, nulbufs);
558  else
559 #endif
560  Socket_putdatas(net->socket, fd.wsbuf0, fd.wsbuf0len, nulbufs);
561 
562  free(fd.wsbuf0); /* free temporary ws header */
563 
564  /* websocket connection is now closed */
565  net->websocket = 0;
566  free( buf0 );
567  }
568  if ( net->websocket_key )
569  {
570  free( net->websocket_key );
571  net->websocket_key = NULL;
572  }
573 exit:
574  FUNC_EXIT;
575 }
576 
590 {
591  int rc = SOCKET_ERROR;
592 
593  FUNC_ENTRY;
594  if ( net->websocket )
595  {
596  struct ws_frame *frame = NULL;
597 
598  if ( in_frames && in_frames->first )
599  frame = in_frames->first->content;
600 
601  if ( !frame || frame->len == frame->pos )
602  {
603  size_t actual_len = 0u;
604  rc = WebSocket_receiveFrame( net, &actual_len);
605  if ( rc != TCPSOCKET_COMPLETE )
606  goto exit;
607 
608  /* we got a frame, let take off the top of queue */
609  if ( in_frames->first )
610  frame = in_frames->first->content;
611  }
612 
613  /* set current working frame */
614  if (frame && frame->len > frame->pos)
615  {
616  unsigned char *buf =
617  (unsigned char *)frame + sizeof(struct ws_frame);
618  *c = buf[frame->pos++];
619  rc = TCPSOCKET_COMPLETE;
620  }
621  }
622 #if defined(OPENSSL)
623  else if ( net->ssl )
624  rc = SSLSocket_getch(net->ssl, net->socket, c);
625 #endif
626  else
627  rc = Socket_getch(net->socket, c);
628 
629 exit:
630  FUNC_EXIT_RC(rc);
631  return rc;
632 }
633 
635 {
636  if ( in_frames && in_frames->first )
637  {
638  struct ws_frame *frame = in_frames->first->content;
639  return frame->pos;
640  }
641  else
642  {
643  return 0;
644  }
645 }
646 
648 {
649  if ( in_frames && in_frames->first )
650  {
651  struct ws_frame *frame = in_frames->first->content;
652  frame->pos = pos;
653  }
654 }
655 
669 char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len)
670 {
671  char *rv = NULL;
672  int rc;
673 
674  FUNC_ENTRY;
675  if ( net->websocket )
676  {
677  struct ws_frame *frame = NULL;
678 
679  if ( bytes == 0u )
680  {
681  /* done with current frame, move it to last frame */
682  if ( in_frames && in_frames->first )
683  frame = in_frames->first->content;
684 
685  /* return the data from the next frame, if we have one */
686  if ( frame && frame->pos == frame->len )
687  {
688  rv = (char *)frame +
689  sizeof(struct ws_frame) + frame->pos;
690  *actual_len = frame->len - frame->pos;
691 
692  if ( last_frame )
693  free( last_frame );
694  last_frame = ListDetachHead(in_frames);
695  }
696  goto exit;
697  }
698 
699  /* look at the first websocket frame */
700  if ( in_frames && in_frames->first )
701  frame = in_frames->first->content;
702 
703  /* no current frame, so let's go receive one for the network */
704  if ( !frame )
705  {
706  const int rc =
707  WebSocket_receiveFrame( net, actual_len );
708 
709  if ( rc == TCPSOCKET_COMPLETE && in_frames && in_frames->first)
710  frame = in_frames->first->content;
711  }
712 
713  if ( frame )
714  {
715  rv = (char *)frame + sizeof(struct ws_frame) + frame->pos;
716  *actual_len = frame->len - frame->pos; /* use the rest of the frame */
717 
718 
719  while (*actual_len < bytes) {
720  const int rc = WebSocket_receiveFrame(net, actual_len);
721 
722  if (rc != TCPSOCKET_COMPLETE) {
723  goto exit;
724  }
725 
726  /* refresh pointers */
727  frame = in_frames->first->content;
728  rv = (char *)frame + sizeof(struct ws_frame) + frame->pos;
729  *actual_len = frame->len - frame->pos; /* use the rest of the frame */
730 
731  } /* end while */
732 
733  if (*actual_len > bytes)
734  {
735  frame->pos += bytes;
736  }
737  else if (*actual_len == bytes && in_frames)
738  {
739  if ( last_frame )
740  free( last_frame );
741  last_frame = ListDetachHead(in_frames);
742  }
743  }
744  }
745 #if defined(OPENSSL)
746  else if ( net->ssl )
747  rv = SSLSocket_getdata(net->ssl, net->socket, bytes, actual_len, &rc);
748 #endif
749  else
750  rv = Socket_getdata(net->socket, bytes, actual_len, &rc);
751 
752 exit:
753  FUNC_EXIT_RC(rv);
754  return rv;
755 }
756 
758 {
759  frame_buffer_index = 0;
760 }
761 
771 char *WebSocket_getRawSocketData(networkHandles *net, size_t bytes, size_t* actual_len, int* rc)
772 {
773  char *rv = NULL;
774 
775  size_t bytes_requested = bytes;
776 
777  FUNC_ENTRY;
778  if (bytes > 0)
779  {
781  {
782  *actual_len = bytes;
784  frame_buffer_index += bytes;
785 
786  goto exit;
787  }
788  else
789  {
790  bytes = bytes - (frame_buffer_data_len - frame_buffer_index);
791  }
792  }
793 
794  *actual_len = 0;
795 
796  // not enough data in the buffer, get data from socket
797 #if defined(OPENSSL)
798  if ( net->ssl )
799  rv = SSLSocket_getdata(net->ssl, net->socket, bytes, actual_len, rc);
800  else
801 #endif
802  rv = Socket_getdata(net->socket, bytes, actual_len, rc);
803 
804  if (*rc == 0)
805  {
806  *rc = SOCKET_ERROR;
807  goto exit;
808  }
809 
810  // clear buffer
811  if (bytes == 0)
812  {
813  frame_buffer_index = 0;
815  frame_buffer_len = 0;
816 
817  free (frame_buffer);
818  frame_buffer = NULL;
819  }
820  // append data to the buffer
821  else if (rv != NULL && *actual_len != 0U)
822  {
823  // no buffer allocated
824  if (!frame_buffer)
825  {
826  if ((frame_buffer = (char *)malloc(*actual_len)) == NULL)
827  {
828  rv = NULL;
829  goto exit;
830  }
831  memcpy(frame_buffer, rv, *actual_len);
832 
833  frame_buffer_index = 0;
834  frame_buffer_data_len = *actual_len;
835  frame_buffer_len = *actual_len;
836  }
837  // buffer size is big enough
838  else if (frame_buffer_data_len + *actual_len < frame_buffer_len)
839  {
840  memcpy(frame_buffer + frame_buffer_data_len, rv, *actual_len);
841  frame_buffer_data_len += *actual_len;
842  }
843  // resize buffer
844  else
845  {
847  frame_buffer_len = frame_buffer_data_len + *actual_len;
848 
849  memcpy(frame_buffer + frame_buffer_data_len, rv, *actual_len);
850  frame_buffer_data_len += *actual_len;
851  }
852 
854  }
855  else
856  goto exit;
857 
858  bytes = bytes_requested;
859 
860  // if possible, return data from the buffer
861  if (bytes > 0)
862  {
864  {
865  *actual_len = bytes;
867  frame_buffer_index += bytes;
868  }
869  else
870  {
873  frame_buffer_index += *actual_len;
874  }
875  }
876 
877 exit:
878  FUNC_EXIT;
879  return rv;
880 }
881 
889 void WebSocket_pong(networkHandles *net, char *app_data, size_t app_data_len)
890 {
891  FUNC_ENTRY;
892  if ( net->websocket )
893  {
894  char *buf0 = NULL;
895  size_t buf0len = 0;
896  int freeData = 0;
897  struct frameData fd;
898  const int mask_data = 1; /* all frames from client must be masked */
899  PacketBuffers appbuf = {1, &app_data, &app_data_len, &freeData, {0, 0, 0, 0}};
900 
901  fd = WebSocket_buildFrame( net, WebSocket_OP_PONG, mask_data, &buf0, &buf0len, &appbuf);
902 
903  Log(TRACE_PROTOCOL, 1, "Sending WebSocket PONG" );
904 
905 #if defined(OPENSSL)
906  if (net->ssl)
907  SSLSocket_putdatas(net->ssl, net->socket, fd.wsbuf0, fd.wsbuf0len /*header_len + app_data_len*/, appbuf);
908  else
909 #endif
910  Socket_putdatas(net->socket, fd.wsbuf0, fd.wsbuf0len /*header_len + app_data_len*/, appbuf);
911 
912  free(fd.wsbuf0);
913  free(buf0);
914  }
915  FUNC_EXIT;
916 }
917 
938 int WebSocket_putdatas(networkHandles* net, char** buf0, size_t* buf0len, PacketBuffers* bufs)
939 {
940  const int mask_data = 1; /* must mask websocket data from client */
941  int rc;
942 
943  FUNC_ENTRY;
944  if (net->websocket)
945  {
946  struct frameData wsdata;
947 
948  wsdata = WebSocket_buildFrame(net, WebSocket_OP_BINARY, mask_data, buf0, buf0len, bufs);
949 
950 #if defined(OPENSSL)
951  if (net->ssl)
952  rc = SSLSocket_putdatas(net->ssl, net->socket, wsdata.wsbuf0, wsdata.wsbuf0len, *bufs);
953  else
954 #endif
955  rc = Socket_putdatas(net->socket, wsdata.wsbuf0, wsdata.wsbuf0len, *bufs);
956 
957  if (rc != TCPSOCKET_INTERRUPTED)
958  {
959  if (mask_data)
960  WebSocket_unmaskData(*buf0len, bufs);
961  free(wsdata.wsbuf0); /* free temporary ws header */
962  }
963  }
964  else
965  {
966 #if defined(OPENSSL)
967  if (net->ssl)
968  rc = SSLSocket_putdatas(net->ssl, net->socket, *buf0, *buf0len, *bufs);
969  else
970 #endif
971  rc = Socket_putdatas(net->socket, *buf0, *buf0len, *bufs);
972  }
973 
974  FUNC_EXIT_RC(rc);
975  return rc;
976 }
977 
990 int WebSocket_receiveFrame(networkHandles *net, size_t *actual_len)
991 {
992  struct ws_frame *res = NULL;
993  int rc = TCPSOCKET_COMPLETE;
994  int opcode = 0;
995 
996  FUNC_ENTRY;
997  if ( !in_frames )
998  in_frames = ListInitialize();
999 
1000  /* see if there is frame currently on queue */
1001  if ( in_frames->first )
1002  res = in_frames->first->content;
1003 
1004  //while( !res )
1005  //{
1006  opcode = WebSocket_OP_BINARY;
1007  do
1008  {
1009  /* obtain all frames in the sequence */
1010  int is_final = 0;
1011  while ( is_final == 0 )
1012  {
1013  char *b;
1014  size_t len = 0u;
1015  int tmp_opcode;
1016  int has_mask;
1017  size_t cur_len = 0u;
1018  uint8_t mask[4] = { 0u, 0u, 0u, 0u };
1019  size_t payload_len;
1020  int rcs; /* socket return code */
1021 
1022  b = WebSocket_getRawSocketData(net, 2u, &len, &rcs);
1023  if (rcs == SOCKET_ERROR)
1024  {
1025  rc = rcs;
1026  goto exit;
1027  }
1028  if ( !b )
1029  {
1030  rc = TCPSOCKET_INTERRUPTED;
1031  goto exit;
1032  }
1033  else if (len < 2u )
1034  {
1035  rc = TCPSOCKET_INTERRUPTED;
1036  goto exit;
1037  }
1038 
1039  /* 1st byte */
1040  is_final = (b[0] & 0xFF) >> 7;
1041  tmp_opcode = (b[0] & 0x0F);
1042 
1043  if ( tmp_opcode ) /* not a continuation frame */
1044  opcode = tmp_opcode;
1045 
1046  /* invalid websocket packet must return error */
1047  if ( opcode < WebSocket_OP_CONTINUE ||
1048  opcode > WebSocket_OP_PONG ||
1049  ( opcode > WebSocket_OP_BINARY &&
1050  opcode < WebSocket_OP_CLOSE ) )
1051  {
1052  rc = SOCKET_ERROR;
1053  goto exit;
1054  }
1055 
1056  /* 2nd byte */
1057  has_mask = (b[1] & 0xFF) >> 7;
1058  payload_len = (b[1] & 0x7F);
1059 
1060  /* determine payload length */
1061  if ( payload_len == 126 )
1062  {
1063  /* If 126, the following 2 bytes interpreted as a
1064  16-bit unsigned integer are the payload length. */
1065  b = WebSocket_getRawSocketData(net, 2u, &len, &rcs);
1066  if (rcs == SOCKET_ERROR)
1067  {
1068  rc = rcs;
1069  goto exit;
1070  }
1071  if ( !b )
1072  {
1073  rc = SOCKET_ERROR;
1074  goto exit;
1075  }
1076  else if (len < 2u )
1077  {
1078  rc = TCPSOCKET_INTERRUPTED;
1079  goto exit;
1080  }
1081  /* convert from big endian 16 to host */
1082  payload_len = be16toh(*(uint16_t*)b);
1083  }
1084  else if ( payload_len == 127 )
1085  {
1086  /* If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the
1087  most significant bit MUST be 0) are the payload length */
1088  b = WebSocket_getRawSocketData(net, 8u, &len, &rcs);
1089  if (rcs == SOCKET_ERROR)
1090  {
1091  rc = rcs;
1092  goto exit;
1093  }
1094  if ( !b )
1095  {
1096  rc = SOCKET_ERROR;
1097  goto exit;
1098  }
1099  else if (len < 8u )
1100  {
1101  rc = TCPSOCKET_INTERRUPTED;
1102  goto exit;
1103  }
1104  /* convert from big-endian 64 to host */
1105  payload_len = (size_t)be64toh(*(uint64_t*)b);
1106  }
1107 
1108  if ( has_mask )
1109  {
1110  uint8_t mask[4];
1111  b = WebSocket_getRawSocketData(net, 4u, &len, &rcs);
1112  if (rcs == SOCKET_ERROR)
1113  {
1114  rc = rcs;
1115  goto exit;
1116  }
1117  if ( !b )
1118  {
1119  rc = SOCKET_ERROR;
1120  goto exit;
1121  }
1122  if (len < 4u )
1123  {
1124  rc = TCPSOCKET_INTERRUPTED;
1125  goto exit;
1126  }
1127  memcpy( &mask[0], b, sizeof(uint32_t));
1128  }
1129 
1130  /* use the socket buffer to read in the whole websocket frame */
1131  b = WebSocket_getRawSocketData(net, payload_len, &len, &rcs);
1132  if (rcs == SOCKET_ERROR)
1133  {
1134  rc = rcs;
1135  goto exit;
1136  }
1137  if (!b)
1138  {
1139  rc = SOCKET_ERROR;
1140  goto exit;
1141  }
1142  if (len < payload_len )
1143  {
1144  rc = TCPSOCKET_INTERRUPTED;
1145  goto exit;
1146  }
1147 
1148  /* unmask data */
1149  if ( has_mask )
1150  {
1151  size_t i;
1152  for ( i = 0u; i < payload_len; ++i )
1153  b[i] ^= mask[i % 4];
1154  }
1155 
1156  if ( res )
1157  cur_len = res->len;
1158 
1159  if (res == NULL)
1160  {
1161  if ((res = malloc( sizeof(struct ws_frame) + cur_len + len)) == NULL)
1162  {
1163  rc = PAHO_MEMORY_ERROR;
1164  goto exit;
1165  }
1166  res->pos = 0u;
1167  } else
1168  {
1169  if ((res = realloc( res, sizeof(struct ws_frame) + cur_len + len )) == NULL)
1170  {
1171  rc = PAHO_MEMORY_ERROR;
1172  goto exit;
1173  }
1174  }
1175  if (in_frames && in_frames->first)
1176  in_frames->first->content = res; /* realloc moves the data */
1177  memcpy( (unsigned char *)res + sizeof(struct ws_frame) + cur_len, b, len );
1178  res->len = cur_len + len;
1179 
1180  WebSocket_getRawSocketData(net, 0u, &len, &rcs);
1181  if (rcs == SOCKET_ERROR)
1182  {
1183  rc = rcs;
1184  goto exit;
1185  }
1186  }
1187 
1188  if ( opcode == WebSocket_OP_PING || opcode == WebSocket_OP_PONG )
1189  {
1190  /* respond to a "ping" with a "pong" */
1191  if ( opcode == WebSocket_OP_PING )
1192  WebSocket_pong( net,
1193  (char *)res + sizeof(struct ws_frame),
1194  res->len );
1195 
1196  /* discard message */
1197  free( res );
1198  res = NULL;
1199  }
1200  else if ( opcode == WebSocket_OP_CLOSE )
1201  {
1202  /* server end closed websocket connection */
1203  free( res );
1205  rc = SOCKET_ERROR; /* closes socket */
1206  goto exit;
1207  }
1208  } while ( opcode == WebSocket_OP_PING || opcode == WebSocket_OP_PONG );
1209  //}
1210 
1211  if (in_frames->count == 0)
1212  ListAppend( in_frames, res, sizeof(struct ws_frame) + res->len);
1213  *actual_len = res->len - res->pos;
1214 
1215 exit:
1216  if (rc == TCPSOCKET_INTERRUPTED)
1217  {
1219  }
1220 
1221  FUNC_EXIT_RC(rc);
1222  return rc;
1223 }
1224 
1237 const char *WebSocket_strcasefind(const char *buf, const char *str, size_t len)
1238 {
1239  const char *res = NULL;
1240  if ( buf && len > 0u && str )
1241  {
1242  const size_t str_len = strlen( str );
1243  while ( len >= str_len && !res )
1244  {
1245  if ( strncasecmp( buf, str, str_len ) == 0 )
1246  res = buf;
1247  ++buf;
1248  --len;
1249  }
1250  }
1251  return res;
1252 }
1253 
1258 {
1259  FUNC_ENTRY;
1260  /* clean up and un-processed websocket frames */
1261  if ( in_frames )
1262  {
1263  struct ws_frame *f = ListDetachHead( in_frames );
1264  while ( f )
1265  {
1266  free( f );
1267  f = ListDetachHead( in_frames );
1268  }
1269  ListFree( in_frames );
1270  in_frames = NULL;
1271  }
1272  if ( last_frame )
1273  {
1274  free( last_frame );
1275  last_frame = NULL;
1276  }
1277 
1278  if ( frame_buffer )
1279  {
1280  free( frame_buffer );
1281  frame_buffer = NULL;
1282  }
1283 
1284  frame_buffer_len = 0;
1285  frame_buffer_index = 0;
1287 
1289 #if defined(OPENSSL)
1291 #endif
1292  FUNC_EXIT;
1293 }
1294 
1307 {
1308  static const char *const ws_guid =
1309  "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
1310  int rc = SOCKET_ERROR;
1311 
1312  FUNC_ENTRY;
1313  if ( net->websocket_key )
1314  {
1315  SHA_CTX ctx;
1316  char ws_key[62u] = { 0 };
1317  unsigned char sha_hash[SHA1_DIGEST_LENGTH];
1318  size_t rcv = 0u;
1319  char *read_buf;
1320 
1321  /* calculate the expected websocket key, expected from server */
1322  snprintf( ws_key, sizeof(ws_key), "%s%s", net->websocket_key, ws_guid );
1323  SHA1_Init( &ctx );
1324  SHA1_Update( &ctx, ws_key, strlen(ws_key));
1325  SHA1_Final( sha_hash, &ctx );
1326  Base64_encode( ws_key, sizeof(ws_key), sha_hash, SHA1_DIGEST_LENGTH );
1327 
1328  rc = TCPSOCKET_INTERRUPTED;
1329  read_buf = WebSocket_getRawSocketData( net, 12u, &rcv, &rc);
1330  if (rc == SOCKET_ERROR)
1331  goto exit;
1332 
1333  if ((read_buf == NULL) || rcv < 12u) {
1334  Log(TRACE_PROTOCOL, 1, "WebSocket upgrade read not complete %lu", rcv );
1335  goto exit;
1336  }
1337 
1338  if (strncmp( read_buf, "HTTP/1.1", 8u ) == 0)
1339  {
1340  if (strncmp( &read_buf[9], "101", 3u ) != 0)
1341  {
1342  Log(TRACE_PROTOCOL, 1, "WebSocket HTTP rc %.3s", &read_buf[9]);
1343  rc = SOCKET_ERROR;
1344  goto exit;
1345  }
1346  }
1347 
1348  if (strncmp( read_buf, "HTTP/1.1 101", 12u ) == 0)
1349  {
1350  const char *p;
1351 
1352  read_buf = WebSocket_getRawSocketData(net, 1024u, &rcv, &rc);
1353  if (rc == SOCKET_ERROR)
1354  goto exit;
1355 
1356  /* Did we read the whole response? */
1357  if (read_buf && rcv > 4 && memcmp(&read_buf[rcv-4], "\r\n\r\n", 4) != 0)
1358  {
1359  Log(TRACE_PROTOCOL, -1, "WebSocket HTTP upgrade response read not complete %lu", rcv);
1360  rc = SOCKET_ERROR;
1361  goto exit;
1362  }
1363 
1364  /* check for upgrade */
1366  read_buf, "Connection", rcv );
1367  if ( p )
1368  {
1369  const char *eol;
1370  eol = memchr( p, '\n', rcv-(read_buf-p) );
1371  if ( eol )
1373  p, "Upgrade", eol - p);
1374  else
1375  p = NULL;
1376  }
1377 
1378  /* check key hash */
1379  if ( p )
1380  p = WebSocket_strcasefind( read_buf,
1381  "sec-websocket-accept", rcv );
1382  if ( p )
1383  {
1384  const char *eol;
1385  eol = memchr( p, '\n', rcv-(read_buf-p) );
1386  if ( eol )
1387  {
1388  p = memchr( p, ':', eol-p );
1389  if ( p )
1390  {
1391  size_t hash_len = eol-p-1;
1392  while ( *p == ':' || *p == ' ' )
1393  {
1394  ++p;
1395  --hash_len;
1396  }
1397 
1398  if ( strncmp( p, ws_key, hash_len ) != 0 )
1399  p = NULL;
1400  }
1401  }
1402  else
1403  p = NULL;
1404  }
1405 
1406  if ( p )
1407  {
1408  net->websocket = 1;
1409  Log(TRACE_PROTOCOL, 1, "WebSocket connection upgraded" );
1410  rc = 1;
1411  }
1412  else
1413  {
1414  Log(TRACE_PROTOCOL, 1, "WebSocket failed to upgrade connection" );
1415  rc = SOCKET_ERROR;
1416  }
1417 
1418  if ( net->websocket_key )
1419  {
1420  free(net->websocket_key);
1421  net->websocket_key = NULL;
1422  }
1423 
1424  /* indicate that we done with the packet */
1425  WebSocket_getRawSocketData( net, 0u, &rcv, &rc);
1426  }
1427  }
1428 
1429 exit:
1430  FUNC_EXIT_RC(rc);
1431  return rc;
1432 }
1433 
1445 int WebSocket_proxy_connect( networkHandles *net, int ssl, const char *hostname)
1446 {
1447  int port, i, rc = 0, buf_len=0;
1448  char *buf = NULL;
1449  size_t hostname_len, actual_len = 0;
1450  time_t current, timeout;
1451  PacketBuffers nulbufs = {0, NULL, NULL, NULL, {0, 0, 0, 0}};
1452 
1453  FUNC_ENTRY;
1454  hostname_len = MQTTProtocol_addressPort(hostname, &port, NULL, WS_DEFAULT_PORT);
1455  for ( i = 0; i < 2; ++i ) {
1456 #if defined(OPENSSL)
1457  if(ssl) {
1458  if (net->https_proxy_auth) {
1459  buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
1460  "Host: %.*s\r\n"
1461  "Proxy-authorization: Basic %s\r\n"
1462  "\r\n",
1463  (int)hostname_len, hostname, port,
1464  (int)hostname_len, hostname, net->https_proxy_auth);
1465  }
1466  else {
1467  buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
1468  "Host: %.*s\r\n"
1469  "\r\n",
1470  (int)hostname_len, hostname, port,
1471  (int)hostname_len, hostname);
1472  }
1473  }
1474  else {
1475 #endif
1476  if (net->http_proxy_auth) {
1477  buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
1478  "Host: %.*s\r\n"
1479  "Proxy-authorization: Basic %s\r\n"
1480  "\r\n",
1481  (int)hostname_len, hostname, port,
1482  (int)hostname_len, hostname, net->http_proxy_auth);
1483  }
1484  else {
1485  buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
1486  "Host: %.*s\r\n"
1487  "\r\n",
1488  (int)hostname_len, hostname, port,
1489  (int)hostname_len, hostname);
1490  }
1491 #if defined(OPENSSL)
1492  }
1493 #endif
1494  if ( i==0 && buf_len > 0 ) {
1495  ++buf_len;
1496  if ((buf = malloc( buf_len )) == NULL)
1497  {
1498  rc = PAHO_MEMORY_ERROR;
1499  goto exit;
1500  }
1501 
1502  }
1503  }
1504  Log(TRACE_PROTOCOL, -1, "WebSocket_proxy_connect: \"%s\"", buf);
1505 
1506  Socket_putdatas(net->socket, buf, buf_len, nulbufs);
1507  free(buf);
1508  buf = NULL;
1509 
1510  time(&timeout);
1511  timeout += (time_t)10;
1512 
1513  while(1) {
1514  buf = Socket_getdata(net->socket, (size_t)12, &actual_len, &rc);
1515  if(actual_len) {
1516  if ( (strncmp( buf, "HTTP/1.0 200", 12 ) != 0) && (strncmp( buf, "HTTP/1.1 200", 12 ) != 0) )
1517  rc = SOCKET_ERROR;
1518  break;
1519  }
1520  else {
1521  time(&current);
1522  if(current > timeout) {
1523  rc = SOCKET_ERROR;
1524  break;
1525  }
1526 #if defined(_WIN32) || defined(_WIN64)
1527  Sleep(250);
1528 #else
1529  usleep(250000);
1530 #endif
1531  }
1532  }
1533 
1534  /* flush the SocketBuffer */
1535  actual_len = 1;
1536  while (actual_len)
1537  {
1538  int rc1;
1539 
1540  buf = Socket_getdata(net->socket, (size_t)1, &actual_len, &rc1);
1541  }
1542 
1543 exit:
1544  FUNC_EXIT_RC(rc);
1545  return rc;
1546 }
int WebSocket_proxy_connect(networkHandles *net, int ssl, const char *hostname)
Definition: WebSocket.c:1445
int SHA1_Final(unsigned char *md, SHA_CTX *ctx)
Definition: SHA1.c:139
char * websocket_key
Definition: Clients.h:93
void WebSocket_framePosSeekTo(size_t pos)
Definition: WebSocket.c:647
int SSLSocket_getch(SSL *ssl, int socket, char *c)
int count
Definition: Socket.h:98
#define WebSocket_CLOSE_NORMAL
Definition: WebSocket.h:38
void WebSocket_close(networkHandles *net, int status_code, const char *reason)
Definition: WebSocket.c:521
static char * WebSocket_getRawSocketData(networkHandles *net, size_t bytes, size_t *actual_len, int *rc)
Definition: WebSocket.c:771
size_t pos
Definition: WebSocket.c:151
string topic
Definition: test2.py:8
#define FUNC_EXIT
Definition: StackTrace.h:59
static char * frame_buffer
Definition: WebSocket.c:160
void WebSocket_terminate(void)
Definition: WebSocket.c:1257
struct @73::@74 bytes[4]
static void WebSocket_unmaskData(size_t idx, PacketBuffers *bufs)
Definition: WebSocket.c:355
int Socket_getch(int socket, char *c)
Definition: Socket.c:332
static void WebSocket_pong(networkHandles *net, char *app_data, size_t app_data_len)
Definition: WebSocket.c:889
void Socket_outTerminate(void)
Definition: Socket.c:151
int websocket
Definition: Clients.h:92
#define WebSocket_OP_PING
Definition: WebSocket.h:30
#define PAHO_MEMORY_ERROR
Definition: Heap.h:26
const MQTTClient_nameValue * httpHeaders
Definition: Clients.h:94
builds a websocket frame for data transmission
Definition: WebSocket.c:231
int SHA1_Update(SHA_CTX *ctx, const void *data, size_t len)
Definition: SHA1.c:173
size_t WebSocket_framePos()
Definition: WebSocket.c:634
#define WebSocket_OP_PONG
Definition: WebSocket.h:31
void uuid_generate(uuid_t out)
generates a uuid, compatible with RFC 4122, version 4 (random)
Definition: WebSocket.c:110
char * WebSocket_getdata(networkHandles *net, size_t bytes, size_t *actual_len)
receives data from a socket. It should receive all data from the socket that is immediately available...
Definition: WebSocket.c:669
#define malloc(x)
Definition: Heap.h:41
Definition: SHA1.h:39
int SHA1_Init(SHA_CTX *ctx)
Definition: SHA1.c:77
char ** buffers
Definition: Socket.h:99
size_t * buflens
Definition: Socket.h:100
char * wsbuf0
Definition: WebSocket.c:232
#define free(x)
Definition: Heap.h:55
static int WebSocket_receiveFrame(networkHandles *net, size_t *actual_len)
Definition: WebSocket.c:990
#define HTTP_PROTOCOL(x)
Definition: WebSocket.c:93
const char * value
Definition: MQTTClient.h:781
static const char * WebSocket_strcasefind(const char *buf, const char *str, size_t len)
Definition: WebSocket.c:1237
#define WebSocket_OP_CLOSE
Definition: WebSocket.h:29
#define SHA1_DIGEST_LENGTH
Definition: SHA1.h:53
void * ListDetachHead(List *aList)
Definition: LinkedList.c:268
#define FUNC_EXIT_RC(x)
Definition: StackTrace.h:63
#define SOCKET_ERROR
Definition: Socket.h:76
int count
Definition: LinkedList.h:72
b64_size_t Base64_encode(char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len)
Definition: Base64.c:179
#define realloc(a, b)
Definition: Heap.h:49
void uuid_unparse(uuid_t uu, char *out)
converts a uuid to a string
Definition: WebSocket.c:128
void Log(enum LOG_LEVELS log_level, int msgno, const char *format,...)
Definition: Log.c:417
int WebSocket_upgrade(networkHandles *net)
Definition: WebSocket.c:1306
#define WebSocket_OP_CONTINUE
Definition: WebSocket.h:26
int WebSocket_getch(networkHandles *net, char *c)
receives 1 byte from a socket
Definition: WebSocket.c:589
char * Socket_getdata(int socket, size_t bytes, size_t *actual_len, int *rc)
Definition: Socket.c:370
ListElement * ListAppend(List *aList, void *content, size_t size)
Definition: LinkedList.c:90
static size_t frame_buffer_len
Definition: WebSocket.c:161
size_t len
Definition: WebSocket.c:150
void SSLSocket_terminate(void)
int SSLSocket_putdatas(SSL *ssl, int socket, char *buf0, size_t buf0len, PacketBuffers bufs)
static size_t frame_buffer_data_len
Definition: WebSocket.c:163
static void WebSocket_rewindData(void)
Definition: WebSocket.c:757
size_t WebSocket_calculateFrameHeaderSize(networkHandles *net, int mask_data, size_t data_len)
Definition: WebSocket.c:195
#define FUNC_ENTRY
Definition: StackTrace.h:55
int WebSocket_putdatas(networkHandles *net, char **buf0, size_t *buf0len, PacketBuffers *bufs)
Definition: WebSocket.c:938
static size_t frame_buffer_index
Definition: WebSocket.c:162
#define WebSocket_OP_BINARY
Definition: WebSocket.h:28
uint8_t mask[4]
Definition: Socket.h:102
MQTTClient c
Definition: test10.c:1656
float time
Definition: mqtt_test.py:17
char * SocketBuffer_complete(int socket)
Definition: SocketBuffer.c:281
#define WS_DEFAULT_PORT
int Socket_putdatas(int socket, char *buf0, size_t buf0len, PacketBuffers bufs)
Definition: Socket.c:505
static List * in_frames
Definition: WebSocket.c:158
static int str_len(lua_State *L)
Definition: lstrlib.c:55
unsigned char b64_data_t
Definition: Base64.h:23
List * ListInitialize(void)
Definition: LinkedList.c:52
int WebSocket_connect(networkHandles *net, const char *uri)
Definition: WebSocket.c:383
size_t MQTTProtocol_addressPort(const char *uri, int *port, const char **topic, int default_port)
#define WebSocket_CLOSE_TLS_FAIL
Definition: WebSocket.h:50
char * http_proxy_auth
Definition: Clients.h:91
#define TCPSOCKET_COMPLETE
Definition: Socket.h:73
ListElement * first
Definition: LinkedList.h:69
static struct frameData WebSocket_buildFrame(networkHandles *net, int opcode, int mask_data, char **pbuf0, size_t *pbuf0len, PacketBuffers *bufs)
Definition: WebSocket.c:236
#define WebSocket_CLOSE_GOING_AWAY
Definition: WebSocket.h:39
void ListFree(List *aList)
Definition: LinkedList.c:381
enum MQTTReasonCodes rc
Definition: test10.c:1112
const char * name
Definition: MQTTClient.h:780
struct ws_frame * last_frame
Definition: WebSocket.c:155
#define TCPSOCKET_INTERRUPTED
Definition: Socket.h:79
Definition: format.h:3618
size_t wsbuf0len
Definition: WebSocket.c:233
string hostname
Definition: test2.py:6
char * SSLSocket_getdata(SSL *ssl, int socket, size_t bytes, size_t *actual_len, int *rc)
unsigned char uuid_t[16]
raw uuid type
Definition: WebSocket.c:104


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:48