diff --git a/.gitignore b/.gitignore index 78920f7..e0d14e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,63 +1,63 @@ -*.d -*.o -*.ko -*.obj -*.elf -*.ilk -*.map -*.exp -*.gch -*.pch -*.lib -*.a -*.la -*.lo -*.dll -*.so -*.so.* -*.dylib -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex -*.dSYM/ -*.su -*.idb -*.pdb -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf -CMakeLists.txt.user -CMakeCache.txt -CMakeFiles -CMakeScripts -Testing -Makefile -cmake_install.cmake -install_manifest.txt -compile_commands.json -CTestTestfile.cmake -_deps -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db -*.stackdump -[Dd]esktop.ini -$RECYCLE.BIN/ -*.cab -*.msi -*.msix -*.msm -*.msp -*.lnk -.idea/ -cmake-build-debug/ -dependencies/ -assets/ \ No newline at end of file +*.d +*.o +*.ko +*.obj +*.elf +*.ilk +*.map +*.exp +*.gch +*.pch +*.lib +*.a +*.la +*.lo +*.dll +*.so +*.so.* +*.dylib +*.exe +*.out +*.global_app +*.i*86 +*.x86_64 +*.hex +*.dSYM/ +*.su +*.idb +*.pdb +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +*.stackdump +[Dd]esktop.ini +$RECYCLE.BIN/ +*.cab +*.msi +*.msix +*.msm +*.msp +*.lnk +.idea/ +cmake-build-debug/ +dependencies/ +assets/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 329621c..c542bdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,15 @@ 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 src/packages/game/log/IZ_log.c src/packages/game/log/IZ_log.h src/packages/game/network/IZ_network.h) + src/packages/game/network/IZ_wsclient.c + src/packages/game/network/IZ_wsclient.h + src/packages/game/log/IZ_log.c + src/packages/game/log/IZ_log.h + src/packages/game/util/IZ_midi.c + src/packages/game/util/IZ_midi.h + src/packages/game/network/IZ_websocket.h + src/packages/game/network/IZ_websocket.c +) target_link_libraries( game @@ -121,6 +129,9 @@ add_executable( src/packages/game/input/IZ_midi.h src/packages/game/input/IZ_midi.c + src/packages/game/util/IZ_midi.c + src/packages/game/util/IZ_midi.h + src/packages/game/input/input.test.c ) @@ -173,8 +184,12 @@ add_executable( src/packages/server/log/IZ_log.h src/packages/server/log/IZ_log.c src/packages/server/main.c - src/packages/server/network/IZ_wsserver.c src/packages/server/IZ_app.c src/packages/server/IZ_app.h src/packages/server/network/IZ_wsserver.h - src/packages/server/network/IZ_network.h + src/packages/server/IZ_app.c + src/packages/server/IZ_app.h + src/packages/server/network/IZ_wsserver.c + src/packages/server/network/IZ_wsserver.h + src/packages/server/network/IZ_websocket.h + src/packages/server/network/IZ_websocket.c ) target_link_libraries( diff --git a/src/packages/game/IZ_app.c b/src/packages/game/IZ_app.c index d15d324..4508add 100644 --- a/src/packages/game/IZ_app.c +++ b/src/packages/game/IZ_app.c @@ -1,31 +1,51 @@ #include "IZ_app.h" -IZ_ProcedureResult IZ_AppWSClientCallback( - struct lws* wsi, - enum lws_callback_reasons reason, - void* userraw, - void* in, - size_t len -) { - IZ_App* user = userraw; - switch (reason) { - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - printf("Client Connection Error %llu\n", len); - return 1; - case LWS_CALLBACK_CLIENT_CLOSED: - printf("Client Closed %llu\n", len); - return 0; - case LWS_CALLBACK_CLIENT_RECEIVE: - printf("Client Receive %llu\n", len); - break; - case LWS_CALLBACK_CLIENT_ESTABLISHED: - printf("Client Established %llu\n", len); +IZ_ProcedureResult IZ_AppWSClientInitialize(IZ_App* app) { + IZ_WSClientInitializeParams params = { + .address = "localhost", + .path = "/", + .port = 42069, + }; + + if (IZ_WSClientInitialize(&app->client, params)) { + printf("error\n"); + return -1; + } + return 0; +} + +IZ_ProcedureResult IZ_AppConnect(void* app_raw) { + IZ_App* app = app_raw; + if (IZ_AppWSClientInitialize(app)) { + return -1; + } + + i32 result = 0; + while (true) { + if (IZ_WSClientHandle(&app->client)) { + result = 1; break; - default: + } + + if (app->client.ws.interrupted) { break; + } } - return 0; + IZ_WSClientTeardown(&app->client); + return result; +} + +void IZ_AppEstablishConnection(IZ_App* app) { + app->client_thread = SDL_CreateThread(IZ_AppConnect, "networking", app); + SDL_DetachThread(app->client_thread); +} + +void IZ_AppCloseConnection(IZ_App* app) { + if (!app->client.ws.context) { + return; + } + IZ_WSClientCancelService(&app->client); } IZ_ProcedureResult IZ_AppInitialize(IZ_App* app, u8 argc, const char* argv[]) { @@ -50,16 +70,15 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App* app, u8 argc, const char* argv[]) { IZ_ConfigGetDefaultPath(config_path, 128); } - if (IZ_VideoInitialize(&app->video_state, config_path)) { + if (IZ_VideoInitialize(&app->video_state, config_path, argc, argv)) { return IZ_APP_RUN_VIDEO_INIT_ERROR; } - if (IZ_InputInitialize(&app->input_state, config_path)) { + if (IZ_InputInitialize(&app->input_state, config_path, argc, argv)) { return IZ_APP_RUN_INPUT_INIT_ERROR; } IZ_PoolInitialize(&app->pool, POOL_MAX_SIZE); - IZ_WSClientInitialize(&app->client); // TODO put into its timer module app->ticks = 0; @@ -67,7 +86,7 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App* app, u8 argc, const char* argv[]) { } void IZ_AppTeardown(IZ_App* app) { - IZ_WSClientDisconnect(&app->client); + IZ_AppCloseConnection(app); IZ_PoolTeardown(&app->pool); IZ_InputTeardown(&app->input_state); IZ_VideoTeardown(&app->video_state); @@ -82,10 +101,10 @@ IZ_ProcedureResult IZ_AppHandleSDLEvents(IZ_App* app) { } if (e.type == SDL_KEYDOWN) { - if (e.key.keysym.sym == SDLK_PAGEUP) { - // TODO connect + if (e.key.keysym.sym == SDLK_PAGEUP && !app->client.ws.context) { + IZ_AppEstablishConnection(app); } else if (e.key.keysym.sym == SDLK_PAGEDOWN) { - // TODO disconnect + IZ_AppCloseConnection(app); } } @@ -167,7 +186,6 @@ IZ_ProcedureResult IZ_AppRun(IZ_App* app, u8 argc, const char* argv[]) { //} if (IZ_AppHandleEvents(app)) { - // TODO refactor input handlers to have same function signature. break; } diff --git a/src/packages/game/IZ_app.h b/src/packages/game/IZ_app.h index 1478667..cbd64f0 100644 --- a/src/packages/game/IZ_app.h +++ b/src/packages/game/IZ_app.h @@ -22,7 +22,7 @@ typedef struct { IZ_VideoState video_state; IZ_Pool pool; - IZ_WSClient client; + IZ_WSClientState client; SDL_Thread* client_thread; u64 ticks; } IZ_App; diff --git a/src/packages/game/input/IZ_input.c b/src/packages/game/input/IZ_input.c index c16bb68..f0be556 100644 --- a/src/packages/game/input/IZ_input.c +++ b/src/packages/game/input/IZ_input.c @@ -1,15 +1,15 @@ #include "IZ_input.h" void IZ_InputHandleSDLEvents(IZ_InputState* state, SDL_Event e) { - IZ_JoystickHandleEvents(e, &state->joystick_state, &state->action); - IZ_KeyboardHandleEvents(e, &state->keyboard_state, &state->action); + IZ_JoystickHandleEvents(&state->joystick_state, &state->action, e); + IZ_KeyboardHandleEvents(&state->keyboard_state, &state->action, e); } void IZ_InputHandlePortMIDIEvents(IZ_InputState* state, PmEvent e) { - IZ_MIDIInputHandleEvents(e, &state->midi_input_state, &state->action); + IZ_MIDIInputHandleEvents(&state->midi_input_state, &state->action, e); } -IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_path) { +IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_path, u8 argc, const char** argv) { *state = (IZ_InputState) { .action = {}, .joystick_state = {}, @@ -19,18 +19,15 @@ IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_p IZ_ProcedureResult result = 0; - IZ_ProcedureResult joystick_result = IZ_JoystickInitialize(config_path, &state->joystick_state); - if (joystick_result) { + if (IZ_JoystickInitialize(&state->joystick_state, config_path, argc, argv)) { result |= 1; } - IZ_ProcedureResult keyboard_result = IZ_KeyboardInitialize(config_path, &state->keyboard_state); - if (keyboard_result) { + if (IZ_KeyboardInitialize(&state->keyboard_state, config_path, argc, argv)) { result |= 2; } - IZ_ProcedureResult midi_input_result = IZ_MIDIInputInitialize(config_path, &state->midi_input_state); - if (midi_input_result) { + if (IZ_MIDIInputInitialize(&state->midi_input_state, config_path, argc, argv)) { result |= 4; } @@ -39,7 +36,7 @@ IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_p state->action[player_index] = 0; } - return result; + return -result; } void IZ_InputTeardown(IZ_InputState* state) { diff --git a/src/packages/game/input/IZ_input.h b/src/packages/game/input/IZ_input.h index 0bb390b..c2e7bbf 100644 --- a/src/packages/game/input/IZ_input.h +++ b/src/packages/game/input/IZ_input.h @@ -17,7 +17,7 @@ void IZ_InputHandleSDLEvents(IZ_InputState*, SDL_Event); void IZ_InputHandlePortMIDIEvents(IZ_InputState*, PmEvent); -IZ_ProcedureResult IZ_InputInitialize(IZ_InputState*, const char*); +IZ_ProcedureResult IZ_InputInitialize(IZ_InputState*, const char*, u8, const char**); void IZ_InputTeardown(IZ_InputState*); diff --git a/src/packages/game/input/IZ_joystick.c b/src/packages/game/input/IZ_joystick.c index c0c5c4f..a3820cb 100644 --- a/src/packages/game/input/IZ_joystick.c +++ b/src/packages/game/input/IZ_joystick.c @@ -1,6 +1,6 @@ #include "IZ_joystick.h" -void IZ_JoystickHandleDeviceEvents(SDL_Event e, IZ_JoystickState* state) { +void IZ_JoystickHandleDeviceEvents(IZ_JoystickState* state, SDL_Event e) { if (e.type == SDL_JOYDEVICEADDED) { if (SDL_NumJoysticks() <= PLAYERS && !state->device) { state->device = SDL_JoystickOpen(e.jdevice.which); @@ -18,7 +18,7 @@ void IZ_JoystickHandleDeviceEvents(SDL_Event e, IZ_JoystickState* state) { } } -void IZ_JoystickHandleAxisEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { +void IZ_JoystickHandleAxisEvents(IZ_JoystickState* state, IZ_Action* action, SDL_Event e) { if (e.type == SDL_JOYAXISMOTION) { if ( e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_HORIZONTAL1 @@ -52,7 +52,7 @@ void IZ_JoystickHandleAxisEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action } } -void IZ_JoystickHandleHatEvents(SDL_Event e, IZ_Action* action) { +void IZ_JoystickHandleHatEvents(IZ_Action* action, SDL_Event e) { if (e.type == SDL_JOYHATMOTION) { *action &= ~(0x1 << IZ_ACTION_INDEX_UP); *action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); @@ -64,7 +64,7 @@ void IZ_JoystickHandleHatEvents(SDL_Event e, IZ_Action* action) { } } -void IZ_JoystickHandleButtonEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { +void IZ_JoystickHandleButtonEvents(IZ_JoystickState* state, IZ_Action* action, SDL_Event e) { u8 control_index; for (control_index = 4; control_index < CONTROLS; control_index += 1) { if (e.jbutton.button == state->config.control_mapping[control_index]) { @@ -83,17 +83,17 @@ void IZ_JoystickHandleButtonEvents(SDL_Event e, IZ_JoystickState* state, IZ_Acti } } -void IZ_JoystickHandleEvents(SDL_Event e, IZ_JoystickState(* state)[PLAYERS], IZ_Action(* action)[PLAYERS]) { +void IZ_JoystickHandleEvents(IZ_JoystickState(* state)[PLAYERS], IZ_Action(* action)[PLAYERS], SDL_Event e) { u8 player_index; for (player_index = 0; player_index < PLAYERS; player_index += 1) { - IZ_JoystickHandleDeviceEvents(e, &(*state)[player_index]); - IZ_JoystickHandleAxisEvents(e, &(*state)[player_index], &(*action)[player_index]); - IZ_JoystickHandleHatEvents(e, &(*action)[player_index]); - IZ_JoystickHandleButtonEvents(e, &(*state)[player_index], &(*action)[player_index]); + IZ_JoystickHandleDeviceEvents(&(*state)[player_index], e); + IZ_JoystickHandleAxisEvents(&(*state)[player_index], &(*action)[player_index], e); + IZ_JoystickHandleHatEvents(&(*action)[player_index], e); + IZ_JoystickHandleButtonEvents(&(*state)[player_index], &(*action)[player_index], e); } } -void IZ_JoystickLoadConfig(const char* config_path, IZ_JoystickState(* state)[PLAYERS]) { +void IZ_JoystickLoadConfig(IZ_JoystickState(* state)[PLAYERS], const char* config_path) { char control_mapping_section_name[26]; char main_section_name[11]; @@ -117,7 +117,7 @@ void IZ_JoystickLoadConfig(const char* config_path, IZ_JoystickState(* state)[PL } } -IZ_ProcedureResult IZ_JoystickSaveConfig(const char* config_path, IZ_JoystickState(* state)[PLAYERS]) { +IZ_ProcedureResult IZ_JoystickSaveConfig(IZ_JoystickState(* state)[PLAYERS], const char* config_path) { u8 problem = 0; char control_mapping_section_name[26]; @@ -134,7 +134,7 @@ IZ_ProcedureResult IZ_JoystickSaveConfig(const char* config_path, IZ_JoystickSta (*state)[player_index].config.control_mapping[control_index], config_path )) { - return 1; + problem |= (1 << player_index); } } @@ -158,15 +158,15 @@ IZ_ProcedureResult IZ_JoystickSaveConfig(const char* config_path, IZ_JoystickSta } } - return problem; + return -problem; } -IZ_ProcedureResult IZ_JoystickInitialize(const char* config_path, IZ_JoystickState(* state)[PLAYERS]) { +IZ_ProcedureResult IZ_JoystickInitialize(IZ_JoystickState(* state)[PLAYERS], const char* config_path, u8 argc, const char* argv[]) { SDL_memcpy(state, &IZ_DEFAULT_JOYSTICK_STATE, sizeof(IZ_JoystickState)); - IZ_JoystickLoadConfig(config_path, state); - if (IZ_JoystickSaveConfig(config_path, state)) { - return 1; + IZ_JoystickLoadConfig(state, config_path); + if (IZ_JoystickSaveConfig(state, config_path) < 0) { + return -1; } u8 joysticks_count = SDL_NumJoysticks(); diff --git a/src/packages/game/input/IZ_joystick.h b/src/packages/game/input/IZ_joystick.h index 1d8b9d4..68e6b32 100644 --- a/src/packages/game/input/IZ_joystick.h +++ b/src/packages/game/input/IZ_joystick.h @@ -82,11 +82,11 @@ static const IZ_JoystickState IZ_DEFAULT_JOYSTICK_STATE[PLAYERS] = { }, }; -IZ_ProcedureResult IZ_JoystickSaveConfig(const char*, IZ_JoystickState(*)[PLAYERS]); +IZ_ProcedureResult IZ_JoystickSaveConfig(IZ_JoystickState(*)[PLAYERS], const char*); -void IZ_JoystickHandleEvents(SDL_Event, IZ_JoystickState(*)[PLAYERS], IZ_Action(*)[PLAYERS]); +void IZ_JoystickHandleEvents(IZ_JoystickState(*)[PLAYERS], IZ_Action(*)[PLAYERS], SDL_Event); -IZ_ProcedureResult IZ_JoystickInitialize(const char*, IZ_JoystickState(*)[PLAYERS]); +IZ_ProcedureResult IZ_JoystickInitialize(IZ_JoystickState(*)[PLAYERS], const char*, u8, const char**); void IZ_JoystickTeardown(IZ_JoystickState(*)[PLAYERS]); diff --git a/src/packages/game/input/IZ_keyboard.c b/src/packages/game/input/IZ_keyboard.c index 0487423..e003638 100644 --- a/src/packages/game/input/IZ_keyboard.c +++ b/src/packages/game/input/IZ_keyboard.c @@ -1,6 +1,6 @@ #include "IZ_keyboard.h" -void IZ_KeyboardHandleKeyUpDownEvents(SDL_Event e, IZ_KeyboardState* state, IZ_Action* action) { +void IZ_KeyboardHandleKeyUpDownEvents(IZ_KeyboardState* state, IZ_Action* action, SDL_Event e) { u8 control_index; for (control_index = 0; control_index < CONTROLS; control_index += 1) { if (e.key.keysym.sym == state->config.control_mapping[control_index]) { @@ -17,13 +17,13 @@ void IZ_KeyboardHandleKeyUpDownEvents(SDL_Event e, IZ_KeyboardState* state, IZ_A } } -void IZ_KeyboardHandleEvents(SDL_Event e, IZ_KeyboardState(* state)[PLAYERS], IZ_Action(* action)[PLAYERS]) { +void IZ_KeyboardHandleEvents(IZ_KeyboardState(* state)[PLAYERS], IZ_Action(* action)[PLAYERS], SDL_Event e) { for (u8 player_index = 0; player_index < PLAYERS; player_index += 1) { - IZ_KeyboardHandleKeyUpDownEvents(e, &(*state)[player_index], &(*action)[player_index]); + IZ_KeyboardHandleKeyUpDownEvents(&(*state)[player_index], &(*action)[player_index], e); } } -IZ_ProcedureResult IZ_KeyboardSaveConfig(const char* config_path, IZ_KeyboardState(* state)[PLAYERS]) { +IZ_ProcedureResult IZ_KeyboardSaveConfig(IZ_KeyboardState(* state)[PLAYERS], const char* config_path) { u8 problem = 0; char control_mapping_section_name[26]; @@ -46,7 +46,7 @@ IZ_ProcedureResult IZ_KeyboardSaveConfig(const char* config_path, IZ_KeyboardSta return problem; } -void IZ_KeyboardLoadConfig(const char* config_path, IZ_KeyboardState(* state)[PLAYERS]) { +void IZ_KeyboardLoadConfig(IZ_KeyboardState(* state)[PLAYERS], const char* config_path) { char buffer[128]; char keyboard_section_name[26]; @@ -69,8 +69,8 @@ void IZ_KeyboardLoadConfig(const char* config_path, IZ_KeyboardState(* state)[PL } } -IZ_ProcedureResult IZ_KeyboardInitialize(const char* config_path, IZ_KeyboardState(* state)[PLAYERS]) { +IZ_ProcedureResult IZ_KeyboardInitialize(IZ_KeyboardState(* state)[PLAYERS], const char* config_path, u8 argc, const char* argv[]) { SDL_memcpy(state, &IZ_DEFAULT_KEYBOARD_STATE, sizeof(IZ_KeyboardState)); - IZ_KeyboardLoadConfig(config_path, state); - return IZ_KeyboardSaveConfig(config_path, state); + IZ_KeyboardLoadConfig(state, config_path); + return IZ_KeyboardSaveConfig(state, config_path); } diff --git a/src/packages/game/input/IZ_keyboard.h b/src/packages/game/input/IZ_keyboard.h index dd4b7fc..ff73560 100644 --- a/src/packages/game/input/IZ_keyboard.h +++ b/src/packages/game/input/IZ_keyboard.h @@ -62,10 +62,10 @@ static const IZ_KeyboardState IZ_DEFAULT_KEYBOARD_STATE[PLAYERS] = { }, }; -IZ_ProcedureResult IZ_KeyboardSaveConfig(const char*, IZ_KeyboardState(*)[PLAYERS]); +IZ_ProcedureResult IZ_KeyboardSaveConfig(IZ_KeyboardState(*)[PLAYERS], const char*); -void IZ_KeyboardHandleEvents(SDL_Event, IZ_KeyboardState(*)[PLAYERS], IZ_Action(*)[PLAYERS]); +void IZ_KeyboardHandleEvents(IZ_KeyboardState(*)[PLAYERS], IZ_Action(*)[PLAYERS], SDL_Event); -IZ_ProcedureResult IZ_KeyboardInitialize(const char*, IZ_KeyboardState(*)[PLAYERS]); +IZ_ProcedureResult IZ_KeyboardInitialize(IZ_KeyboardState(*)[PLAYERS], const char*, u8, const char**); #endif diff --git a/src/packages/game/input/IZ_midi.c b/src/packages/game/input/IZ_midi.c index 402e0ad..c2a97c3 100644 --- a/src/packages/game/input/IZ_midi.c +++ b/src/packages/game/input/IZ_midi.c @@ -1,67 +1,6 @@ #include "IZ_midi.h" -char* IZ_MIDIGetNoteName(u8 midi_note) { - static const char* pitch_names[] = { - "C", - "C#", - "D", - "D#", - "E", - "F", - "F#", - "G", - "G#", - "A", - "A#", - "B" - }; - - const u8 pitch_class = midi_note % 12; - const u8 octave = midi_note / 12; - static char note_name[8]; - sprintf_s(note_name, 8, "%s%u", pitch_names[pitch_class], octave); - return note_name; -} - -u8 IZ_MIDIGetNoteFromName(char* name) { - char name_copy[8]; - memcpy_s(name_copy, 8, name, 8); - _strlwr_s(name_copy, 8); - - u8 octave; - const char base_pitch_name[] = "c d ef g a b"; - - if (strlen(name_copy) == 2) { - octave = name_copy[1] - '0'; - u8 pitch_index; - for (pitch_index = 0; pitch_index < 12; pitch_index += 1) { - if (base_pitch_name[pitch_index] == name_copy[0]) { - return (octave * 12) + pitch_index; - } - } - return 255u; - } - - u8 pitch_class; - octave = name_copy[2] - '0'; - if (strstr(name_copy, "c#") || strstr(name_copy, "db")) { - pitch_class = 1; - } else if (strstr(name_copy, "d#") || strstr(name_copy, "eb")) { - pitch_class = 3; - } else if (strstr(name_copy, "f#") || strstr(name_copy, "gb")) { - pitch_class = 6; - } else if (strstr(name_copy, "g#") || strstr(name_copy, "ab")) { - pitch_class = 8; - } else if (strstr(name_copy, "a#") || strstr(name_copy, "bb")) { - pitch_class = 10; - } else { - return 255u; - } - - return (octave * 12) + pitch_class; -} - -void IZ_MIDIInputHandleNoteOnOffEvents(PmEvent e, IZ_MIDIInputState* state, IZ_Action* action) { +void IZ_MIDIInputHandleNoteOnOffEvents(IZ_MIDIInputState* state, IZ_Action* action, PmEvent e) { u32 message = e.message; u8 status = message & 0xF0u; u8 channel = message & 0x0Fu; @@ -90,14 +29,14 @@ void IZ_MIDIInputHandleNoteOnOffEvents(PmEvent e, IZ_MIDIInputState* state, IZ_A } } -void IZ_MIDIInputHandleEvents(PmEvent e, IZ_MIDIInputState(* state)[PLAYERS], IZ_Action(* action)[PLAYERS]) { +void IZ_MIDIInputHandleEvents(IZ_MIDIInputState(* state)[PLAYERS], IZ_Action(* action)[PLAYERS], PmEvent e) { u8 player_index; for (player_index = 0; player_index < PLAYERS; player_index += 1) { - IZ_MIDIInputHandleNoteOnOffEvents(e, &(*state)[player_index], &(*action)[player_index]); + IZ_MIDIInputHandleNoteOnOffEvents(&(*state)[player_index], &(*action)[player_index], e); } } -IZ_ProcedureResult IZ_MIDIInputSaveConfig(const char* config_path, IZ_MIDIInputState(* state)[PLAYERS]) { +IZ_ProcedureResult IZ_MIDIInputSaveConfig(IZ_MIDIInputState(* state)[PLAYERS], const char* config_path) { u8 problem = 0; char control_mapping_section_name[27]; @@ -141,7 +80,7 @@ IZ_ProcedureResult IZ_MIDIInputSaveConfig(const char* config_path, IZ_MIDIInputS return problem; } -void IZ_MIDIInputLoadConfig(const char* config_path, IZ_MIDIInputState(* state)[PLAYERS]) { +void IZ_MIDIInputLoadConfig(IZ_MIDIInputState(* state)[PLAYERS], const char* config_path) { char buffer[128]; char control_mapping_section_name[27]; char main_section_name[12]; @@ -169,14 +108,14 @@ void IZ_MIDIInputLoadConfig(const char* config_path, IZ_MIDIInputState(* state)[ } } -IZ_ProcedureResult IZ_MIDIInputInitialize(const char* config_path, IZ_MIDIInputState(* state)[PLAYERS]) { +IZ_ProcedureResult IZ_MIDIInputInitialize(IZ_MIDIInputState(* state)[PLAYERS], const char* config_path, u8 argc, const char* argv[]) { if (Pm_Initialize()) { return 1; } SDL_memcpy(state, &IZ_DEFAULT_MIDI_INPUT_STATE, sizeof(IZ_MIDIInputState)); - IZ_MIDIInputLoadConfig(config_path, state); - if (IZ_MIDIInputSaveConfig(config_path, state)) { + IZ_MIDIInputLoadConfig(state, config_path); + if (IZ_MIDIInputSaveConfig(state, config_path)) { return 2; } diff --git a/src/packages/game/input/IZ_midi.h b/src/packages/game/input/IZ_midi.h index 40c5969..6a30a66 100644 --- a/src/packages/game/input/IZ_midi.h +++ b/src/packages/game/input/IZ_midi.h @@ -11,6 +11,7 @@ #include #include "IZ_action.h" +#include "../util/IZ_midi.h" #define MIDI_EVENT_BUFFER_SIZE 1024 @@ -91,11 +92,11 @@ static const IZ_MIDIInputState IZ_DEFAULT_MIDI_INPUT_STATE[PLAYERS] = { }, }; -IZ_ProcedureResult IZ_MIDIInputSaveConfig(const char *config_path, IZ_MIDIInputState(*)[PLAYERS]); +IZ_ProcedureResult IZ_MIDIInputSaveConfig(IZ_MIDIInputState(*)[PLAYERS], const char*); -void IZ_MIDIInputHandleEvents(PmEvent e, IZ_MIDIInputState(*)[PLAYERS], IZ_Action(*)[PLAYERS]); +void IZ_MIDIInputHandleEvents(IZ_MIDIInputState(*)[PLAYERS], IZ_Action(*)[PLAYERS], PmEvent); -IZ_ProcedureResult IZ_MIDIInputInitialize(const char *config_path, IZ_MIDIInputState(*)[PLAYERS]); +IZ_ProcedureResult IZ_MIDIInputInitialize(IZ_MIDIInputState(*)[PLAYERS], const char*, u8, const char**); void IZ_MIDIInputTeardown(IZ_MIDIInputState(*)[PLAYERS]); diff --git a/src/packages/game/input/input.test.c b/src/packages/game/input/input.test.c index b39d74c..b3c8ad8 100644 --- a/src/packages/game/input/input.test.c +++ b/src/packages/game/input/input.test.c @@ -41,7 +41,7 @@ spec("input") { } it("sets initial state") { - IZ_JoystickInitialize("config.ini", &state); + IZ_JoystickInitialize(&state, "config.ini", 0, NULL); check(mock_is_called(SDL_memcpy), "Initial state not loaded."); check(mock_is_called(SDL_NumJoysticks), "Connected joysticks not checked."); @@ -50,7 +50,7 @@ spec("input") { it("calls load method") { mock_set_expected_calls(ini_getl, ((CONTROLS - 4) + 2) * PLAYERS); - IZ_JoystickInitialize("config.ini", &state); + IZ_JoystickInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(ini_getl) == mock_get_actual_calls(ini_getl), @@ -63,7 +63,7 @@ spec("input") { it("calls save method") { mock_set_expected_calls(ini_putl, ((CONTROLS - 4) + 2) * PLAYERS); - IZ_JoystickInitialize("config.ini", &state); + IZ_JoystickInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl), @@ -76,7 +76,7 @@ spec("input") { it("opens device handles") { mock_set_expected_calls(SDL_JoystickOpen, MOCK_OPEN_JOYSTICKS); - IZ_JoystickInitialize("config.ini", &state); + IZ_JoystickInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(SDL_JoystickOpen) == mock_get_actual_calls(SDL_JoystickOpen), @@ -111,7 +111,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_RIGHT), "Action not set." @@ -123,7 +123,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_LEFT), "Action not set." @@ -135,7 +135,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == 0, "Action not set." @@ -153,7 +153,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_RIGHT), "Action not set." @@ -165,7 +165,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_LEFT), "Action not set." @@ -177,7 +177,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == 0, "Action not set." @@ -195,7 +195,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_DOWN), "Action not set." @@ -207,7 +207,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_UP), "Action not set." @@ -219,7 +219,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == 0, "Action not set." @@ -237,7 +237,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_DOWN), "Action not set." @@ -249,7 +249,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1 << IZ_ACTION_INDEX_UP), "Action not set." @@ -261,7 +261,7 @@ spec("input") { action[p] = 0; printf("(axis value: %d) ", e.jaxis.value); - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == 0, "Action not set." @@ -280,7 +280,7 @@ spec("input") { e.jhat.value = (0x1u << i); action[p] = 0; - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1u << i), "Action not set." @@ -291,7 +291,7 @@ spec("input") { e.jhat.value = 0; action[p] = ~0; - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( !(action[p] & (0x1 << i)), "Action not unset." @@ -308,7 +308,7 @@ spec("input") { state[p].config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; action[p] = 0; - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( action[p] == (0x1u << i), "Action not set." @@ -321,7 +321,7 @@ spec("input") { state[p].config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; action[p] = ~0; - IZ_JoystickHandleEvents(e, &state, &action); + IZ_JoystickHandleEvents(&state, &action, e); check( !(action[p] & (0x1 << i)), "Action not unset." @@ -351,7 +351,7 @@ spec("input") { it("calls save method") { mock_set_expected_calls(ini_putl, ((CONTROLS - 4) + 2) * PLAYERS); - IZ_JoystickSaveConfig("config.ini", &state); + IZ_JoystickSaveConfig(&state, "config.ini"); check( mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl), @@ -416,7 +416,7 @@ spec("input") { } it("sets initial state") { - IZ_KeyboardInitialize("config.ini", &state); + IZ_KeyboardInitialize(&state, "config.ini", 0, NULL); check(mock_is_called(SDL_memcpy), "Initial state not loaded."); } @@ -424,7 +424,7 @@ spec("input") { it("calls load method") { mock_set_expected_calls(ini_gets, CONTROLS * PLAYERS); - IZ_KeyboardInitialize("config.ini", &state); + IZ_KeyboardInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(ini_gets) == mock_get_actual_calls(ini_gets), @@ -437,7 +437,7 @@ spec("input") { it("calls save method") { mock_set_expected_calls(ini_puts, CONTROLS * PLAYERS); - IZ_KeyboardInitialize("config.ini", &state); + IZ_KeyboardInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts), @@ -462,7 +462,7 @@ spec("input") { state[p].config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; action[p] = 0; - IZ_KeyboardHandleEvents(e, &state, &action); + IZ_KeyboardHandleEvents(&state, &action, e); check( action[p] == (0x1 << i), "Action not set." @@ -475,7 +475,7 @@ spec("input") { state[p].config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; action[p] = ~0; - IZ_KeyboardHandleEvents(e, &state, &action); + IZ_KeyboardHandleEvents(&state, &action, e); check( !(action[p] & (0x1 << i)), "Action not unset." @@ -549,7 +549,7 @@ spec("input") { } it("sets initial state") { - IZ_MIDIInputInitialize("config.ini", &state); + IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL); check(mock_is_called(SDL_memcpy), "Initial state not loaded."); check(mock_is_called(Pm_CountDevices), "Connected MIDI devices not checked."); @@ -559,7 +559,7 @@ spec("input") { mock_set_expected_calls(ini_gets, CONTROLS * PLAYERS); mock_set_expected_calls(ini_getl, 2 * PLAYERS); - IZ_MIDIInputInitialize("config.ini", &state); + IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(ini_gets) == mock_get_actual_calls(ini_gets), @@ -580,7 +580,7 @@ spec("input") { mock_set_expected_calls(ini_puts, CONTROLS * PLAYERS); mock_set_expected_calls(ini_putl, 2 * PLAYERS); - IZ_MIDIInputInitialize("config.ini", &state); + IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts), @@ -600,7 +600,7 @@ spec("input") { it("opens device handles") { mock_set_expected_calls(Pm_OpenInput, MOCK_OPEN_JOYSTICKS); - IZ_MIDIInputInitialize("config.ini", &state); + IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL); check( mock_get_expected_calls(Pm_OpenInput) == mock_get_actual_calls(Pm_OpenInput), @@ -657,7 +657,7 @@ spec("input") { state[p].config.control_mapping[i] = IZ_DEFAULT_MIDI_INPUT_STATE[p].config.control_mapping[i]; action[p] = 0; - IZ_MIDIInputHandleEvents(e, &state, &action); + IZ_MIDIInputHandleEvents(&state, &action, e); check( action[p] == (0x1 << i), "Action not set." @@ -669,7 +669,7 @@ spec("input") { state[p].config.control_mapping[i] = IZ_DEFAULT_MIDI_INPUT_STATE[p].config.control_mapping[i]; action[p] = ~0; - IZ_MIDIInputHandleEvents(e, &state, &action); + IZ_MIDIInputHandleEvents(&state, &action, e); check( !(action[p] & (0x1 << i)), "Action not unset." diff --git a/src/packages/game/network/IZ_network.h b/src/packages/game/network/IZ_network.h deleted file mode 100644 index 13ff580..0000000 --- a/src/packages/game/network/IZ_network.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef IZ_NETWORK_H -#define IZ_NETWORK_H - -#define NETWORK_PROTOCOL "izanagi-networking" - -#endif diff --git a/src/packages/game/network/IZ_websocket.c b/src/packages/game/network/IZ_websocket.c new file mode 100644 index 0000000..3bbd9a4 --- /dev/null +++ b/src/packages/game/network/IZ_websocket.c @@ -0,0 +1,28 @@ +#include "IZ_websocket.h" + +void IZ_WebsocketInitialize(IZ_Websocket* ws) { + ws->context = NULL; + ws->interrupted = false; +} + +IZ_ProcedureResult IZ_WebsocketHandle(IZ_Websocket* ws) { + // FIXME: https://libwebsockets.org/git/libwebsockets/tree/minimal-examples-lowlevel/http-server/minimal-http-server-eventlib-foreign + return lws_service(ws->context, 0); +} + +void IZ_WebsocketCancelService(IZ_Websocket* ws) { + ws->interrupted = true; + lws_cancel_service(ws->context); +} + +void IZ_WebsocketTeardown(IZ_Websocket* ws) { + lws_context_destroy(ws->context); + ws->context = NULL; +} + +void IZ_WebsocketDestroyMessage(void* msg_raw) { + IZ_WebsocketMessage* msg = msg_raw; + free(msg->payload); + msg->payload = NULL; + msg->len = 0; +} diff --git a/src/packages/game/network/IZ_websocket.h b/src/packages/game/network/IZ_websocket.h new file mode 100644 index 0000000..bd08d89 --- /dev/null +++ b/src/packages/game/network/IZ_websocket.h @@ -0,0 +1,34 @@ +#ifndef IZ_WEBSOCKET_H +#define IZ_WEBSOCKET_H + +#include +#include "../IZ_common.h" + +#define NETWORK_PROTOCOL "izanagi-networking" +#define RING_COUNT 32 + +/* one of these created for each message */ +typedef struct { + u8 binary: 1; + void* payload; /* is malloc'd */ + size_t len; + u8 first: 1; + u8 final: 1; +} IZ_WebsocketMessage; + +typedef struct { + struct lws_context* context; + u8 interrupted: 1; +} IZ_Websocket; + +void IZ_WebsocketInitialize(IZ_Websocket*); + +IZ_ProcedureResult IZ_WebsocketHandle(IZ_Websocket*); + +void IZ_WebsocketTeardown(IZ_Websocket*); + +void IZ_WebsocketDestroyMessage(void*); + +void IZ_WebsocketCancelService(IZ_Websocket*); + +#endif diff --git a/src/packages/game/network/IZ_wsclient.c b/src/packages/game/network/IZ_wsclient.c index a64a166..c0d295e 100644 --- a/src/packages/game/network/IZ_wsclient.c +++ b/src/packages/game/network/IZ_wsclient.c @@ -1,90 +1,303 @@ #include "IZ_wsclient.h" -IZ_ProcedureResult IZ_WSClientCreateConnection(IZ_WSClient* client, IZ_WSClientConnectParams params) { - static struct lws_client_connect_info info; - memset(&info, 0, sizeof info); +void IZ_WSClientAttemptConnect(struct lws_sorted_usec_list *sul) { + IZ_WSClientVHostData* vhd = lws_container_of(sul, IZ_WSClientVHostData, sul); - 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; + printf("%s %s %u", vhd->address, vhd->path, *vhd->port); + + vhd->i.context = vhd->context; + vhd->i.port = *vhd->port; + vhd->i.address = vhd->address; + vhd->i.path = vhd->path; + vhd->i.host = vhd->i.address; + vhd->i.origin = vhd->i.address; + vhd->i.ssl_connection = 0; + + vhd->i.protocol = NETWORK_PROTOCOL; + vhd->i.pwsi = &vhd->client_wsi; + + if (lws_client_connect_via_info(&vhd->i)) { + return; } + lws_sul_schedule( + vhd->context, + 0, + &vhd->sul, + IZ_WSClientAttemptConnect, + 10 * LWS_US_PER_SEC + ); +} + +IZ_ProcedureResult IZ_WSClientProtocolInitialize(struct lws* wsi, void* in) { + IZ_WSClientVHostData* vhd_instance = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get( + lws_get_vhost(wsi), + lws_get_protocol(wsi) + ); + IZ_WSClientVHostData** vhd = &vhd_instance; + *vhd = lws_protocol_vh_priv_zalloc( + lws_get_vhost(wsi), + lws_get_protocol(wsi), + sizeof(IZ_WSClientVHostData) + ); + (*vhd)->context = lws_get_context(wsi); + (*vhd)->protocol = lws_get_protocol(wsi); + (*vhd)->vhost = lws_get_vhost(wsi); + (*vhd)->port = (u16*) lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "port")->value; + (*vhd)->address = lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "address")->value; + (*vhd)->path = lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "path")->value; + (*vhd)->ring = lws_ring_create( + sizeof(IZ_WebsocketMessage), + RING_COUNT, + IZ_WebsocketDestroyMessage + ); + if (!(*vhd)->ring) { + return 1; + } + IZ_WSClientAttemptConnect(&(*vhd)->sul); return 0; } -IZ_ProcedureResult IZ_WSClientCreateContext(IZ_WSClient* client, lws_callback_function* callback, void* userdata) { - static struct lws_protocols protocols[] = { - { - .name = "http", - .callback = NULL, - .per_session_data_size = 0, - .rx_buffer_size = 0, - .id = 0, - .user = NULL, - .tx_packet_size = 0, - }, - LWS_PROTOCOL_LIST_TERM, - }; +void IZ_WSClientProtocolTeardown(struct lws* wsi) { + IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get( + lws_get_vhost(wsi), + lws_get_protocol(wsi) + ); - protocols[0].callback = callback; - protocols[0].user = userdata; - 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, + vhd->finished = true; + if (vhd->ring) { + lws_ring_destroy(vhd->ring); + } - client->context = lws_create_context(&info); - if (!client->context) { - return 1; + lws_sul_cancel(&vhd->sul); +} + +void IZ_WSClientConnectionError(struct lws* wsi, void* in) { + IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get( + lws_get_vhost(wsi), + lws_get_protocol(wsi) + ); + + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); + vhd->client_wsi = NULL; + lws_sul_schedule( + vhd->context, + 0, + &vhd->sul, + IZ_WSClientAttemptConnect, + LWS_US_PER_SEC + ); +} + +void IZ_WSClientOnOpen(struct lws* wsi) { + IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get( + lws_get_vhost(wsi), + lws_get_protocol(wsi) + ); + + vhd->established = true; +} + +IZ_ProcedureResult IZ_WSClientWritable(struct lws* wsi) { + IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get( + lws_get_vhost(wsi), + lws_get_protocol(wsi) + ); + + const IZ_WebsocketMessage* pmsg = lws_ring_get_element(vhd->ring, &vhd->tail); + if (!pmsg) { + return 0; + } + + /* notice we allowed for LWS_PRE in the payload already */ + i32 m = lws_write( + wsi, + ((unsigned char*) pmsg->payload) + LWS_PRE, + pmsg->len, + pmsg->binary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT + ); + + if (m < (i32)pmsg->len) { + lwsl_err("ERROR %d writing to ws socket\n", m); + return -1; + } + + lws_ring_consume_single_tail(vhd->ring, &vhd->tail, 1); + + /* more to do for us? */ + if (lws_ring_get_element(vhd->ring, &vhd->tail)) { + /* come back as soon as we can write more */ + lws_callback_on_writable(wsi); } return 0; } -void IZ_WSClientInitialize(IZ_WSClient* client) { - // TODO delegate logs to SDL - //lws_set_log_level(0, NULL); - client->context = NULL; - client->connection = NULL; +void IZ_WSClientOnClose(struct lws* wsi) { + IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get( + lws_get_vhost(wsi), + lws_get_protocol(wsi) + ); + + vhd->client_wsi = NULL; + vhd->established = false; + lws_sul_schedule( + vhd->context, + 0, + &vhd->sul, + IZ_WSClientAttemptConnect, + LWS_US_PER_SEC + ); } -IZ_ProcedureResult IZ_WSClientConnect(IZ_WSClient* client, IZ_WSClientConnectParams params) { - if (IZ_WSClientCreateContext(client, params.callback, params.userdata)) { - return 1; +void IZ_WSClientOnReceive(struct lws* wsi, IZ_WSClientSessionData* pss, void* in, size_t len) { + lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: %4d (rpp %5d, first %d, last %d, bin %d)\n", + (int)len, (int)lws_remaining_packet_payload(wsi), + lws_is_first_fragment(wsi), + lws_is_final_fragment(wsi), + lws_frame_is_binary(wsi)); + + // lwsl_hexdump_notice(in, len); + IZ_WebsocketMessage amsg; + amsg.first = (char)lws_is_first_fragment(wsi); + amsg.final = (char)lws_is_final_fragment(wsi); + amsg.binary = (char)lws_frame_is_binary(wsi); + i32 n = (int)lws_ring_get_count_free_elements(pss->ring); + if (!n) { + lwsl_user("dropping!\n"); + return; } - if (IZ_WSClientCreateConnection(client, params)) { - return 2; + amsg.len = len; + /* notice we over-allocate by LWS_PRE */ + amsg.payload = malloc(LWS_PRE + len); + if (!amsg.payload) { + lwsl_user("OOM: dropping\n"); + return; } - return 0; + memcpy((char *)amsg.payload + LWS_PRE, in, len); + if (!lws_ring_insert(pss->ring, &amsg, 1)) { + IZ_WebsocketDestroyMessage(&amsg); + lwsl_user("dropping!\n"); + return; + } + lws_callback_on_writable(wsi); + + if (!pss->flow_controlled && n < 3) { + pss->flow_controlled = 1; + lws_rx_flow_control(wsi, 0); + } } -IZ_ProcedureResult IZ_WSClientHandle(IZ_WSClient* client) { - i32 response = lws_service(client->context, 0); - if (response < 0) { - return 1; +IZ_ProcedureResult IZ_WSClientCallback( + struct lws* wsi, + enum lws_callback_reasons reason, + void* user, + void* in, + size_t len +) { + switch (reason) { + case LWS_CALLBACK_PROTOCOL_INIT: + return IZ_WSClientProtocolInitialize(wsi, in); + case LWS_CALLBACK_PROTOCOL_DESTROY: + IZ_WSClientProtocolTeardown(wsi); + break; + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + IZ_WSClientConnectionError(wsi, in); + break; + case LWS_CALLBACK_CLIENT_ESTABLISHED: + IZ_WSClientOnOpen(wsi); + break; + case LWS_CALLBACK_CLIENT_CLOSED: + IZ_WSClientOnClose(wsi); + break; + case LWS_CALLBACK_CLIENT_RECEIVE: + IZ_WSClientOnReceive(wsi, user, in, len); + break; + case LWS_CALLBACK_CLIENT_WRITEABLE: + return IZ_WSClientWritable(wsi); + default: + break; } + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +IZ_ProcedureResult IZ_WSClientInitialize(IZ_WSClientState* state, IZ_WSClientInitializeParams params) { + struct lws_context_creation_info info; + memset(&info, 0, sizeof info); + info.port = CONTEXT_PORT_NO_LISTEN; + + static const struct lws_protocols protocols[] = { + { + .name = NETWORK_PROTOCOL, + .callback = IZ_WSClientCallback, + .per_session_data_size = sizeof(IZ_WSClientSessionData), + .rx_buffer_size = 1024, + .id = 0, + .user = NULL, + .tx_packet_size = 0, + }, + LWS_PROTOCOL_LIST_TERM + }; + info.protocols = protocols; + + static struct lws_protocol_vhost_options pvo_address = { + NULL, + NULL, + "address", /* pvo name */ + "localhost" /* pvo value */ + }; + pvo_address.value = params.address; + + static struct lws_protocol_vhost_options pvo_path = { + &pvo_address, + NULL, + "path", /* pvo name */ + "/" /* pvo value */ + }; + pvo_path.value = params.path; + + static struct lws_protocol_vhost_options pvo_port = { + &pvo_path, + NULL, + "port", /* pvo name */ + NULL /* pvo value */ + }; + pvo_port.value = (void*) ¶ms.port; + + static const struct lws_protocol_vhost_options pvo = { + NULL, /* "next" pvo linked-list */ + &pvo_port, /* "child" pvo linked-list */ + NETWORK_PROTOCOL, /* protocol name we belong to on this vhost */ + "" /* ignored */ + }; + + info.pvo = &pvo; + info.fd_limit_per_thread = 1 + 1 + 1; + IZ_WebsocketInitialize(&state->ws); + state->ws.context = lws_create_context(&info); + if (!state->ws.context) { + return -1; + } return 0; } -void IZ_WSClientDisconnect(IZ_WSClient* client) { - lws_context_destroy(client->context); +IZ_ProcedureResult IZ_WSClientHandle(IZ_WSClientState* state) { + return IZ_WebsocketHandle(&state->ws); +} + +void IZ_WSClientTeardown(IZ_WSClientState* state) { + IZ_WebsocketTeardown(&state->ws); +} + +void IZ_WSClientCancelService(IZ_WSClientState* state) { + IZ_WebsocketCancelService(&state->ws); } diff --git a/src/packages/game/network/IZ_wsclient.h b/src/packages/game/network/IZ_wsclient.h index 975b9d6..90c0a54 100644 --- a/src/packages/game/network/IZ_wsclient.h +++ b/src/packages/game/network/IZ_wsclient.h @@ -3,28 +3,52 @@ #include #include "../IZ_common.h" -#include "IZ_network.h" +#include "IZ_websocket.h" typedef struct { - struct lws_context* context; - struct lws* connection; -} IZ_WSClient; + struct lws_context *context; + struct lws_vhost *vhost; + const struct lws_protocols *protocol; + + lws_sorted_usec_list_t sul; + + struct lws_ring *ring; /* ringbuffer holding unsent messages */ + u32 tail; + + struct lws_client_connect_info i; + struct lws *client_wsi; + + u8 finished: 1; + u8 established: 1; + const char* address; + const char* path; + u16* port; +} IZ_WSClientVHostData; + +typedef struct { + struct lws_ring *ring; + u32 tail; + char flow_controlled; + u8 completed: 1; + u8 write_consume_pending: 1; +} IZ_WSClientSessionData; typedef struct { - u16 port; const char* address; const char* path; - const char* protocol; - void* userdata; - lws_callback_function* callback; -} IZ_WSClientConnectParams; + u16 port; +} IZ_WSClientInitializeParams; + +typedef struct { + IZ_Websocket ws; +} IZ_WSClientState; -void IZ_WSClientInitialize(IZ_WSClient*); +IZ_ProcedureResult IZ_WSClientInitialize(IZ_WSClientState*, IZ_WSClientInitializeParams); -IZ_ProcedureResult IZ_WSClientConnect(IZ_WSClient*, IZ_WSClientConnectParams); +IZ_ProcedureResult IZ_WSClientHandle(IZ_WSClientState*); -IZ_ProcedureResult IZ_WSClientHandle(IZ_WSClient*); +void IZ_WSClientTeardown(IZ_WSClientState*); -void IZ_WSClientDisconnect(IZ_WSClient*); +void IZ_WSClientCancelService(IZ_WSClientState*); #endif diff --git a/src/packages/game/output/IZ_video.c b/src/packages/game/output/IZ_video.c index af28b22..d789936 100644 --- a/src/packages/game/output/IZ_video.c +++ b/src/packages/game/output/IZ_video.c @@ -1,30 +1,30 @@ #include "IZ_video.h" -IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoConfig* config, const char* config_path) { - if (!ini_putl("Video", "Width", config->width, config_path)) { - return 1; +IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoState* state, const char* config_path) { + if (!ini_putl("Video", "Width", state->config.width, config_path)) { + return -1; } - if (!ini_putl("Video", "Height", config->height, config_path)) { - return 1; + if (!ini_putl("Video", "Height", state->config.height, config_path)) { + return -1; } - if (!ini_putl("Video", "MaxFps", config->max_fps, config_path)) { - return 1; + if (!ini_putl("Video", "MaxFps", state->config.max_fps, config_path)) { + return -1; } return 0; } -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); +void IZ_VideoLoadConfig(IZ_VideoState* state, const char* config_path) { + state->config.width = ini_getl("Video", "Width", IZ_DEFAULT_VIDEO_STATE.config.width, config_path); + state->config.height = ini_getl("Video", "Height", IZ_DEFAULT_VIDEO_STATE.config.height, config_path); + state->config.max_fps = ini_getl("Video", "MaxFps", IZ_DEFAULT_VIDEO_STATE.config.max_fps, config_path); } -IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState* state, const char* config_path) { +IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState* state, const char* config_path, u8 argc, const char* argv[]) { SDL_memcpy(state, &IZ_DEFAULT_VIDEO_STATE, sizeof(IZ_VideoState)); - IZ_VideoLoadConfig(&state->config, config_path); - if (IZ_VideoSaveConfig(&state->config, config_path)) { + IZ_VideoLoadConfig(state, config_path); + if (IZ_VideoSaveConfig(state, config_path)) { // fprintf_s(stderr, "Error committing video config.\n"); } state->last_update_at = 0u; diff --git a/src/packages/game/output/IZ_video.h b/src/packages/game/output/IZ_video.h index 48562e5..4cdffef 100644 --- a/src/packages/game/output/IZ_video.h +++ b/src/packages/game/output/IZ_video.h @@ -40,9 +40,9 @@ static const IZ_VideoState IZ_DEFAULT_VIDEO_STATE = { .active_sprites = {}, }; -IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState*, const char*); +IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState*, const char*, u8, const char**); -IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoConfig*, const char*); +IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoState*, const char*); void IZ_VideoUpdate(IZ_VideoState*, u64, IZ_InputState*); diff --git a/src/packages/game/output/output.test.c b/src/packages/game/output/output.test.c index 63a0029..b660aa6 100644 --- a/src/packages/game/output/output.test.c +++ b/src/packages/game/output/output.test.c @@ -21,7 +21,7 @@ spec("output") { it("calls save method") { mock_set_expected_calls(ini_putl, 3); - IZ_VideoSaveConfig("config.ini", &config); + IZ_VideoSaveConfig(&config, "config.ini"); check( mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl), diff --git a/src/packages/game/util/IZ_midi.c b/src/packages/game/util/IZ_midi.c new file mode 100644 index 0000000..f0612a3 --- /dev/null +++ b/src/packages/game/util/IZ_midi.c @@ -0,0 +1,62 @@ +#include "IZ_midi.h" + +char* IZ_MIDIGetNoteName(u8 midi_note) { + static const char* pitch_names[] = { + "C", + "C#", + "D", + "D#", + "E", + "F", + "F#", + "G", + "G#", + "A", + "A#", + "B" + }; + + const u8 pitch_class = midi_note % 12; + const u8 octave = midi_note / 12; + static char note_name[8]; + sprintf_s(note_name, 8, "%s%u", pitch_names[pitch_class], octave); + return note_name; +} + +u8 IZ_MIDIGetNoteFromName(char* name) { + char name_copy[8]; + memcpy_s(name_copy, 8, name, 8); + _strlwr_s(name_copy, 8); + + u8 octave; + const char base_pitch_name[] = "c d ef g a b"; + + if (strlen(name_copy) == 2) { + octave = name_copy[1] - '0'; + u8 pitch_index; + for (pitch_index = 0; pitch_index < 12; pitch_index += 1) { + if (base_pitch_name[pitch_index] == name_copy[0]) { + return (octave * 12) + pitch_index; + } + } + return 255u; + } + + u8 pitch_class; + octave = name_copy[2] - '0'; + if (strstr(name_copy, "c#") || strstr(name_copy, "db")) { + pitch_class = 1; + } else if (strstr(name_copy, "d#") || strstr(name_copy, "eb")) { + pitch_class = 3; + } else if (strstr(name_copy, "f#") || strstr(name_copy, "gb")) { + pitch_class = 6; + } else if (strstr(name_copy, "g#") || strstr(name_copy, "ab")) { + pitch_class = 8; + } else if (strstr(name_copy, "a#") || strstr(name_copy, "bb")) { + pitch_class = 10; + } else { + return 255u; + } + + return (octave * 12) + pitch_class; +} diff --git a/src/packages/game/util/IZ_midi.h b/src/packages/game/util/IZ_midi.h new file mode 100644 index 0000000..0ec36e5 --- /dev/null +++ b/src/packages/game/util/IZ_midi.h @@ -0,0 +1,11 @@ +#ifndef IZ_UTIL_MIDI_H +#define IZ_UTIL_MIDI_H + +#include +#include +#include "../IZ_common.h" + +char* IZ_MIDIGetNoteName(u8); +u8 IZ_MIDIGetNoteFromName(char*); + +#endif diff --git a/src/packages/server/IZ_app.c b/src/packages/server/IZ_app.c index 074a29a..fab0c11 100644 --- a/src/packages/server/IZ_app.c +++ b/src/packages/server/IZ_app.c @@ -1,7 +1,7 @@ #include "IZ_app.h" void IZ_AppHandleSignal(i32 _signal) { - interrupted = true; + IZ_WSServerCancelService(&global_app.server); } // TODO move to each subsystem @@ -20,19 +20,17 @@ void IZ_AppLoadConfig(IZ_App *app, u8 argc, const char **argv) { } IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { - interrupted = false; signal(SIGINT, IZ_AppHandleSignal); - //signal(SIGTERM, IZ_AppHandleSignal); IZ_AppLoadConfig(app, argc, argv); IZ_LogInterceptWSMessages(app->config.log_level); - if (IZ_WSServerCreateContext(&app->context, (IZ_WSServerCreateContextParams) { + if (IZ_WSServerInitialize(&app->server, (IZ_WSServerInitializeParams) { .protocol = NULL, .port = app->config.port, .default_filename = NULL, .origin = NULL, })) { - return 1; + return -1; } return 0; @@ -40,14 +38,26 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { IZ_ProcedureResult IZ_AppRun(IZ_App *app, u8 argc, const char **argv) { if (IZ_AppInitialize(app, argc, argv)) { - return 1; + return -1; } - i32 n = 0; - while (n >= 0 && !interrupted) { - n = lws_service(app->context, 0); + i32 result = 0; + while (!app->server.ws.interrupted) { + printf("A\n"); + if (IZ_WSServerHandle(&app->server)) { + printf("B\n"); + result = -1; + break; + } + + if (app->server.ws.interrupted) { + printf("C\n"); + break; + } + printf("D\n"); } - lws_context_destroy(app->context); - return 0; + IZ_WSServerTeardown(&app->server); + printf("%u\n", result); + return result; } diff --git a/src/packages/server/IZ_app.h b/src/packages/server/IZ_app.h index bc1707f..c7550c0 100644 --- a/src/packages/server/IZ_app.h +++ b/src/packages/server/IZ_app.h @@ -7,8 +7,6 @@ #include "log/IZ_log.h" #include "IZ_common.h" -static bool interrupted; - typedef struct { i32 log_level; u16 port; @@ -16,7 +14,7 @@ typedef struct { typedef struct { IZ_AppConfig config; - struct lws_context* context; + IZ_WSServerState server; } IZ_App; static const IZ_App IZ_APP_DEFAULT_STATE = { @@ -24,9 +22,10 @@ static const IZ_App IZ_APP_DEFAULT_STATE = { .log_level = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, .port = 42069, }, - .context = NULL, }; +static IZ_App global_app; + IZ_ProcedureResult IZ_AppRun(IZ_App*, u8, const char**); #endif diff --git a/src/packages/server/main.c b/src/packages/server/main.c index 243bde6..3642ec0 100644 --- a/src/packages/server/main.c +++ b/src/packages/server/main.c @@ -1,6 +1,5 @@ #include "IZ_app.h" IZ_ProcedureResult main(i32 argc, const char *argv[]) { - IZ_App app; - return IZ_AppRun(&app, argc, argv); + return IZ_AppRun(&global_app, argc, argv); } diff --git a/src/packages/server/network/IZ_network.h b/src/packages/server/network/IZ_network.h deleted file mode 120000 index ded7f28..0000000 --- a/src/packages/server/network/IZ_network.h +++ /dev/null @@ -1 +0,0 @@ -E:/Projects/Games/izanagi/src/packages/game/network/IZ_network.h \ No newline at end of file diff --git a/src/packages/server/network/IZ_websocket.c b/src/packages/server/network/IZ_websocket.c new file mode 120000 index 0000000..1577459 --- /dev/null +++ b/src/packages/server/network/IZ_websocket.c @@ -0,0 +1 @@ +E:/Projects/Games/izanagi/src/packages/game/network/IZ_websocket.c \ No newline at end of file diff --git a/src/packages/server/network/IZ_websocket.h b/src/packages/server/network/IZ_websocket.h new file mode 120000 index 0000000..d6affe3 --- /dev/null +++ b/src/packages/server/network/IZ_websocket.h @@ -0,0 +1 @@ +E:/Projects/Games/izanagi/src/packages/game/network/IZ_websocket.h \ No newline at end of file diff --git a/src/packages/server/network/IZ_wsserver.c b/src/packages/server/network/IZ_wsserver.c index 14b6fe6..4d5625f 100644 --- a/src/packages/server/network/IZ_wsserver.c +++ b/src/packages/server/network/IZ_wsserver.c @@ -1,6 +1,6 @@ #include "IZ_wsserver.h" -static void IZ_ProtocolCullLaggingClients(IZ_WSServerVHostData *vhd) { +void IZ_ProtocolCullLaggingClients(IZ_WSServerVHostData *vhd) { u32 oldest_tail = lws_ring_get_oldest_tail(vhd->ring); IZ_WSServerSessionData *old_pss = NULL; i32 most = 0; @@ -93,15 +93,7 @@ static void IZ_ProtocolCullLaggingClients(IZ_WSServerVHostData *vhd) { /* destroys the message when everyone has had a copy of it */ -void IZ_ProtocolDestroyMessage(void* msg_raw) { - IZ_WSServerMessage *msg = msg_raw; - - free(msg->payload); - msg->payload = NULL; - msg->len = 0; -} - -i32 IZ_WSServerInitialize(struct lws* wsi) { +IZ_ProcedureResult IZ_WSServerProtocolInitialize(struct lws* wsi) { IZ_WSServerVHostData* vhd_instance = (IZ_WSServerVHostData*) lws_protocol_vh_priv_get( lws_get_vhost(wsi), lws_get_protocol(wsi) @@ -116,9 +108,9 @@ i32 IZ_WSServerInitialize(struct lws* wsi) { (*vhd)->protocol = lws_get_protocol(wsi); (*vhd)->vhost = lws_get_vhost(wsi); (*vhd)->ring = lws_ring_create( - sizeof(IZ_WSServerMessage), + sizeof(IZ_WebsocketMessage), RING_COUNT, - IZ_ProtocolDestroyMessage + IZ_WebsocketDestroyMessage ); if (!(*vhd)->ring) { return 1; @@ -126,7 +118,7 @@ i32 IZ_WSServerInitialize(struct lws* wsi) { return 0; } -void IZ_WSServerTeardown(struct lws* wsi) { +void IZ_WSServerProtocolTeardown(struct lws* wsi) { IZ_WSServerVHostData* vhd = (IZ_WSServerVHostData*) lws_protocol_vh_priv_get( lws_get_vhost(wsi), lws_get_protocol(wsi) @@ -158,7 +150,7 @@ void IZ_WSServerOnClose(struct lws* wsi, IZ_WSServerSessionData* pss) { lws_ll_fwd_remove(IZ_WSServerSessionData, pss_list, pss, vhd->pss_list); } -IZ_ProcedureResult IZ_WSServerOnSend(struct lws* wsi, IZ_WSServerSessionData* pss) { +IZ_ProcedureResult IZ_WSServerWritable(struct lws* wsi, IZ_WSServerSessionData* pss) { IZ_WSServerVHostData* vhd = (IZ_WSServerVHostData*) lws_protocol_vh_priv_get( lws_get_vhost(wsi), lws_get_protocol(wsi) @@ -167,7 +159,7 @@ IZ_ProcedureResult IZ_WSServerOnSend(struct lws* wsi, IZ_WSServerSessionData* ps if (pss->culled) { return 0; } - const IZ_WSServerMessage *pmsg = lws_ring_get_element(vhd->ring, &pss->tail); + const IZ_WebsocketMessage* pmsg = lws_ring_get_element(vhd->ring, &pss->tail); if (!pmsg) { return 0; } @@ -175,7 +167,7 @@ IZ_ProcedureResult IZ_WSServerOnSend(struct lws* wsi, IZ_WSServerSessionData* ps /* notice we allowed for LWS_PRE in the payload already */ i32 m = lws_write( wsi, - ((unsigned char *) pmsg->payload) + LWS_PRE, + ((unsigned char*) pmsg->payload) + LWS_PRE, pmsg->len, pmsg->binary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT ); @@ -209,7 +201,7 @@ void IZ_WSServerOnReceive(struct lws* wsi, void* in, size_t len) { lws_get_vhost(wsi), lws_get_protocol(wsi) ); - IZ_WSServerMessage amsg; + IZ_WebsocketMessage amsg; i32 n = (i32) lws_ring_get_count_free_elements(vhd->ring); if (!n) { /* forcibly make space */ @@ -235,7 +227,7 @@ void IZ_WSServerOnReceive(struct lws* wsi, void* in, size_t len) { /* ...and we copy the payload in at +LWS_PRE */ memcpy((char *) amsg.payload + LWS_PRE, in, len); if (!lws_ring_insert(vhd->ring, &amsg, 1)) { - IZ_ProtocolDestroyMessage(&amsg); + IZ_WebsocketDestroyMessage(&amsg); lwsl_user("dropping!\n"); return; } @@ -251,7 +243,7 @@ void IZ_WSServerOnReceive(struct lws* wsi, void* in, size_t len) { lws_end_foreach_llp(ppss, pss_list); } -i32 IZ_WSServerCallback( +IZ_ProcedureResult IZ_WSServerCallback( struct lws* wsi, enum lws_callback_reasons reason, void* user, @@ -260,9 +252,9 @@ i32 IZ_WSServerCallback( ) { switch (reason) { case LWS_CALLBACK_PROTOCOL_INIT: - return IZ_WSServerInitialize(wsi); + return IZ_WSServerProtocolInitialize(wsi); case LWS_CALLBACK_PROTOCOL_DESTROY: - IZ_WSServerTeardown(wsi); + IZ_WSServerProtocolTeardown(wsi); break; case LWS_CALLBACK_ESTABLISHED: IZ_WSServerOnOpen(wsi, user); @@ -271,7 +263,7 @@ i32 IZ_WSServerCallback( IZ_WSServerOnClose(wsi, user); break; case LWS_CALLBACK_SERVER_WRITEABLE: - return IZ_WSServerOnSend(wsi, user); + return IZ_WSServerWritable(wsi, user); case LWS_CALLBACK_RECEIVE: IZ_WSServerOnReceive(wsi, in, len); break; @@ -282,7 +274,7 @@ i32 IZ_WSServerCallback( return 0; } -IZ_ProcedureResult IZ_WSServerCreateContext(struct lws_context** context, IZ_WSServerCreateContextParams params) { +IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState* state, IZ_WSServerInitializeParams params) { struct lws_context_creation_info info; memset(&info, 0, sizeof info); info.port = params.port; @@ -347,10 +339,23 @@ IZ_ProcedureResult IZ_WSServerCreateContext(struct lws_context** context, IZ_WSS | LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE ); - *context = lws_create_context(&info); - if (!*context) { - return 1; + IZ_WebsocketInitialize(&state->ws); + state->ws.context = lws_create_context(&info); + if (!state->ws.context) { + return -1; } return 0; } + +IZ_ProcedureResult IZ_WSServerHandle(IZ_WSServerState* state) { + return IZ_WebsocketHandle(&state->ws); +} + +void IZ_WSServerTeardown(IZ_WSServerState* state) { + IZ_WebsocketTeardown(&state->ws); +} + +void IZ_WSServerCancelService(IZ_WSServerState* state) { + IZ_WebsocketCancelService(&state->ws); +} diff --git a/src/packages/server/network/IZ_wsserver.h b/src/packages/server/network/IZ_wsserver.h index df1fdc5..7bc4759 100644 --- a/src/packages/server/network/IZ_wsserver.h +++ b/src/packages/server/network/IZ_wsserver.h @@ -4,16 +4,7 @@ #include "libwebsockets.h" #include #include "../IZ_common.h" -#include "IZ_network.h" - -#define RING_COUNT 32 - -/* one of these created for each message */ -typedef struct { - void* payload; /* is malloc'd */ - size_t len; - u8 binary: 1; -} IZ_WSServerMessage; +#include "IZ_websocket.h" /* one of these is created for each client connecting to us */ typedef struct IZ_WSServerSessionData { @@ -32,7 +23,7 @@ typedef struct { struct lws_ring *ring; /* ringbuffer holding unsent messages */ } IZ_WSServerVHostData; -i32 IZ_WSServerCallback( +IZ_ProcedureResult IZ_WSServerCallback( struct lws*, enum lws_callback_reasons, void*, @@ -45,8 +36,24 @@ typedef struct { const char* origin; const char* default_filename; const char* protocol; -} IZ_WSServerCreateContextParams; +} IZ_WSServerInitializeParams; + +typedef struct { + i32 log_level; + u16 port; +} IZ_WSServerConfig; + +typedef struct { + IZ_WSServerConfig config; + IZ_Websocket ws; +} IZ_WSServerState; + +IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState*, IZ_WSServerInitializeParams); + +IZ_ProcedureResult IZ_WSServerHandle(IZ_WSServerState*); + +void IZ_WSServerTeardown(IZ_WSServerState*); -IZ_ProcedureResult IZ_WSServerCreateContext(struct lws_context**, IZ_WSServerCreateContextParams); +void IZ_WSServerCancelService(IZ_WSServerState*); #endif