diff --git a/CMakeLists.txt b/CMakeLists.txt index fbca47b..6dffe1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 $) # <--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 + $) # <--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 + $) # <--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 + $) # <--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 diff --git a/src/packages/game/IZ_app.c b/src/packages/game/IZ_app.c index f28037f..6827034 100644 --- a/src/packages/game/IZ_app.c +++ b/src/packages/game/IZ_app.c @@ -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); diff --git a/src/packages/game/IZ_app.h b/src/packages/game/IZ_app.h index 8641cb7..e52f566 100644 --- a/src/packages/game/IZ_app.h +++ b/src/packages/game/IZ_app.h @@ -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; diff --git a/src/packages/game/input/IZ_input.c b/src/packages/game/input/IZ_input.c index e802509..c7b983c 100644 --- a/src/packages/game/input/IZ_input.c +++ b/src/packages/game/input/IZ_input.c @@ -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 = {}, diff --git a/src/packages/game/input/IZ_input.h b/src/packages/game/input/IZ_input.h index 478aa57..66cbe42 100644 --- a/src/packages/game/input/IZ_input.h +++ b/src/packages/game/input/IZ_input.h @@ -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*); diff --git a/src/packages/game/network/IZ_wsclient.c b/src/packages/game/network/IZ_wsclient.c new file mode 100644 index 0000000..a74d7b5 --- /dev/null +++ b/src/packages/game/network/IZ_wsclient.c @@ -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); +} diff --git a/src/packages/game/network/IZ_wsclient.h b/src/packages/game/network/IZ_wsclient.h new file mode 100644 index 0000000..28be87e --- /dev/null +++ b/src/packages/game/network/IZ_wsclient.h @@ -0,0 +1,29 @@ +#ifndef IZ_WSCLIENT_H +#define IZ_WSCLIENT_H + +#include +#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 diff --git a/src/packages/game/output/IZ_video.c b/src/packages/game/output/IZ_video.c index c682a8b..70c5517 100644 --- a/src/packages/game/output/IZ_video.c +++ b/src/packages/game/output/IZ_video.c @@ -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); diff --git a/src/packages/game/output/IZ_video.h b/src/packages/game/output/IZ_video.h index 3daddcc..eff33e9 100644 --- a/src/packages/game/output/IZ_video.h +++ b/src/packages/game/output/IZ_video.h @@ -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*); diff --git a/src/packages/server/main.c b/src/packages/server/main.c index d2aa919..23f18a9 100644 --- a/src/packages/server/main.c +++ b/src/packages/server/main.c @@ -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; }