-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.c
144 lines (114 loc) · 3.92 KB
/
server.c
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#define PORT 8080
#define BUFFER_SIZE 1024
void WS_die();
struct Route {
char *path;
char *(*renderFunction)();
};
struct Server {
int port;
int buffer_size;
WSADATA wsaData;
char buffer[BUFFER_SIZE];
SOCKET server_fd, connection;
struct sockaddr_in address;
struct Route routes[100];
int numRoutes;
void (*setup)(struct Server server);
void (*startListen)(struct Server server);
void (*addRoute)(struct Server server, char *path, char *(*renderFunction)());
};
void setup(struct Server server);
void startListen(struct Server server);
void addRoute(struct Server server, char *path, char *(*renderFunction)());
struct Server makeServer() {
struct Server server;
if (WSAStartup(MAKEWORD(2,2), &server.wsaData) != 0) WS_die("Winsock init");
server.port = PORT;
server.buffer_size = BUFFER_SIZE;
server.server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server.server_fd == INVALID_SOCKET) WS_die("Creating socket");
server.setup = setup;
server.startListen = startListen;
server.addRoute = addRoute;
server.numRoutes = 0;
server.address.sin_family = AF_INET; // Address family = Internet
server.address.sin_addr.s_addr = INADDR_ANY; // Accept connections from any IP address
server.address.sin_port = htons(server.port); // Port in network byte order (ie, converting it form an integer to address of the port)
return server;
}
void startServer(struct Server server) {
server.setup(server);
server.startListen(server);
}
void setup(struct Server server) {
if (bind(server.server_fd, (struct sockaddr *)&server.address, sizeof(server.address)) == SOCKET_ERROR) WS_die("Binding");
if (listen(server.server_fd, 3) == SOCKET_ERROR) WS_die("Initiating Listening");
}
void startListen(struct Server server) {
while (1) {
server.connection = accept(server.server_fd, NULL, NULL);
if (server.connection == INVALID_SOCKET) WS_die("Accepting request");
int valread = recv(server.connection, server.buffer, server.buffer_size, 0);
if (valread == SOCKET_ERROR) WS_die("Receiving request");
printf("%s", server.buffer);
send(server.connection, "HTTP/1.1 200 OK\nContent-Type: text/html\n\nHello World!", 53, 0);
closesocket(server.connection);
}
}
void WS_die(char* checkName) {
printf("At %s, Winsock error: %d", checkName, WSAGetLastError());
WSACleanup();
exit(1);
}
#define NUM_STATUS_CODES 2
struct codeMsgMapStruct {
int code;
char* msg;
} codeMsgMap[NUM_STATUS_CODES] = {
{200, "OK"},
{404, "Not Found"}
};
char* getMsgForCode(int code) {
for (int i = 0; i < NUM_STATUS_CODES -1; i++ ) {
if (codeMsgMap[i].code == code) return codeMsgMap[i].msg;
}
return "OK";
};
char* makeResponse(int statusCode, char* contentType, char* body) {
char *response = malloc(10000);
sprintf(response, "HTTP/1.1 %d %s\nContent-Type: %s\n\n%s", statusCode, getMsgForCode(statusCode), contentType, body);
};
char* readTemplate(char *path) {
FILE *file = fopen(path, "r");
if (file == NULL) {
printf("Error opening file");
exit(1);
}
fseek(file, 0, SEEK_END);
long fsize = ftell(file);
fseek(file, 0, SEEK_SET);
char *string = malloc(fsize + 1);
fread(string, fsize, 1, file);
fclose(file);
string[fsize] = 0;
return string;
};
/* WHAT_GOES_HERE? */ getRenderFunction(struct Server server, char* path) {
for (int i=0; i < server.numRoutes; i++) {
if (server.routes[i].path == path) {
return server.routes[i].renderFunction;
}
}
printf("Path %s Not Found", path);
}
void addRoute(struct Server server, char *path, char *(*renderFunction)()) {
struct Route route;
route.path = path;
route.renderFunction = renderFunction;
server.routes[++server.numRoutes] = route;
}