mirror of
https://github.com/defold/extension-websocket.git
synced 2025-09-30 09:12:18 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
39abd7cdea | ||
|
f988413a74 | ||
|
73b236b249 | ||
|
636a11daa3 | ||
|
0f147ef180 | ||
|
3cd0328c2a | ||
|
f5aa57452f | ||
|
7e89b8a685 | ||
|
ba7454a431 | ||
|
b93a91c9b8 | ||
|
0bf63cbdf8 | ||
|
8a9dc759a4 | ||
|
70afde4cfa | ||
|
ed6d131470 | ||
|
2c9c0b74f1 | ||
|
8450a88640 | ||
|
3636ea73db | ||
|
1cc1d802b3 | ||
|
94bcc82f25 | ||
|
d62a53cbcc |
76
.github/workflows/bob.yml
vendored
Normal file
76
.github/workflows/bob.yml
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: Build with bob
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request_target:
|
||||||
|
schedule:
|
||||||
|
# nightly at 05:00 on the 1st and 15th
|
||||||
|
- cron: 0 5 1,15 * *
|
||||||
|
|
||||||
|
env:
|
||||||
|
VERSION_FILENAME: 'info.json'
|
||||||
|
BUILD_SERVER: 'https://build.defold.com'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_with_bob:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform: [armv7-android, x86_64-linux, x86_64-win32, x86-win32, js-web]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
name: Build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: '11.0.2'
|
||||||
|
|
||||||
|
- name: Get Defold version
|
||||||
|
run: |
|
||||||
|
TMPVAR=`curl -s http://d.defold.com/stable/${{env.VERSION_FILENAME}} | jq -r '.sha1'`
|
||||||
|
echo "DEFOLD_VERSION=${TMPVAR}" >> $GITHUB_ENV
|
||||||
|
echo "Found version ${TMPVAR}"
|
||||||
|
|
||||||
|
- name: Download bob.jar
|
||||||
|
run: |
|
||||||
|
wget -q http://d.defold.com/archive/stable/${{env.DEFOLD_VERSION}}/bob/bob.jar
|
||||||
|
java -jar bob.jar --version
|
||||||
|
|
||||||
|
- name: Resolve libraries
|
||||||
|
run: java -jar bob.jar resolve --email a@b.com --auth 123456
|
||||||
|
- name: Build
|
||||||
|
run: java -jar bob.jar --platform=${{ matrix.platform }} build --archive --build-server=${{env.BUILD_SERVER}}
|
||||||
|
- name: Bundle
|
||||||
|
run: java -jar bob.jar --platform=${{ matrix.platform }} bundle
|
||||||
|
|
||||||
|
# macOS is not technically needed for building, but we want to test bundling as well, since we're also testing the manifest merging
|
||||||
|
build_with_bob_macos:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform: [armv7-darwin, x86_64-darwin]
|
||||||
|
runs-on: macOS-latest
|
||||||
|
|
||||||
|
name: Build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: '11.0.2'
|
||||||
|
|
||||||
|
- name: Get Defold version
|
||||||
|
run: |
|
||||||
|
TMPVAR=`curl -s http://d.defold.com/stable/${{env.VERSION_FILENAME}} | jq -r '.sha1'`
|
||||||
|
echo "DEFOLD_VERSION=${TMPVAR}" >> $GITHUB_ENV
|
||||||
|
echo "Found version ${TMPVAR}"
|
||||||
|
|
||||||
|
- name: Download bob.jar
|
||||||
|
run: |
|
||||||
|
wget -q http://d.defold.com/archive/stable/${{env.DEFOLD_VERSION}}/bob/bob.jar
|
||||||
|
java -jar bob.jar --version
|
||||||
|
|
||||||
|
- name: Resolve libraries
|
||||||
|
run: java -jar bob.jar resolve --email a@b.com --auth 123456
|
||||||
|
- name: Build
|
||||||
|
run: java -jar bob.jar --platform=${{ matrix.platform }} build --archive --build-server=${{env.BUILD_SERVER}}
|
||||||
|
- name: Bundle
|
||||||
|
run: java -jar bob.jar --platform=${{ matrix.platform }} bundle
|
5
.github/workflows/trigger-site-rebuild.yml
vendored
5
.github/workflows/trigger-site-rebuild.yml
vendored
@@ -1,6 +1,9 @@
|
|||||||
name: Trigger site rebuild
|
name: Trigger site rebuild
|
||||||
|
|
||||||
on: [push]
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
site-rebuild:
|
site-rebuild:
|
||||||
|
10
README.md
10
README.md
@@ -1,5 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
# Defold websocket extension
|
# Defold websocket extension
|
||||||
|
|
||||||
|
[](https://github.com/defold/extension-websocket/actions)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
To use this library in your Defold project, add the following URL to your `game.project` dependencies:
|
To use this library in your Defold project, add the following URL to your `game.project` dependencies:
|
||||||
|
|
||||||
@@ -40,3 +44,9 @@ For command line debugging, there's
|
|||||||
* tcpdump: `sudo tcpdump -X -s0 -ilo0 port 8080 ` (example for local ws:// connection)
|
* tcpdump: `sudo tcpdump -X -s0 -ilo0 port 8080 ` (example for local ws:// connection)
|
||||||
|
|
||||||
* tcpdump: `sudo tcpdump -X -s0 host echo.websocket.org` (Monitors packets to/from echo.websocket.org)
|
* tcpdump: `sudo tcpdump -X -s0 host echo.websocket.org` (Monitors packets to/from echo.websocket.org)
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
This extension makes use of the C library WSlay by @tatsuhiro-t:
|
||||||
|
|
||||||
|
* https://github.com/tatsuhiro-t/wslay
|
||||||
|
@@ -73,7 +73,7 @@ local function websocket_callback(self, conn, data)
|
|||||||
update_gui(self)
|
update_gui(self)
|
||||||
log("Connected: " .. tostring(conn))
|
log("Connected: " .. tostring(conn))
|
||||||
elseif data.event == websocket.EVENT_ERROR then
|
elseif data.event == websocket.EVENT_ERROR then
|
||||||
log("Error: '" .. data.error .. "'")
|
log("Error: '" .. tostring(data.error) .. "'")
|
||||||
elseif data.event == websocket.EVENT_MESSAGE then
|
elseif data.event == websocket.EVENT_MESSAGE then
|
||||||
log("Receiving: '" .. tostring(data.message) .. "'")
|
log("Receiving: '" .. tostring(data.message) .. "'")
|
||||||
end
|
end
|
||||||
|
@@ -19,7 +19,11 @@
|
|||||||
members:
|
members:
|
||||||
- name: timeout
|
- name: timeout
|
||||||
type: number
|
type: number
|
||||||
desc: Timeout for the connection sequence (milliseconds). Not used on HTML5. Default: 3000
|
desc: Timeout for the connection sequence (milliseconds). Not used on HTML5. (Default is 3000)
|
||||||
|
|
||||||
|
- name: protocol
|
||||||
|
type: string
|
||||||
|
desc: the protocol to use (e.g. 'chat'). If not set, no `Sec-WebSocket-Protocol` header is sent.
|
||||||
|
|
||||||
- name: headers
|
- name: headers
|
||||||
type: string
|
type: string
|
||||||
@@ -55,11 +59,7 @@
|
|||||||
|
|
||||||
- name: message
|
- name: message
|
||||||
type: string
|
type: string
|
||||||
desc: The received data. Only valid if event is `websocket.EVENT_MESSAGE`
|
desc: The received data if event is `websocket.EVENT_MESSAGE`. Error message otherwise
|
||||||
|
|
||||||
- name: error
|
|
||||||
type: string
|
|
||||||
desc: The error string. Only valid if event is `websocket.EVENT_ERROR`
|
|
||||||
|
|
||||||
|
|
||||||
returns:
|
returns:
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
update_gui(self)
|
update_gui(self)
|
||||||
log("Connected: " .. tostring(conn))
|
log("Connected: " .. tostring(conn))
|
||||||
elseif data.event == websocket.EVENT_ERROR then
|
elseif data.event == websocket.EVENT_ERROR then
|
||||||
log("Error: '" .. data.error .. "'")
|
log("Error: '" .. data.message .. "'")
|
||||||
elseif data.event == websocket.EVENT_MESSAGE then
|
elseif data.event == websocket.EVENT_MESSAGE then
|
||||||
log("Receiving: '" .. tostring(data.message) .. "'")
|
log("Receiving: '" .. tostring(data.message) .. "'")
|
||||||
end
|
end
|
||||||
|
@@ -40,8 +40,12 @@ static Result SendClientHandshakeHeaders(WebsocketConnection* conn)
|
|||||||
dmSnPrintf(port, sizeof(port), ":%d", conn->m_Url.m_Port);
|
dmSnPrintf(port, sizeof(port), ":%d", conn->m_Url.m_Port);
|
||||||
|
|
||||||
dmSocket::Result sr;
|
dmSocket::Result sr;
|
||||||
WS_SENDALL("GET /");
|
WS_SENDALL("GET ");
|
||||||
WS_SENDALL(conn->m_Url.m_Path);
|
if (conn->m_Url.m_Path[0] == '\0') {
|
||||||
|
WS_SENDALL("/"); // Default to / for empty path
|
||||||
|
} else {
|
||||||
|
WS_SENDALL(conn->m_Url.m_Path);
|
||||||
|
}
|
||||||
WS_SENDALL(" HTTP/1.1\r\n");
|
WS_SENDALL(" HTTP/1.1\r\n");
|
||||||
WS_SENDALL("Host: ");
|
WS_SENDALL("Host: ");
|
||||||
WS_SENDALL(conn->m_Url.m_Hostname);
|
WS_SENDALL(conn->m_Url.m_Hostname);
|
||||||
@@ -66,6 +70,12 @@ static Result SendClientHandshakeHeaders(WebsocketConnection* conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->m_Protocol) {
|
||||||
|
WS_SENDALL("Sec-WebSocket-Protocol: ");
|
||||||
|
WS_SENDALL(conn->m_Protocol);
|
||||||
|
WS_SENDALL("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
WS_SENDALL("\r\n");
|
WS_SENDALL("\r\n");
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
@@ -109,17 +119,12 @@ Result ReceiveHeaders(WebsocketConnection* conn)
|
|||||||
#else
|
#else
|
||||||
Result ReceiveHeaders(WebsocketConnection* conn)
|
Result ReceiveHeaders(WebsocketConnection* conn)
|
||||||
{
|
{
|
||||||
dmSocket::Selector selector;
|
dmSocket::Result sr = WaitForSocket(conn, dmSocket::SELECTOR_KIND_READ, SOCKET_WAIT_TIMEOUT);
|
||||||
dmSocket::SelectorZero(&selector);
|
|
||||||
dmSocket::SelectorSet(&selector, dmSocket::SELECTOR_KIND_READ, conn->m_Socket);
|
|
||||||
|
|
||||||
dmSocket::Result sr = dmSocket::Select(&selector, SOCKET_WAIT_TIMEOUT);
|
|
||||||
|
|
||||||
if (dmSocket::RESULT_OK != sr)
|
if (dmSocket::RESULT_OK != sr)
|
||||||
{
|
{
|
||||||
if (dmSocket::RESULT_WOULDBLOCK)
|
if (dmSocket::RESULT_WOULDBLOCK)
|
||||||
{
|
{
|
||||||
DebugLog(1, "Waiting for socket to be available for reading");
|
DebugLog(2, "Waiting for socket to be available for reading");
|
||||||
return RESULT_WOULDBLOCK;
|
return RESULT_WOULDBLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,9 +207,6 @@ Result VerifyHeaders(WebsocketConnection* conn)
|
|||||||
bool connection = false;
|
bool connection = false;
|
||||||
bool upgrade = false;
|
bool upgrade = false;
|
||||||
bool valid_key = false;
|
bool valid_key = false;
|
||||||
const char* protocol = "";
|
|
||||||
|
|
||||||
// TODO: Perhaps also support the Sec-WebSocket-Protocol
|
|
||||||
|
|
||||||
// parse the headers in place
|
// parse the headers in place
|
||||||
while (r < endtag)
|
while (r < endtag)
|
||||||
|
@@ -195,7 +195,6 @@ static WebsocketConnection* CreateConnection(const char* url)
|
|||||||
conn->m_SSLSocket = 0;
|
conn->m_SSLSocket = 0;
|
||||||
conn->m_Status = RESULT_OK;
|
conn->m_Status = RESULT_OK;
|
||||||
conn->m_HasHandshakeData = 0;
|
conn->m_HasHandshakeData = 0;
|
||||||
conn->m_WasConnected = 0;
|
|
||||||
|
|
||||||
#if defined(HAVE_WSLAY)
|
#if defined(HAVE_WSLAY)
|
||||||
conn->m_Ctx = 0;
|
conn->m_Ctx = 0;
|
||||||
@@ -212,6 +211,7 @@ static void DestroyConnection(WebsocketConnection* conn)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
free((void*)conn->m_CustomHeaders);
|
free((void*)conn->m_CustomHeaders);
|
||||||
|
free((void*)conn->m_Protocol);
|
||||||
|
|
||||||
if (conn->m_Callback)
|
if (conn->m_Callback)
|
||||||
dmScript::DestroyCallback(conn->m_Callback);
|
dmScript::DestroyCallback(conn->m_Callback);
|
||||||
@@ -271,6 +271,7 @@ static int LuaConnect(lua_State* L)
|
|||||||
const char* url = luaL_checkstring(L, 1);
|
const char* url = luaL_checkstring(L, 1);
|
||||||
lua_Number timeout = dmScript::CheckTableNumber(L, 2, "timeout", 3000);
|
lua_Number timeout = dmScript::CheckTableNumber(L, 2, "timeout", 3000);
|
||||||
const char* custom_headers = dmScript::CheckTableString(L, 2, "headers", 0);
|
const char* custom_headers = dmScript::CheckTableString(L, 2, "headers", 0);
|
||||||
|
const char* protocol = dmScript::CheckTableString(L, 2, "protocol", 0);
|
||||||
|
|
||||||
if (custom_headers != 0)
|
if (custom_headers != 0)
|
||||||
{
|
{
|
||||||
@@ -283,6 +284,7 @@ static int LuaConnect(lua_State* L)
|
|||||||
WebsocketConnection* conn = CreateConnection(url);
|
WebsocketConnection* conn = CreateConnection(url);
|
||||||
conn->m_ConnectTimeout = dmTime::GetTime() + timeout * 1000;
|
conn->m_ConnectTimeout = dmTime::GetTime() + timeout * 1000;
|
||||||
conn->m_CustomHeaders = custom_headers ? strdup(custom_headers) : 0;
|
conn->m_CustomHeaders = custom_headers ? strdup(custom_headers) : 0;
|
||||||
|
conn->m_Protocol = protocol ? strdup(protocol) : 0;
|
||||||
|
|
||||||
conn->m_Callback = dmScript::CreateCallback(L, 3);
|
conn->m_Callback = dmScript::CreateCallback(L, 3);
|
||||||
|
|
||||||
@@ -506,6 +508,12 @@ static dmExtension::Result AppFinalize(dmExtension::AppParams* params)
|
|||||||
|
|
||||||
static dmExtension::Result Finalize(dmExtension::Params* params)
|
static dmExtension::Result Finalize(dmExtension::Params* params)
|
||||||
{
|
{
|
||||||
|
while (!g_Websocket.m_Connections.Empty())
|
||||||
|
{
|
||||||
|
WebsocketConnection* conn = g_Websocket.m_Connections.Back();
|
||||||
|
g_Websocket.m_Connections.Pop();
|
||||||
|
DestroyConnection(conn);
|
||||||
|
}
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,10 +571,7 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
|||||||
conn->m_BufferSize = 0;
|
conn->m_BufferSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->m_WasConnected)
|
HandleCallback(conn, EVENT_DISCONNECTED, 0, conn->m_BufferSize);
|
||||||
{
|
|
||||||
HandleCallback(conn, EVENT_DISCONNECTED, 0, conn->m_BufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Websocket.m_Connections.EraseSwap(i);
|
g_Websocket.m_Connections.EraseSwap(i);
|
||||||
--i;
|
--i;
|
||||||
@@ -673,7 +678,6 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
|||||||
#endif
|
#endif
|
||||||
dmSocket::SetBlocking(conn->m_Socket, false);
|
dmSocket::SetBlocking(conn->m_Socket, false);
|
||||||
|
|
||||||
conn->m_WasConnected = 1;
|
|
||||||
SetState(conn, STATE_CONNECTED);
|
SetState(conn, STATE_CONNECTED);
|
||||||
HandleCallback(conn, EVENT_CONNECTED, 0, 0);
|
HandleCallback(conn, EVENT_CONNECTED, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -709,6 +713,11 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params)
|
|||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
conn->m_SSLSocket = dmSSLSocket::INVALID_SOCKET_HANDLE;
|
conn->m_SSLSocket = dmSSLSocket::INVALID_SOCKET_HANDLE;
|
||||||
|
|
||||||
|
EM_ASM({
|
||||||
|
// https://emscripten.org/docs/porting/networking.html#emulated-posix-tcp-sockets-over-websockets
|
||||||
|
Module["websocket"]["subprotocol"] = $0 ? UTF8ToString($0) : null;
|
||||||
|
}, conn->m_Protocol);
|
||||||
|
|
||||||
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') {
|
if (conn->m_Url.m_Path[0] != '\0') {
|
||||||
|
@@ -91,6 +91,7 @@ namespace dmWebsocket
|
|||||||
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];
|
||||||
|
const char* m_Protocol;
|
||||||
const char* m_CustomHeaders;
|
const char* m_CustomHeaders;
|
||||||
State m_State;
|
State m_State;
|
||||||
char* m_Buffer;
|
char* m_Buffer;
|
||||||
@@ -99,8 +100,7 @@ namespace dmWebsocket
|
|||||||
Result m_Status;
|
Result m_Status;
|
||||||
uint8_t m_SSL:1;
|
uint8_t m_SSL:1;
|
||||||
uint8_t m_HasHandshakeData:1;
|
uint8_t m_HasHandshakeData:1;
|
||||||
uint8_t m_WasConnected:1;
|
uint8_t :7;
|
||||||
uint8_t :6;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set error message
|
// Set error message
|
||||||
|
Reference in New Issue
Block a user