From abf5ede03ebb2acef768b64304fa859fab0b714c Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Sun, 12 Jun 2022 11:17:11 +0800 Subject: [PATCH] Add Websockets server Websockets server is for game networking. --- CMakeLists.txt | 96 ++++++++++++++++++++++++++------- README.md | 37 +++++++------ dependencies.txt | 1 + src/packages/game/IZ_common.h | 2 +- src/packages/game/main.c | 3 +- src/packages/server/IZ_common.h | 1 + src/packages/server/main.c | 95 ++++++++++++++++++++++++++++++++ 7 files changed, 195 insertions(+), 40 deletions(-) create mode 120000 src/packages/server/IZ_common.h create mode 100644 src/packages/server/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b2be4b..a37f989 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,14 @@ project(izanagi C) set(CMAKE_C_STANDARD 11) +if (WIN32) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(PROJECT_ARCH x64) + else () + set(PROJECT_ARCH x86) + endif () +endif () + include_directories( "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" @@ -12,31 +20,27 @@ include_directories( "${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common" "${PROJECT_SOURCE_DIR}/dependencies/spine-runtimes/spine-c/spine-c/include" "${PROJECT_SOURCE_DIR}/dependencies/getopt-for-windows" + "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/include" + "${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/include" ) -if (WIN32) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PROJECT_ARCH x64) - else () - set(PROJECT_ARCH x86) - endif () -endif () - link_directories( "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}" "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release" + "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/lib/Release" + "${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/lib" ) add_executable( game dependencies/minIni/dev/minIni.h dependencies/minIni/dev/minIni.c - dependencies/getopt-for-windows/getopt.h - dependencies/getopt-for-windows/getopt.c + dependencies/getopt-for-windows/getopt.h + dependencies/getopt-for-windows/getopt.c src/packages/game/output/IZ_video.h src/packages/game/output/IZ_video.c src/packages/game/IZ_common.h - src/packages/game/input/IZ_action.h + src/packages/game/input/IZ_action.h src/packages/game/IZ_app.h src/packages/game/IZ_app.c src/packages/game/main.c @@ -46,7 +50,27 @@ add_executable( src/packages/game/input/IZ_keyboard.h src/packages/game/IZ_config.c src/packages/game/IZ_config.h - src/packages/game/geometry/IZ_point2d.c src/packages/game/geometry/IZ_point2d.h src/packages/game/geometry/IZ_vector2d.c src/packages/game/geometry/IZ_vector2d.h src/packages/game/geometry/IZ_rect.c src/packages/game/geometry/IZ_rect.h src/packages/game/core/IZ_object.c src/packages/game/core/IZ_object.h src/packages/game/core/IZ_creature.c src/packages/game/core/IZ_creature.h src/packages/game/core/IZ_entity.c src/packages/game/core/IZ_entity.h src/packages/game/memory/IZ_pool.c src/packages/game/memory/IZ_pool.h src/packages/game/input/IZ_input.c src/packages/game/input/IZ_input.h src/packages/game/input/IZ_midi.c src/packages/game/input/IZ_midi.h src/packages/game/data/IZ_list.c src/packages/game/data/IZ_list.h) + src/packages/game/geometry/IZ_point2d.c + src/packages/game/geometry/IZ_point2d.h + src/packages/game/geometry/IZ_vector2d.c + src/packages/game/geometry/IZ_vector2d.h + src/packages/game/geometry/IZ_rect.c + src/packages/game/geometry/IZ_rect.h + src/packages/game/core/IZ_object.c + src/packages/game/core/IZ_object.h + src/packages/game/core/IZ_creature.c + src/packages/game/core/IZ_creature.h + src/packages/game/core/IZ_entity.c + src/packages/game/core/IZ_entity.h + src/packages/game/memory/IZ_pool.c + src/packages/game/memory/IZ_pool.h + src/packages/game/input/IZ_input.c + src/packages/game/input/IZ_input.h + src/packages/game/input/IZ_midi.c + src/packages/game/input/IZ_midi.h + src/packages/game/data/IZ_list.c + src/packages/game/data/IZ_list.h +) target_link_libraries( game @@ -67,7 +91,8 @@ add_executable( src/packages/game/geometry/IZ_rect.c src/packages/game/geometry/IZ_vector2d.h src/packages/game/geometry/IZ_vector2d.c - src/packages/game/geometry/geometry.test.c) + src/packages/game/geometry/geometry.test.c +) add_executable( game-test-input @@ -96,7 +121,6 @@ add_executable( src/packages/game/input/input.test.c ) - add_executable( game-test-output dependencies/bdd-for-c/bdd-for-c.h @@ -122,7 +146,10 @@ add_executable( src/packages/game/memory/IZ_pool.h src/packages/game/memory/IZ_pool.c - src/packages/game/memory/memory.test.c src/packages/game/data/IZ_list.c src/packages/game/data/IZ_list.h) + src/packages/game/memory/memory.test.c + src/packages/game/data/IZ_list.c + src/packages/game/data/IZ_list.h +) add_executable( game-test-data @@ -130,20 +157,49 @@ add_executable( src/packages/test/IZ_mock.h src/packages/test/IZ_test.h - src/packages/game/data/IZ_list.h - src/packages/game/data/IZ_list.c - src/packages/game/data/data.test.c) + src/packages/game/data/IZ_list.h + src/packages/game/data/IZ_list.c + src/packages/game/data/data.test.c +) + +add_executable( + server + dependencies/minIni/dev/minIni.h + dependencies/minIni/dev/minIni.c + src/packages/server/IZ_common.h + src/packages/server/main.c +) + +target_link_libraries( + server + libcrypto + libssl + websockets +) if (WIN32) add_custom_command(TARGET game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}/SDL2.dll" # <--this is in-file $) # <--this is out-file path -endif () -if (WIN32) add_custom_command(TARGET game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release/portmidi.dll" # <--this is in-file $) # <--this is out-file path + + add_custom_command(TARGET server POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." + "${PROJECT_SOURCE_DIR}/dependencies/libwebsockets/build/bin/Release/websockets.dll" # <--this is in-file + $) # <--this is out-file path + + add_custom_command(TARGET server POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." + "${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/bin/libssl-1_1-x64.dll" # <--this is in-file + $) # <--this is out-file path + + add_custom_command(TARGET server POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." + "${PROJECT_SOURCE_DIR}/dependencies/openssl/${PROJECT_ARCH}/bin/libcrypto-1_1-x64.dll" # <--this is in-file + $) # <--this is out-file path endif () diff --git a/README.md b/README.md index a08e21d..4ff7ba6 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,20 @@ -# sdl2-hello-world - -A beginner template for SDL2 powered by CMake. - -## Setup - -1. Clone this repo. -2. Download the **SDL2 Development Libraries** from the [official download page](https://www.libsdl.org/download-2.0.php). - - For Windows - 1. Unpack the **MSVC** archive under `dependencies` folder in this project's root. - 2. Rename the directory as `SDL2`. - - For macOS - - `TODO` - - _Alternatively, on Windows, you can link the external libraries via symlink._ -3. Build via CMake. +# sdl2-hello-world + +A beginner template for SDL2 powered by CMake. + +## Setup + +1. Clone this repo. +2. Download the **SDL2 Development Libraries** from the [official download page](https://www.libsdl.org/download-2.0.php). + - For Windows + 1. Unpack the **MSVC** archive under `dependencies` folder in this project's root. + 2. Rename the directory as `SDL2`. + - For macOS + + `TODO` + + _Alternatively, on Windows, you can link the external libraries via symlink._ +3. Build the following dependencies first: + - `portmidi` + - `libwebsockets` (follow the [instructions on building LWS](https://libwebsockets.org/lws-api-doc-master/html/md_README_8build.html)) +4. Build via CMake. diff --git a/dependencies.txt b/dependencies.txt index e082b10..6c94729 100644 --- a/dependencies.txt +++ b/dependencies.txt @@ -3,3 +3,4 @@ https://github.com/grassator/bdd-for-c https://github.com/PortMidi/portmidi https://github.com/EsotericSoftware/spine-runtimes https://github.com/Chunde/getopt-for-windows +https://libwebsockets.org/repo/libwebsockets diff --git a/src/packages/game/IZ_common.h b/src/packages/game/IZ_common.h index d1448e2..a36086b 100644 --- a/src/packages/game/IZ_common.h +++ b/src/packages/game/IZ_common.h @@ -18,6 +18,6 @@ typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; -typedef u8 IZ_ProcedureResult; +typedef i32 IZ_ProcedureResult; #endif diff --git a/src/packages/game/main.c b/src/packages/game/main.c index 5191331..907d3d6 100644 --- a/src/packages/game/main.c +++ b/src/packages/game/main.c @@ -1,7 +1,6 @@ -#include #include "IZ_app.h" -int main(int arg_count, char* arg_values[]) { +IZ_ProcedureResult main(i32 arg_count, char* arg_values[]) { IZ_App app; return IZ_AppRun(&app, arg_count, arg_values); } diff --git a/src/packages/server/IZ_common.h b/src/packages/server/IZ_common.h new file mode 120000 index 0000000..8bb3059 --- /dev/null +++ b/src/packages/server/IZ_common.h @@ -0,0 +1 @@ +E:/Projects/Games/izanagi/src/packages/game/IZ_common.h \ No newline at end of file diff --git a/src/packages/server/main.c b/src/packages/server/main.c new file mode 100644 index 0000000..cb1490d --- /dev/null +++ b/src/packages/server/main.c @@ -0,0 +1,95 @@ +#include +#include +#include "IZ_common.h" + +static struct lws_protocols protocols[] = { + { "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0}, + LWS_PROTOCOL_LIST_TERM +}; + +static const lws_retry_bo_t retry = { + .secs_since_valid_ping = 3, + .secs_since_valid_hangup = 10, +}; + +static i32 interrupted; + +static const struct lws_http_mount mount = { + /* .mount_next */ NULL, /* linked-list "next" */ + /* .mountpoint */ "/", /* mountpoint URL */ + /* .origin */ "./mount-origin", /* serve from dir */ + /* .def */ "index.html", /* default filename */ + /* .protocol */ NULL, + /* .cgienv */ NULL, + /* .extra_mimetypes */ NULL, + /* .interpret */ NULL, + /* .cgi_timeout */ 0, + /* .cache_max_age */ 0, + /* .auth_mask */ 0, + /* .cache_reusable */ 0, + /* .cache_revalidate */ 0, + /* .cache_intermediaries */ 0, + /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ + /* .mountpoint_len */ 1, /* char count */ + /* .basic_auth_login_file */ NULL, +}; + +void sigint_handler(i32 sig) { + interrupted = 1; +} + +IZ_ProcedureResult main(i32 arg_count, char* arg_values[]) { + struct lws_context_creation_info info; + struct lws_context* context; + const char* p; + i32 n = 0; + i32 logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(arg_count, arg_values, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal ws server | visit http://localhost:7681 (-s = use TLS / https)\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = 7681; + info.mounts = &mount; + info.protocols = protocols; + info.vhost_name = "localhost"; +#if defined(LWS_WITH_PLUGINS) + info.pvo = &pvo; +#endif + info.options = + LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + +#if defined(LWS_WITH_TLS) + if (lws_cmdline_option(arg_count, arg_values, "-s")) { + lwsl_user("Server using TLS\n"); + info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.ssl_cert_filepath = "localhost-100y.cert"; + info.ssl_private_key_filepath = "localhost-100y.key"; + } +#endif + + if (lws_cmdline_option(arg_count, arg_values, "-h")) + info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; + + if (lws_cmdline_option(arg_count, arg_values, "-v")) + info.retry_and_idle_policy = &retry; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + + return 0; +}