From 8db36e1912d4ed04e82ea9ec4cbf844a666a1395 Mon Sep 17 00:00:00 2001 From: Vlad Paiu Date: Thu, 12 Dec 2024 12:08:26 +0000 Subject: [PATCH 1/2] Support HTTP fragmentation --- modules/httpd/httpd_proc.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/modules/httpd/httpd_proc.c b/modules/httpd/httpd_proc.c index c097640ed8a..fa989fa2da2 100644 --- a/modules/httpd/httpd_proc.c +++ b/modules/httpd/httpd_proc.c @@ -132,6 +132,24 @@ int httpd_get_val(void *e_data, void *data, void *r_data) return 0; } +static char httpd_full_buff[16384]; +static int httpd_full_buff_pos=0; +int httpd_merge_data(void *e_data, void *data, void *r_data) +{ + str_str_t *kv = (str_str_t*)e_data; + if (kv==NULL) { + LM_ERR("null data\n"); + } else { + LM_DBG("data=[%p] [%p][%p] [%.*s]->[%.*s]\n", + kv, kv->key.s, kv->val.s, + kv->key.len, kv->key.s, + kv->val.len, kv->val.s); + memcpy(httpd_full_buff+httpd_full_buff_pos,kv->val.s,kv->val.len); + httpd_full_buff_pos+=kv->val.len; + } + return 0; +} + /** * Function to print data stored in slinkedl_list list elemnts. * For debugging purposes only. @@ -498,9 +516,12 @@ MHD_RET answer_to_connection (void *cls, struct MHD_Connection *connection, if (cb) { normalised_url = &url[cb->http_root->len+1]; LM_DBG("normalised_url=[%s]\n", normalised_url); - kv = slinkedl_peek(pr->p_list); - if (kv) - saved_body = ((str_str_t *)kv)->val; + httpd_full_buff_pos=0; + slinkedl_traverse(pr->p_list,&httpd_merge_data, NULL, NULL); + if (httpd_full_buff_pos>0) { + saved_body.len = httpd_full_buff_pos; + saved_body.s = httpd_full_buff; + } ret_code = cb->callback(cls, (void*)connection, normalised_url, method, version, @@ -529,11 +550,6 @@ MHD_RET answer_to_connection (void *cls, struct MHD_Connection *connection, err log printed in getConnectionHeader() */ return MHD_NO; } - if (*upload_data_size != pr->content_len) { - /* For now, we don't support large POST with truncated data */ - LM_ERR("got a truncated POST request\n"); - return MHD_NO; - } LM_DBG("got ContentType [%d] with len [%d]: %.*s\n", pr->content_type, pr->content_len, (int)*upload_data_size, upload_data); From 15d433d8531fc208741af0e77412bb8ad736648d Mon Sep 17 00:00:00 2001 From: Vlad Paiu Date: Thu, 12 Dec 2024 20:32:07 +0200 Subject: [PATCH 2/2] Add receive_buf_size param --- modules/httpd/doc/httpd_admin.xml | 19 +++++++++++++++++++ modules/httpd/httpd.c | 10 ++++++++++ modules/httpd/httpd_proc.c | 23 +++++++++++++++-------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/modules/httpd/doc/httpd_admin.xml b/modules/httpd/doc/httpd_admin.xml index 4107b8c523a..2174d8f8b2a 100644 --- a/modules/httpd/doc/httpd_admin.xml +++ b/modules/httpd/doc/httpd_admin.xml @@ -190,6 +190,25 @@ modparam("httpd", "buf_size", 524288) ... modparam("httpd", "post_buf_size", 4096) ... + + + + +
+ <varname>receive_buf_size</varname> (integer) + + It specifies the maximum length (in bytes) of the received HTTP requests. + For receiving large POST request, the default value might require to be increased. + + + The default value is 1024. + + + Set <varname>receive_buf_size</varname> parameter + +... +modparam("httpd", "receive_buf_size", 4096) +...
diff --git a/modules/httpd/httpd.c b/modules/httpd/httpd.c index 3ae1ffb0538..1c64d34214f 100644 --- a/modules/httpd/httpd.c +++ b/modules/httpd/httpd.c @@ -64,8 +64,11 @@ str tls_cert_file = {NULL, 0}; str tls_key_file = {NULL, 0}; str tls_ciphers = {"SECURE256:+SECURE192:-VERS-ALL:+VERS-TLS1.2", 45}; int post_buf_size = DEFAULT_POST_BUF_SIZE; +int receive_buf_size = DEFAULT_POST_BUF_SIZE; struct httpd_cb *httpd_cb_list = NULL; +char *httpd_receive_buff = NULL; +int httpd_receive_buff_pos=0; static const proc_export_t mi_procs[] = { {"HTTPD", 0, 0, httpd_proc, 1, @@ -81,6 +84,7 @@ static const param_export_t params[] = { {"buf_size", INT_PARAM, &buffer.len}, {"conn_timeout", INT_PARAM, &hd_conn_timeout_s}, {"post_buf_size", INT_PARAM, &post_buf_size}, + {"receive_buf_size", INT_PARAM, &receive_buf_size}, {"tls_cert_file", STR_PARAM, &tls_cert_file.s}, {"tls_key_file", STR_PARAM, &tls_key_file.s}, {"tls_ciphers", STR_PARAM, &tls_ciphers.s}, @@ -185,6 +189,12 @@ static int mod_init(void) buffer.len = (pkg_mem_size/4); LM_DBG("buf_size=[%d]\n", buffer.len); + httpd_receive_buff = pkg_malloc(receive_buf_size); + if (httpd_receive_buff == NULL) { + LM_ERR("No more pkg\n"); + return -1; + } + return 0; } diff --git a/modules/httpd/httpd_proc.c b/modules/httpd/httpd_proc.c index fa989fa2da2..0d4b43f207d 100644 --- a/modules/httpd/httpd_proc.c +++ b/modules/httpd/httpd_proc.c @@ -62,6 +62,11 @@ extern str tls_ciphers; extern struct httpd_cb *httpd_cb_list; static union sockaddr_union httpd_server_info; + +extern int receive_buf_size; +extern char *httpd_receive_buff; +extern int httpd_receive_buff_pos; + static const str MI_HTTP_U_URL = str_init("" "Unable to parse URL!"); static const str MI_HTTP_U_METHOD = str_init("" @@ -132,8 +137,6 @@ int httpd_get_val(void *e_data, void *data, void *r_data) return 0; } -static char httpd_full_buff[16384]; -static int httpd_full_buff_pos=0; int httpd_merge_data(void *e_data, void *data, void *r_data) { str_str_t *kv = (str_str_t*)e_data; @@ -144,8 +147,12 @@ int httpd_merge_data(void *e_data, void *data, void *r_data) kv, kv->key.s, kv->val.s, kv->key.len, kv->key.s, kv->val.len, kv->val.s); - memcpy(httpd_full_buff+httpd_full_buff_pos,kv->val.s,kv->val.len); - httpd_full_buff_pos+=kv->val.len; + if (httpd_receive_buff_pos + kv->val.len > receive_buf_size) { + LM_ERR("Received too big HTTP request ( %d bytes ), increase receive_buf_size param value\n", httpd_receive_buff_pos + kv->val.len); + } else { + memcpy(httpd_receive_buff+httpd_receive_buff_pos,kv->val.s,kv->val.len); + httpd_receive_buff_pos+=kv->val.len; + } } return 0; } @@ -516,11 +523,11 @@ MHD_RET answer_to_connection (void *cls, struct MHD_Connection *connection, if (cb) { normalised_url = &url[cb->http_root->len+1]; LM_DBG("normalised_url=[%s]\n", normalised_url); - httpd_full_buff_pos=0; + httpd_receive_buff_pos=0; slinkedl_traverse(pr->p_list,&httpd_merge_data, NULL, NULL); - if (httpd_full_buff_pos>0) { - saved_body.len = httpd_full_buff_pos; - saved_body.s = httpd_full_buff; + if (httpd_receive_buff_pos>0) { + saved_body.len = httpd_receive_buff_pos; + saved_body.s = httpd_receive_buff; } ret_code = cb->callback(cls, (void*)connection, normalised_url,