Implement Emscripten Websockets
This commit is contained in:
parent
09637d4db4
commit
bc935312b3
@ -146,6 +146,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL Emscripten)
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_options(${MAIN_NAME} PRIVATE
|
target_link_options(${MAIN_NAME} PRIVATE
|
||||||
|
"-lwebsocket.js"
|
||||||
"-sUSE_SDL=2"
|
"-sUSE_SDL=2"
|
||||||
"-sASYNCIFY"
|
"-sASYNCIFY"
|
||||||
"-sUSE_WEBGL2=1"
|
"-sUSE_WEBGL2=1"
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5_webgl.h>
|
#include <emscripten/html5_webgl.h>
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
#include <emscripten/websocket.h>
|
||||||
#else
|
#else
|
||||||
#include <easywsclient.hpp>
|
#include <easywsclient.hpp>
|
||||||
#endif // EMSCRIPTEN
|
#endif // EMSCRIPTEN
|
||||||
@ -151,12 +153,153 @@ static void PollEvents()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WS_URL "ws://deadfish.cz:11200/ws"
|
||||||
|
|
||||||
|
static bool s_ws_connected = false;
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
|
||||||
|
static EMSCRIPTEN_WEBSOCKET_T s_ws = 0;
|
||||||
|
|
||||||
|
static EM_BOOL OnWSOpen(int type, const EmscriptenWebSocketOpenEvent *ev, void *ud)
|
||||||
|
{
|
||||||
|
s_ws_connected = true;
|
||||||
|
s_app->Connected();
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EM_BOOL OnWSMessage(int type, const EmscriptenWebSocketMessageEvent *ev, void *ud)
|
||||||
|
{
|
||||||
|
if (ev->isText)
|
||||||
|
return EM_TRUE;
|
||||||
|
|
||||||
|
net::InMessage msg(reinterpret_cast<char*>(ev->data), ev->numBytes);
|
||||||
|
s_app->ProcessMessage(msg);
|
||||||
|
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EM_BOOL OnWSClose(int type, const EmscriptenWebSocketCloseEvent *ev, void *ud)
|
||||||
|
{
|
||||||
|
s_ws_connected = false;
|
||||||
|
s_app->Disconnected("");
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EM_BOOL OnWSError(int type, const EmscriptenWebSocketErrorEvent *ev, void *ud)
|
||||||
|
{
|
||||||
|
s_ws_connected = false;
|
||||||
|
s_app->Disconnected("error");
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool WSInit()
|
||||||
|
{
|
||||||
|
if (!emscripten_websocket_is_supported())
|
||||||
|
{
|
||||||
|
std::cerr << "EMSCRIPTEN WS NOT SUPPORTED" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EmscriptenWebSocketCreateAttributes ws_attrs = {
|
||||||
|
WS_URL,
|
||||||
|
NULL,
|
||||||
|
EM_TRUE
|
||||||
|
};
|
||||||
|
|
||||||
|
s_ws = emscripten_websocket_new(&ws_attrs);
|
||||||
|
emscripten_websocket_set_onopen_callback(s_ws, NULL, OnWSOpen);
|
||||||
|
emscripten_websocket_set_onmessage_callback(s_ws, NULL, OnWSMessage);
|
||||||
|
emscripten_websocket_set_onclose_callback(s_ws, NULL, OnWSClose);
|
||||||
|
emscripten_websocket_set_onerror_callback(s_ws, NULL, OnWSError);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WSSend(std::span<const char> data)
|
||||||
|
{
|
||||||
|
emscripten_websocket_send_binary(s_ws, (void*)data.data(), static_cast<uint32_t>(data.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WSPoll() {}
|
||||||
|
static void WSClose() {}
|
||||||
|
|
||||||
|
#else /* !EMSCRIPTEN */
|
||||||
|
|
||||||
|
using namespace easywsclient;
|
||||||
|
|
||||||
|
static std::unique_ptr<WebSocket> s_ws;
|
||||||
|
|
||||||
|
static bool WSInit()
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
INT rc;
|
||||||
|
WSADATA wsaData;
|
||||||
|
|
||||||
|
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
printf("WSAStartup Failed.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s_ws = std::unique_ptr<WebSocket>(WebSocket::from_url(WS_URL));
|
||||||
|
|
||||||
|
if (!s_ws)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WSSend(std::span<const char> data)
|
||||||
|
{
|
||||||
|
static std::vector<uint8_t> data;
|
||||||
|
data.resize(msg.size_bytes());
|
||||||
|
memcpy(data.data(), msg.data(), msg.size_bytes());
|
||||||
|
ws->sendBinary(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WSPoll()
|
||||||
|
{
|
||||||
|
s_ws->poll();
|
||||||
|
|
||||||
|
auto ws_state = s_ws->getReadyState();
|
||||||
|
if (ws_state == WebSocket::OPEN && !connected)
|
||||||
|
{
|
||||||
|
connected = true;
|
||||||
|
s_app->Connected();
|
||||||
|
}
|
||||||
|
else if (ws_state != WebSocket::OPEN && connected)
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
s_app->Disconnected("WS closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
s_ws->dispatchBinary([&](const std::vector<uint8_t>& data) {
|
||||||
|
net::InMessage msg(reinterpret_cast<const char*>(data.data()), data.size());
|
||||||
|
s_app->ProcessMessage(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WSClose()
|
||||||
|
{
|
||||||
|
s_ws.reset();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* EMSCRIPTEN */
|
||||||
|
|
||||||
static void Frame()
|
static void Frame()
|
||||||
{
|
{
|
||||||
Uint32 current_time = SDL_GetTicks();
|
Uint32 current_time = SDL_GetTicks();
|
||||||
s_app->SetTime(current_time / 1000.0f); // Set time in seconds
|
s_app->SetTime(current_time / 1000.0f); // Set time in seconds
|
||||||
|
|
||||||
PollEvents();
|
PollEvents();
|
||||||
|
WSPoll();
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSize(s_window, &width, &height);
|
SDL_GetWindowSize(s_window, &width, &height);
|
||||||
@ -204,10 +347,25 @@ static void Frame()
|
|||||||
s_app->SetInput(input);
|
s_app->SetInput(input);
|
||||||
|
|
||||||
s_app->Frame();
|
s_app->Frame();
|
||||||
|
|
||||||
|
if (s_ws_connected)
|
||||||
|
{
|
||||||
|
auto msg = s_app->GetMsg();
|
||||||
|
if (!msg.empty())
|
||||||
|
{
|
||||||
|
WSSend(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_app->ResetMsg();
|
||||||
|
|
||||||
SDL_GL_SwapWindow(s_window);
|
SDL_GL_SwapWindow(s_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Main() {
|
static void Main() {
|
||||||
|
if (!WSInit())
|
||||||
|
return;
|
||||||
|
|
||||||
InitSDL();
|
InitSDL();
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -228,76 +386,18 @@ static void Main() {
|
|||||||
emscripten_set_main_loop(Frame, 0, true);
|
emscripten_set_main_loop(Frame, 0, true);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
INT rc;
|
|
||||||
WSADATA wsaData;
|
|
||||||
|
|
||||||
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
printf("WSAStartup Failed.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_GL_SetSwapInterval(0);
|
SDL_GL_SetSwapInterval(0);
|
||||||
|
|
||||||
|
while (!s_quit)
|
||||||
{
|
{
|
||||||
using namespace easywsclient;
|
Frame();
|
||||||
|
|
||||||
auto ws = std::unique_ptr<WebSocket>(WebSocket::from_url("ws://127.0.0.1:11200/ws"));
|
|
||||||
bool connected = false;
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
|
|
||||||
while (ws && !s_quit)
|
|
||||||
{
|
|
||||||
ws->poll();
|
|
||||||
|
|
||||||
auto ws_state = ws->getReadyState();
|
|
||||||
if (ws_state == WebSocket::OPEN && !connected)
|
|
||||||
{
|
|
||||||
connected = true;
|
|
||||||
s_app->Connected();
|
|
||||||
}
|
|
||||||
else if (ws_state != WebSocket::OPEN && connected)
|
|
||||||
{
|
|
||||||
connected = false;
|
|
||||||
s_app->Disconnected("WS closed");
|
|
||||||
}
|
|
||||||
|
|
||||||
ws->dispatchBinary([&](const std::vector<uint8_t>& data) {
|
|
||||||
net::InMessage msg(reinterpret_cast<const char*>(data.data()), data.size());
|
|
||||||
s_app->ProcessMessage(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
Frame();
|
|
||||||
|
|
||||||
if (connected)
|
|
||||||
{
|
|
||||||
auto msg = s_app->GetMsg();
|
|
||||||
if (!msg.empty())
|
|
||||||
{
|
|
||||||
data.resize(msg.size_bytes());
|
|
||||||
memcpy(data.data(), msg.data(), msg.size_bytes());
|
|
||||||
ws->sendBinary(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s_app->ResetMsg();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s_app.reset();
|
s_app.reset();
|
||||||
|
|
||||||
ShutdownGL();
|
ShutdownGL();
|
||||||
ShutdownSDL();
|
ShutdownSDL();
|
||||||
|
WSClose();
|
||||||
#ifdef _WIN32
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // EMSCRIPTEN
|
#endif // EMSCRIPTEN
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user