1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include "socket_server.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
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;
}
|