Skip to content

Commit

Permalink
Enable modules using httpd to trace their packets
Browse files Browse the repository at this point in the history
	Modules implementing httpd interface can now choose to
trace their httpd requests and replies by returning a trace
destination in their 'answer_to_connection' function.
	In order to get a trace destination one should be defined
within the implementing module and then searched using the interface
provided by the trace_api.
  • Loading branch information
ionutrazvanionita committed Oct 27, 2016
1 parent 8b5beec commit 37e1424
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 13 deletions.
13 changes: 12 additions & 1 deletion modules/httpd/httpd.c
Expand Up @@ -59,6 +59,8 @@ str buffer = {NULL, 0};
int post_buf_size = DEFAULT_POST_BUF_SIZE;
struct httpd_cb *httpd_cb_list = NULL;

union sockaddr_union httpd_server_info;


static proc_export_t mi_procs[] = {
{"HTTPD", 0, 0, httpd_proc, 1, PROC_FLAG_INITCHILD },
Expand Down Expand Up @@ -113,12 +115,20 @@ static int mod_init(void)
{
struct ip_addr *_ip;

memset(&httpd_server_info, 0, sizeof(union sockaddr_union));
httpd_server_info.sin.sin_port = port;

if (ip.s) {
ip.len = strlen(ip.s);
if ( (_ip=str2ip(&ip)) == NULL ) {
LM_ERR("invalid IP [%.*s]\n", ip.len, ip.s);
return -1;
}
httpd_server_info.sin.sin_addr.s_addr = _ip->u.addr32[0];
httpd_server_info.sin.sin_family = _ip->af;
} else {
httpd_server_info.sin.sin_addr.s_addr = INADDR_LOOPBACK;
httpd_server_info.sin.sin_family = AF_INET;
}

if (post_buf_size < MIN_POST_BUF_SIZE) {
Expand Down Expand Up @@ -209,8 +219,9 @@ int httpd_bind(httpd_api_t *api)
return -1;
}

api->lookup_arg = httpd_lookup_arg;
api->lookup_arg = httpd_lookup_arg;
api->register_httpdcb = httpd_register_httpdcb;

return 0;
}

Expand Down
7 changes: 6 additions & 1 deletion modules/httpd/httpd_load.h
Expand Up @@ -29,6 +29,8 @@

#define HTTPD_UNKNOWN_CONTENT_LEN -1

#include "../../mi/mi_trace.h"

enum HTTPD_CONTENT_TYPE {
HTTPD_UNKNOWN_CNT_TYPE = -1,
HTTPD_STD_CNT_TYPE = 0,
Expand Down Expand Up @@ -62,13 +64,16 @@ enum HTTPD_CONTENT_TYPE {
* @param page the page to return. If no page is returned,
* then the page will be built later on via a
* callback (see httpd_flush_data_cb)
* @param dest trace destination. if is set to something different
* than NULL the httpd request and respond will be traced
* to that destination
* @returns code the HTTP code to be returned to the client
*/
typedef int (httpd_acces_handler_cb) (void *cls, void *connection, const char *url,
const char *method, const char *version,
const char *upload_data, size_t *upload_data_size,
void **con_cls,
str *buffer, str *page);
str *buffer, str *page, trace_dest* dest);

/**
* Callback used by httpd in order to obtain content. The
Expand Down
105 changes: 102 additions & 3 deletions modules/httpd/httpd_proc.c
Expand Up @@ -48,18 +48,28 @@
#include "../../sliblist.h"
#include "httpd_load.h"

/* should be more than enough */
#define REQ_BUF_SIZE 2048

extern int port;
extern str ip;
extern str buffer;
extern int post_buf_size;
extern struct httpd_cb *httpd_cb_list;

/* if tracing is activated we'll store the request here */
static char req_buf[REQ_BUF_SIZE];


static const str MI_HTTP_U_URL = str_init("<html><body>"
"Unable to parse URL!</body></html>");
static const str MI_HTTP_U_METHOD = str_init("<html><body>"
"Unsupported HTTP request!</body></html>");

extern union sockaddr_union httpd_server_info;
static inline int trace_httpd_message(union sockaddr_union* src, union sockaddr_union* dst,
str* body, trace_dest trace_dst);

/**
* Data structure to store inside elents of slinkedl_list list.
*/
Expand Down Expand Up @@ -387,6 +397,51 @@ void httpd_lookup_arg(void *connection, const char *key,
return;
}

int reqHdrs_Iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
{
int bytes;
str* http_req = cls;


bytes = snprintf(http_req->s + http_req->len, REQ_BUF_SIZE - http_req->len,
"%s: %s\r\n", key, value);

http_req->len += bytes;

/* if no space in the buffer stop iterating through headers */
if (bytes <= 0) {
LM_ERR("buffer too small! failed to create http request!\n");
return MHD_NO;
}

return MHD_YES;
}

/*
* WARNING as the httpd documentation states this function shall only be
* called from answer_to_connection(MHD_AccessHandlerCallback) otherwise,
* access maybe improperly synchronized
*
*/
static int get_request_buffer(struct MHD_Connection *connection, const char *url,
const char *method, const char *version, str* request)
{
str http_req = {req_buf, 0};

if (request == NULL) {
LM_ERR("bad usage!\n");
return -1;
}

http_req.len = snprintf(http_req.s, REQ_BUF_SIZE, "%s %s %s\r\n", method, url, version);

/* don't check retcode; it's the number of headers iterated through, we don't need that */
MHD_get_connection_values(connection, MHD_HEADER_KIND, reqHdrs_Iterator, &http_req);

*request = http_req;

return 0;
}

int answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
Expand All @@ -406,6 +461,10 @@ int answer_to_connection (void *cls, struct MHD_Connection *connection,
int accept_type = HTTPD_STD_CNT_TYPE;
int ret_code = MHD_HTTP_OK;

str http_request;
union sockaddr_union* cl_socket;
trace_dest t_dst=NULL;

LM_DBG("START *** cls=%p, connection=%p, url=%s, method=%s, "
"versio=%s, upload_data[%zu]=%p, *con_cls=%p\n",
cls, connection, url, method, version,
Expand Down Expand Up @@ -503,7 +562,7 @@ int answer_to_connection (void *cls, struct MHD_Connection *connection,
normalised_url,
method, version,
upload_data, upload_data_size, con_cls,
&buffer, &page);
&buffer, &page, &t_dst);
} else {
page = MI_HTTP_U_URL;
ret_code = MHD_HTTP_BAD_REQUEST;
Expand Down Expand Up @@ -589,7 +648,7 @@ int answer_to_connection (void *cls, struct MHD_Connection *connection,
normalised_url,
method, version,
upload_data, upload_data_size, con_cls,
&buffer, &page);
&buffer, &page, &t_dst);
} else {
page = MI_HTTP_U_URL;
ret_code = MHD_HTTP_BAD_REQUEST;
Expand All @@ -613,7 +672,7 @@ int answer_to_connection (void *cls, struct MHD_Connection *connection,
normalised_url,
method, version,
upload_data, upload_data_size, con_cls,
&buffer, &page);
&buffer, &page, &t_dst);
} else {
page = MI_HTTP_U_URL;
ret_code = MHD_HTTP_BAD_REQUEST;
Expand Down Expand Up @@ -649,6 +708,27 @@ int answer_to_connection (void *cls, struct MHD_Connection *connection,
(void*)async_data,
NULL);
}

