diff options
Diffstat (limited to 'data/server.c')
| -rw-r--r-- | data/server.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/data/server.c b/data/server.c new file mode 100644 index 0000000..3ed2c64 --- /dev/null +++ b/data/server.c @@ -0,0 +1,110 @@ +#include <arpa/inet.h> +#include <assert.h> +#include <json-c/json.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <threads.h> +#include <unistd.h> + +#include "logger.c" + +#define BACKLOG 10 + +struct Client { + int fd; + struct sockaddr_in addr; +}; + +void sig_handler(int signo) { + log_warn("Signal %d received, shutting down data server", signo); + exit(0); +} + +void respond_name(int client_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_put(sim_name); +} + +void respond_opts(int client_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_put(sim_opts); +} + +void respond_hash(int client_fd) { + log_info("Client requested git hash"); + + char buff[41] = { 0 }; + FILE *pipe = popen("git rev-parse HEAD", "r"); + fread(buff, sizeof(char), 40, pipe); + pclose(pipe); + + 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_put(git_hash); +} + +int handle_client(struct Client *client) { + assert(client); + + 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 request = '\0'; + recv(client->fd, &request, 1, 0); + + switch (request) { + case REQUEST_NAME: respond_name(client->fd); break; + case REQUEST_OPTS: respond_opts(client->fd); break; + case REQUEST_HASH: respond_hash(client->fd); break; + default: log_warn("Client made invalid request"); + } + + log_info("Client disconnected: %s:%d", client_ip, ntohs(client->addr.sin_port)); + close(client->fd); + + free(client); + return 0; +} + +int main(void) { + signal(SIGINT, sig_handler); + 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("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)); + + log_info("Listening..."); + listen(server_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); + + thrd_t thrd; + thrd_create(&thrd, (thrd_start_t)handle_client, client); + thrd_detach(thrd); + } + + close(server_fd); + return 0; +} |
