104 lines
2.8 KiB
C
104 lines
2.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <netinet/in.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include "httplib.h"
|
|
#include "httplib_internal.h"
|
|
|
|
int httplib_start_server(int port, http_request_handler handler) {
|
|
|
|
int rfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (rfd < 0) {
|
|
return SOCKET_ERROR;
|
|
}
|
|
int option = 1;
|
|
setsockopt(rfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(int));
|
|
|
|
struct sockaddr_in server;
|
|
struct sockaddr client;
|
|
socklen_t client_len = sizeof(struct sockaddr);
|
|
|
|
server.sin_family = AF_INET;
|
|
server.sin_addr.s_addr = INADDR_ANY;
|
|
server.sin_port = htons(port);
|
|
if (bind(rfd, (const struct sockaddr *) &server, sizeof(server)) < 0) {
|
|
return BIND_ERROR;
|
|
}
|
|
if (listen(rfd, 3) < 0) {
|
|
return LISTEN_ERROR;
|
|
}
|
|
|
|
int cfd;
|
|
|
|
while (1) {
|
|
cfd = accept(rfd, &client, &client_len);
|
|
if (cfd < 0) {
|
|
printf("Connection Error, waiting for next connection\n");
|
|
continue;
|
|
}
|
|
int pid = fork();
|
|
if (pid == 0) {
|
|
|
|
http_request * req = httplib_request_new();
|
|
|
|
int result = httplib_receive(cfd, req);
|
|
|
|
http_response * res = httplib_response_new();
|
|
|
|
if (result == 1) handler(req, res);
|
|
else if (result == 3) httplib_response_set_status(res, 505, "HTTP Version Not Supported");
|
|
else if (result == 4) httplib_response_set_status(res, 400, "Bad Request");
|
|
else httplib_response_set_status(res, 500, "Internal Server Error");
|
|
|
|
httplib_request_free(req);
|
|
|
|
httplib_respond(cfd, res);
|
|
|
|
close(cfd);
|
|
exit(0);
|
|
}
|
|
close(cfd);
|
|
}
|
|
}
|
|
|
|
int httplib_receive(int cfd, http_request * req_out) {
|
|
char buf[1024];
|
|
size_t bytes_received;
|
|
|
|
enum req_pos pos = METHOD;
|
|
int was_cr = 0;
|
|
int result = 0;
|
|
|
|
struct tmp tmp;
|
|
tmp.buf = malloc(1024);
|
|
bzero(tmp.buf, 1024);
|
|
tmp.size = 1024;
|
|
tmp.pos = 0;
|
|
|
|
do {
|
|
bytes_received = read(cfd, buf, 1024);
|
|
if ((result = httplib_parse_buffer(buf, bytes_received, req_out, &tmp, &pos, &was_cr))) break;
|
|
} while (bytes_received > 0);
|
|
free(tmp.buf);
|
|
return result;
|
|
}
|
|
|
|
void httplib_respond(int cfd, http_response * res) {
|
|
size_t res_size = httplib_response_string_size(res);
|
|
char * res_bytes = malloc(res_size);
|
|
int ser_err = httplib_response_serialize(res, res_bytes);
|
|
if (ser_err != 0) {
|
|
http_response * err_res = httplib_response_new();
|
|
httplib_response_set_status(res, 500, "Internal Server Error");
|
|
res_size = httplib_response_string_size(err_res);
|
|
res_bytes = realloc(res_bytes, res_size);
|
|
httplib_response_serialize(err_res, res_bytes);
|
|
httplib_response_free(err_res);
|
|
}
|
|
httplib_response_free(res);
|
|
write(cfd, res_bytes, res_size);
|
|
free(res_bytes);
|
|
}
|
|
|