@@ -27,6 +27,7 @@ include_directories( | |||||
"${PROJECT_SOURCE_DIR}/dependencies/getopt-for-windows" | "${PROJECT_SOURCE_DIR}/dependencies/getopt-for-windows" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/include" | "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/include" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/include" | "${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/include" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/sqlite" | |||||
) | ) | ||||
link_directories( | link_directories( | ||||
@@ -183,6 +184,8 @@ add_executable( | |||||
add_executable( | add_executable( | ||||
server | server | ||||
# dependencies/sqlite/sqlite3.h | |||||
# dependencies/sqlite/sqlite3.c | |||||
dependencies/minIni/dev/minIni.h | dependencies/minIni/dev/minIni.h | ||||
dependencies/minIni/dev/minIni.c | dependencies/minIni/dev/minIni.c | ||||
src/packages/server/IZ_common.h | src/packages/server/IZ_common.h | ||||
@@ -197,7 +200,7 @@ add_executable( | |||||
src/packages/server/net/svc/IZ_wsserver.h | src/packages/server/net/svc/IZ_wsserver.h | ||||
src/packages/server/net/core/IZ_websocket.h | src/packages/server/net/core/IZ_websocket.h | ||||
src/packages/server/net/core/IZ_websocket.c | src/packages/server/net/core/IZ_websocket.c | ||||
) | |||||
src/packages/server/net/IZ_net.c src/packages/server/net/IZ_net.h) | |||||
target_link_libraries( | target_link_libraries( | ||||
server | server | ||||
@@ -4,3 +4,4 @@ https://github.com/PortMidi/portmidi | |||||
https://github.com/EsotericSoftware/spine-runtimes | https://github.com/EsotericSoftware/spine-runtimes | ||||
https://github.com/Chunde/getopt-for-windows | https://github.com/Chunde/getopt-for-windows | ||||
https://libwebsockets.org/repo/libwebsockets | https://libwebsockets.org/repo/libwebsockets | ||||
https://www.sqlite.org/download.html (use SQLite amalgamated source code) |
@@ -106,7 +106,7 @@ void IZ_JoystickLoadConfig(IZ_JoystickState(* state)[IZ_PLAYERS], const char* co | |||||
(*state)[player_index].config.control_mapping[control_index] = ini_getl( | (*state)[player_index].config.control_mapping[control_index] = ini_getl( | ||||
control_mapping_section_name, | control_mapping_section_name, | ||||
ACTION_NAMES[control_index], | ACTION_NAMES[control_index], | ||||
IZ_DEFAULT_JOYSTICK_STATE[player_index].config.control_mapping[control_index], | |||||
IZ_JOYSTICK_DEFAULT_STATE[player_index].config.control_mapping[control_index], | |||||
config_path | config_path | ||||
); | ); | ||||
} | } | ||||
@@ -162,7 +162,7 @@ IZ_ProcedureResult IZ_JoystickSaveConfig(IZ_JoystickState(* state)[IZ_PLAYERS], | |||||
} | } | ||||
IZ_ProcedureResult IZ_JoystickInitialize(IZ_JoystickState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) { | IZ_ProcedureResult IZ_JoystickInitialize(IZ_JoystickState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) { | ||||
SDL_memcpy(state, &IZ_DEFAULT_JOYSTICK_STATE, sizeof(IZ_JoystickState)); | |||||
SDL_memcpy(state, &IZ_JOYSTICK_DEFAULT_STATE, sizeof(IZ_JoystickState)); | |||||
IZ_JoystickLoadConfig(state, config_path); | IZ_JoystickLoadConfig(state, config_path); | ||||
if (IZ_JoystickSaveConfig(state, config_path) < 0) { | if (IZ_JoystickSaveConfig(state, config_path) < 0) { | ||||
@@ -29,7 +29,7 @@ typedef struct { | |||||
IZ_JoystickConfig config; | IZ_JoystickConfig config; | ||||
} IZ_JoystickState; | } IZ_JoystickState; | ||||
static const IZ_JoystickState IZ_DEFAULT_JOYSTICK_STATE[IZ_PLAYERS] = { | |||||
static const IZ_JoystickState IZ_JOYSTICK_DEFAULT_STATE[IZ_PLAYERS] = { | |||||
{ | { | ||||
.config = { | .config = { | ||||
.control_mapping = { | .control_mapping = { | ||||
@@ -58,7 +58,7 @@ void IZ_KeyboardLoadConfig(IZ_KeyboardState(* state)[IZ_PLAYERS], const char* co | |||||
ini_gets( | ini_gets( | ||||
keyboard_section_name, | keyboard_section_name, | ||||
ACTION_NAMES[control_index], | ACTION_NAMES[control_index], | ||||
SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_STATE[player_index].config.control_mapping[control_index]), | |||||
SDL_GetKeyName(IZ_KEYBOARD_DEFAULT_STATE[player_index].config.control_mapping[control_index]), | |||||
buffer, | buffer, | ||||
128, | 128, | ||||
config_path | config_path | ||||
@@ -70,7 +70,7 @@ void IZ_KeyboardLoadConfig(IZ_KeyboardState(* state)[IZ_PLAYERS], const char* co | |||||
} | } | ||||
IZ_ProcedureResult IZ_KeyboardInitialize(IZ_KeyboardState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) { | IZ_ProcedureResult IZ_KeyboardInitialize(IZ_KeyboardState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) { | ||||
SDL_memcpy(state, &IZ_DEFAULT_KEYBOARD_STATE, sizeof(IZ_KeyboardState)); | |||||
SDL_memcpy(state, &IZ_KEYBOARD_DEFAULT_STATE, sizeof(IZ_KeyboardState)); | |||||
IZ_KeyboardLoadConfig(state, config_path); | IZ_KeyboardLoadConfig(state, config_path); | ||||
return IZ_KeyboardSaveConfig(state, config_path); | return IZ_KeyboardSaveConfig(state, config_path); | ||||
} | } |
@@ -15,7 +15,7 @@ typedef struct { | |||||
IZ_KeyboardConfig config; | IZ_KeyboardConfig config; | ||||
} IZ_KeyboardState; | } IZ_KeyboardState; | ||||
static const IZ_KeyboardState IZ_DEFAULT_KEYBOARD_STATE[IZ_PLAYERS] = { | |||||
static const IZ_KeyboardState IZ_KEYBOARD_DEFAULT_STATE[IZ_PLAYERS] = { | |||||
{ | { | ||||
.config = { | .config = { | ||||
.control_mapping = { | .control_mapping = { | ||||
@@ -93,7 +93,7 @@ void IZ_MIDIInputLoadConfig(IZ_MIDIInputState(* state)[IZ_PLAYERS], const char* | |||||
ini_gets( | ini_gets( | ||||
control_mapping_section_name, | control_mapping_section_name, | ||||
ACTION_NAMES[control_index], | ACTION_NAMES[control_index], | ||||
IZ_MIDIGetNoteName(IZ_DEFAULT_MIDI_INPUT_STATE[player_index].config.control_mapping[control_index]), | |||||
IZ_MIDIGetNoteName(IZ_MIDI_INPUT_DEFAULT_STATE[player_index].config.control_mapping[control_index]), | |||||
buffer, | buffer, | ||||
128, | 128, | ||||
config_path | config_path | ||||
@@ -113,7 +113,7 @@ IZ_ProcedureResult IZ_MIDIInputInitialize(IZ_MIDIInputState(* state)[IZ_PLAYERS] | |||||
return 1; | return 1; | ||||
} | } | ||||
SDL_memcpy(state, &IZ_DEFAULT_MIDI_INPUT_STATE, sizeof(IZ_MIDIInputState)); | |||||
SDL_memcpy(state, &IZ_MIDI_INPUT_DEFAULT_STATE, sizeof(IZ_MIDIInputState)); | |||||
IZ_MIDIInputLoadConfig(state, config_path); | IZ_MIDIInputLoadConfig(state, config_path); | ||||
if (IZ_MIDIInputSaveConfig(state, config_path)) { | if (IZ_MIDIInputSaveConfig(state, config_path)) { | ||||
return 2; | return 2; | ||||
@@ -35,7 +35,7 @@ typedef struct { | |||||
i32 midi_events_count; | i32 midi_events_count; | ||||
} IZ_MIDIInputState; | } IZ_MIDIInputState; | ||||
static const IZ_MIDIInputState IZ_DEFAULT_MIDI_INPUT_STATE[IZ_PLAYERS] = { | |||||
static const IZ_MIDIInputState IZ_MIDI_INPUT_DEFAULT_STATE[IZ_PLAYERS] = { | |||||
{ | { | ||||
.config = { | .config = { | ||||
.control_mapping = { | .control_mapping = { | ||||
@@ -304,8 +304,8 @@ spec("input") { | |||||
for (u8 i = 4; i < CONTROLS; i += 1) { | for (u8 i = 4; i < CONTROLS; i += 1) { | ||||
it("handles %s action activation", ACTION_NAMES[i]) { | it("handles %s action activation", ACTION_NAMES[i]) { | ||||
e.type = SDL_JOYBUTTONDOWN; | e.type = SDL_JOYBUTTONDOWN; | ||||
e.jbutton.button = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; | |||||
e.jbutton.button = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
action[p] = 0; | action[p] = 0; | ||||
IZ_JoystickHandleEvents(&state, &action, e); | IZ_JoystickHandleEvents(&state, &action, e); | ||||
@@ -317,8 +317,8 @@ spec("input") { | |||||
it("handles %s action deactivation", ACTION_NAMES[i]) { | it("handles %s action deactivation", ACTION_NAMES[i]) { | ||||
e.type = SDL_JOYBUTTONUP; | e.type = SDL_JOYBUTTONUP; | ||||
e.jbutton.button = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; | |||||
e.jbutton.button = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
action[p] = ~0; | action[p] = ~0; | ||||
IZ_JoystickHandleEvents(&state, &action, e); | IZ_JoystickHandleEvents(&state, &action, e); | ||||
@@ -343,7 +343,7 @@ spec("input") { | |||||
before_each() { | before_each() { | ||||
for (u8 p = 0; p < IZ_PLAYERS; p += 1) { | for (u8 p = 0; p < IZ_PLAYERS; p += 1) { | ||||
for (u8 i = 0; i < CONTROLS; i += 1) { | for (u8 i = 0; i < CONTROLS; i += 1) { | ||||
state[p].config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -410,7 +410,7 @@ spec("input") { | |||||
before_each() { | before_each() { | ||||
for (u8 p = 0; p < IZ_PLAYERS; p += 1) { | for (u8 p = 0; p < IZ_PLAYERS; p += 1) { | ||||
for (u8 i = 0; i < CONTROLS; i += 1) { | for (u8 i = 0; i < CONTROLS; i += 1) { | ||||
state[p].config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -458,8 +458,8 @@ spec("input") { | |||||
for (u8 i = 0; i < CONTROLS; i += 1) { | for (u8 i = 0; i < CONTROLS; i += 1) { | ||||
it("handles %s action activation", ACTION_NAMES[i]) { | it("handles %s action activation", ACTION_NAMES[i]) { | ||||
e.type = SDL_KEYDOWN; | e.type = SDL_KEYDOWN; | ||||
e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; | |||||
e.key.keysym.sym = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
action[p] = 0; | action[p] = 0; | ||||
IZ_KeyboardHandleEvents(&state, &action, e); | IZ_KeyboardHandleEvents(&state, &action, e); | ||||
@@ -471,8 +471,8 @@ spec("input") { | |||||
it("handles %s action deactivation", ACTION_NAMES[i]) { | it("handles %s action deactivation", ACTION_NAMES[i]) { | ||||
e.type = SDL_KEYUP; | e.type = SDL_KEYUP; | ||||
e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; | |||||
e.key.keysym.sym = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
action[p] = ~0; | action[p] = ~0; | ||||
IZ_KeyboardHandleEvents(&state, &action, e); | IZ_KeyboardHandleEvents(&state, &action, e); | ||||
@@ -496,7 +496,7 @@ spec("input") { | |||||
before_each() { | before_each() { | ||||
for (u8 p = 0; p < IZ_PLAYERS; p += 1) { | for (u8 p = 0; p < IZ_PLAYERS; p += 1) { | ||||
for (u8 i = 0; i < CONTROLS; i += 1) { | for (u8 i = 0; i < CONTROLS; i += 1) { | ||||
state[p].config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[p].config.control_mapping[i]; | |||||
state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -653,8 +653,8 @@ spec("input") { | |||||
describe("on player %u", p) { | describe("on player %u", p) { | ||||
for (u8 i = 0; i < CONTROLS; i += 1) { | for (u8 i = 0; i < CONTROLS; i += 1) { | ||||
it("handles %s action activation", ACTION_NAMES[i]) { | it("handles %s action activation", ACTION_NAMES[i]) { | ||||
e.message = IZ_MIDI_NOTE_ON | (IZ_DEFAULT_MIDI_INPUT_STATE[p].config.control_mapping[i] << 8); | |||||
state[p].config.control_mapping[i] = IZ_DEFAULT_MIDI_INPUT_STATE[p].config.control_mapping[i]; | |||||
e.message = IZ_MIDI_NOTE_ON | (IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i] << 8); | |||||
state[p].config.control_mapping[i] = IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
action[p] = 0; | action[p] = 0; | ||||
IZ_MIDIInputHandleEvents(&state, &action, e); | IZ_MIDIInputHandleEvents(&state, &action, e); | ||||
@@ -665,8 +665,8 @@ spec("input") { | |||||
} | } | ||||
it("handles %s action deactivation", ACTION_NAMES[i]) { | it("handles %s action deactivation", ACTION_NAMES[i]) { | ||||
e.message = IZ_MIDI_NOTE_OFF | (IZ_DEFAULT_MIDI_INPUT_STATE[p].config.control_mapping[i] << 8); | |||||
state[p].config.control_mapping[i] = IZ_DEFAULT_MIDI_INPUT_STATE[p].config.control_mapping[i]; | |||||
e.message = IZ_MIDI_NOTE_OFF | (IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i] << 8); | |||||
state[p].config.control_mapping[i] = IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i]; | |||||
action[p] = ~0; | action[p] = ~0; | ||||
IZ_MIDIInputHandleEvents(&state, &action, e); | IZ_MIDIInputHandleEvents(&state, &action, e); | ||||
@@ -19,9 +19,38 @@ void IZ_WebsocketTeardown(IZ_Websocket* ws) { | |||||
ws->context = NULL; | ws->context = NULL; | ||||
} | } | ||||
void IZ_WebsocketDestroyMessage(void* msg_raw) { | |||||
IZ_WebsocketMessage* msg = msg_raw; | |||||
void IZ_WebsocketDestroyMessage(IZ_WebsocketMessage* msg) { | |||||
free(msg->payload); | free(msg->payload); | ||||
msg->payload = NULL; | msg->payload = NULL; | ||||
msg->len = 0; | msg->len = 0; | ||||
} | } | ||||
IZ_ProcedureResult IZ_WebsocketCreateBinaryMessage(struct lws* wsi, IZ_WebsocketMessage* amsg, void* in, size_t len) { | |||||
/* notice we over-allocate by LWS_PRE */ | |||||
amsg->payload = malloc(LWS_PRE + len); | |||||
if (!amsg->payload) { | |||||
return -1; | |||||
} | |||||
amsg->first = (u8) lws_is_first_fragment(wsi); | |||||
amsg->final = (u8) lws_is_final_fragment(wsi); | |||||
amsg->binary = true; | |||||
amsg->len = len; | |||||
memcpy((char*) amsg->payload + LWS_PRE, in, len); | |||||
return 0; | |||||
} | |||||
IZ_ProcedureResult IZ_WebsocketCreateTextMessage(struct lws* wsi, IZ_WebsocketMessage* amsg, void* in, size_t len) { | |||||
/* notice we over-allocate by LWS_PRE */ | |||||
amsg->payload = malloc(LWS_PRE + len); | |||||
if (!amsg->payload) { | |||||
return -1; | |||||
} | |||||
amsg->first = (u8) lws_is_first_fragment(wsi); | |||||
amsg->final = (u8) lws_is_final_fragment(wsi); | |||||
amsg->binary = false; | |||||
amsg->len = len; | |||||
memcpy((char*) amsg->payload + LWS_PRE, in, len); | |||||
return 0; | |||||
} |
@@ -9,16 +9,17 @@ | |||||
/* one of these created for each message */ | /* one of these created for each message */ | ||||
typedef struct { | typedef struct { | ||||
u8 binary: 1; | |||||
void* payload; /* is malloc'd */ | |||||
size_t len; | size_t len; | ||||
u8 binary: 1; | |||||
u8 first: 1; | u8 first: 1; | ||||
u8 final: 1; | u8 final: 1; | ||||
void* payload; /* is malloc'd */ | |||||
} IZ_WebsocketMessage; | } IZ_WebsocketMessage; | ||||
typedef struct { | typedef struct { | ||||
struct lws_context* context; | struct lws_context* context; | ||||
struct lws* connection; | struct lws* connection; | ||||
void* user_data; | |||||
u8 interrupted: 1; | u8 interrupted: 1; | ||||
} IZ_Websocket; | } IZ_Websocket; | ||||
@@ -28,7 +29,11 @@ IZ_ProcedureResult IZ_WebsocketHandle(IZ_Websocket*); | |||||
void IZ_WebsocketTeardown(IZ_Websocket*); | void IZ_WebsocketTeardown(IZ_Websocket*); | ||||
void IZ_WebsocketDestroyMessage(void*); | |||||
IZ_ProcedureResult IZ_WebsocketCreateBinaryMessage(struct lws*, IZ_WebsocketMessage*, void*, size_t); | |||||
IZ_ProcedureResult IZ_WebsocketCreateTextMessage(struct lws*, IZ_WebsocketMessage*, void*, size_t); | |||||
void IZ_WebsocketDestroyMessage(IZ_WebsocketMessage*); | |||||
void IZ_WebsocketCancelService(IZ_Websocket*); | void IZ_WebsocketCancelService(IZ_Websocket*); | ||||
@@ -3,8 +3,8 @@ | |||||
static IZ_App* global_app; | static IZ_App* global_app; | ||||
void IZ_AppHandleSignal(i32 _signal) { | void IZ_AppHandleSignal(i32 _signal) { | ||||
global_app->server.ws.interrupted = true; | |||||
IZ_WSServerCancelService(&global_app->server); | |||||
global_app->net_state.ws.interrupted = true; | |||||
IZ_WSServerCancelService(&global_app->net_state.ws); | |||||
} | } | ||||
IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { | IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { | ||||
@@ -24,7 +24,7 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App *app, u8 argc, const char **argv) { | |||||
IZ_ConfigGetDefaultPath(config_path, 128); | IZ_ConfigGetDefaultPath(config_path, 128); | ||||
} | } | ||||
if (IZ_WSServerInitialize(&app->server, app, config_path, argc, argv)) { | |||||
if (IZ_NetInitialize(&app->net_state, app, config_path, argc, argv)) { | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -36,19 +36,25 @@ IZ_ProcedureResult IZ_AppRun(IZ_App *app, u8 argc, const char **argv) { | |||||
return -1; | return -1; | ||||
} | } | ||||
if (IZ_WSServerInitialize(&app->net_state.ws, (IZ_WSServerInitializeParams) { | |||||
.port = app->net_state.config.port, | |||||
})) { | |||||
return -1; | |||||
} | |||||
i32 result = 0; | i32 result = 0; | ||||
while (true) { | while (true) { | ||||
if (IZ_WSServerHandle(&app->server)) { | |||||
if (IZ_WSServerHandle(&app->net_state.ws)) { | |||||
result = -1; | result = -1; | ||||
break; | break; | ||||
} | } | ||||
if (app->server.ws.interrupted) { | |||||
if (app->net_state.ws.interrupted) { | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
IZ_WSServerTeardown(&app->server); | |||||
IZ_WSServerTeardown(&app->net_state.ws); | |||||
lwsl_user("Server closed. Bye!\n"); | lwsl_user("Server closed. Bye!\n"); | ||||
return result; | return result; | ||||
} | } | ||||
@@ -276,17 +282,17 @@ IZ_ProcedureResult IZ_WSServerOnReceive(struct lws* wsi, void* in, size_t len) { | |||||
lwsl_user("LWS_CALLBACK_RECEIVE: free space %d\n", n); | lwsl_user("LWS_CALLBACK_RECEIVE: free space %d\n", n); | ||||
IZ_WebsocketMessage amsg; | IZ_WebsocketMessage amsg; | ||||
amsg.len = len; | |||||
/* notice we over-allocate by LWS_PRE... */ | |||||
amsg.payload = malloc(LWS_PRE + len); | |||||
amsg.binary = (u8) lws_frame_is_binary(wsi); | |||||
if (!amsg.payload) { | |||||
const u8 result = ( | |||||
lws_frame_is_binary(wsi) | |||||
? IZ_WebsocketCreateBinaryMessage(wsi, &amsg, in, len) | |||||
: IZ_WebsocketCreateTextMessage(wsi, &amsg, in, len) | |||||
); | |||||
if (result) { | |||||
lwsl_user("OOM: dropping\n"); | lwsl_user("OOM: dropping\n"); | ||||
return 1; | return 1; | ||||
} | } | ||||
/* ...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)) { | if (!lws_ring_insert(vhd->ring, &amsg, 1)) { | ||||
IZ_WebsocketDestroyMessage(&amsg); | IZ_WebsocketDestroyMessage(&amsg); | ||||
lwsl_user("dropping!\n"); | lwsl_user("dropping!\n"); | ||||
@@ -7,9 +7,10 @@ | |||||
#include "log/IZ_log.h" | #include "log/IZ_log.h" | ||||
#include "IZ_common.h" | #include "IZ_common.h" | ||||
#include "IZ_config.h" | #include "IZ_config.h" | ||||
#include "net/IZ_net.h" | |||||
typedef struct { | typedef struct { | ||||
IZ_WSServerState server; | |||||
IZ_NetState net_state; | |||||
} IZ_App; | } IZ_App; | ||||
IZ_ProcedureResult IZ_AppRun(IZ_App*, u8, const char**); | IZ_ProcedureResult IZ_AppRun(IZ_App*, u8, const char**); | ||||
@@ -0,0 +1,64 @@ | |||||
#include "IZ_net.h" | |||||
void IZ_NetLoadConfig(IZ_NetState* state, const char* config_path) { | |||||
char buffer[128]; | |||||
ini_gets("Network", "Name", IZ_APP_NAME, buffer, 128, config_path); | |||||
memcpy_s(state->config.name, 64, buffer, 64); | |||||
ini_gets("Network", "Motd", "", buffer, 128, config_path); | |||||
memcpy_s(state->config.motd, 128, buffer, 128); | |||||
state->config.port = ini_getl("Network", "Port", IZ_NET_DEFAULT_STATE.config.port, config_path); | |||||
} | |||||
IZ_ProcedureResult IZ_NetSaveConfig(IZ_NetState* state, const char* config_path) { | |||||
if (!ini_puts("Network", "Name", state->config.name, config_path)) { | |||||
return -1; | |||||
} | |||||
if (!ini_puts("Network", "Motd", state->config.motd, config_path)) { | |||||
return -1; | |||||
} | |||||
if (!ini_putl("Network", "Port", state->config.port, config_path)) { | |||||
return -1; | |||||
} | |||||
return 0; | |||||
} | |||||
void IZ_NetOverrideConfig(IZ_NetState* state, u8 argc, const char* argv[]) { | |||||
const char* cmdline_buffer; | |||||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-p"))) { | |||||
state->config.port = atoi(cmdline_buffer); | |||||
} | |||||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-n"))) { | |||||
memcpy_s(state->config.name, 64, cmdline_buffer, 128); | |||||
} | |||||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-m"))) { | |||||
memcpy_s(state->config.motd, 128, cmdline_buffer, 128); | |||||
} | |||||
} | |||||
IZ_ProcedureResult IZ_NetInitialize( | |||||
IZ_NetState* state, | |||||
void* user_data, | |||||
const char* config_path, | |||||
u8 argc, | |||||
const char* argv[] | |||||
) { | |||||
memcpy_s(state, sizeof(IZ_NetState), &IZ_NET_DEFAULT_STATE, sizeof(IZ_NetState)); | |||||
IZ_NetLoadConfig(state, config_path); | |||||
if (IZ_NetSaveConfig(state, config_path) < 0) { | |||||
return -1; | |||||
} | |||||
IZ_NetOverrideConfig(state, argc, argv); | |||||
if (!user_data) { | |||||
return -2; | |||||
} | |||||
state->ws.user_data = user_data; | |||||
return 0; | |||||
} |
@@ -0,0 +1,38 @@ | |||||
#ifndef IZ_NET_H | |||||
#define IZ_NET_H | |||||
#include <minIni.h> | |||||
#include "../IZ_common.h" | |||||
#include "../IZ_config.h" | |||||
#include "core/IZ_websocket.h" | |||||
typedef struct { | |||||
u16 port; | |||||
char name[64]; | |||||
char motd[128]; | |||||
} IZ_NetConfig; | |||||
typedef struct { | |||||
IZ_NetConfig config; | |||||
IZ_Websocket ws; | |||||
} IZ_NetState; | |||||
static IZ_NetState IZ_NET_DEFAULT_STATE = { | |||||
.config = { | |||||
.port = 42069, | |||||
.name = IZ_APP_NAME, | |||||
.motd = "", | |||||
}, | |||||
.ws = { | |||||
.interrupted = false, | |||||
.context = NULL, | |||||
.connection = NULL, | |||||
.user_data = NULL, | |||||
}, | |||||
}; | |||||
IZ_ProcedureResult IZ_NetInitialize(IZ_NetState*, void*, const char*, u8, const char**); | |||||
IZ_ProcedureResult IZ_NetSaveConfig(IZ_NetState*, const char*); | |||||
#endif |
@@ -30,24 +30,6 @@ IZ_ProcedureResult IZ_WSServerCallback( | |||||
return 0; | return 0; | ||||
} | } | ||||
void IZ_WSServerLoadConfig(IZ_WSServerState* state, const char* config_path, u8 argc, const char* argv[]) { | |||||
// TODO unify loading of config from cmdline and config file | |||||
memcpy_s(state, sizeof(IZ_WSServerState), &IZ_DEFAULT_STATE, sizeof(IZ_WSServerState)); | |||||
const char *cmdline_buffer; | |||||
// if ((cmdline_buffer = lws_cmdline_option(argc, argv, "-d"))) { | |||||
// state->config.log_level = atoi(cmdline_buffer); | |||||
// } | |||||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-p"))) { | |||||
state->config.port = atoi(cmdline_buffer); | |||||
} | |||||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-n"))) { | |||||
memcpy_s(state->config.server_name, 64, cmdline_buffer, 64); | |||||
} | |||||
} | |||||
const char* IZ_WSServerTestPath(const char* base_dir, const char* file) { | const char* IZ_WSServerTestPath(const char* base_dir, const char* file) { | ||||
static char test_path[32]; | static char test_path[32]; | ||||
sprintf_s(test_path, 32, "%s/%s", base_dir, file); | sprintf_s(test_path, 32, "%s/%s", base_dir, file); | ||||
@@ -59,20 +41,10 @@ const char* IZ_WSServerTestPath(const char* base_dir, const char* file) { | |||||
return NULL; | return NULL; | ||||
} | } | ||||
IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState* state, void* userdata, const char* config_path, u8 argc, const char* argv[]) { | |||||
IZ_WSServerLoadConfig(state, config_path, argc, argv); | |||||
state->userdata = userdata; | |||||
IZ_ProcedureResult IZ_WSServerInitialize(IZ_Websocket* state, IZ_WSServerInitializeParams params) { | |||||
struct lws_context_creation_info info; | struct lws_context_creation_info info; | ||||
memset(&info, 0, sizeof info); | memset(&info, 0, sizeof info); | ||||
info.port = state->config.port; | |||||
// char server_string[64]; | |||||
// if (*state->config.server_name) { | |||||
// sprintf_s(server_string, 64, "%s Dedicated Server [%s]", IZ_APP_NAME, state->config.server_name); | |||||
// } else { | |||||
// sprintf_s(server_string, 64, "%s Dedicated Server", IZ_APP_NAME, state->config.server_name); | |||||
// } | |||||
// info.server_string = server_string; | |||||
info.port = params.port; | |||||
const char* origin = "./public"; | const char* origin = "./public"; | ||||
struct stat stats; | struct stat stats; | ||||
@@ -143,7 +115,7 @@ IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState* state, void* userdata | |||||
"port", /* pvo name */ | "port", /* pvo name */ | ||||
NULL /* pvo value */ | NULL /* pvo value */ | ||||
}; | }; | ||||
pvo_port.value = (void*) &state->config.port; | |||||
pvo_port.value = (void*) ¶ms.port; | |||||
static struct lws_protocol_vhost_options pvo_app = { | static struct lws_protocol_vhost_options pvo_app = { | ||||
&pvo_port, | &pvo_port, | ||||
@@ -151,7 +123,7 @@ IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState* state, void* userdata | |||||
"app", | "app", | ||||
NULL, | NULL, | ||||
}; | }; | ||||
pvo_app.value = state->userdata; | |||||
pvo_app.value = state->user_data; | |||||
static const struct lws_protocol_vhost_options pvo = { | static const struct lws_protocol_vhost_options pvo = { | ||||
NULL, /* "next" pvo linked-list */ | NULL, /* "next" pvo linked-list */ | ||||
@@ -165,23 +137,23 @@ IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState* state, void* userdata | |||||
| LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE | | LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE | ||||
); | ); | ||||
IZ_WebsocketInitialize(&state->ws); | |||||
state->ws.context = lws_create_context(&info); | |||||
if (!state->ws.context) { | |||||
IZ_WebsocketInitialize(state); | |||||
state->context = lws_create_context(&info); | |||||
if (!state->context) { | |||||
return -1; | return -1; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
IZ_ProcedureResult IZ_WSServerHandle(IZ_WSServerState* state) { | |||||
return IZ_WebsocketHandle(&state->ws); | |||||
IZ_ProcedureResult IZ_WSServerHandle(IZ_Websocket* state) { | |||||
return IZ_WebsocketHandle(state); | |||||
} | } | ||||
void IZ_WSServerTeardown(IZ_WSServerState* state) { | |||||
IZ_WebsocketTeardown(&state->ws); | |||||
void IZ_WSServerTeardown(IZ_Websocket* state) { | |||||
IZ_WebsocketTeardown(state); | |||||
} | } | ||||
void IZ_WSServerCancelService(IZ_WSServerState* state) { | |||||
IZ_WebsocketCancelService(&state->ws); | |||||
void IZ_WSServerCancelService(IZ_Websocket* state) { | |||||
IZ_WebsocketCancelService(state); | |||||
} | } |
@@ -22,45 +22,26 @@ typedef struct IZ_WSServerSessionData { | |||||
/* one of these is created for each vhost our protocol is used with */ | /* one of these is created for each vhost our protocol is used with */ | ||||
typedef struct { | typedef struct { | ||||
struct lws_context *context; | |||||
struct lws_vhost *vhost; | |||||
const struct lws_protocols *protocol; | |||||
IZ_WSServerSessionData *pss_list; /* linked-list of live pss*/ | |||||
struct lws_ring *ring; /* ringbuffer holding unsent messages */ | |||||
struct lws_context* context; | |||||
struct lws_vhost* vhost; | |||||
const struct lws_protocols* protocol; | |||||
IZ_WSServerSessionData* pss_list; /* linked-list of live pss*/ | |||||
struct lws_ring* ring; /* ringbuffer holding unsent messages */ | |||||
u16* port; | u16* port; | ||||
const void* app; | const void* app; | ||||
} IZ_WSServerVHostData; | } IZ_WSServerVHostData; | ||||
typedef struct { | typedef struct { | ||||
u16 port; | u16 port; | ||||
char server_name[64]; | |||||
} IZ_WSServerInitializeParams; | } IZ_WSServerInitializeParams; | ||||
typedef struct { | |||||
IZ_WSServerInitializeParams config; | |||||
void* userdata; | |||||
IZ_Websocket ws; | |||||
} IZ_WSServerState; | |||||
static IZ_WSServerState IZ_DEFAULT_STATE = { | |||||
.config = { | |||||
.port = 42069, | |||||
.server_name = NULL, | |||||
}, | |||||
.userdata = NULL, | |||||
.ws = { | |||||
.interrupted = false, | |||||
.context = NULL, | |||||
}, | |||||
}; | |||||
IZ_ProcedureResult IZ_WSServerInitialize(IZ_WSServerState*, void*, const char*, u8, const char**); | |||||
IZ_ProcedureResult IZ_WSServerHandle(IZ_WSServerState*); | |||||
void IZ_WSServerTeardown(IZ_WSServerState*); | |||||
void IZ_WSServerCancelService(IZ_WSServerState*); | |||||
IZ_ProcedureResult IZ_WSServerInitialize(IZ_Websocket*, IZ_WSServerInitializeParams); | |||||
IZ_ProcedureResult IZ_WSServerHandle(IZ_Websocket*); | |||||
void IZ_WSServerTeardown(IZ_Websocket*); | |||||
void IZ_WSServerCancelService(IZ_Websocket*); | |||||
IZ_ProcedureResult IZ_WSServerProtocolInitialize(struct lws*, void*); | IZ_ProcedureResult IZ_WSServerProtocolInitialize(struct lws*, void*); | ||||