mirror of
https://github.com/defold/extension-websocket.git
synced 2025-09-30 09:12:18 +02:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ba2b8e4a69 | ||
|
176f213060 | ||
|
dc1d57d661 | ||
|
5b0a9960a8 | ||
|
40ba1b334c |
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user