Commit a75e3d27 authored by Ian Craggs's avatar Ian Craggs

Check the websocket HTTP response #506

parent b00e6980
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "SHA1.h" #include "SHA1.h"
#include "LinkedList.h" #include "LinkedList.h"
#include "MQTTProtocolOut.h" #include "MQTTProtocolOut.h"
#include "StackTrace.h"
#if defined(__linux__) #if defined(__linux__)
# include <endian.h> # include <endian.h>
...@@ -180,6 +181,7 @@ static int WebSocket_buildFrame(networkHandles* net, int opcode, int mask_data, ...@@ -180,6 +181,7 @@ static int WebSocket_buildFrame(networkHandles* net, int opcode, int mask_data,
int buf_len = 0u; int buf_len = 0u;
size_t data_len = buf0len; size_t data_len = buf0len;
FUNC_ENTRY;
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
data_len += buflens[i]; data_len += buflens[i];
...@@ -255,6 +257,8 @@ static int WebSocket_buildFrame(networkHandles* net, int opcode, int mask_data, ...@@ -255,6 +257,8 @@ static int WebSocket_buildFrame(networkHandles* net, int opcode, int mask_data,
} }
} }
} }
FUNC_EXIT_RC(buf_len);
return buf_len; return buf_len;
} }
...@@ -310,6 +314,7 @@ int WebSocket_connect( networkHandles *net, const char *uri ) ...@@ -310,6 +314,7 @@ int WebSocket_connect( networkHandles *net, const char *uri )
int port = 80; int port = 80;
const char *topic = NULL; const char *topic = NULL;
FUNC_ENTRY;
/* Generate UUID */ /* Generate UUID */
if (net->websocket_key == NULL) if (net->websocket_key == NULL)
net->websocket_key = malloc(25u); net->websocket_key = malloc(25u);
...@@ -374,6 +379,8 @@ int WebSocket_connect( networkHandles *net, const char *uri ) ...@@ -374,6 +379,8 @@ int WebSocket_connect( networkHandles *net, const char *uri )
net->websocket_key = NULL; net->websocket_key = NULL;
rc = SOCKET_ERROR; rc = SOCKET_ERROR;
} }
FUNC_EXIT_RC(rc);
return rc; return rc;
} }
...@@ -386,6 +393,8 @@ int WebSocket_connect( networkHandles *net, const char *uri ) ...@@ -386,6 +393,8 @@ int WebSocket_connect( networkHandles *net, const char *uri )
*/ */
void WebSocket_close(networkHandles *net, int status_code, const char *reason) void WebSocket_close(networkHandles *net, int status_code, const char *reason)
{ {
FUNC_ENTRY;
if ( net->websocket ) if ( net->websocket )
{ {
char *buf0; char *buf0;
...@@ -436,6 +445,8 @@ void WebSocket_close(networkHandles *net, int status_code, const char *reason) ...@@ -436,6 +445,8 @@ void WebSocket_close(networkHandles *net, int status_code, const char *reason)
free( net->websocket_key ); free( net->websocket_key );
net->websocket_key = NULL; net->websocket_key = NULL;
} }
FUNC_EXIT;
} }
/** /**
...@@ -453,6 +464,8 @@ void WebSocket_close(networkHandles *net, int status_code, const char *reason) ...@@ -453,6 +464,8 @@ void WebSocket_close(networkHandles *net, int status_code, const char *reason)
int WebSocket_getch(networkHandles *net, char* c) int WebSocket_getch(networkHandles *net, char* c)
{ {
int rc = SOCKET_ERROR; int rc = SOCKET_ERROR;
FUNC_ENTRY;
if ( net->websocket ) if ( net->websocket )
{ {
struct ws_frame *frame = NULL; struct ws_frame *frame = NULL;
...@@ -487,6 +500,8 @@ int WebSocket_getch(networkHandles *net, char* c) ...@@ -487,6 +500,8 @@ int WebSocket_getch(networkHandles *net, char* c)
#endif #endif
else else
rc = Socket_getch(net->socket, c); rc = Socket_getch(net->socket, c);
FUNC_EXIT_RC(rc);
return rc; return rc;
} }
...@@ -504,6 +519,9 @@ int WebSocket_getch(networkHandles *net, char* c) ...@@ -504,6 +519,9 @@ int WebSocket_getch(networkHandles *net, char* c)
char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len) char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len)
{ {
char *rv = NULL; char *rv = NULL;
int rc = 0;
FUNC_ENTRY;
if ( net->websocket ) if ( net->websocket )
{ {
struct ws_frame *frame = NULL; struct ws_frame *frame = NULL;
...@@ -558,6 +576,9 @@ char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len) ...@@ -558,6 +576,9 @@ char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len)
} }
else else
rv = WebSocket_getRawSocketData(net, bytes, actual_len); rv = WebSocket_getRawSocketData(net, bytes, actual_len);
rc = rv != NULL;
FUNC_EXIT_RC(rc);
return rv; return rv;
} }
...@@ -593,6 +614,7 @@ char *WebSocket_getRawSocketData( ...@@ -593,6 +614,7 @@ char *WebSocket_getRawSocketData(
void WebSocket_pong(networkHandles *net, char *app_data, void WebSocket_pong(networkHandles *net, char *app_data,
size_t app_data_len) size_t app_data_len)
{ {
FUNC_ENTRY;
if ( net->websocket ) if ( net->websocket )
{ {
char *buf0; char *buf0;
...@@ -625,6 +647,7 @@ void WebSocket_pong(networkHandles *net, char *app_data, ...@@ -625,6 +647,7 @@ void WebSocket_pong(networkHandles *net, char *app_data,
/* clean up memory */ /* clean up memory */
free( buf0 ); free( buf0 );
} }
FUNC_EXIT;
} }
/** /**
...@@ -652,6 +675,7 @@ int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len, ...@@ -652,6 +675,7 @@ int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len,
{ {
int rc; int rc;
FUNC_ENTRY;
/* prepend WebSocket frame */ /* prepend WebSocket frame */
if ( net->websocket ) if ( net->websocket )
{ {
...@@ -682,6 +706,8 @@ int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len, ...@@ -682,6 +706,8 @@ int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len,
else else
#endif #endif
rc = Socket_putdatas(net->socket, buf0, buf0len, count, buffers, buflens, freeData); rc = Socket_putdatas(net->socket, buf0, buf0len, count, buffers, buflens, freeData);
FUNC_EXIT_RC(rc);
return rc; return rc;
} }
...@@ -700,7 +726,9 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -700,7 +726,9 @@ int WebSocket_receiveFrame(networkHandles *net,
size_t bytes, size_t *actual_len ) size_t bytes, size_t *actual_len )
{ {
struct ws_frame *res = NULL; struct ws_frame *res = NULL;
int rc = TCPSOCKET_COMPLETE;
FUNC_ENTRY;
if ( !in_frames ) if ( !in_frames )
in_frames = ListInitialize(); in_frames = ListInitialize();
...@@ -727,7 +755,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -727,7 +755,10 @@ int WebSocket_receiveFrame(networkHandles *net,
b = WebSocket_getRawSocketData(net, 2u, &len); b = WebSocket_getRawSocketData(net, 2u, &len);
if ( !b || len == 0u ) if ( !b || len == 0u )
return TCPSOCKET_INTERRUPTED; {
rc = TCPSOCKET_INTERRUPTED;
goto exit;
}
/* 1st byte */ /* 1st byte */
final = (b[0] & 0xFF) >> 7; final = (b[0] & 0xFF) >> 7;
...@@ -741,7 +772,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -741,7 +772,10 @@ int WebSocket_receiveFrame(networkHandles *net,
opcode > WebSocket_OP_PONG || opcode > WebSocket_OP_PONG ||
( opcode > WebSocket_OP_BINARY && ( opcode > WebSocket_OP_BINARY &&
opcode < WebSocket_OP_CLOSE ) ) opcode < WebSocket_OP_CLOSE ) )
return SOCKET_ERROR; {
rc = SOCKET_ERROR;
goto exit;
}
/* 2nd byte */ /* 2nd byte */
has_mask = (b[1] & 0xFF) >> 7; has_mask = (b[1] & 0xFF) >> 7;
...@@ -753,7 +787,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -753,7 +787,10 @@ int WebSocket_receiveFrame(networkHandles *net,
b = WebSocket_getRawSocketData( net, b = WebSocket_getRawSocketData( net,
2u, &len); 2u, &len);
if ( !b || len == 0u ) if ( !b || len == 0u )
return TCPSOCKET_INTERRUPTED; {
rc = TCPSOCKET_INTERRUPTED;
goto exit;
}
/* convert from big endian 16 to host */ /* convert from big endian 16 to host */
payload_len = be16toh(*(uint16_t*)b); payload_len = be16toh(*(uint16_t*)b);
} }
...@@ -762,7 +799,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -762,7 +799,10 @@ int WebSocket_receiveFrame(networkHandles *net,
b = WebSocket_getRawSocketData( net, b = WebSocket_getRawSocketData( net,
8u, &len); 8u, &len);
if ( !b || len == 0u ) if ( !b || len == 0u )
return TCPSOCKET_INTERRUPTED; {
rc = TCPSOCKET_INTERRUPTED;
goto exit;
}
/* convert from big-endian 64 to host */ /* convert from big-endian 64 to host */
payload_len = (size_t)be64toh(*(uint64_t*)b); payload_len = (size_t)be64toh(*(uint64_t*)b);
} }
...@@ -772,7 +812,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -772,7 +812,10 @@ int WebSocket_receiveFrame(networkHandles *net,
uint8_t mask[4]; uint8_t mask[4];
b = WebSocket_getRawSocketData(net, 4u, &len); b = WebSocket_getRawSocketData(net, 4u, &len);
if ( !b || len == 0u ) if ( !b || len == 0u )
return TCPSOCKET_INTERRUPTED; {
rc = TCPSOCKET_INTERRUPTED;
goto exit;
}
memcpy( &mask[0], b, sizeof(uint32_t)); memcpy( &mask[0], b, sizeof(uint32_t));
} }
...@@ -780,7 +823,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -780,7 +823,10 @@ int WebSocket_receiveFrame(networkHandles *net,
payload_len, &len); payload_len, &len);
if ( !b || len == 0u ) if ( !b || len == 0u )
return TCPSOCKET_INTERRUPTED; {
rc = TCPSOCKET_INTERRUPTED;
goto exit;
}
/* unmask data */ /* unmask data */
if ( has_mask ) if ( has_mask )
...@@ -821,7 +867,8 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -821,7 +867,8 @@ int WebSocket_receiveFrame(networkHandles *net,
/* server end closed websocket connection */ /* server end closed websocket connection */
free( res ); free( res );
WebSocket_close( net, WebSocket_CLOSE_GOING_AWAY, NULL ); WebSocket_close( net, WebSocket_CLOSE_GOING_AWAY, NULL );
return SOCKET_ERROR; /* closes socket */ rc = SOCKET_ERROR; /* closes socket */
goto exit;
} }
} while ( opcode == WebSocket_OP_PING || opcode == WebSocket_OP_PONG ); } while ( opcode == WebSocket_OP_PING || opcode == WebSocket_OP_PONG );
} }
...@@ -829,7 +876,10 @@ int WebSocket_receiveFrame(networkHandles *net, ...@@ -829,7 +876,10 @@ int WebSocket_receiveFrame(networkHandles *net,
/* add new frame to end of list */ /* add new frame to end of list */
ListAppend( in_frames, res, sizeof(struct ws_frame) + res->len); ListAppend( in_frames, res, sizeof(struct ws_frame) + res->len);
*actual_len = res->len - res->pos; *actual_len = res->len - res->pos;
return TCPSOCKET_COMPLETE;
exit:
FUNC_EXIT_RC(rc);
return rc;
} }
/** /**
...@@ -866,6 +916,7 @@ const char *WebSocket_strcasefind(const char *buf, const char *str, size_t len) ...@@ -866,6 +916,7 @@ const char *WebSocket_strcasefind(const char *buf, const char *str, size_t len)
*/ */
void WebSocket_terminate( void ) void WebSocket_terminate( void )
{ {
FUNC_ENTRY;
/* clean up and un-processed websocket frames */ /* clean up and un-processed websocket frames */
if ( in_frames ) if ( in_frames )
{ {
...@@ -887,6 +938,7 @@ void WebSocket_terminate( void ) ...@@ -887,6 +938,7 @@ void WebSocket_terminate( void )
#if defined(OPENSSL) #if defined(OPENSSL)
SSLSocket_terminate(); SSLSocket_terminate();
#endif #endif
FUNC_EXIT;
} }
/** /**
...@@ -904,6 +956,8 @@ int WebSocket_upgrade( networkHandles *net ) ...@@ -904,6 +956,8 @@ int WebSocket_upgrade( networkHandles *net )
static const char *const ws_guid = static const char *const ws_guid =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
int rc = SOCKET_ERROR; int rc = SOCKET_ERROR;
FUNC_ENTRY;
if ( net->websocket_key ) if ( net->websocket_key )
{ {
SHA_CTX ctx; SHA_CTX ctx;
...@@ -921,7 +975,18 @@ int WebSocket_upgrade( networkHandles *net ) ...@@ -921,7 +975,18 @@ int WebSocket_upgrade( networkHandles *net )
rc = TCPSOCKET_INTERRUPTED; rc = TCPSOCKET_INTERRUPTED;
read_buf = WebSocket_getRawSocketData( net, 12u, &rcv ); read_buf = WebSocket_getRawSocketData( net, 12u, &rcv );
if ( rcv > 0 && strncmp( read_buf, "HTTP/1.1 101", 11u ) == 0 )
if ( rcv > 0 && strncmp( read_buf, "HTTP/1.1", 8u ) == 0 )
{
if (strncmp( &read_buf[9], "101", 3u ) != 0)
{
Log(TRACE_PROTOCOL, 1, "WebSocket HTTP rc %.3s", &read_buf[9]);
rc = SOCKET_ERROR;
goto exit;
}
}
if ( rcv > 0 && strncmp( read_buf, "HTTP/1.1 101", 12u ) == 0 )
{ {
const char *p; const char *p;
read_buf = WebSocket_getRawSocketData( net, 500u, &rcv ); read_buf = WebSocket_getRawSocketData( net, 500u, &rcv );
...@@ -990,6 +1055,9 @@ int WebSocket_upgrade( networkHandles *net ) ...@@ -990,6 +1055,9 @@ int WebSocket_upgrade( networkHandles *net )
WebSocket_getRawSocketData( net, 0u, &rcv ); WebSocket_getRawSocketData( net, 0u, &rcv );
} }
} }
exit:
FUNC_EXIT_RC(rc);
return rc; return rc;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment