#include "socket_server.h" #include #include #include #include static socket_server* __new_socket_server(uint16_t port, uint32_t incoming_ip) { socket_server* srv = malloc(sizeof(socket_server)); srv->socket = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr = { .sin_family = AF_INET, // Address Family Internet .sin_port = htons(port), // Host to network short .sin_addr.s_addr = htonl(incoming_ip), // Host to network long }; while (bind(srv->socket, (struct sockaddr*)&addr, sizeof(addr)) != 0) { perror("Socket bind"); sleep(5); } return srv; } /*** Single Request Server ***/ static int start_single_req(socket_server* this); static void destroy_single_req(socket_server* this); socket_server* new_socket_server_single_req(uint16_t port, uint32_t incoming_ip) { socket_server* res = __new_socket_server(port, incoming_ip); res->start = start_single_req; res->destroy = destroy_single_req; return res; } static int ends_on_two_newlines(char str[2]) { return (str[0] == '\n' || str[0] == '\r') && (str[1] == '\n' || str[1] == '\r'); } static int start_single_req(socket_server* this) { if (this == NULL) return -1; listen(this->socket, 1); struct sockaddr_in client = { .sin_family = AF_INET, .sin_port = 0, .sin_addr.s_addr = 0, }; socklen_t client_size = sizeof(client); int client_socket = accept(this->socket, (struct sockaddr*)&client, &client_size); char input[1024] = { 0 }; size_t input_size = 0; char line[256] = { 0 }; size_t line_size = 0; do { input_size += line_size = recv(client_socket, line, 255, 0); line[line_size] = '\0'; strcat(input, line); } while (input_size > 0 && !ends_on_two_newlines(input + input_size - 2)); callback_args ca_args = { .input = input, .input_size = input_size, .output = NULL, .output_size = 0, .free_output = 0, .extra = this->callback_args, .extra_size = this->callback_argc, }; if (this->callback != NULL) this->callback(&ca_args); if (ca_args.output != NULL && ca_args.output_size > 0) send(client_socket, ca_args.output, ca_args.output_size, 0); if (ca_args.free_output) free(ca_args.output); close(client_socket); return 0; } static void destroy_single_req(socket_server* this) { if (this == NULL) return; close(this->socket); free(this); this = NULL; }