5 Commits
1.1.0 ... 1.3.0

Author SHA1 Message Date
JCash
ba2b8e4a69 Updated hex string logging to use our internal logging functions
This will keep the output in-order
2020-10-13 09:33:38 +02:00
JCash
176f213060 updated documentation 2020-10-13 09:14:21 +02:00
Mathias Westerdahl
dc1d57d661 Merge pull request #10 from defold/issue-4-case-insensitive-header
Issue 4: Compare header keys without case sensitivity
2020-10-12 09:59:55 +02:00
JCash
5b0a9960a8 Check the response headers more thoroughly 2020-10-12 09:45:05 +02:00
JCash
40ba1b334c Issue 4: Compare header keys without case sensitivity 2020-10-12 09:33:47 +02:00
4 changed files with 85 additions and 28 deletions

View File

@@ -14,18 +14,16 @@ Here is how you connect to a websocket and listen to events:
```lua ```lua
local function websocket_callback(self, conn, data) local function websocket_callback(self, conn, data)
if data.event == websocket.EVENT_DISCONNECTED then if data.event == websocket.EVENT_DISCONNECTED then
print("disconnected " .. conn) log("Disconnected: " .. tostring(conn))
self.connection = nil self.connection = nil
update_gui(self)
elseif data.event == websocket.EVENT_CONNECTED then elseif data.event == websocket.EVENT_CONNECTED then
print("Connected " .. conn) update_gui(self)
-- self.connection = conn log("Connected: " .. tostring(conn))
elseif data.event == websocket.EVENT_ERROR then elseif data.event == websocket.EVENT_ERROR then
print("Error:", data.message) log("Error: '" .. data.error .. "'")
elseif data.event == websocket.EVENT_MESSAGE then elseif data.event == websocket.EVENT_MESSAGE then
print("Receiving: '" .. tostring(data.message) .. "'") log("Receiving: '" .. tostring(data.message) .. "'")
end
elseif data.event == websocket.EVENT_DISCONNECTED then
print("Disconnected: '" .. tostring(data.message) .. "'")
end end
end end

View File

@@ -65,15 +65,16 @@
```lua ```lua
local function websocket_callback(self, conn, data) local function websocket_callback(self, conn, data)
if data.event == websocket.EVENT_DISCONNECTED then if data.event == websocket.EVENT_DISCONNECTED then
print("disconnected " .. conn) log("Disconnected: " .. tostring(conn))
self.connection = nil self.connection = nil
update_gui(self)
elseif data.event == websocket.EVENT_CONNECTED then elseif data.event == websocket.EVENT_CONNECTED then
print("Connected " .. conn) update_gui(self)
-- self.connection = conn log("Connected: " .. tostring(conn))
elseif data.event == websocket.EVENT_ERROR then elseif data.event == websocket.EVENT_ERROR then
print("Error:", data.error) log("Error: '" .. data.error .. "'")
elseif data.event == websocket.EVENT_MESSAGE then elseif data.event == websocket.EVENT_MESSAGE then
print("Receiving: '" .. tostring(data.message) .. "'") log("Receiving: '" .. tostring(data.message) .. "'")
end end
end end

View File