/* trace response and request
* FIXME is the len in 'page' str good if MHD_create_response_from_callback
* is used? (it looks like not). how shall we get the buffer
* */
if (t_dst) {
/* FIXME get this only if trace is on */
cl_socket = *(union sockaddr_union**)MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
get_request_buffer(connection, url, method, version, &http_request);

if (trace_httpd_message(cl_socket, NULL, &http_request, t_dst) < 0) {
LM_ERR("failed to trace http request!\n");
return -1;
}

if (trace_httpd_message(NULL, cl_socket, &page, t_dst) < 0) {
LM_ERR("failed to trace http reply!\n");
return -1;
}
}

if (cnt_type==HTTPD_TEXT_XML_CNT_TYPE || accept_type==HTTPD_TEXT_XML_CNT_TYPE)
MHD_add_response_header(response,
MHD_HTTP_HEADER_CONTENT_TYPE,
Expand Down Expand Up @@ -765,3 +845,22 @@ void httpd_proc_destroy(void)
#endif
return;
}


/*
* trace httpd message function(the module is not related only to mi requests
* trace_mi_message name might be confusing
*
*/
static inline int trace_httpd_message(union sockaddr_union* src, union sockaddr_union* dst,
str* body, trace_dest trace_dst)
{
/* one of them must be null; this will be the server for whom we already know
* listening socket information */
if ((src && dst) || !(src || dst)) {
LM_ERR("bad usage! one of the source and destination must be null!\n");
return -1;
}

return trace_mi_message(src?src:&httpd_server_info, dst?dst:&httpd_server_info, body, trace_dst);
}
4 changes: 2 additions & 2 deletions modules/mi_http/mi_http.c
Expand Up @@ -41,7 +41,7 @@ int mi_http_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page);
str *buffer, str *page, trace_dest* dest);
static ssize_t mi_http_flush_data(void *cls, uint64_t pos, char *buf, size_t max);

str http_root = str_init("mi");
Expand Down Expand Up @@ -252,7 +252,7 @@ int mi_http_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page)
str *buffer, str *page, trace_dest* dest)
{
int mod = -1;
int cmd = -1;
Expand Down
4 changes: 2 additions & 2 deletions modules/mi_json/mi_json.c
Expand Up @@ -41,7 +41,7 @@ int mi_json_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page);
str *buffer, str *page, trace_dest* dest);
static ssize_t mi_json_flush_data(void *cls, uint64_t pos, char *buf,
size_t max);

Expand Down Expand Up @@ -243,7 +243,7 @@ int mi_json_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page)
str *buffer, str *page, trace_dest* dest)
{
str command = {NULL, 0};
str params = {NULL, 0};
Expand Down
4 changes: 2 additions & 2 deletions modules/mi_xmlrpc_ng/mi_xmlrpc_http.c
Expand Up @@ -41,7 +41,7 @@ int mi_xmlrpc_http_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page);
str *buffer, str *page, trace_dest* dest);
static ssize_t mi_xmlrpc_http_flush_data(void *cls, uint64_t pos, char *buf, size_t max);

str http_root = str_init("RPC2");
Expand Down Expand Up @@ -256,7 +256,7 @@ int mi_xmlrpc_http_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page)
str *buffer, str *page, trace_dest* dest)
{
str arg = {NULL, 0};
struct mi_root *tree = NULL;
Expand Down
4 changes: 2 additions & 2 deletions modules/pi_http/pi_http.c
Expand Up @@ -47,7 +47,7 @@ int ph_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page);
str *buffer, str *page, trace_dest* dest);
static ssize_t ph_flush_data(void *cls, uint64_t pos, char *buf, size_t max);
static struct mi_root *mi_framework_reload(struct mi_root* cmd, void* param);

Expand Down Expand Up @@ -238,7 +238,7 @@ int ph_answer_to_connection (void *cls, void *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls,
str *buffer, str *page)
str *buffer, str *page, trace_dest* dest)
{
int mod = -1;
int cmd = -1;
Expand Down

0 comments on commit 37e1424

Please sign in to comment.