diff options
Diffstat (limited to 'data/server.c')
| -rw-r--r-- | data/server.c | 109 |
1 files changed, 72 insertions, 37 deletions
diff --git a/data/server.c b/data/server.c index 2d96b81..ea94364 100644 --- a/data/server.c +++ b/data/server.c @@ -1,6 +1,7 @@ #include <arpa/inet.h> #include <json-c/json.h> #include <signal.h> +#include <sqlite3.h> #include <string.h> #include <threads.h> @@ -8,34 +9,46 @@ #define BACKLOG 10 -struct Client { +struct Socket { int fd; struct sockaddr_in addr; }; +sqlite3 *g_sim_db; +void (*g_info)(const char *fmt, ...) = log_info; +void (*g_warn)(const char *fmt, ...) = log_warn; +#include "sql.c" + +// ---------------------------------------------------------------------------- +// SQL functions +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Main functions +// ---------------------------------------------------------------------------- void sig_handler(int signo) { log_warn("Signal %d received, shutting down data server", signo); exit(0); } -void respond_name(int client_fd) { +void respond_name(int socket_fd) { log_info("Client requested simulation name"); struct json_object *sim_name = json_object_new_object(); json_object_object_add(sim_name, "name", json_object_new_string(NAME)); - json_object_to_fd(client_fd, sim_name, JSON_C_TO_STRING_PRETTY); + json_object_to_fd(socket_fd, sim_name, 0); json_object_put(sim_name); } -void respond_opts(int client_fd) { +void respond_opts(int socket_fd) { log_info("Client requested simulation options"); struct json_object *sim_opts = json_object_from_file(SIM_OPTS); - json_object_to_fd(client_fd, sim_opts, JSON_C_TO_STRING_PRETTY); + json_object_to_fd(socket_fd, sim_opts, 0); json_object_put(sim_opts); } -void respond_hash(int client_fd) { +void respond_hash(int socket_fd) { log_info("Client requested git hash"); char buff[41] = { 0 }; @@ -45,23 +58,34 @@ void respond_hash(int client_fd) { struct json_object *git_hash = json_object_new_object(); json_object_object_add(git_hash, "hash", json_object_new_string(buff)); - json_object_to_fd(client_fd, git_hash, JSON_C_TO_STRING_PRETTY); + json_object_to_fd(socket_fd, git_hash, 0); json_object_put(git_hash); } -void respond_data(int client_fd, struct json_object *request_json) { - assert(request_json); - (void)client_fd; +void respond_data(int socket_fd, struct json_object *request) { + assert(request); + + const char *request_str = json_object_to_json_string(request); + log_info("Client requested simulation data with the following parameters: %s", request_str); + + struct json_object *response = json_object_new_object(); + json_object_object_add(response, "response", json_object_new_string("hello!")); + const char *response_str = json_object_to_json_string(response); + log_info("Sending response to client: %s", response_str); + json_object_to_fd(socket_fd, response, 0); + + shutdown(socket_fd, SHUT_WR); + json_object_put(response); } -int handle_client(struct Client *client) { - assert(client); +int handle_client(struct Socket *socket) { + assert(socket); - char client_ip[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &client->addr.sin_addr, client_ip, INET_ADDRSTRLEN); - log_info("Client connected: %s:%d", client_ip, ntohs(client->addr.sin_port)); + char socket_ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &socket->addr.sin_addr, socket_ip, INET_ADDRSTRLEN); + log_info("Client connected: %s:%d", socket_ip, ntohs(socket->addr.sin_port)); - struct json_object *request_json = json_object_from_fd(client->fd); + struct json_object *request_json = json_object_from_fd(socket->fd); struct json_object *request_str = NULL; if (!json_object_object_get_ex(request_json, "request", &request_str)) assert(false); @@ -70,23 +94,23 @@ int handle_client(struct Client *client) { assert(request); if (!strcmp(request, "name")) { - respond_name(client->fd); + respond_name(socket->fd); } else if (!strcmp(request, "opts")) { - respond_opts(client->fd); + respond_opts(socket->fd); } else if (!strcmp(request, "hash")) { - respond_hash(client->fd); + respond_hash(socket->fd); } else if (!strcmp(request, "data")) { - respond_data(client->fd, request_json); + respond_data(socket->fd, request_json); } else { assert(false); } json_object_put(request_json); - log_info("Client disconnected: %s:%d", client_ip, ntohs(client->addr.sin_port)); - close(client->fd); + log_info("Client disconnected: %s:%d", socket_ip, ntohs(socket->addr.sin_port)); + close(socket->fd); - free(client); + free(socket); return 0; } @@ -95,30 +119,41 @@ int main(void) { signal(SIGTERM, sig_handler); log_info("Initializing salis data server"); - int opt = 1; - int server_fd = socket(AF_INET, SOCK_STREAM, 0); - setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + log_info("Connecting to database in: %s", DATA_PUSH_PATH); + sqlite3_open(DATA_PUSH_PATH, &g_sim_db); + assert(g_sim_db); + + // Install busy handler to retry transactions if DB is locked + sqlite3_busy_timeout(g_sim_db, DATA_PUSH_BUSY_TIMEOUT); + + // Enable Write-Ahead Logging (WAL) + // This seems to help prevent DB locks when displaying live data. + // See: https://sqlite.org/wal.html + salis_exec_sql(0, NULL, NULL, "pragma journal_mode=wal;"); log_info("Binding to port: %d", PORT); - struct sockaddr_in server_addr = { 0 }; - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = htons(PORT); - bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)); + int opt = 1; + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + struct sockaddr_in socket_addr = { 0 }; + socket_addr.sin_family = AF_INET; + socket_addr.sin_addr.s_addr = INADDR_ANY; + socket_addr.sin_port = htons(PORT); + bind(socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)); log_info("Listening..."); - listen(server_fd, BACKLOG); + listen(socket_fd, BACKLOG); while (true) { - struct Client *client = calloc(1, sizeof(struct Client)); - socklen_t client_len = sizeof(struct sockaddr_in); - client->fd = accept(server_fd, (struct sockaddr *)&client->addr, &client_len); + struct Socket *socket = calloc(1, sizeof(struct Socket)); + socklen_t socket_len = sizeof(struct sockaddr_in); + socket->fd = accept(socket_fd, (struct sockaddr *)&socket->addr, &socket_len); thrd_t thrd; - thrd_create(&thrd, (thrd_start_t)handle_client, client); + thrd_create(&thrd, (thrd_start_t)handle_client, socket); thrd_detach(thrd); } - close(server_fd); + close(socket_fd); return 0; } |
