#include #include #include #include #include #include "logger.c" #define BACKLOG 10 #define REQUEST_OPTS 'o' struct Client { int fd; struct sockaddr_in addr; }; void sig_handler(int signo) { log_warn("Signal %d received, shutting down server", signo); exit(0); } void respond_opts(int client_fd) { log_info("Client requested simulator options"); struct json_object *response = json_object_new_object(); json_object_object_add(response, "anc", json_object_new_string(ANC)); json_object_object_add(response, "arch", json_object_new_string(ARCH)); json_object_object_add(response, "auto-save-interval", json_object_new_int64(AUTOSAVE_INTERVAL)); json_object_object_add(response, "clones", json_object_new_int64(CLONES)); json_object_object_add(response, "compress", json_object_new_boolean(COMPRESS)); json_object_object_add(response, "cores", json_object_new_int64(CORES)); json_object_object_add(response, "data-push", json_object_new_boolean(DATA_PUSH)); json_object_object_add(response, "data-push-interval", json_object_new_int64(DATA_PUSH_INTERVAL)); json_object_object_add(response, "muta-flip", json_object_new_boolean(MUTA_FLIP)); json_object_object_add(response, "muta-range", json_object_new_int64(MUTA_RANGE)); json_object_object_add(response, "mvec-loop", json_object_new_boolean(MVEC_LOOP)); json_object_object_add(response, "mvec-size", json_object_new_int64(MVEC_SIZE)); json_object_object_add(response, "name", json_object_new_string(NAME)); json_object_object_add(response, "seed", json_object_new_int64(SEED)); json_object_object_add(response, "sync-interval", json_object_new_int64(SYNC_INTERVAL)); const char *str_rep = json_object_to_json_string_ext(response, JSON_C_TO_STRING_PRETTY); send(client_fd, str_rep, strlen(str_rep), 0); json_object_put(response); } 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_OPTS: respond_opts(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; }