#include #include "http_loop.h" #include "log.h" #define MIN(x, y) (((x) < (y)) ? (x) : (y)) static const char *http_response_format = "HTTP/1.1 %i %s\n" "Content-Length: %lu\n\n"; void http_loop_init_header(http_response *res) { const char *response_type_name = http_response_type_names[res->type / 100 - 1][res->type % 100]; // Running snprintf with size 0 prevents it from writing any bytes, while // still letting it calculate how many bytes it would have written int buf_size = snprintf(NULL, 0, http_response_format, res->type, response_type_name, res->body_len); char *buf = malloc(buf_size + 1); sprintf(buf, http_response_format, res->type, response_type_name, res->body_len); res->head = buf; res->head_len = buf_size; } void http_loop_write_response(event_loop_conn *conn) { http_response *res = &((http_loop_ctx *)conn->ctx)->res; // Create head response if (res->head == NULL) { http_loop_init_header(res); } // The final iteration marks the end of the response, after which we reset the // context so a next request can be processed if (res->head_written == res->head_len && res->body_written == res->body_len) { http_loop_ctx_reset(conn->ctx); conn->state = event_loop_conn_state_req; return; } if (res->head_written < res->head_len) { size_t bytes_to_write = MIN(res->head_len - res->head_written, EVENT_LOOP_BUFFER_SIZE - conn->wbuf_size); memcpy(&conn->wbuf[conn->wbuf_size], &res->head[res->head_written], bytes_to_write); conn->wbuf_size += bytes_to_write; res->head_written += bytes_to_write; } if (res->body_written < res->body_len) { size_t bytes_to_write = MIN(res->body_len - res->body_written, EVENT_LOOP_BUFFER_SIZE - conn->wbuf_size); memcpy(&conn->wbuf[conn->wbuf_size], &res->body[res->body_written], bytes_to_write); conn->wbuf_size += bytes_to_write; res->body_written += bytes_to_write; } }