24 #if defined(_WIN32) || defined(_WIN64) 40 #if defined(__MINGW32__) 41 #define htonll __builtin_bswap64 42 #define ntohll __builtin_bswap64 45 #if defined(__linux__) 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") 60 # define strncasecmp(s1,s2,c) _strnicmp(s1,s2,c) 61 # define htonll(x) _byteswap_uint64(x) 62 # define ntohll(x) _byteswap_uint64(x) 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) 79 # error "unknown endian" 82 # if defined(_MSC_VER) && _MSC_VER < 1900 83 # define snprintf _snprintf 89 #include <openssl/rand.h> 93 #define HTTP_PROTOCOL(x) x ? "https" : "http" 95 #if !(defined(_WIN32) || defined(_WIN64)) 97 #include <uuid/uuid.h> 113 int rc = RAND_bytes( out,
sizeof(
uuid_t));
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;
131 for ( i = 0; i < 16; ++i )
133 if ( i == 4 || i == 6 || i == 8 || i == 10 )
138 out += sprintf( out,
"%02x", uu[i] );
167 const char *buf,
const char *str,
size_t len);
200 if ( data_len < 126u)
202 else if ( data_len < 65536u )
204 else if ( data_len < 0xFFFFFFFFFFFFFFFF )
206 if ( mask_data & 0x1 )
207 ret +=
sizeof(uint32_t);
244 memset(&rc,
'\0',
sizeof(rc));
245 if ( net->websocket )
247 size_t ws_header_size = 0u;
248 size_t data_len = 0L;
252 data_len = *pbuf0len;
253 for (i = 0; i < bufs->count; ++i)
254 data_len += bufs->buflens[i];
260 rc.
wsbuf0len = *pbuf0len + ws_header_size;
264 memcpy(&rc.
wsbuf0[ws_header_size], *pbuf0, *pbuf0len);
274 if (mask_data && (bufs->mask[0] == 0))
278 RAND_bytes(&bufs->mask[0],
sizeof(bufs->mask));
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);
289 rc.
wsbuf0[buf_len] = (char)(1 << 7);
291 rc.
wsbuf0[buf_len] |= (char)(opcode & 0x0F);
295 rc.
wsbuf0[buf_len] = (char)((mask_data & 0x1) << 7);
298 if ( data_len < 126u )
299 rc.
wsbuf0[buf_len++] |= data_len & 0x7F;
302 else if ( data_len < 65536u )
304 uint16_t
len = htobe16((uint16_t)data_len);
305 rc.
wsbuf0[buf_len++] |= (126u & 0x7F);
306 memcpy( &rc.
wsbuf0[buf_len], &len, 2u );
309 else if ( data_len < 0xFFFFFFFFFFFFFFFF )
311 uint64_t
len = htobe64((uint64_t)data_len);
312 rc.
wsbuf0[buf_len++] |= (127u & 0x7F);
313 memcpy( &rc.
wsbuf0[buf_len], &len, 8 );
327 memcpy( &rc.
wsbuf0[buf_len], &bufs->mask,
sizeof(uint32_t));
328 buf_len +=
sizeof(uint32_t);
331 for (i = (
int)ws_header_size; i < (int)rc.
wsbuf0len; ++i, ++idx)
332 rc.
wsbuf0[i] ^= bufs->mask[idx % 4];
335 for (i = 0; i < bufs->count; ++i)
339 if (new_mask == 0 && (i == 2 || i == bufs->count-1))
342 for ( j = 0u; j < bufs->buflens[i]; ++j, ++idx )
344 bufs->buffers[i][j] ^= bufs->mask[idx % 4];
360 for (i = 0; i < bufs->
count; ++i)
363 for (j = 0u; j < bufs->
buflens[i]; ++j, ++idx)
387 char *headers_buf = NULL;
390 int headers_buf_len = 0;
393 const char *
topic = NULL;
394 #if defined(_WIN32) || defined(_WIN64) 411 #if defined(_WIN32) || defined(_WIN64) 412 ZeroMemory( &uuid,
sizeof(UUID) );
428 char *headers_buf_cur = NULL;
429 while ( headers->
name != NULL && headers->
value != NULL )
431 headers_buf_len += (int)(strlen(headers->
name) + strlen(headers->
value) + 4);
436 if ((headers_buf =
malloc(headers_buf_len)) == NULL)
442 headers_buf_cur = headers_buf;
444 while ( headers->
name != NULL && headers->
value != NULL )
446 headers_buf_cur += sprintf(headers_buf_cur,
"%s: %s\r\n", headers->
name, headers->
value);
449 *headers_buf_cur =
'\0';
452 for ( i = 0; i < 2; ++i )
454 buf_len = snprintf( buf, (
size_t)buf_len,
455 "GET %s HTTP/1.1\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" 465 (
int)hostname_len, uri, port,
472 (
int)hostname_len, uri, port,
474 headers_buf ? headers_buf :
"");
476 if ( i == 0 && buf_len > 0 )
479 if ((buf =
malloc( buf_len )) == NULL)
530 size_t buf0len =
sizeof(uint16_t);
531 uint16_t status_code_be;
532 const int mask_data = 1;
539 buf0len += strlen(reason);
546 status_code_be = htobe16((uint16_t)status_code);
547 memcpy(buf0, &status_code_be,
sizeof(uint16_t));
551 strcpy( &buf0[
sizeof(uint16_t)], reason );
598 if ( in_frames && in_frames->
first )
601 if ( !frame || frame->
len == frame->
pos )
603 size_t actual_len = 0u;
609 if ( in_frames->
first )
614 if (frame && frame->
len > frame->
pos)
617 (
unsigned char *)frame +
sizeof(
struct ws_frame);
618 *c = buf[frame->
pos++];
636 if ( in_frames && in_frames->
first )
649 if ( in_frames && in_frames->
first )
682 if ( in_frames && in_frames->
first )
686 if ( frame && frame->
pos == frame->
len )
690 *actual_len = frame->
len - frame->
pos;
700 if ( in_frames && in_frames->
first )
715 rv = (
char *)frame +
sizeof(
struct ws_frame) + frame->
pos;
716 *actual_len = frame->
len - frame->
pos;
719 while (*actual_len < bytes) {
728 rv = (
char *)frame +
sizeof(
struct ws_frame) + frame->
pos;
729 *actual_len = frame->
len - frame->
pos;
733 if (*actual_len > bytes)
737 else if (*actual_len == bytes && in_frames)
775 size_t bytes_requested =
bytes;
784 frame_buffer_index +=
bytes;
821 else if (rv != NULL && *actual_len != 0U)
858 bytes = bytes_requested;
867 frame_buffer_index +=
bytes;
873 frame_buffer_index += *actual_len;
898 const int mask_data = 1;
899 PacketBuffers appbuf = {1, &app_data, &app_data_len, &freeData, {0, 0, 0, 0}};
940 const int mask_data = 1;
1001 if ( in_frames->
first )
1011 while ( is_final == 0 )
1017 size_t cur_len = 0u;
1018 uint8_t mask[4] = { 0u, 0u, 0u, 0u };
1040 is_final = (b[0] & 0xFF) >> 7;
1041 tmp_opcode = (b[0] & 0x0F);
1044 opcode = tmp_opcode;
1057 has_mask = (b[1] & 0xFF) >> 7;
1058 payload_len = (b[1] & 0x7F);
1061 if ( payload_len == 126 )
1082 payload_len = be16toh(*(uint16_t*)b);
1084 else if ( payload_len == 127 )
1105 payload_len = (size_t)be64toh(*(uint64_t*)b);
1127 memcpy( &mask[0], b,
sizeof(uint32_t));
1142 if (len < payload_len )
1152 for ( i = 0u; i < payload_len; ++i )
1153 b[i] ^= mask[i % 4];
1161 if ((res =
malloc(
sizeof(
struct ws_frame) + cur_len + len)) == NULL)
1169 if ((res =
realloc( res,
sizeof(
struct ws_frame) + cur_len + len )) == NULL)
1175 if (in_frames && in_frames->
first)
1177 memcpy( (
unsigned char *)res +
sizeof(
struct ws_frame) + cur_len, b, len );
1178 res->
len = cur_len +
len;
1193 (
char *)res +
sizeof(
struct ws_frame),
1211 if (in_frames->
count == 0)
1213 *actual_len = res->
len - res->
pos;
1239 const char *res = NULL;
1240 if ( buf && len > 0u && str )
1242 const size_t str_len = strlen( str );
1243 while ( len >= str_len && !res )
1245 if ( strncasecmp( buf, str, str_len ) == 0 )
1289 #if defined(OPENSSL) 1308 static const char *
const ws_guid =
1309 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
1316 char ws_key[62u] = { 0 };
1322 snprintf( ws_key,
sizeof(ws_key),
"%s%s", net->
websocket_key, ws_guid );
1333 if ((read_buf == NULL) || rcv < 12u) {
1338 if (strncmp( read_buf,
"HTTP/1.1", 8u ) == 0)
1340 if (strncmp( &read_buf[9],
"101", 3u ) != 0)
1348 if (strncmp( read_buf,
"HTTP/1.1 101", 12u ) == 0)
1357 if (read_buf && rcv > 4 && memcmp(&read_buf[rcv-4],
"\r\n\r\n", 4) != 0)
1359 Log(
TRACE_PROTOCOL, -1,
"WebSocket HTTP upgrade response read not complete %lu", rcv);
1366 read_buf,
"Connection", rcv );
1370 eol = memchr( p,
'\n', rcv-(read_buf-p) );
1373 p,
"Upgrade", eol - p);
1381 "sec-websocket-accept", rcv );
1385 eol = memchr( p,
'\n', rcv-(read_buf-p) );
1388 p = memchr( p,
':', eol-p );
1391 size_t hash_len = eol-p-1;
1392 while ( *p ==
':' || *p ==
' ' )
1398 if ( strncmp( p, ws_key, hash_len ) != 0 )
1447 int port, i,
rc = 0, buf_len=0;
1449 size_t hostname_len, actual_len = 0;
1450 time_t current, timeout;
1451 PacketBuffers nulbufs = {0, NULL, NULL, NULL, {0, 0, 0, 0}};
1455 for ( i = 0; i < 2; ++i ) {
1456 #if defined(OPENSSL) 1458 if (net->https_proxy_auth) {
1459 buf_len = snprintf( buf, (
size_t)buf_len,
"CONNECT %.*s:%d HTTP/1.1\r\n" 1461 "Proxy-authorization: Basic %s\r\n" 1463 (
int)hostname_len, hostname, port,
1464 (
int)hostname_len, hostname, net->https_proxy_auth);
1467 buf_len = snprintf( buf, (
size_t)buf_len,
"CONNECT %.*s:%d HTTP/1.1\r\n" 1470 (
int)hostname_len, hostname, port,
1471 (
int)hostname_len, hostname);
1477 buf_len = snprintf( buf, (
size_t)buf_len,
"CONNECT %.*s:%d HTTP/1.1\r\n" 1479 "Proxy-authorization: Basic %s\r\n" 1481 (
int)hostname_len, hostname, port,
1485 buf_len = snprintf( buf, (
size_t)buf_len,
"CONNECT %.*s:%d HTTP/1.1\r\n" 1488 (
int)hostname_len, hostname, port,
1489 (
int)hostname_len, hostname);
1491 #if defined(OPENSSL) 1494 if ( i==0 && buf_len > 0 ) {
1496 if ((buf =
malloc( buf_len )) == NULL)
1511 timeout += (time_t)10;
1516 if ( (strncmp( buf,
"HTTP/1.0 200", 12 ) != 0) && (strncmp( buf,
"HTTP/1.1 200", 12 ) != 0) )
1522 if(current > timeout) {
1526 #if defined(_WIN32) || defined(_WIN64) int WebSocket_proxy_connect(networkHandles *net, int ssl, const char *hostname)
int SHA1_Final(unsigned char *md, SHA_CTX *ctx)
void WebSocket_framePosSeekTo(size_t pos)
int SSLSocket_getch(SSL *ssl, int socket, char *c)
#define WebSocket_CLOSE_NORMAL
void WebSocket_close(networkHandles *net, int status_code, const char *reason)
static char * WebSocket_getRawSocketData(networkHandles *net, size_t bytes, size_t *actual_len, int *rc)
static char * frame_buffer
void WebSocket_terminate(void)
static void WebSocket_unmaskData(size_t idx, PacketBuffers *bufs)
int Socket_getch(int socket, char *c)
static void WebSocket_pong(networkHandles *net, char *app_data, size_t app_data_len)
void Socket_outTerminate(void)
#define WebSocket_OP_PING
#define PAHO_MEMORY_ERROR
const MQTTClient_nameValue * httpHeaders
builds a websocket frame for data transmission
int SHA1_Update(SHA_CTX *ctx, const void *data, size_t len)
size_t WebSocket_framePos()
#define WebSocket_OP_PONG
void uuid_generate(uuid_t out)
generates a uuid, compatible with RFC 4122, version 4 (random)
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...
int SHA1_Init(SHA_CTX *ctx)
static int WebSocket_receiveFrame(networkHandles *net, size_t *actual_len)
static const char * WebSocket_strcasefind(const char *buf, const char *str, size_t len)
#define WebSocket_OP_CLOSE
#define SHA1_DIGEST_LENGTH
void * ListDetachHead(List *aList)
b64_size_t Base64_encode(char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len)
void uuid_unparse(uuid_t uu, char *out)
converts a uuid to a string
void Log(enum LOG_LEVELS log_level, int msgno, const char *format,...)
int WebSocket_upgrade(networkHandles *net)
#define WebSocket_OP_CONTINUE
int WebSocket_getch(networkHandles *net, char *c)
receives 1 byte from a socket
char * Socket_getdata(int socket, size_t bytes, size_t *actual_len, int *rc)
ListElement * ListAppend(List *aList, void *content, size_t size)
static size_t frame_buffer_len
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
static void WebSocket_rewindData(void)
size_t WebSocket_calculateFrameHeaderSize(networkHandles *net, int mask_data, size_t data_len)
int WebSocket_putdatas(networkHandles *net, char **buf0, size_t *buf0len, PacketBuffers *bufs)
static size_t frame_buffer_index
#define WebSocket_OP_BINARY
char * SocketBuffer_complete(int socket)
int Socket_putdatas(int socket, char *buf0, size_t buf0len, PacketBuffers bufs)
static int str_len(lua_State *L)
List * ListInitialize(void)
int WebSocket_connect(networkHandles *net, const char *uri)
size_t MQTTProtocol_addressPort(const char *uri, int *port, const char **topic, int default_port)
#define WebSocket_CLOSE_TLS_FAIL
#define TCPSOCKET_COMPLETE
static struct frameData WebSocket_buildFrame(networkHandles *net, int opcode, int mask_data, char **pbuf0, size_t *pbuf0len, PacketBuffers *bufs)
#define WebSocket_CLOSE_GOING_AWAY
void ListFree(List *aList)
struct ws_frame * last_frame
#define TCPSOCKET_INTERRUPTED
char * SSLSocket_getdata(SSL *ssl, int socket, size_t bytes, size_t *actual_len, int *rc)
unsigned char uuid_t[16]
raw uuid type