#include #include #include #include #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; }