From 597284e28fff7a86cade01f3fca69b76c059c561 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Sun, 9 Jan 2022 19:54:03 -0600 Subject: [PATCH] Game server now reads configuration settings from web server. --- LICENSE | 16 ++ .../plugins/kangaworld-integration/api.php | 7 +- .../kangaworld-integration/api/config.php | 9 + .../kangaworld-integration/{ => api}/user.php | 0 .../plugins/kangaworld-integration/areas.php | 3 - .../kangaworld-integration/collections.php | 11 + .../plugins/kangaworld-integration/index.php | 10 +- kpmpgsmkii.pro | 2 +- server/server.pro | 9 +- server/src/database.c | 111 -------- server/src/main.c | 49 ++-- server/src/rest.c | 259 ++++++++++++++++++ server/src/{database.h => rest.h} | 16 +- 13 files changed, 343 insertions(+), 159 deletions(-) create mode 100644 kanga.world/site/plugins/kangaworld-integration/api/config.php rename kanga.world/site/plugins/kangaworld-integration/{ => api}/user.php (100%) create mode 100644 kanga.world/site/plugins/kangaworld-integration/collections.php delete mode 100644 server/src/database.c create mode 100644 server/src/rest.c rename server/src/{database.h => rest.h} (67%) diff --git a/LICENSE b/LICENSE index 4a316bf..e85ff7d 100644 --- a/LICENSE +++ b/LICENSE @@ -95,11 +95,26 @@ ENet https://github.com/zpl-c/enet MIT +GnuTLS +------ +https://gnutls.org/ +LGPL 2.1 + ini --- https://github.com/rxi/ini MIT +json-c +------ +https://github.com/json-c/json-c +Attribution + +MariaDB Client Library +---------------------- +https://mariadb.org/ +LGPL 2.1 + MemWatch -------- http://www.linkdata.se/sourcecode/memwatch/ @@ -119,3 +134,4 @@ tiny-AES128-C ------------- https://github.com/bonybrown/tiny-AES128-C Unlicense + diff --git a/kanga.world/site/plugins/kangaworld-integration/api.php b/kanga.world/site/plugins/kangaworld-integration/api.php index 0028c2b..719c7c2 100644 --- a/kanga.world/site/plugins/kangaworld-integration/api.php +++ b/kanga.world/site/plugins/kangaworld-integration/api.php @@ -1,6 +1,7 @@ filterBy('type', 'config'); + $response['result'] = 'true'; + $response['reason'] = 'Configuration entries returned.'; +} + +?> diff --git a/kanga.world/site/plugins/kangaworld-integration/user.php b/kanga.world/site/plugins/kangaworld-integration/api/user.php similarity index 100% rename from kanga.world/site/plugins/kangaworld-integration/user.php rename to kanga.world/site/plugins/kangaworld-integration/api/user.php diff --git a/kanga.world/site/plugins/kangaworld-integration/areas.php b/kanga.world/site/plugins/kangaworld-integration/areas.php index d474bf3..bd86b07 100644 --- a/kanga.world/site/plugins/kangaworld-integration/areas.php +++ b/kanga.world/site/plugins/kangaworld-integration/areas.php @@ -1,8 +1,5 @@ __DIR__ . '/classes/KwConfig.php']); - - return [ 'kwconfig' => [ diff --git a/kanga.world/site/plugins/kangaworld-integration/collections.php b/kanga.world/site/plugins/kangaworld-integration/collections.php new file mode 100644 index 0000000..6d782ed --- /dev/null +++ b/kanga.world/site/plugins/kangaworld-integration/collections.php @@ -0,0 +1,11 @@ + function($site) { + return new Collection(KwConfig::list()); + } +]; + +?> diff --git a/kanga.world/site/plugins/kangaworld-integration/index.php b/kanga.world/site/plugins/kangaworld-integration/index.php index cd7b56b..250f073 100644 --- a/kanga.world/site/plugins/kangaworld-integration/index.php +++ b/kanga.world/site/plugins/kangaworld-integration/index.php @@ -1,9 +1,15 @@ __DIR__ . '/classes/KwConfig.php' +]); + + Kirby::plugin('kangaroopunch/kangaworld-integration', [ - 'api' => require __DIR__ . '/api.php', - 'areas' => require __DIR__ . '/areas.php' + 'api' => require __DIR__ . '/api.php', + 'areas' => require __DIR__ . '/areas.php', + 'collections' => require __DIR__ . '/collections.php' ]); diff --git a/kpmpgsmkii.pro b/kpmpgsmkii.pro index 00ff9fd..197a241 100644 --- a/kpmpgsmkii.pro +++ b/kpmpgsmkii.pro @@ -20,7 +20,7 @@ TEMPLATE = subdirs CONFIG *= ORDERED SUBDIRS = \ - client \ +# client \ server # font \ # primes diff --git a/server/server.pro b/server/server.pro index 3facf9a..7edd1cf 100644 --- a/server/server.pro +++ b/server/server.pro @@ -51,9 +51,9 @@ HEADERS = \ $$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.h \ src/client.h \ src/console.h \ - src/database.h \ src/network.h \ src/os.h \ + src/rest.h \ src/server.h SOURCES = \ @@ -68,18 +68,19 @@ SOURCES = \ $$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \ src/client.c \ src/console.c \ - src/database.c \ src/main.c \ src/network.c \ + src/rest.c \ src/server.c LIBS = \ -L/usr/lib/x86_64-linux-gnu/ \ - -lmariadb \ -ldl \ -lm \ -lpthread \ -lgnutls \ - -lcrypt + -lcrypt \ + -lcurl \ + -ljson-c OTHER_FILES = diff --git a/server/src/database.c b/server/src/database.c deleted file mode 100644 index 75c76e8..0000000 --- a/server/src/database.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Kangaroo Punch MultiPlayer Game Server Mark II - * Copyright (C) 2020-2021 Scott Duensing - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -#include -#include - -#include "database.h" - - -#define STATEMENT_MAX 2048 - - -static MYSQL *_sql = NULL; -static char _statement[STATEMENT_MAX]; -static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; - - -uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password) { - uint8_t reconnect = 1; - - if (_sql == NULL) { - _sql = mysql_init(NULL); - mysql_options(_sql, MYSQL_OPT_RECONNECT, (const void *)&reconnect); - if (mysql_real_connect(_sql, host, user, password, database, port, NULL, 0) == NULL) { - logWrite("dbConnect: %s\n", mysql_error(_sql)); - return FAIL; - } - if (pthread_mutex_init(&_mutex, NULL)) { - logWrite("dbConnect: SQL mutex creation failed.\n"); - return FAIL; - } - return SUCCESS; - } - return FAIL; -} - - -uint8_t dbDisconnect(void) { - if (_sql) { - mysql_close(_sql); - _sql = NULL; - pthread_mutex_destroy(&_mutex); - return SUCCESS; - } - - return FAIL; -} - - -uint8_t dbSettingsValueGet(char *key, int32_t *value) { - char *p = _statement; - MYSQL_RES *result = NULL; - MYSQL_ROW row; - int count; - - pthread_mutex_lock(&_mutex); - - if (!_sql) { - pthread_mutex_unlock(&_mutex); - return FAIL; - } - - p += sprintf(p, "SELECT data FROM config where NAME='"); - p += mysql_real_escape_string(_sql, p, key, strlen(key)); - p += sprintf(p, "'"); - if (mysql_real_query(_sql, _statement, p - _statement) != 0) { - logWrite("dbConfigValueGet: %s\n", mysql_error(_sql)); - pthread_mutex_unlock(&_mutex); - return FAIL; - } - - result = mysql_store_result(_sql); - count = mysql_num_rows(result); - if (count != 1) { - logWrite("dbConfigValueGet: Too many rows returned: %d.\n", count); - mysql_free_result(result); - pthread_mutex_unlock(&_mutex); - return FAIL; - } - - if ((row = mysql_fetch_row(result)) == NULL) { - logWrite("dbConfigValueGet: %s\n", mysql_error(_sql)); - pthread_mutex_unlock(&_mutex); - return FAIL; - } - - *value = atoi(row[0]); - - mysql_free_result(result); - - pthread_mutex_unlock(&_mutex); - - return SUCCESS; -} diff --git a/server/src/main.c b/server/src/main.c index 045ee08..aa6e579 100644 --- a/server/src/main.c +++ b/server/src/main.c @@ -20,9 +20,9 @@ #include "os.h" #include "console.h" -#include "database.h" #include "stddclmr.h" #include "server.h" +#include "rest.h" #include "thirdparty/ini/src/ini.h" @@ -32,11 +32,9 @@ uint8_t _running = 1; // Exported in os.h // "Config" items come from the INI file. "Settings" are from the database. -static char *_configServer = NULL; -static uint16_t _configPort = 0; -static char *_configDatabase = NULL; static char *_configUser = NULL; static char *_configPassword = NULL; +static char *_configREST = NULL; static void configRead(char *file); @@ -46,24 +44,18 @@ static void configWrite(char *file); static void configRead(char *file) { ini_t *ini = NULL; - // Numeric defaults. - _configPort = 16550; - ini = ini_load(file); if (ini) { - ini_sget(ini, "SERVER", "PORT", "%d", &_configPort); - _configServer = strdup(ini_get(ini, "SERVER", "HOST")); - _configDatabase = strdup(ini_get(ini, "SERVER", "DATA")); _configUser = strdup(ini_get(ini, "SERVER", "USER")); _configPassword = strdup(ini_get(ini, "SERVER", "PASS")); + _configREST = strdup(ini_get(ini, "SERVER", "REST")); ini_free(ini); } // String defaults. - if (!_configServer) strdup("kanga.world"); - if (!_configDatabase) strdup("kpmpgsmkii"); if (!_configUser) strdup(""); if (!_configPassword) strdup(""); + if (!_configREST) strdup("http://localhost:8000/api/kp/kangaworld/v1"); } @@ -74,22 +66,17 @@ static void configWrite(char *file) { if (out) { fprintf(out, "[SERVER]\n" - "HOST=%s\n" - "PORT=%d\n" - "DATA=%s\n" + "REST=%s\n" "USER=%s\n" "PASS=%s\n", - _configServer, - _configPort, - _configDatabase, + _configREST, _configUser, _configPassword ); fclose(out); } - DEL(_configServer); - DEL(_configDatabase); + DEL(_configREST); DEL(_configUser); DEL(_configPassword); } @@ -98,9 +85,10 @@ static void configWrite(char *file) { int main(int argc, char *argv[]) { char *configFile = NULL; - uint32_t settingsMaxClients = 0; - uint32_t settingsPortNumber = 0; - uint32_t settingsClientVersion = 0; + int64_t settingsMaxClients = 0; + int64_t settingsPortNumber = 0; + int64_t settingsClientVersion = 0; + json_object *response = NULL; (void)argc; @@ -111,14 +99,15 @@ int main(int argc, char *argv[]) { configFile = utilAppNameWithNewExtensionGet(argv[0], "ini"); configRead(configFile); - if (!dbConnect(_configServer, _configPort, _configDatabase, _configUser, _configPassword)) { - utilDie("Unable to connect to database.\n"); + if (!restStartup(_configREST, _configUser, _configPassword)) { + utilDie("Unable to start REST.\n"); } - // Fetch settings needed to start server. - if (!dbSettingsValueGet("maxClients", (int32_t *)&settingsMaxClients)) utilDie("Unable to load maxClients.\n"); - if (!dbSettingsValueGet("portNumber", (int32_t *)&settingsPortNumber)) utilDie("Unable to load portNumber.\n"); - if (!dbSettingsValueGet("clientVersion", (int32_t *)&settingsClientVersion)) utilDie("Unable to load clientVersion.\n"); + response = restRequest("CONFIG_GET_CONFIG", NULL); + settingsMaxClients = restHelperConfigIntegerGet(response, "maxClients", 2); + settingsPortNumber = restHelperConfigIntegerGet(response, "portNumber", 16550); + settingsClientVersion = restHelperConfigIntegerGet(response, "clientVersion", 1); + restRelease(response); serverStartup(settingsPortNumber, settingsMaxClients); logWrite("Server online.\n"); @@ -134,7 +123,7 @@ int main(int argc, char *argv[]) { serverShutdown(); // Shut down. - dbDisconnect(); + restShutdown(); configWrite(configFile); DEL(configFile); logWrite("Shutdown complete.\n"); diff --git a/server/src/rest.c b/server/src/rest.c new file mode 100644 index 0000000..0a9d2c1 --- /dev/null +++ b/server/src/rest.c @@ -0,0 +1,259 @@ +/* + * Kangaroo Punch MultiPlayer Game Server Mark II + * Copyright (C) 2020-2021 Scott Duensing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include +#include +#include + +#include "os.h" +#include "rest.h" + + +typedef struct RestResponseS { + uint64_t length; + char *data; +} RestResponseT; + + +static char *_restURL = NULL; +static char *_restUser = NULL; +static char *_restPass = NULL; +static pthread_mutex_t *_restMutexBuffer = NULL; + + +static void restMutexLocker(int mode, int n, const char *file, int line); +static size_t restResponseWrite(void *ptr, size_t size, size_t nmemb, RestResponseT *s); +static unsigned long restThreadtIdGet(void); +static json_object *restUrlPost(json_object *request); + + +int64_t restHelperConfigIntegerGet(json_object *object, char *name, int64_t defaultValue) { + uint64_t i = 0; + json_object *config = NULL; + json_object *data = NULL; + json_object *item = NULL; + int64_t result = defaultValue; + + config = json_object_object_get(object, "config"); + //logWrite("Config: %d %s\n", json_object_get_type(config), json_object_to_json_string_ext(config, JSON_C_TO_STRING_PRETTY)); + if (config) { + data = json_object_object_get(config, "data"); + //logWrite("Data: %d %s\n", json_object_get_type(data), json_object_to_json_string_ext(data, JSON_C_TO_STRING_PRETTY)); + if (data) { + for (i=0; ilength + size * nmemb; + + s->data = realloc(s->data, newLength + 1); + if (s->data == NULL) { + utilDie("restResponseWrite: realloc() failed.\n"); + } + memcpy(s->data + s->length, ptr, size*nmemb); + s->data[newLength] = 0; + s->length = newLength; + + return size * nmemb; +} + + +void restShutdown(void) { + uint64_t i; + + DEL(_restPass); + DEL(_restUser); + DEL(_restURL); + + if (_restMutexBuffer) { + CRYPTO_set_id_callback(NULL); + CRYPTO_set_locking_callback(NULL); + for (i=0; i -uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password); -uint8_t dbDisconnect(void); -uint8_t dbSettingsValueGet(char *key, int32_t *value); +int64_t restHelperConfigIntegerGet(json_object *object, char *name, int64_t defaultValue); +void restRelease(json_object *object); +json_object *restRequest(char *command, char *format, ...); +void restShutdown(void); +uint8_t restStartup(char *url, char *user, char *password); -#endif // DATABASE_H +#endif // REST_H