refactor(http): initial refactoring (wip)
This commit is contained in:
@@ -9,17 +9,18 @@
|
|||||||
#define CWS_HTTP_HEADER_CONTENT_MAX 1024
|
#define CWS_HTTP_HEADER_CONTENT_MAX 1024
|
||||||
|
|
||||||
typedef enum cws_http_method {
|
typedef enum cws_http_method {
|
||||||
CWS_HTTP_GET,
|
HTTP_GET,
|
||||||
CWS_HTTP_POST,
|
HTTP_POST,
|
||||||
CWS_HTTP_PUT,
|
HTTP_PUT,
|
||||||
CWS_HTTP_DELETE,
|
HTTP_DELETE,
|
||||||
CWS_HTTP_HEAD,
|
HTTP_HEAD,
|
||||||
|
HTTP_UNKNOWN,
|
||||||
} cws_http_method_e;
|
} cws_http_method_e;
|
||||||
|
|
||||||
typedef enum cws_http_status {
|
typedef enum cws_http_status {
|
||||||
CWS_HTTP_OK,
|
HTTP_OK,
|
||||||
CWS_HTTP_NOT_FOUND,
|
HTTP_NOT_FOUND,
|
||||||
CWS_HTTP_NOT_IMPLEMENTED,
|
HTTP_NOT_IMPLEMENTED,
|
||||||
} cws_http_status_e;
|
} cws_http_status_e;
|
||||||
|
|
||||||
typedef struct cws_http {
|
typedef struct cws_http {
|
||||||
@@ -31,18 +32,11 @@ typedef struct cws_http {
|
|||||||
hashmap_s *headers;
|
hashmap_s *headers;
|
||||||
} cws_http_s;
|
} cws_http_s;
|
||||||
|
|
||||||
cws_http_s *cws_http_parse(string_s *request_str, int sockfd);
|
cws_http_s *cws_http_parse(string_s *request_str);
|
||||||
|
|
||||||
int cws_http_get_content_type(cws_http_s *request, char *content_type);
|
|
||||||
|
|
||||||
size_t cws_http_response_builder(char **response, char *http_version, cws_http_status_e status, char *content_type, char *connection, char *body,
|
|
||||||
size_t body_len_bytes);
|
|
||||||
|
|
||||||
void cws_http_send_response(cws_http_s *request, cws_http_status_e status);
|
void cws_http_send_response(cws_http_s *request, cws_http_status_e status);
|
||||||
|
|
||||||
int cws_http_send_resource(cws_http_s *request);
|
size_t http_response_builder(char **response, char *http_version, cws_http_status_e status, char *content_type, char *body, size_t body_len_bytes);
|
||||||
|
|
||||||
void cws_http_send_simple_html(cws_http_s *request, cws_http_status_e status, char *title, char *description);
|
|
||||||
|
|
||||||
void cws_http_free(cws_http_s *request);
|
void cws_http_free(cws_http_s *request);
|
||||||
|
|
||||||
|
|||||||
349
src/http/http.c
349
src/http/http.c
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "http/http.h"
|
#include "http/http.h"
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -12,42 +11,173 @@
|
|||||||
#include "utils/debug.h"
|
#include "utils/debug.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
||||||
static void cws_http_init(cws_http_s **request) {
|
static cws_http_s *http_new() {
|
||||||
*request = calloc(1, sizeof(cws_http_s));
|
cws_http_s *request = malloc(sizeof(cws_http_s));
|
||||||
if (!*request) {
|
if (!request) {
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*request)->http_version = string_new("", 16);
|
request->http_version = string_new("", 16);
|
||||||
(*request)->location = string_new("", 128);
|
request->location = string_new("", 128);
|
||||||
(*request)->location_path = string_new("", 512);
|
request->location_path = string_new("", 512);
|
||||||
|
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cws_http_parse_method(cws_http_s *request, const char *method) {
|
static cws_http_method_e http_parse_method(const char *method) {
|
||||||
if (strcmp(method, "GET") == 0) {
|
if (strcmp(method, "GET") == 0) {
|
||||||
request->method = CWS_HTTP_GET;
|
return HTTP_GET;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(method, "POST") == 0) {
|
if (strcmp(method, "POST") == 0) {
|
||||||
request->method = CWS_HTTP_POST;
|
return HTTP_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTTP_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_get_content_type(char *location_path, char *content_type) {
|
||||||
|
/* Find last occurrence of a string */
|
||||||
|
char *ptr = strrchr(location_path, '.');
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
char ct[32] = {0};
|
||||||
|
|
||||||
|
if (strcmp(ptr, "html") == 0 || strcmp(ptr, "css") == 0 || strcmp(ptr, "javascript") == 0) {
|
||||||
|
strncpy(ct, "text", sizeof ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(ptr, "jpg") == 0 || strcmp(ptr, "png") == 0) {
|
||||||
|
strncpy(ct, "image", sizeof ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(content_type, 1024, "%s/%s", ct, ptr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *http_status_string(cws_http_status_e status) {
|
||||||
|
switch (status) {
|
||||||
|
case HTTP_OK: {
|
||||||
|
return "200 OK";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HTTP_NOT_FOUND: {
|
||||||
|
return "404 Not Found";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HTTP_NOT_IMPLEMENTED: {
|
||||||
|
return "501 Not Implemented";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t file_data(const char *path, char **data) {
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
|
if (!file) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve file size */
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
const size_t content_length = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
/* Retrieve file data */
|
||||||
|
*data = malloc(content_length);
|
||||||
|
if (!data) {
|
||||||
|
fclose(file);
|
||||||
|
CWS_LOG_ERROR("Unable to allocate file data");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read file data */
|
||||||
|
size_t read_bytes = fread(data, 1, content_length, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (read_bytes != content_length) {
|
||||||
|
free(data);
|
||||||
|
CWS_LOG_ERROR("Partial read from file");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return content_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_http_s *cws_http_parse(string_s *request_str, int sockfd) {
|
static cws_server_ret http_send_resource(cws_http_s *request) {
|
||||||
|
/* Retrieve correct Content-Type */
|
||||||
|
char content_type[1024];
|
||||||
|
http_get_content_type(request->location_path->data, content_type);
|
||||||
|
|
||||||
|
/* TODO: Check for keep-alive */
|
||||||
|
|
||||||
|
char *data;
|
||||||
|
char *response;
|
||||||
|
size_t content_length = file_data(request->location_path->data, &data);
|
||||||
|
|
||||||
|
size_t response_len = http_response_builder(&response, "HTTP/1.1", HTTP_OK, content_type, data, content_length);
|
||||||
|
|
||||||
|
ssize_t sent = send(request->sockfd, response, response_len, MSG_NOSIGNAL);
|
||||||
|
CWS_LOG_DEBUG("Sent %zu bytes", sent);
|
||||||
|
|
||||||
|
free(response);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return CWS_SERVER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void http_send_simple_html(cws_http_s *request, cws_http_status_e status, char *title, char *description) {
|
||||||
|
char body[512];
|
||||||
|
memset(body, 0, sizeof(body));
|
||||||
|
|
||||||
|
snprintf(body, sizeof(body),
|
||||||
|
"<html>\n"
|
||||||
|
"<head>\n"
|
||||||
|
" <title>%s</title>\n"
|
||||||
|
"</head>\n"
|
||||||
|
"<body>\n"
|
||||||
|
"<p>%s</p>\n"
|
||||||
|
"</body>"
|
||||||
|
"</html>",
|
||||||
|
title, description);
|
||||||
|
size_t body_len = strlen(body);
|
||||||
|
|
||||||
|
char conn[32] = "keep-alive";
|
||||||
|
bucket_s *connection = hm_get(request->headers, "Connection");
|
||||||
|
if (connection) {
|
||||||
|
strncpy(conn, (char *)connection->value, sizeof(conn) - 1);
|
||||||
|
conn[sizeof(conn) - 1] = '\0';
|
||||||
|
}
|
||||||
|
hm_free_bucket(connection);
|
||||||
|
|
||||||
|
char *response = NULL;
|
||||||
|
size_t response_len = http_response_builder(&response, "HTTP/1.1", status, "text/html", body, body_len);
|
||||||
|
|
||||||
|
ssize_t sent = send(request->sockfd, response, response_len, MSG_NOSIGNAL);
|
||||||
|
if (sent < 0) {
|
||||||
|
CWS_LOG_ERROR("Failed to send response");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
cws_http_s *cws_http_parse(string_s *request_str) {
|
||||||
if (!request_str) {
|
if (!request_str) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_http_s *request;
|
cws_http_s *request = http_new();
|
||||||
cws_http_init(&request);
|
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
request->sockfd = sockfd;
|
|
||||||
|
|
||||||
char *request_str_cpy = strdup(string_cstr(request_str));
|
char *request_str_cpy = strdup(string_cstr(request_str));
|
||||||
if (!request_str_cpy) {
|
if (!request_str_cpy) {
|
||||||
@@ -60,7 +190,6 @@ cws_http_s *cws_http_parse(string_s *request_str, int sockfd) {
|
|||||||
char *pch = NULL;
|
char *pch = NULL;
|
||||||
|
|
||||||
/* Parse HTTP method */
|
/* Parse HTTP method */
|
||||||
// TODO: fix strtok_r
|
|
||||||
pch = strtok_r(request_str_cpy, " ", &saveptr);
|
pch = strtok_r(request_str_cpy, " ", &saveptr);
|
||||||
if (pch == NULL) {
|
if (pch == NULL) {
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
@@ -70,13 +199,14 @@ cws_http_s *cws_http_parse(string_s *request_str, int sockfd) {
|
|||||||
}
|
}
|
||||||
// CWS_LOG_DEBUG("method: %s", pch);
|
// CWS_LOG_DEBUG("method: %s", pch);
|
||||||
|
|
||||||
int ret = cws_http_parse_method(request, pch);
|
request->method = http_parse_method(pch);
|
||||||
|
// TODO: fix here
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* Not implemented */
|
/* Not implemented */
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
free(request_str_cpy);
|
free(request_str_cpy);
|
||||||
|
|
||||||
cws_http_send_response(request, CWS_HTTP_NOT_IMPLEMENTED);
|
cws_http_send_response(request, HTTP_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -150,36 +280,15 @@ cws_http_s *cws_http_parse(string_s *request_str, int sockfd) {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *cws_http_status_string(cws_http_status_e status) {
|
size_t http_response_builder(char **response, char *http_version, cws_http_status_e status, char *content_type, char *body, size_t body_len_bytes) {
|
||||||
switch (status) {
|
char *status_code = http_status_string(status);
|
||||||
case CWS_HTTP_OK: {
|
|
||||||
return "200 OK";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWS_HTTP_NOT_FOUND: {
|
|
||||||
return "404 Not Found";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWS_HTTP_NOT_IMPLEMENTED: {
|
|
||||||
return "501 Not Implemented";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "?";
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cws_http_response_builder(char **response, char *http_version, cws_http_status_e status, char *content_type, char *connection, char *body,
|
|
||||||
size_t body_len_bytes) {
|
|
||||||
char *status_code = cws_http_status_string(status);
|
|
||||||
|
|
||||||
size_t header_len = snprintf(NULL, 0,
|
size_t header_len = snprintf(NULL, 0,
|
||||||
"%s %s\r\n"
|
"%s %s\r\n"
|
||||||
"Content-Type: %s\r\n"
|
"Content-Type: %s\r\n"
|
||||||
"Content-Length: %ld\r\n"
|
"Content-Length: %ld\r\n"
|
||||||
"Connection: %s\r\n"
|
|
||||||
"\r\n",
|
"\r\n",
|
||||||
http_version, status_code, content_type, body_len_bytes, connection);
|
http_version, status_code, content_type, body_len_bytes);
|
||||||
|
|
||||||
size_t total_len = header_len + body_len_bytes;
|
size_t total_len = header_len + body_len_bytes;
|
||||||
|
|
||||||
@@ -188,8 +297,7 @@ size_t cws_http_response_builder(char **response, char *http_version, cws_http_s
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(*response, header_len + 1, "%s %s\r\nContent-Type: %s\r\nContent-Length: %ld\r\nConnection: %s\r\n\r\n", http_version, status_code, content_type,
|
snprintf(*response, header_len + 1, "%s %s\r\nContent-Type: %s\r\nContent-Length: %ld\r\n\r\n", http_version, status_code, content_type, body_len_bytes);
|
||||||
body_len_bytes, connection);
|
|
||||||
|
|
||||||
/* Only append body if we have it */
|
/* Only append body if we have it */
|
||||||
if (body && body_len_bytes > 0) {
|
if (body && body_len_bytes > 0) {
|
||||||
@@ -201,157 +309,20 @@ size_t cws_http_response_builder(char **response, char *http_version, cws_http_s
|
|||||||
|
|
||||||
void cws_http_send_response(cws_http_s *request, cws_http_status_e status) {
|
void cws_http_send_response(cws_http_s *request, cws_http_status_e status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case CWS_HTTP_OK:
|
case HTTP_OK:
|
||||||
|
http_send_resource(request);
|
||||||
break;
|
break;
|
||||||
case CWS_HTTP_NOT_FOUND: {
|
case HTTP_NOT_FOUND: {
|
||||||
cws_http_send_simple_html(request, CWS_HTTP_NOT_FOUND, "404 Not Found", "Resource not found, 404.");
|
http_send_simple_html(request, HTTP_NOT_FOUND, "404 Not Found", "Resource not found, 404.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CWS_HTTP_NOT_IMPLEMENTED: {
|
case HTTP_NOT_IMPLEMENTED: {
|
||||||
cws_http_send_simple_html(request, CWS_HTTP_NOT_IMPLEMENTED, "501 Not Implemented", "Method not implemented, 501.");
|
http_send_simple_html(request, HTTP_NOT_IMPLEMENTED, "501 Not Implemented", "Method not implemented, 501.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cws_http_send_resource(cws_http_s *request) {
|
|
||||||
/* keep-alive by default */
|
|
||||||
int keepalive = 1;
|
|
||||||
|
|
||||||
FILE *file = fopen(string_cstr(request->location_path), "rb");
|
|
||||||
if (file == NULL) {
|
|
||||||
cws_http_send_response(request, CWS_HTTP_NOT_FOUND);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve correct Content-Type */
|
|
||||||
char content_type[1024];
|
|
||||||
int ret = cws_http_get_content_type(request, content_type);
|
|
||||||
if (ret < 0) {
|
|
||||||
fclose(file);
|
|
||||||
cws_http_send_response(request, CWS_HTTP_NOT_FOUND);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve file size */
|
|
||||||
fseek(file, 0, SEEK_END);
|
|
||||||
const size_t content_length = ftell(file);
|
|
||||||
rewind(file);
|
|
||||||
|
|
||||||
/* Retrieve file data */
|
|
||||||
char *file_data = malloc(content_length);
|
|
||||||
if (file_data == NULL) {
|
|
||||||
fclose(file);
|
|
||||||
CWS_LOG_ERROR("Unable to allocate file data");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read file data */
|
|
||||||
size_t read_bytes = fread(file_data, 1, content_length, file);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
if (read_bytes != content_length) {
|
|
||||||
free(file_data);
|
|
||||||
CWS_LOG_ERROR("Partial read from file");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for keep-alive */
|
|
||||||
char conn[32] = "keep-alive";
|
|
||||||
bucket_s *connection = hm_get(request->headers, "Connection");
|
|
||||||
if (connection && strcmp((char *)connection->value, "keep-alive") == 0) {
|
|
||||||
strcpy(conn, "keep-alive");
|
|
||||||
keepalive = 0;
|
|
||||||
}
|
|
||||||
hm_free_bucket(connection);
|
|
||||||
|
|
||||||
char *response = NULL;
|
|
||||||
size_t response_len = cws_http_response_builder(&response, "HTTP/1.1", CWS_HTTP_OK, content_type, conn, file_data, content_length);
|
|
||||||
|
|
||||||
/* Send response in chunks to avoid blocking */
|
|
||||||
size_t bytes_sent = 0;
|
|
||||||
ssize_t sent;
|
|
||||||
const size_t chunk_size = 8192;
|
|
||||||
|
|
||||||
while (bytes_sent < response_len) {
|
|
||||||
size_t to_send = (response_len - bytes_sent > chunk_size) ? chunk_size : (response_len - bytes_sent);
|
|
||||||
sent = send(request->sockfd, response + bytes_sent, to_send, MSG_NOSIGNAL);
|
|
||||||
|
|
||||||
if (sent <= 0) {
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bytes_sent += sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(response);
|
|
||||||
free(file_data);
|
|
||||||
|
|
||||||
return keepalive;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cws_http_get_content_type(cws_http_s *request, char *content_type) {
|
|
||||||
char *ptr = strrchr(string_cstr(request->location_path), '.');
|
|
||||||
if (ptr == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
char ct[32] = {0};
|
|
||||||
|
|
||||||
/* TODO: Improve content_type (used to test) */
|
|
||||||
if (strcmp(ptr, "html") == 0 || strcmp(ptr, "css") == 0 || strcmp(ptr, "javascript") == 0) {
|
|
||||||
strncpy(ct, "text", sizeof ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(ptr, "jpg") == 0 || strcmp(ptr, "png") == 0) {
|
|
||||||
strncpy(ct, "image", sizeof ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(content_type, 1024, "%s/%s", ct, ptr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cws_http_send_simple_html(cws_http_s *request, cws_http_status_e status, char *title, char *description) {
|
|
||||||
char body[512];
|
|
||||||
memset(body, 0, sizeof(body));
|
|
||||||
|
|
||||||
snprintf(body, sizeof(body),
|
|
||||||
"<html>\n"
|
|
||||||
"<head>\n"
|
|
||||||
" <title>%s</title>\n"
|
|
||||||
"</head>\n"
|
|
||||||
"<body>\n"
|
|
||||||
"<p>%s</p>\n"
|
|
||||||
"</body>"
|
|
||||||
"</html>",
|
|
||||||
title, description);
|
|
||||||
size_t body_len = strlen(body);
|
|
||||||
|
|
||||||
char conn[32] = "keep-alive";
|
|
||||||
bucket_s *connection = hm_get(request->headers, "Connection");
|
|
||||||
if (connection) {
|
|
||||||
strncpy(conn, (char *)connection->value, sizeof(conn) - 1);
|
|
||||||
conn[sizeof(conn) - 1] = '\0';
|
|
||||||
}
|
|
||||||
hm_free_bucket(connection);
|
|
||||||
|
|
||||||
char *response = NULL;
|
|
||||||
size_t response_len = cws_http_response_builder(&response, "HTTP/1.1", status, "text/html", conn, body, body_len);
|
|
||||||
|
|
||||||
/* Send response with error handling */
|
|
||||||
ssize_t sent = send(request->sockfd, response, response_len, MSG_NOSIGNAL);
|
|
||||||
if (sent < 0) {
|
|
||||||
CWS_LOG_ERROR("Failed to send response: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cws_http_free(cws_http_s *request) {
|
void cws_http_free(cws_http_s *request) {
|
||||||
hm_free(request->headers);
|
hm_free(request->headers);
|
||||||
string_free(request->http_version);
|
string_free(request->http_version);
|
||||||
|
|||||||
@@ -34,14 +34,10 @@ static int cws_worker_setup_epoll(cws_worker_s *worker) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t cws_read_data(int sockfd, string_s **str) {
|
static size_t cws_read_data(int sockfd, string_s *str) {
|
||||||
size_t total_bytes = 0;
|
size_t total_bytes = 0;
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
|
|
||||||
if (*str == NULL) {
|
|
||||||
*str = string_new("", 4096);
|
|
||||||
}
|
|
||||||
|
|
||||||
char tmp[4096];
|
char tmp[4096];
|
||||||
memset(tmp, 0, sizeof(tmp));
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
|
||||||
@@ -63,7 +59,7 @@ static size_t cws_read_data(int sockfd, string_s **str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
total_bytes += bytes_read;
|
total_bytes += bytes_read;
|
||||||
string_append(*str, tmp);
|
string_append(str, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return total_bytes;
|
return total_bytes;
|
||||||
@@ -191,8 +187,8 @@ cws_server_ret cws_epoll_del(int epfd, int sockfd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cws_server_ret cws_server_handle_client_data(int epfd, int client_fd) {
|
cws_server_ret cws_server_handle_client_data(int epfd, int client_fd) {
|
||||||
string_s *data;
|
string_s *data = string_new("", 4096);
|
||||||
size_t total_bytes = cws_read_data(client_fd, &data);
|
size_t total_bytes = cws_read_data(client_fd, data);
|
||||||
if (total_bytes <= 0) {
|
if (total_bytes <= 0) {
|
||||||
if (data) {
|
if (data) {
|
||||||
string_free(data);
|
string_free(data);
|
||||||
@@ -202,7 +198,8 @@ cws_server_ret cws_server_handle_client_data(int epfd, int client_fd) {
|
|||||||
return CWS_SERVER_CLIENT_DISCONNECTED_ERROR;
|
return CWS_SERVER_CLIENT_DISCONNECTED_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_http_s *request = cws_http_parse(data, client_fd);
|
/* TODO: set sockfd to request */
|
||||||
|
cws_http_s *request = cws_http_parse(data);
|
||||||
string_free(data);
|
string_free(data);
|
||||||
|
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
@@ -211,11 +208,11 @@ cws_server_ret cws_server_handle_client_data(int epfd, int client_fd) {
|
|||||||
return CWS_SERVER_HTTP_PARSE_ERROR;
|
return CWS_SERVER_HTTP_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int keepalive = cws_http_send_resource(request);
|
// cws_http_send_resource(request);
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
if (!keepalive) {
|
// if (!keepalive) {
|
||||||
cws_server_close_client(epfd, client_fd);
|
// cws_server_close_client(epfd, client_fd);
|
||||||
}
|
//}
|
||||||
|
|
||||||
return CWS_SERVER_OK;
|
return CWS_SERVER_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user