Browse Source

Implement connectivity

Attempt to connect client to server.
feature/data-structs
TheoryOfNekomata 2 years ago
parent
commit
4e4924ec0b
31 changed files with 755 additions and 398 deletions
  1. +63
    -63
      .gitignore
  2. +18
    -3
      CMakeLists.txt
  3. +48
    -30
      src/packages/game/IZ_app.c
  4. +1
    -1
      src/packages/game/IZ_app.h
  5. +8
    -11
      src/packages/game/input/IZ_input.c
  6. +1
    -1
      src/packages/game/input/IZ_input.h
  7. +17
    -17
      src/packages/game/input/IZ_joystick.c
  8. +3
    -3
      src/packages/game/input/IZ_joystick.h
  9. +8
    -8
      src/packages/game/input/IZ_keyboard.c
  10. +3
    -3
      src/packages/game/input/IZ_keyboard.h
  11. +8
    -69
      src/packages/game/input/IZ_midi.c
  12. +4
    -3
      src/packages/game/input/IZ_midi.h
  13. +32
    -32
      src/packages/game/input/input.test.c
  14. +0
    -6
      src/packages/game/network/IZ_network.h
  15. +28
    -0
      src/packages/game/network/IZ_websocket.c
  16. +34
    -0
      src/packages/game/network/IZ_websocket.h
  17. +274
    -61
      src/packages/game/network/IZ_wsclient.c
  18. +37
    -13
      src/packages/game/network/IZ_wsclient.h
  19. +14
    -14
      src/packages/game/output/IZ_video.c
  20. +2
    -2
      src/packages/game/output/IZ_video.h
  21. +1
    -1
      src/packages/game/output/output.test.c
  22. +62
    -0
      src/packages/game/util/IZ_midi.c
  23. +11
    -0
      src/packages/game/util/IZ_midi.h
  24. +21
    -11
      src/packages/server/IZ_app.c
  25. +3
    -4
      src/packages/server/IZ_app.h
  26. +1
    -2
      src/packages/server/main.c
  27. +0
    -1
      src/packages/server/network/IZ_network.h
  28. +1
    -0
      src/packages/server/network/IZ_websocket.c
  29. +1
    -0
      src/packages/server/network/IZ_websocket.h
  30. +31
    -26
      src/packages/server/network/IZ_wsserver.c
  31. +20
    -13
      src/packages/server/network/IZ_wsserver.h

+ 63
- 63
.gitignore View File

@@ -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/
*.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/

+ 18
- 3
CMakeLists.txt View File

@@ -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(


+ 48
- 30
src/packages/game/IZ_app.c View File

@@ -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;
}



+ 1
- 1
src/packages/game/IZ_app.h View File

@@ -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;


+ 8
- 11
src/packages/game/input/IZ_input.c View File

@@ -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) {


+ 1
- 1
src/packages/game/input/IZ_input.h View File

@@ -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*);



+ 17
- 17
src/packages/game/input/IZ_joystick.c View File

@@ -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();


+ 3
- 3
src/packages/game/input/IZ_joystick.h View File

@@ -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]);



+ 8
- 8
src/packages/game/input/IZ_keyboard.c View File

@@ -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);
}

+ 3
- 3
src/packages/game/input/IZ_keyboard.h View File

@@ -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

+ 8
- 69
src/packages/game/input/IZ_midi.c View File

@@ -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;
}



+ 4
- 3
src/packages/game/input/IZ_midi.h View File

@@ -11,6 +11,7 @@

#include <minIni.h>
#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]);



+ 32
- 32
src/packages/game/input/input.test.c View File

@@ -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."


+ 0
- 6
src/packages/game/network/IZ_network.h View File

@@ -1,6 +0,0 @@
#ifndef IZ_NETWORK_H
#define IZ_NETWORK_H

#define NETWORK_PROTOCOL "izanagi-networking"

#endif

+ 28
- 0
src/packages/game/network/IZ_websocket.c View File

@@ -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;
}

+ 34
- 0
src/packages/game/network/IZ_websocket.h View File

@@ -0,0 +1,34 @@
#ifndef IZ_WEBSOCKET_H
#define IZ_WEBSOCKET_H

#include <libwebsockets.h>
#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

+ 274
- 61
src/packages/game/network/IZ_wsclient.c View File

@@ -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*) &params.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);
}

+ 37
- 13
src/packages/game/network/IZ_wsclient.h View File

@@ -3,28 +3,52 @@

#include <libwebsockets.h>
#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

+ 14
- 14
src/packages/game/output/IZ_video.c View File

@@ -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;


+ 2
- 2
src/packages/game/output/IZ_video.h View File

@@ -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*);



+ 1
- 1
src/packages/game/output/output.test.c View File

@@ -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),


+ 62
- 0
src/packages/game/util/IZ_midi.c View File

@@ -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;
}

+ 11
- 0
src/packages/game/util/IZ_midi.h View File

@@ -0,0 +1,11 @@
#ifndef IZ_UTIL_MIDI_H
#define IZ_UTIL_MIDI_H

#include <stdio.h>
#include <string.h>
#include "../IZ_common.h"

char* IZ_MIDIGetNoteName(u8);
u8 IZ_MIDIGetNoteFromName(char*);

#endif

+ 21
- 11
src/packages/server/IZ_app.c View File

@@ -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;
}

+ 3
- 4
src/packages/server/IZ_app.h View File

@@ -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

+ 1
- 2
src/packages/server/main.c View File

@@ -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);
}

+ 0
- 1
src/packages/server/network/IZ_network.h View File

@@ -1 +0,0 @@
E:/Projects/Games/izanagi/src/packages/game/network/IZ_network.h

+ 1
- 0
src/packages/server/network/IZ_websocket.c View File

@@ -0,0 +1 @@
E:/Projects/Games/izanagi/src/packages/game/network/IZ_websocket.c

+ 1
- 0
src/packages/server/network/IZ_websocket.h View File

@@ -0,0 +1 @@
E:/Projects/Games/izanagi/src/packages/game/network/IZ_websocket.h

+ 31
- 26
src/packages/server/network/IZ_wsserver.c View File

@@ -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);
}

+ 20
- 13
src/packages/server/network/IZ_wsserver.h View File

@@ -4,16 +4,7 @@
#include "libwebsockets.h"
#include <string.h>
#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

Loading…
Cancel
Save