@@ -1,5 +1,6 @@
#include "websocket.h" #include "websocket.h"
#include <dmsdk/dlib/socket.h> #include <dmsdk/dlib/socket.h>
#include <ctype.h> // tolower
namespace dmWebsocket namespace dmWebsocket
{ {
@@ -156,6 +157,20 @@ Result ReceiveHeaders(WebsocketConnection* conn)
} }
#endif #endif
static int dmStriCmp(const char* s1, const char* s2)
{
for (;;)
{
if (!*s1 || !*s2 || tolower((unsigned char) *s1) != tolower((unsigned char) *s2))
{
return (unsigned char) *s1 - (unsigned char) *s2;
}
s1++;
s2++;
}
}
#if defined(__EMSCRIPTEN__) #if defined(__EMSCRIPTEN__)
Result VerifyHeaders(WebsocketConnection* conn) Result VerifyHeaders(WebsocketConnection* conn)
{ {
@@ -176,7 +191,8 @@ Result VerifyHeaders(WebsocketConnection* conn)
r = strstr(r, "\r\n") + 2; r = strstr(r, "\r\n") + 2;
bool upgraded = false; bool connection = false;
bool upgrade = false;
bool valid_key = false; bool valid_key = false;
const char* protocol = ""; const char* protocol = "";
@@ -197,27 +213,39 @@ Result VerifyHeaders(WebsocketConnection* conn)
*r = 0; *r = 0;
r += 2; r += 2;
if (strcmp(key, "Connection") == 0 && strcmp(value, "Upgrade") == 0) // Page 18 in https://tools.ietf.org/html/rfc6455#section-11.3.3
upgraded = true; if (dmStriCmp(key, "Connection") == 0 && dmStriCmp(value, "Upgrade") == 0)
else if (strcmp(key, "Sec-WebSocket-Accept") == 0) connection = true;
else if (dmStriCmp(key, "Upgrade") == 0 && dmStriCmp(value, "websocket") == 0)
upgrade = true;
else if (dmStriCmp(key, "Sec-WebSocket-Accept") == 0)
{ {
uint8_t client_key[32 + 40]; uint8_t client_key[32 + 40];
uint32_t client_key_len = sizeof(client_key); uint32_t client_key_len = sizeof(client_key);
dmCrypt::Base64Encode(conn->m_Key, sizeof(conn->m_Key), client_key, &client_key_len); dmCrypt::Base64Encode(conn->m_Key, sizeof(conn->m_Key), client_key, &client_key_len);
client_key[client_key_len] = 0; client_key[client_key_len] = 0;
DebugLog(2, "Secret key (base64): %s", client_key);
memcpy(client_key + client_key_len, RFC_MAGIC, strlen(RFC_MAGIC)); memcpy(client_key + client_key_len, RFC_MAGIC, strlen(RFC_MAGIC));
client_key_len += strlen(RFC_MAGIC); client_key_len += strlen(RFC_MAGIC);
client_key[client_key_len] = 0; client_key[client_key_len] = 0;
DebugLog(2, "Secret key + RFC_MAGIC: %s", client_key);
uint8_t client_key_sha1[20]; uint8_t client_key_sha1[20];
dmCrypt::HashSha1(client_key, client_key_len, client_key_sha1); dmCrypt::HashSha1(client_key, client_key_len, client_key_sha1);
DebugPrint(2, "Hashed key (sha1):", client_key_sha1, sizeof(client_key_sha1));
client_key_len = sizeof(client_key); client_key_len = sizeof(client_key);
dmCrypt::Base64Encode(client_key_sha1, sizeof(client_key_sha1), client_key, &client_key_len); dmCrypt::Base64Encode(client_key_sha1, sizeof(client_key_sha1), client_key, &client_key_len);
client_key[client_key_len] = 0; client_key[client_key_len] = 0;
DebugLog(2, "Client key (base64): %s", client_key);
DebugLog(2, "Server key (base64): %s", value);
if (strcmp(value, (const char*)client_key) == 0) if (strcmp(value, (const char*)client_key) == 0)
valid_key = true; valid_key = true;
} }
@@ -231,16 +259,19 @@ Result VerifyHeaders(WebsocketConnection* conn)
conn->m_Buffer[size] = 0; conn->m_Buffer[size] = 0;
conn->m_HasHandshakeData = conn->m_BufferSize != 0 ? 1 : 0; conn->m_HasHandshakeData = conn->m_BufferSize != 0 ? 1 : 0;
if (!upgraded) if (!connection)
dmLogError("Failed to find the Connection keyword in the response headers");
if (!upgrade)
dmLogError("Failed to find the Upgrade keyword in the response headers"); dmLogError("Failed to find the Upgrade keyword in the response headers");
if (!valid_key) if (!valid_key)
dmLogError("Failed to find valid key in the response headers"); dmLogError("Failed to find valid key in the response headers");
if (!(upgraded && valid_key)) { bool ok = connection && upgrade && valid_key;
if (!ok) {
dmLogError("Response:\n\"%s\"\n", conn->m_Buffer); dmLogError("Response:\n\"%s\"\n", conn->m_Buffer);
} }
return (upgraded && valid_key) ? RESULT_OK : RESULT_HANDSHAKE_FAILED; return ok ? RESULT_OK : RESULT_HANDSHAKE_FAILED;
} }
#endif #endif

View File

@@ -87,23 +87,50 @@ void DebugPrint(int level, const char* msg, const void* _bytes, uint32_t num_byt
if (level > g_DebugWebSocket) if (level > g_DebugWebSocket)
return; return;
char buffer[1024];
char submessage[128];
uint32_t sublength = 0;
uint32_t len = dmSnPrintf(buffer, sizeof(buffer), "%s '", msg);
const uint8_t* bytes = (const uint8_t*)_bytes; const uint8_t* bytes = (const uint8_t*)_bytes;
printf("%s '", msg);
for (uint32_t i = 0; i < num_bytes; ++i) for (uint32_t i = 0; i < num_bytes; ++i)
{ {
if (len + 2 >= sizeof(buffer))
{
dmLogWarning("%s", buffer);
buffer[0] = 0;
len = 0;
}
sublength = 0;
int c = bytes[i]; int c = bytes[i];
if (isprint(c)) if (isprint(c))
printf("%c", c); sublength = dmSnPrintf(submessage, sizeof(submessage), "%c", c);
else if (c == '\r') else if (c == '\r')
printf("\\r"); sublength = dmSnPrintf(submessage, sizeof(submessage), "\\r");
else if (c == '\n') else if (c == '\n')
printf("\\n"); sublength = dmSnPrintf(submessage, sizeof(submessage), "\\n");
else if (c == '\t') else if (c == '\t')
printf("\\t"); sublength = dmSnPrintf(submessage, sizeof(submessage), "\\t");
else else
printf("\\%02x", c); sublength = dmSnPrintf(submessage, sizeof(submessage), "\\%02x", c);
dmStrlCat(buffer, submessage, sizeof(buffer));
len += sublength;
} }
printf("' %u bytes\n", num_bytes);
if (len + 2 >= sizeof(buffer))
{
dmLogWarning("%s", buffer);
buffer[0] = 0;
len = 0;
}
sublength = dmSnPrintf(submessage, sizeof(submessage), "' %u bytes", num_bytes);
dmStrlCat(buffer, submessage, sizeof(buffer));
len += sublength;
dmLogWarning("%s", buffer);
} }