mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-10 19:08:39 +00:00
http server working
This commit is contained in:
parent
2059cc6e77
commit
98ca778dfc
|
|
@ -251,11 +251,8 @@ HttpRequest* http_request_create(ThreadedChunkMemory* mem)
|
|||
request->size = request_buffer_count;
|
||||
request->protocol = HTTP_PROTOCOL_1_1;
|
||||
|
||||
// Create content length placehoder, this header element is always required
|
||||
http_header_value_set(&request, HTTP_HEADER_KEY_CONTENT_LENGTH, " ", mem);
|
||||
|
||||
// Prepare the chunked sub-regions
|
||||
request->header_available_count = 16;
|
||||
request->header_available_count = 25;
|
||||
request->header_available_size = 4 * 256 * sizeof(char);
|
||||
request->body_offset = request->header_available_count * sizeof(HttpHeaderElement) + request->header_available_size;
|
||||
|
||||
|
|
@ -268,6 +265,22 @@ HttpRequest* http_request_create(ThreadedChunkMemory* mem)
|
|||
return request;
|
||||
}
|
||||
|
||||
FORCE_INLINE
|
||||
void http_request_free(HttpRequest** request, ThreadedChunkMemory* mem)
|
||||
{
|
||||
thrd_chunk_free_elements(mem, (*request)->id, (*request)->size);
|
||||
*request = NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
uint32 http_request_free_body_space(const HttpRequest* request, ThreadedChunkMemory* mem)
|
||||
{
|
||||
return request->size * mem->chunk_size
|
||||
- request->body_offset
|
||||
- request->body_used_size
|
||||
- sizeof(HttpRequest);
|
||||
}
|
||||
|
||||
inline
|
||||
const char* http_request_body(const HttpRequest* request) {
|
||||
return ((const char *) (request + 1)) + request->body_offset;
|
||||
|
|
@ -356,30 +369,36 @@ void http_header_parse(HttpRequest** http_request, const char* request, Threaded
|
|||
http_req->method = HTTP_METHOD_UNKNOWN;
|
||||
}
|
||||
|
||||
// @bug the uri offsets are wrong (they miss the header elements)
|
||||
// however, if we put them after the header elements we would also have to grow this if we ever need to grow the heder element array
|
||||
|
||||
int32 header_count_bytes = http_req->header_available_count * sizeof(HttpHeaderElement);
|
||||
|
||||
// Parse reuqest path
|
||||
str_move_past(&request, ' ');
|
||||
http_req->uri.path_offset = request - request_start;
|
||||
http_req->uri.path_offset = request - request_start + header_count_bytes;
|
||||
|
||||
str_skip_until_list(&request, ":?# ");
|
||||
http_req->uri.path_length = (request - request_start) - http_req->uri.path_offset;
|
||||
http_req->uri.path_length = (request - request_start + header_count_bytes) - http_req->uri.path_offset;
|
||||
|
||||
// Parse port
|
||||
if (*request == ':') {
|
||||
http_req->uri.port = (uint16) str_to_int(request, &request);
|
||||
str_skip_until_list(&request, "?# ");
|
||||
}
|
||||
|
||||
// Parse query parameters
|
||||
if (*request == '?') {
|
||||
http_req->uri.parameter_offset = request - request_start;
|
||||
http_req->uri.parameter_offset = request - request_start + header_count_bytes;
|
||||
str_skip_until_list(&request, "# ");
|
||||
//http_req->uri.parameter_length = (request - request_start) - http_req->uri.parameter_offset;
|
||||
}
|
||||
|
||||
// Parse fragment
|
||||
if (*request == '#') {
|
||||
http_req->uri.fragment_offset = request - request_start;
|
||||
http_req->uri.fragment_offset = request - request_start + header_count_bytes;
|
||||
str_move_to(&request, ' ');
|
||||
http_req->uri.fragment_length = (request - request_start) - http_req->uri.fragment_offset;
|
||||
http_req->uri.fragment_length = (request - request_start + header_count_bytes) - http_req->uri.fragment_offset;
|
||||
}
|
||||
|
||||
// Parse protocol
|
||||
|
|
@ -406,7 +425,53 @@ void http_header_parse(HttpRequest** http_request, const char* request, Threaded
|
|||
// Parsing HTTP headers
|
||||
//////////////////////////////////////////////////
|
||||
// The HTTP headers end with \r\n\r\n (= one empty line/element)
|
||||
|
||||
HttpHeaderElement* elements = (HttpHeaderElement *) (http_req + 1);
|
||||
|
||||
int32 i = 0;
|
||||
while (request[0] != '\r' && request[1] != '\n' && request[2] != '\r' && request[3] != '\n') {
|
||||
if (i >= http_req->header_available_count) {
|
||||
// Ideally this if body almost never gets executed since the initial area is sufficiently large
|
||||
// @todo consider to log actual usage to possibly reduce the size from 50 to maybe 25?
|
||||
http_request_grow(http_request, 1, mem);
|
||||
http_req = *http_request;
|
||||
|
||||
int32 offset = 50 * sizeof(HttpHeaderElement);
|
||||
int32 request_offset = request - request_start;
|
||||
|
||||
// Grow header element area
|
||||
memmove(
|
||||
((char *) (http_req + 1)) + http_req->body_offset + offset,
|
||||
((char *) (http_req + 1)) + http_req->body_offset,
|
||||
http_req->header_available_size + http_req->body_used_size
|
||||
);
|
||||
|
||||
// Re-adjust uri as well
|
||||
http_req->uri.path_offset += offset;
|
||||
|
||||
if (http_req->uri.parameter_offset) {
|
||||
http_req->uri.parameter_offset += offset;
|
||||
}
|
||||
|
||||
if (http_req->uri.fragment_offset) {
|
||||
http_req->uri.fragment_offset += offset;
|
||||
}
|
||||
|
||||
// Reset request after moving
|
||||
request = ((char *) (http_req + 1)) + request_offset;
|
||||
|
||||
// Adjust value offsets
|
||||
elements = (HttpHeaderElement *) (http_req + 1);
|
||||
for (int32 j = 0; j < http_req->header_used_count; ++j) {
|
||||
elements[j].value_offset += offset;
|
||||
}
|
||||
|
||||
http_req->body_offset += offset;
|
||||
|
||||
// Reset request start position
|
||||
request_start = ((const char *) (http_req + 1)) + http_req->header_available_count * sizeof(HttpHeaderElement);
|
||||
}
|
||||
|
||||
str_move_past(&request, '\n');
|
||||
const char* key = request;
|
||||
|
||||
|
|
@ -415,8 +480,27 @@ void http_header_parse(HttpRequest** http_request, const char* request, Threaded
|
|||
const char* value = request;
|
||||
str_move_to(&request, '\r');
|
||||
|
||||
http_header_value_set(http_request, http_header_key_text(key), value, mem, request - value);
|
||||
elements[i].key = http_header_key_text(key);
|
||||
elements[i].value_offset = http_req->header_available_count * sizeof(HttpHeaderElement)
|
||||
+ ((uintptr_t) value - (uintptr_t) (http_req + 1));
|
||||
elements[i].value_length = request - value;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
http_req->header_used_count = i;
|
||||
http_req->header_available_size = 0;
|
||||
http_req->header_used_size = 0;
|
||||
|
||||
if (i > 0) {
|
||||
// Available size = used size
|
||||
http_req->header_available_size = (request - request_start);
|
||||
http_req->header_used_size = http_req->header_available_size;
|
||||
}
|
||||
|
||||
http_req->body_offset = http_req->header_available_count * sizeof(HttpHeaderElement)
|
||||
+ http_req->header_available_size
|
||||
+ 4; // skipping \r\n\r\n
|
||||
}
|
||||
|
||||
void parse_multipart_data(const char *body, const char *boundary) {
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ void http_header_value_set(
|
|||
|
||||
// Set value
|
||||
memcpy(((char *) (resp + 1)) + element->value_offset, value, value_length);
|
||||
resp->body_used_size += value_length;
|
||||
// resp->body_used_size += value_length; // @bug Why was this here?
|
||||
|
||||
resp->header_used_size += (uint16) value_length;
|
||||
++resp->header_used_count;
|
||||
|
|
@ -239,11 +239,8 @@ HttpResponse* http_response_create(ThreadedChunkMemory* mem)
|
|||
response->protocol = HTTP_PROTOCOL_1_1;
|
||||
response->status_code = HTTP_STATUS_CODE_200;
|
||||
|
||||
// Create content length placehoder, this header element is always required
|
||||
http_header_value_set(&response, HTTP_HEADER_KEY_CONTENT_LENGTH, " ", mem);
|
||||
|
||||
// Prepare the chunked sub-regions
|
||||
response->header_available_count = 16;
|
||||
response->header_available_count = 25;
|
||||
response->header_available_size = 4 * 256 * sizeof(char);
|
||||
response->body_offset = response->header_available_count * sizeof(HttpHeaderElement) + response->header_available_size;
|
||||
|
||||
|
|
@ -256,6 +253,22 @@ HttpResponse* http_response_create(ThreadedChunkMemory* mem)
|
|||
return response;
|
||||
}
|
||||
|
||||
FORCE_INLINE
|
||||
void http_response_free(HttpResponse** response, ThreadedChunkMemory* mem)
|
||||
{
|
||||
thrd_chunk_free_elements(mem, (*response)->id, (*response)->size);
|
||||
*response = NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
uint32 http_response_free_body_space(const HttpResponse* response, ThreadedChunkMemory* mem)
|
||||
{
|
||||
return response->size * mem->chunk_size
|
||||
- response->body_offset
|
||||
- response->body_used_size
|
||||
- sizeof(HttpResponse);
|
||||
}
|
||||
|
||||
inline
|
||||
const char* http_response_body(const HttpResponse* response) {
|
||||
return ((const char *) (response + 1)) + response->body_offset;
|
||||
|
|
@ -282,7 +295,11 @@ const char* http_header_value_get(const HttpResponse* response, const HttpHeader
|
|||
|
||||
// @todo we need a streamed response version http_response_stream()
|
||||
// WARNING: We expect response to already contain a header element called content-length
|
||||
void http_response_send(const SocketConnection* __restrict socket, HttpResponse* __restrict response)
|
||||
void http_response_send(
|
||||
const SocketConnection* __restrict socket,
|
||||
HttpResponse* __restrict response,
|
||||
ThreadedChunkMemory* mem
|
||||
)
|
||||
{
|
||||
char header[4096];
|
||||
char* header_ref;
|
||||
|
|
@ -293,13 +310,15 @@ void http_response_send(const SocketConnection* __restrict socket, HttpResponse*
|
|||
header_ref += str_copy(header_ref, http_protocol_text(response->protocol));
|
||||
*header_ref++ = ' ';
|
||||
|
||||
header_ref += int_to_str(response->status_code, header_ref);
|
||||
*header_ref++ = ' ';
|
||||
header_ref += str_copy(header_ref, http_status_text(response->status_code));
|
||||
*header_ref++ = '\r';
|
||||
*header_ref++ = '\n';
|
||||
|
||||
char content_length[12];
|
||||
int_to_str(response->body_used_size, content_length);
|
||||
http_header_value_set(&response, HTTP_HEADER_KEY_CONTENT_LENGTH, content_length, NULL);
|
||||
http_header_value_set(&response, HTTP_HEADER_KEY_CONTENT_LENGTH, content_length, mem);
|
||||
|
||||
const HttpHeaderElement* elements = (HttpHeaderElement *) (response + 1);
|
||||
|
||||
|
|
@ -308,9 +327,11 @@ void http_response_send(const SocketConnection* __restrict socket, HttpResponse*
|
|||
const HttpHeaderElement* element = &elements[i];
|
||||
|
||||
header_ref += str_copy(header_ref, http_header_key_text(element->key));
|
||||
*header_ref++ = ':';
|
||||
*header_ref++ = ' ';
|
||||
|
||||
memcpy(header_ref, (const char *) elements + element->value_offset, element->value_length);
|
||||
// @bug What if the header array cannot fit the data from the memcpy?
|
||||
memcpy(header_ref, ((const char *) elements) + element->value_offset, element->value_length);
|
||||
header_ref += element->value_length;
|
||||
|
||||
*header_ref++ = '\r';
|
||||
|
|
@ -338,7 +359,7 @@ void http_response_send(const SocketConnection* __restrict socket, HttpResponse*
|
|||
send(socket->sd, header, header_ref - header, 0);
|
||||
|
||||
// Do we have data remaining to be sent?
|
||||
if (response->body_offset && response->body_used_size - body_size_to_add > 0) {
|
||||
if (response->body_used_size - body_size_to_add > 0) {
|
||||
// @question Do we need chunked sends?
|
||||
send(
|
||||
socket->sd,
|
||||
|
|
@ -365,7 +386,12 @@ void http_response_body_add(HttpResponse** response, const char* __restrict body
|
|||
response_body = (char*) (resp + 1);
|
||||
}
|
||||
|
||||
memcpy(response_body + resp->body_used_size, body, length);
|
||||
memcpy(
|
||||
response_body + resp->body_offset + resp->body_used_size,
|
||||
body,
|
||||
length
|
||||
);
|
||||
|
||||
resp->body_used_size += length;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <sys/syscall.h>
|
||||
|
||||
#define THREAD_RETURN int32
|
||||
#define THREAD_RETURN_BODY int32
|
||||
typedef THREAD_RETURN (*ThreadJobFunc)(void*);
|
||||
|
||||
struct mutex {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <windows.h>
|
||||
|
||||
#define THREAD_RETURN DWORD WINAPI
|
||||
#define THREAD_RETURN_BODY DWORD
|
||||
typedef DWORD (WINAPI *ThreadJobFunc)(void*);
|
||||
typedef CRITICAL_SECTION mutex;
|
||||
typedef void mutexattr_t;
|
||||
|
|
|
|||
|
|
@ -1165,7 +1165,7 @@ bool str_contains(const char* __restrict haystack, const char* __restrict needle
|
|||
inline constexpr
|
||||
bool str_contains(const char* __restrict haystack, const char* __restrict needle, size_t length) noexcept
|
||||
{
|
||||
while (*haystack != '\0' && length > 0) {
|
||||
while (*haystack != '\0' || length > 0) {
|
||||
const char* p1 = haystack;
|
||||
const char* p2 = needle;
|
||||
size_t remaining = length;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user