pico-bmc/http_parser.h
Arthur Lu e55c54f292 update sdk to 2.0,
fix potential buffer overflow issue in http_parser
2024-09-18 10:46:19 -07:00

146 lines
4.3 KiB
C

#ifndef HTTP_PARSER_H
#define HTTP_PARSER_H
#include "llhttp.h"
#define HTTP_RESPONSE_HEADER_TEMPLATE "HTTP/1.1 %d %s\nContent-Length: %d\nContent-Type: %s; charset=utf-8\nConnection: close\n\n"
typedef struct HTTP_REQUEST_DATA_T_ {
llhttp_method_t method;
char url[128];
char body[128];
} HTTP_REQUEST_DATA_T;
typedef struct HTTP_REQUEST_PARSER_T_ {
llhttp_t parser;
llhttp_settings_t settings;
} HTTP_REQUEST_PARSER_T;
int request_parser_on_url(llhttp_t * parser, const char * start, size_t length) {
HTTP_REQUEST_DATA_T * http_request = parser->data;
strncat(http_request->url, start, length);
return 0;
}
int request_parser_on_body(llhttp_t * parser, const char * start, size_t length) {
HTTP_REQUEST_DATA_T * http_request = parser->data;
strncat(http_request->body, start, length);
return 0;
}
int parse_http_request (HTTP_REQUEST_PARSER_T * wrapper, char * content, size_t len) {
llhttp_t parser = wrapper->parser;
llhttp_errno_t err = llhttp_execute(&parser, content, len);
HTTP_REQUEST_DATA_T * http_request = parser.data;
llhttp_method_t method = llhttp_get_method(&parser);
http_request->method = method;
return 0;
}
llhttp_method_t get_method (HTTP_REQUEST_PARSER_T * wrapper) {
HTTP_REQUEST_DATA_T * http_request = wrapper->parser.data;
return http_request->method;
}
char * get_url (HTTP_REQUEST_PARSER_T * wrapper) {
HTTP_REQUEST_DATA_T * http_request = wrapper->parser.data;
return http_request->url;
}
char * get_body (HTTP_REQUEST_PARSER_T * wrapper) {
HTTP_REQUEST_DATA_T * http_request = wrapper->parser.data;
return http_request->body;
}
HTTP_REQUEST_PARSER_T * new_request_parser () {
// create new response parser wrapper
HTTP_REQUEST_PARSER_T * wrapper = calloc(1, sizeof(HTTP_REQUEST_PARSER_T));
// create a new request data struct
HTTP_REQUEST_DATA_T * http_request = calloc(1, sizeof(HTTP_REQUEST_DATA_T));
// init http parser settings
llhttp_settings_init(&wrapper->settings);
wrapper->settings.on_url = &request_parser_on_url;
wrapper->settings.on_body = &request_parser_on_body;
// init http request parser parser
llhttp_init(&wrapper->parser, HTTP_REQUEST, &wrapper->settings);
wrapper->parser.data = http_request;
return wrapper;
}
void delete_request_parser (HTTP_REQUEST_PARSER_T * wrapper) {
free(wrapper->parser.data);
free(wrapper);
}
typedef struct HTTP_RESPONSE_DATA_T_ {
llhttp_status_t status;
char type[128];
char body[128];
} HTTP_RESPONSE_DATA_T;
typedef struct HTTP_RESPONSE_COMPOSER_T_ {
HTTP_RESPONSE_DATA_T * response_data;
char header[1024];
char body[128];
uint32_t header_length;
uint32_t content_length;
} HTTP_RESPONSE_COMPOSER_T;
void set_status (HTTP_RESPONSE_COMPOSER_T * composer, llhttp_status_t status) {
HTTP_RESPONSE_DATA_T * response_data = composer->response_data;
response_data->status = status;
}
void set_type (HTTP_RESPONSE_COMPOSER_T * composer, char * type) {
HTTP_RESPONSE_DATA_T * response_data = composer->response_data;
strncpy(response_data->type, type, 128);
}
void set_body (HTTP_RESPONSE_COMPOSER_T * composer, char * body) {
HTTP_RESPONSE_DATA_T * response_data = composer->response_data;
strncpy(response_data->body, body, 128);
}
void compose_http_response (HTTP_RESPONSE_COMPOSER_T * composer) {
HTTP_RESPONSE_DATA_T * response_data = composer->response_data;
composer->content_length = snprintf(composer->body, sizeof(composer->body), "%s", response_data->body);
const char * status_name = llhttp_status_name(response_data->status);
composer->header_length = snprintf(composer->header, sizeof(composer->header), HTTP_RESPONSE_HEADER_TEMPLATE, response_data->status, status_name, composer->content_length, response_data->type);
}
HTTP_RESPONSE_COMPOSER_T * new_response_composer () {
// create new response composer wrapper
HTTP_RESPONSE_COMPOSER_T * wrapper = calloc(1, sizeof(HTTP_RESPONSE_COMPOSER_T));
// create a new response data struct
HTTP_RESPONSE_DATA_T * http_response = calloc(1, sizeof(HTTP_RESPONSE_DATA_T));
wrapper->response_data = http_response;
return wrapper;
}
void delete_response_composer (HTTP_RESPONSE_COMPOSER_T * composer) {
free(composer->response_data);
free(composer);
}
int http_parser_init () {
return 0;
}
int http_parser_deinit () {
return 0;
}
#endif