mirror of
https://github.com/defold/extension-websocket.git
synced 2025-09-30 09:12:18 +02:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d5237bbee1 | ||
|
daffff4c06 | ||
|
0f841f16af | ||
|
97cca427d7 | ||
|
cba11de5f1 | ||
|
4e67c4dfaa |
@@ -7,7 +7,7 @@
|
|||||||
#include "websocket.h"
|
#include "websocket.h"
|
||||||
#include "script_util.h"
|
#include "script_util.h"
|
||||||
#include <dmsdk/dlib/connection_pool.h>
|
#include <dmsdk/dlib/connection_pool.h>
|
||||||
#include <dmsdk/dlib/dns.h>
|
#include <dmsdk/dlib/thread.h>
|
||||||
#include <dmsdk/dlib/sslsocket.h>
|
#include <dmsdk/dlib/sslsocket.h>
|
||||||
#include <ctype.h> // isprint et al
|
#include <ctype.h> // isprint et al
|
||||||
|
|
||||||
@@ -31,7 +31,6 @@ struct WebsocketContext
|
|||||||
int m_Timeout;
|
int m_Timeout;
|
||||||
dmArray<WebsocketConnection*> m_Connections;
|
dmArray<WebsocketConnection*> m_Connections;
|
||||||
dmConnectionPool::HPool m_Pool;
|
dmConnectionPool::HPool m_Pool;
|
||||||
dmDNS::HChannel m_Channel;
|
|
||||||
uint32_t m_Initialized:1;
|
uint32_t m_Initialized:1;
|
||||||
} g_Websocket;
|
} g_Websocket;
|
||||||
|
|
||||||
@@ -193,6 +192,7 @@ static WebsocketConnection* CreateConnection(const char* url)
|
|||||||
conn->m_Status = RESULT_OK;
|
conn->m_Status = RESULT_OK;
|
||||||
conn->m_HasHandshakeData = 0;
|
conn->m_HasHandshakeData = 0;
|
||||||
conn->m_HandshakeResponse = 0;
|
conn->m_HandshakeResponse = 0;
|
||||||
|
conn->m_ConnectionThread = 0;
|
||||||
|
|
||||||
#if defined(HAVE_WSLAY)
|
#if defined(HAVE_WSLAY)
|
||||||
conn->m_Ctx = 0;
|
conn->m_Ctx = 0;
|
||||||
@@ -232,6 +232,13 @@ static void DestroyConnection(WebsocketConnection* conn)
|
|||||||
|
|
||||||
|
|
||||||
free((void*)conn->m_Buffer);
|
free((void*)conn->m_Buffer);
|
||||||
|
|
||||||
|
if (conn->m_ConnectionThread)
|
||||||
|
{
|
||||||
|
dmThread::Join(conn->m_ConnectionThread);
|
||||||
|
conn->m_ConnectionThread = 0;
|
||||||
|
}
|
||||||
|
|
||||||
delete conn;
|
delete conn;
|
||||||
DebugLog(2, "DestroyConnection: %p", conn);
|
DebugLog(2, "DestroyConnection: %p", conn);
|
||||||
}
|
}
|
||||||
@@ -242,10 +249,7 @@ static void CloseConnection(WebsocketConnection* conn)
|
|||||||
// we want it to send this message in the polling
|
// we want it to send this message in the polling
|
||||||
if (conn->m_State == STATE_CONNECTED) {
|
if (conn->m_State == STATE_CONNECTED) {
|
||||||
#if defined(HAVE_WSLAY)
|
#if defined(HAVE_WSLAY)
|
||||||
// close the connection and immediately transition to the DISCONNECTED
|
|
||||||
// state
|
|
||||||
WSL_Close(conn->m_Ctx);
|
WSL_Close(conn->m_Ctx);
|
||||||
SetState(conn, STATE_DISCONNECTED);
|
|
||||||
#else
|
#else
|
||||||
// start disconnecting by closing the WebSocket through the JS API
|
// start disconnecting by closing the WebSocket through the JS API
|
||||||
// we transition to the DISCONNECTED state when we receive the
|
// we transition to the DISCONNECTED state when we receive the
|
||||||
@@ -255,6 +259,11 @@ static void CloseConnection(WebsocketConnection* conn)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_WSLAY)
|
||||||
|
// close the connection and immediately transition to the DISCONNECTED
|
||||||
|
// state
|
||||||
|
SetState(conn, STATE_DISCONNECTED);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsConnectionValid(WebsocketConnection* conn)
|
static bool IsConnectionValid(WebsocketConnection* conn)
|
||||||
@@ -518,8 +527,8 @@ static dmExtension::Result AppInitialize(dmExtension::AppParams* params)
|
|||||||
g_Websocket.m_BufferSize = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.buffer_size", 64 * 1024);
|
g_Websocket.m_BufferSize = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.buffer_size", 64 * 1024);
|
||||||
g_Websocket.m_Timeout = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.socket_timeout", 500 * 1000);
|
g_Websocket.m_Timeout = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.socket_timeout", 500 * 1000);
|
||||||
g_Websocket.m_Connections.SetCapacity(4);
|
g_Websocket.m_Connections.SetCapacity(4);
|
||||||
g_Websocket.m_Channel = 0;
|
|
||||||
g_Websocket.m_Pool = 0;
|
g_Websocket.m_Pool = 0;
|
||||||
|
g_Websocket.m_Initialized = 0;
|
||||||
|
|
||||||
dmConnectionPool::Params pool_params;
|
dmConnectionPool::Params pool_params;
|
||||||
pool_params.m_MaxConnections = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.max_connections", 2);
|
pool_params.m_MaxConnections = dmConfigFile::GetInt(params->m_ConfigFile, "websocket.max_connections", 2);
|
||||||
@@ -532,31 +541,10 @@ static dmExtension::Result AppInitialize(dmExtension::AppParams* params)
|
|||||||
if (dmConnectionPool::RESULT_OK != result)
|
if (dmConnectionPool::RESULT_OK != result)
|
||||||
{
|
{
|
||||||
dmLogError("Failed to create connection pool: %d", result);
|
dmLogError("Failed to create connection pool: %d", result);
|
||||||
|
return dmExtension::RESULT_INIT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can do without the channel, it will then fallback to the dmSocket::GetHostname (as opposed to dmDNS::GetHostname)
|
|
||||||
#if defined(HAVE_WSLAY)
|
|
||||||
dmDNS::Result dns_result = dmDNS::NewChannel(&g_Websocket.m_Channel);
|
|
||||||
|
|
||||||
if (dmDNS::RESULT_OK != dns_result)
|
|
||||||
{
|
|
||||||
dmLogError("Failed to create connection pool: %d", dns_result);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_Websocket.m_Initialized = 1;
|
g_Websocket.m_Initialized = 1;
|
||||||
if (!g_Websocket.m_Pool)
|
|
||||||
{
|
|
||||||
if (!g_Websocket.m_Pool)
|
|
||||||
{
|
|
||||||
dmLogInfo("pool is null!");
|
|
||||||
dmConnectionPool::Delete(g_Websocket.m_Pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
dmLogInfo("%s extension not initialized", MODULE_NAME);
|
|
||||||
g_Websocket.m_Initialized = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,6 +610,19 @@ static bool CheckConnectTimeout(WebsocketConnection* conn)
|
|||||||
return t >= conn->m_ConnectTimeout;
|
return t >= conn->m_ConnectTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ConnectionWorker(void* _conn)
|
||||||
|
{
|
||||||
|
WebsocketConnection* conn = (WebsocketConnection*)_conn;
|
||||||
|
dmSocket::Result sr;
|
||||||
|
dmConnectionPool::Result pool_result = dmConnectionPool::Dial(g_Websocket.m_Pool, conn->m_Url.m_Hostname, conn->m_Url.m_Port, conn->m_SSL, g_Websocket.m_Timeout, &conn->m_Connection, &sr);
|
||||||
|
if (dmConnectionPool::RESULT_OK != pool_result)
|
||||||
|
{
|
||||||
|
CLOSE_CONN("Failed to open connection: %s", dmSocket::ResultToString(sr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetState(conn, STATE_HANDSHAKE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
||||||
{
|
{
|
||||||
uint32_t size = g_Websocket.m_Connections.Size();
|
uint32_t size = g_Websocket.m_Connections.Size();
|
||||||
@@ -739,6 +740,13 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->m_ConnectionThread)
|
||||||
|
{
|
||||||
|
dmThread::Join(conn->m_ConnectionThread);
|
||||||
|
conn->m_ConnectionThread = 0;
|
||||||
|
}
|
||||||
|
conn->m_Socket = dmConnectionPool::GetSocket(g_Websocket.m_Pool, conn->m_Connection);
|
||||||
|
conn->m_SSLSocket = dmConnectionPool::GetSSLSocket(g_Websocket.m_Pool, conn->m_Connection);
|
||||||
Result result = SendClientHandshake(conn);
|
Result result = SendClientHandshake(conn);
|
||||||
if (RESULT_WOULDBLOCK == result)
|
if (RESULT_WOULDBLOCK == result)
|
||||||
{
|
{
|
||||||
@@ -763,11 +771,23 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
|||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
char uri_buffer[dmURI::MAX_URI_LEN];
|
char uri_buffer[dmURI::MAX_URI_LEN];
|
||||||
const char* uri;
|
const char* uri;
|
||||||
if (conn->m_Url.m_Path[0] != '\0') {
|
bool no_path = conn->m_Url.m_Path[0] == '\0';
|
||||||
dmSnPrintf(uri_buffer, sizeof(uri_buffer), "%s://%s%s", conn->m_Url.m_Scheme, conn->m_Url.m_Hostname, conn->m_Url.m_Path);
|
bool no_port = conn->m_Url.m_Port == -1;
|
||||||
} else {
|
if (no_path && no_port)
|
||||||
|
{
|
||||||
dmSnPrintf(uri_buffer, sizeof(uri_buffer), "%s://%s", conn->m_Url.m_Scheme, conn->m_Url.m_Hostname);
|
dmSnPrintf(uri_buffer, sizeof(uri_buffer), "%s://%s", conn->m_Url.m_Scheme, conn->m_Url.m_Hostname);
|
||||||
}
|
}
|
||||||
|
else if (no_port)
|
||||||
|
{
|
||||||
|
dmSnPrintf(uri_buffer, sizeof(uri_buffer), "%s://%s%s", conn->m_Url.m_Scheme, conn->m_Url.m_Hostname, conn->m_Url.m_Path);
|
||||||
|
}
|
||||||
|
else if (no_path)
|
||||||
|
{
|
||||||
|
dmSnPrintf(uri_buffer, sizeof(uri_buffer), "%s://%s:%d", conn->m_Url.m_Scheme, conn->m_Url.m_Hostname, conn->m_Url.m_Port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dmSnPrintf(uri_buffer, sizeof(uri_buffer), "%s://%s:%d%s", conn->m_Url.m_Scheme, conn->m_Url.m_Hostname, conn->m_Url.m_Port, conn->m_Url.m_Path);
|
||||||
|
}
|
||||||
uri = uri_buffer;
|
uri = uri_buffer;
|
||||||
|
|
||||||
EmscriptenWebSocketCreateAttributes ws_attrs = {
|
EmscriptenWebSocketCreateAttributes ws_attrs = {
|
||||||
@@ -787,28 +807,20 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
|||||||
emscripten_websocket_set_onerror_callback(ws, conn, Emscripten_WebSocketOnError);
|
emscripten_websocket_set_onerror_callback(ws, conn, Emscripten_WebSocketOnError);
|
||||||
emscripten_websocket_set_onclose_callback(ws, conn, Emscripten_WebSocketOnClose);
|
emscripten_websocket_set_onclose_callback(ws, conn, Emscripten_WebSocketOnClose);
|
||||||
emscripten_websocket_set_onmessage_callback(ws, conn, Emscripten_WebSocketOnMessage);
|
emscripten_websocket_set_onmessage_callback(ws, conn, Emscripten_WebSocketOnMessage);
|
||||||
SetState(conn, STATE_CONNECTING);
|
|
||||||
#else
|
#else
|
||||||
dmSocket::Result sr;
|
conn->m_ConnectionThread = dmThread::New((dmThread::ThreadStart)ConnectionWorker, 0x80000, conn, "WSConnect");
|
||||||
int timeout = g_Websocket.m_Timeout;
|
|
||||||
dmConnectionPool::Result pool_result = dmConnectionPool::Dial(g_Websocket.m_Pool, conn->m_Url.m_Hostname, conn->m_Url.m_Port, g_Websocket.m_Channel, conn->m_SSL, timeout, &conn->m_Connection, &sr);
|
|
||||||
if (dmConnectionPool::RESULT_OK != pool_result)
|
|
||||||
{
|
|
||||||
CLOSE_CONN("Failed to open connection: %s", dmSocket::ResultToString(sr));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
conn->m_Socket = dmConnectionPool::GetSocket(g_Websocket.m_Pool, conn->m_Connection);
|
|
||||||
conn->m_SSLSocket = dmConnectionPool::GetSSLSocket(g_Websocket.m_Pool, conn->m_Connection);
|
|
||||||
SetState(conn, STATE_HANDSHAKE_WRITE);
|
|
||||||
#endif
|
#endif
|
||||||
|
SetState(conn, STATE_CONNECTING);
|
||||||
}
|
}
|
||||||
else if (STATE_CONNECTING == conn->m_State)
|
else if (STATE_CONNECTING == conn->m_State)
|
||||||
{
|
{
|
||||||
|
#if defined(__EMSCRIPTEN__)
|
||||||
if (CheckConnectTimeout(conn))
|
if (CheckConnectTimeout(conn))
|
||||||
{
|
{
|
||||||
CLOSE_CONN("Connect sequence timed out");
|
CLOSE_CONN("Connect sequence timed out");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,9 +21,9 @@
|
|||||||
|
|
||||||
#include <dmsdk/dlib/connection_pool.h>
|
#include <dmsdk/dlib/connection_pool.h>
|
||||||
#include <dmsdk/dlib/socket.h>
|
#include <dmsdk/dlib/socket.h>
|
||||||
#include <dmsdk/dlib/dns.h>
|
|
||||||
#include <dmsdk/dlib/uri.h>
|
#include <dmsdk/dlib/uri.h>
|
||||||
#include <dmsdk/dlib/array.h>
|
#include <dmsdk/dlib/array.h>
|
||||||
|
#include <dmsdk/dlib/thread.h>
|
||||||
|
|
||||||
namespace dmCrypt
|
namespace dmCrypt
|
||||||
{
|
{
|
||||||
@@ -118,6 +118,7 @@ namespace dmWebsocket
|
|||||||
dmConnectionPool::HConnection m_Connection;
|
dmConnectionPool::HConnection m_Connection;
|
||||||
dmSocket::Socket m_Socket;
|
dmSocket::Socket m_Socket;
|
||||||
dmSSLSocket::Socket m_SSLSocket;
|
dmSSLSocket::Socket m_SSLSocket;
|
||||||
|
dmThread::Thread m_ConnectionThread;
|
||||||
dmArray<Message> m_Messages; // lengths of the messages in the data buffer
|
dmArray<Message> m_Messages; // lengths of the messages in the data buffer
|
||||||
uint64_t m_ConnectTimeout;
|
uint64_t m_ConnectTimeout;
|
||||||
uint8_t m_Key[16];
|
uint8_t m_Key[16];
|
||||||
|
Reference in New Issue
Block a user