Add libwebsockets client to game executable.feature/data-structs
@@ -70,13 +70,16 @@ add_executable( | |||
src/packages/game/input/IZ_midi.h | |||
src/packages/game/data/IZ_list.c | |||
src/packages/game/data/IZ_list.h | |||
) | |||
src/packages/game/network/IZ_wsclient.c src/packages/game/network/IZ_wsclient.h) | |||
target_link_libraries( | |||
game | |||
SDL2main | |||
SDL2 | |||
portmidi | |||
libcrypto | |||
libssl | |||
websockets | |||
) | |||
add_executable( | |||
@@ -188,6 +191,21 @@ if (WIN32) | |||
"${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release/portmidi.dll" # <--this is in-file | |||
$<TARGET_FILE_DIR:game>) # <--this is out-file path | |||
add_custom_command(TARGET game POST_BUILD | |||
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." | |||
"${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/bin/Release/websockets.dll" # <--this is in-file | |||
$<TARGET_FILE_DIR:game>) # <--this is out-file path | |||
add_custom_command(TARGET game POST_BUILD | |||
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." | |||
"${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/bin/libssl-1_1-x64.dll" # <--this is in-file | |||
$<TARGET_FILE_DIR:game>) # <--this is out-file path | |||
add_custom_command(TARGET game POST_BUILD | |||
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." | |||
"${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/bin/libcrypto-1_1-x64.dll" # <--this is in-file | |||
$<TARGET_FILE_DIR:game>) # <--this is out-file path | |||
add_custom_command(TARGET server POST_BUILD | |||
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." | |||
"${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/bin/Release/websockets.dll" # <--this is in-file | |||
@@ -15,15 +15,16 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App* app) { | |||
char config_path[128]; | |||
IZ_ConfigGetPath(config_path, 128); | |||
if (IZ_VideoInitialize(config_path, &app->video_state)) { | |||
if (IZ_VideoInitialize(&app->video_state, config_path)) { | |||
return 2; | |||
} | |||
if (IZ_InputInitialize(config_path, &app->input_state)) { | |||
if (IZ_InputInitialize(&app->input_state, config_path)) { | |||
return 3; | |||
} | |||
IZ_PoolInitialize(&app->pool, POOL_MAX_SIZE); | |||
IZ_WSClientInitialize(&app->client, app); | |||
// TODO put into its timer module | |||
app->ticks = 0; | |||
@@ -31,6 +32,7 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App* app) { | |||
} | |||
void IZ_AppTeardown(IZ_App* app) { | |||
IZ_WSClientTeardown(&app->client); | |||
IZ_PoolTeardown(&app->pool); | |||
IZ_InputTeardown(&app->input_state); | |||
IZ_VideoTeardown(&app->video_state); | |||
@@ -66,8 +68,8 @@ void IZ_AppHandlePortMIDIEvents(IZ_App* app) { | |||
for (midi_event_index = 0; midi_event_index < *midi_events_count; midi_event_index += 1) { | |||
IZ_InputHandlePortMIDIEvents( | |||
app->input_state.midi_input_state[player_index].event_buffer[midi_event_index], | |||
&app->input_state | |||
&app->input_state, | |||
app->input_state.midi_input_state[player_index].event_buffer[midi_event_index] | |||
); | |||
} | |||
} | |||
@@ -104,7 +106,7 @@ IZ_ProcedureResult IZ_AppRun(IZ_App* app, u8 arg_count, char* arg_values[]) { | |||
break; | |||
} | |||
IZ_VideoUpdate(&app->video_state, &app->input_state, app->ticks); | |||
IZ_VideoUpdate(&app->video_state, app->ticks, &app->input_state); | |||
} | |||
IZ_AppTeardown(app); | |||
@@ -10,12 +10,14 @@ | |||
#include "input/IZ_input.h" | |||
#include "output/IZ_video.h" | |||
#include "memory/IZ_pool.h" | |||
#include "network/IZ_wsclient.h" | |||
typedef struct { | |||
IZ_InputState input_state; | |||
IZ_VideoState video_state; | |||
IZ_Pool pool; | |||
IZ_WSClient client; | |||
u64 ticks; | |||
} IZ_App; | |||
@@ -5,11 +5,11 @@ void IZ_InputHandleSDLEvents(IZ_InputState* state) { | |||
IZ_KeyboardHandleEvents(state->sdl_event, &state->keyboard_state, &state->action); | |||
} | |||
void IZ_InputHandlePortMIDIEvents(PmEvent e, IZ_InputState* state) { | |||
void IZ_InputHandlePortMIDIEvents(IZ_InputState* state, PmEvent e) { | |||
IZ_MIDIInputHandleEvents(e, &state->midi_input_state, &state->action); | |||
} | |||
IZ_ProcedureResult IZ_InputInitialize(const char* config_path, IZ_InputState* state) { | |||
IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_path) { | |||
*state = (IZ_InputState) { | |||
.action = {}, | |||
.joystick_state = {}, | |||
@@ -16,9 +16,9 @@ typedef struct { | |||
void IZ_InputHandleSDLEvents(IZ_InputState*); | |||
void IZ_InputHandlePortMIDIEvents(PmEvent, IZ_InputState*); | |||
void IZ_InputHandlePortMIDIEvents(IZ_InputState*, PmEvent); | |||
IZ_ProcedureResult IZ_InputInitialize(const char*, IZ_InputState*); | |||
IZ_ProcedureResult IZ_InputInitialize(IZ_InputState*, const char*); | |||
void IZ_InputTeardown(IZ_InputState*); | |||
@@ -0,0 +1,90 @@ | |||
#include "IZ_wsclient.h" | |||
IZ_ProcedureResult IZ_WSClientCallback( | |||
struct lws* wsi, | |||
enum lws_callback_reasons reason, | |||
void* user, | |||
void* in, | |||
size_t len | |||
) { | |||
switch (reason) { | |||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: | |||
return 1; | |||
case LWS_CALLBACK_CLIENT_CLOSED: | |||
return 0; | |||
case LWS_CALLBACK_CLIENT_RECEIVE: | |||
case LWS_CALLBACK_CLIENT_ESTABLISHED: | |||
default: | |||
break; | |||
} | |||
return lws_callback_http_dummy(wsi, reason, user, in, len); | |||
} | |||
IZ_ProcedureResult IZ_WSClientConnect(IZ_WSClient* client, IZ_WSClientConnectParams params) { | |||
static struct lws_client_connect_info info; | |||
memset(&info, 0, sizeof info); | |||
info.context = client->context; | |||
info.port = params.port; | |||
info.address = params.address; | |||
info.host = params.address; | |||
info.origin = params.address; | |||
info.protocol = params.protocol; | |||
info.path = params.path; | |||
info.userdata = params.userdata; | |||
// info.ssl_connection = ( | |||
// LCCSCF_ALLOW_SELFSIGNED | |||
// | LCCSCF_ALLOW_INSECURE | |||
// | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | |||
// | LCCSCF_ALLOW_EXPIRED | |||
// ); | |||
client->connection = lws_client_connect_via_info(&info); | |||
if (!client->connection) { | |||
return 1; | |||
} | |||
return 0; | |||
} | |||
IZ_ProcedureResult IZ_WSClientInitialize(IZ_WSClient* client, void* app) { | |||
static struct lws_protocols protocols[] = { | |||
{ | |||
.name = "lws-minimal-client", | |||
.callback = IZ_WSClientCallback, | |||
.per_session_data_size = 0, | |||
.rx_buffer_size = 0, | |||
.id = 0, | |||
.user = NULL, | |||
.tx_packet_size = 0, | |||
}, | |||
LWS_PROTOCOL_LIST_TERM, | |||
}; | |||
protocols[0].user = app; | |||
static struct lws_context_creation_info info; | |||
memset(&info, 0, sizeof info); | |||
info.port = CONTEXT_PORT_NO_LISTEN, | |||
info.protocols = protocols, | |||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT, | |||
client->context = lws_create_context(&info); | |||
if (!client->context) { | |||
return 1; | |||
} | |||
return 0; | |||
} | |||
IZ_ProcedureResult IZ_WSClientHandle(IZ_WSClient* client) { | |||
i32 response = lws_service(client->context, 0); | |||
if (response < 0) { | |||
return 1; | |||
} | |||
return 0; | |||
} | |||
void IZ_WSClientTeardown(IZ_WSClient* client) { | |||
lws_context_destroy(client->context); | |||
} |
@@ -0,0 +1,29 @@ | |||
#ifndef IZ_WSCLIENT_H | |||
#define IZ_WSCLIENT_H | |||
#include <libwebsockets.h> | |||
#include "../IZ_common.h" | |||
typedef struct { | |||
struct lws_context* context; | |||
struct lws* connection; | |||
i32 n; | |||
} IZ_WSClient; | |||
typedef struct { | |||
u16 port; | |||
const char* address; | |||
const char* path; | |||
const char* protocol; | |||
void* userdata; | |||
} IZ_WSClientConnectParams; | |||
IZ_ProcedureResult IZ_WSClientInitialize(IZ_WSClient*, void*); | |||
IZ_ProcedureResult IZ_WSClientConnect(IZ_WSClient*, IZ_WSClientConnectParams); | |||
IZ_ProcedureResult IZ_WSClientHandle(IZ_WSClient*); | |||
void IZ_WSClientTeardown(IZ_WSClient*); | |||
#endif |
@@ -1,6 +1,6 @@ | |||
#include "IZ_video.h" | |||
IZ_ProcedureResult IZ_VideoSaveConfig(const char* config_path, IZ_VideoConfig* config) { | |||
IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoConfig* config, const char* config_path) { | |||
if (!ini_putl("Video", "Width", config->width, config_path)) { | |||
return 1; | |||
} | |||
@@ -14,17 +14,17 @@ IZ_ProcedureResult IZ_VideoSaveConfig(const char* config_path, IZ_VideoConfig* c | |||
return 0; | |||
} | |||
void IZ_VideoLoadConfig(const char* config_path, IZ_VideoConfig* config) { | |||
void IZ_VideoLoadConfig(IZ_VideoConfig* config, const char* config_path) { | |||
config->width = ini_getl("Video", "Width", IZ_DEFAULT_VIDEO_STATE.config.width, config_path); | |||
config->height = ini_getl("Video", "Height", IZ_DEFAULT_VIDEO_STATE.config.height, config_path); | |||
config->max_fps = ini_getl("Video", "MaxFps", IZ_DEFAULT_VIDEO_STATE.config.max_fps, config_path); | |||
} | |||
IZ_ProcedureResult IZ_VideoInitialize(const char* config_path, IZ_VideoState* state) { | |||
IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState* state, const char* config_path) { | |||
SDL_memcpy(state, &IZ_DEFAULT_VIDEO_STATE, sizeof(IZ_VideoState)); | |||
IZ_VideoLoadConfig(config_path, &state->config); | |||
if (IZ_VideoSaveConfig(config_path, &state->config)) { | |||
IZ_VideoLoadConfig(&state->config, config_path); | |||
if (IZ_VideoSaveConfig(&state->config, config_path)) { | |||
// fprintf_s(stderr, "Error committing video config.\n"); | |||
} | |||
state->last_update_at = 0u; | |||
@@ -103,7 +103,7 @@ void IZ_VideoUpdateForDebug(IZ_VideoState* video_state, IZ_InputState* input_sta | |||
IZ_VideoUpdateForDebugInput(video_state, input_state); | |||
} | |||
void IZ_VideoUpdate(IZ_VideoState* video_state, IZ_InputState* input_state, u64 ticks) { | |||
void IZ_VideoUpdate(IZ_VideoState* video_state, u64 ticks, IZ_InputState* input_state) { | |||
if (ticks - video_state->last_update_at > 1000 / video_state->config.max_fps) { | |||
// Update window | |||
SDL_SetRenderDrawColor(video_state->renderer, 0x00, 0x00, 0x00, 0xff); | |||
@@ -34,11 +34,11 @@ static const IZ_VideoState IZ_DEFAULT_VIDEO_STATE = { | |||
.window = NULL, | |||
}; | |||
IZ_ProcedureResult IZ_VideoInitialize(const char*, IZ_VideoState*); | |||
IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState*, const char*); | |||
IZ_ProcedureResult IZ_VideoSaveConfig(const char*, IZ_VideoConfig*); | |||
IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoConfig*, const char*); | |||
void IZ_VideoUpdate(IZ_VideoState*, IZ_InputState*, u64); | |||
void IZ_VideoUpdate(IZ_VideoState*, u64, IZ_InputState*); | |||
void IZ_VideoTeardown(IZ_VideoState*); | |||
@@ -19,25 +19,30 @@ static const lws_retry_bo_t retry = { | |||
static i32 interrupted; | |||
static const struct lws_http_mount mount = { | |||
/* .mount_next */ NULL, /* linked-list "next" */ | |||
/* .mountpoint */ "/", /* mountpoint URL */ | |||
/* .origin */ "./mount-origin", /* serve from dir */ | |||
/* .def */ "index.html", /* default filename */ | |||
/* .protocol */ NULL, | |||
/* .cgienv */ NULL, | |||
/* .extra_mimetypes */ NULL, | |||
/* .interpret */ NULL, | |||
/* .cgi_timeout */ 0, | |||
/* .cache_max_age */ 0, | |||
/* .auth_mask */ 0, | |||
/* .cache_reusable */ 0, | |||
/* .cache_revalidate */ 0, | |||
/* .cache_intermediaries */ 0, | |||
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ | |||
/* .mountpoint_len */ 1, /* char count */ | |||
/* .basic_auth_login_file */ NULL, | |||
.mount_next = NULL, /* linked-list "next" */ | |||
.mountpoint = "/", /* mountpoint URL */ | |||
.origin = "./mount-origin", /* serve from dir */ | |||
.def = "index.html", /* default filename */ | |||
.protocol = NULL, | |||
.cgienv = NULL, | |||
.extra_mimetypes = NULL, | |||
.interpret = NULL, | |||
.cgi_timeout = 0, | |||
.cache_max_age = 0, | |||
.auth_mask = 0, | |||
.cache_reusable = 0, | |||
.cache_revalidate = 0, | |||
.cache_intermediaries = 0, | |||
.origin_protocol = LWSMPRO_FILE, /* files in a dir */ | |||
.mountpoint_len = 1, /* char count */ | |||
.basic_auth_login_file = NULL, | |||
}; | |||
#if defined(LWS_WITH_PLUGINS) | |||
/* if plugins enabled, only protocols explicitly named in pvo bind to vhost */ | |||
static struct lws_protocol_vhost_options pvo = { NULL, NULL, "lws-minimal", "" }; | |||
#endif | |||
void sigint_handler(i32 sig) { | |||
interrupted = 1; | |||
} | |||