Skip to content
This repository has been archived by the owner on Jun 30, 2021. It is now read-only.

[#93] make on_conn_error and on_error hooks unique #98

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

NathanFrench
Copy link
Collaborator

@NathanFrench NathanFrench commented Jun 23, 2018

The functions htp_hook_error_() is only called for request-ish errors
while htp_hook_connection_error_() is only called for connection-ish
errors.

This mainly applies to the following functions:

htp__connection_readcb_ :
if EVHTP_RES_DATA_TOO_LONG is the connection request return value,
both hook_error_() and hook_connection_error() are called.

if there is a parser error, hook_connection_error_() is called
with the error type of EVHTP_RES_PARSER_ERROR

evbuffer_drain is now called before the connection request status
switch/case statement, and EVHTP_RES_PAUSE is now a case (moved)

htp__connection_eventcb_
!!!!! PLEASE MAKE NOTE OF THIS CHANGE !!!!!

this function now calls htp__hook_connection_error_() but no
longer calls htp__hook_request_error_() to match the naming
scheme.

prior to this, both request_error and connection_error was called
within this function.

The functions htp_hook_error_() is only called for request-ish errors
while htp_hook_connection_error_() is only called for connection-ish
errors.

This mainly applies to the following functions:

`htp__connection_readcb_` :
    if `EVHTP_RES_DATA_TOO_LONG` is the connection request return value,
    both `hook_error_()` and `hook_connection_error()` are called.

    if there is a parser error, `hook_connection_error_()` is called
    with the error type of `EVHTP_RES_PARSER_ERROR`

    `evbuffer_drain` is now called before the connection request status
    switch/case statement, and `EVHTP_RES_PAUSE` is now a case (moved)

`htp__connection_eventcb_`
    !!!!! PLEASE MAKE NOTE OF THIS CHANGE !!!!!
    this function now calls `htp__hook_connection_error_()` but no
    longer calls `htp__hook_request_error_()` to match the naming
    scheme.

    prior to this, both request_error and connection_error was called
    within this function.
@damonearp
Copy link

Just did a test of the connection timeouts and found a segfault.

set error handlers like so:

static void connection_error_callback(evhtp_connection_t *conn, evhtp_error_flags type, void *arg)
{
    log("unhandled connection error of type: 0x%02x", type);
}

static void request_error_callback(evhtp_request_t *req, evhtp_error_flags type, void *arg)
{
    log("unhandled request error of type: 0x%02x", type);
}

evhtp_res pre_accept_callback(evhtp_connection_t *conn, void *arg)
{
    evhtp_connection_set_hook(conn, evhtp_hook_on_conn_error, (void*) &connection_error_callback,  NULL);
    evhtp_connection_set_hook(conn, evhtp_hook_on_error,      (void*) &request_error_callback,     NULL);
    return EVHTP_RES_OK;
}

int server_init()
{
    struct timeval connection_timeout;
    connection_timeout.tv_sec = 1;
    connection_timeout.tv_usec = 0;
    evhtp_set_timeouts(server->evhtp, &connection_timeout, &connection_timeout);
    ...
}

I then connected to the server with nc and no http request:

$ nc localhost 8080

Server Output

$ ./evhtp_to 
connection_error_callback:159   unhandled connection error of type: 0x41
Segmentation fault: 11

Debugging with lldb

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
    frame #0: 0x000000010003f276 evhtp_to `htp__hook_request_error_(req=0x0000000000000000, err='A') at evhtp.c:776
   773 	static inline void
   774 	htp__hook_request_error_(struct evhtp_request * req, evhtp_error_flags err)
   775 	{
-> 776 	    if (HOOK_AVAIL(req, on_error)) {
   777 	        (req->rh_err)(req, err, req->rh_err_arg);
   778 	    }
   779 	}
Target 0: (evhtp_to) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
  * frame #0: 0x000000010003f276 evhtp_to `htp__hook_request_error_(req=0x0000000000000000, err='A') at evhtp.c:776
    frame #1: 0x000000010003db19 evhtp_to `htp__connection_eventcb_(bev=0x00000001006004a0, events=65, arg=0x00000001006001e0) at evhtp.c:2569
    frame #2: 0x00000001003d011a libevent_core-2.1.6.dylib`bufferevent_run_deferred_callbacks_locked + 266
    frame #3: 0x00000001003dd0c1 libevent_core-2.1.6.dylib`event_process_active_single_queue + 1009
    frame #4: 0x00000001003d91af libevent_core-2.1.6.dylib`event_base_loop + 1119
    frame #5: 0x00000001000035d1 evhtp_to`main(argc=1, argv=0x00007fff5fbff9f0) at main.c:39
    frame #6: 0x00007fffbdd6c235 libdyld.dylib`start + 1
(lldb) up 1
frame #1: 0x000000010003db19 evhtp_to`htp__connection_eventcb_(bev=0x00000001006004a0, events=65, arg=0x00000001006001e0) at evhtp.c:2569
   2566	    HTP_FLAG_OFF(c, EVHTP_CONN_FLAG_CONNECTED);
   2567	
   2568	    htp__hook_connection_error_(c, events);
-> 2569	    htp__hook_request_error_(c->request, events);
   2570	
   2571	    if (c->flags & EVHTP_CONN_FLAG_PAUSED)
   2572	    {
(lldb) 

@NathanFrench
Copy link
Collaborator Author

NathanFrench commented Jun 26, 2018

I'm thinking about removing the request error callback, as it was not being used before, and it's even confusing me, as request can free connection, and vice versa. (That's what is happening here, connection_free frees request, and sets the pointer to NULL

So I think it would be prudent to have an event callback, and a generic error callback. You know, like it was before, but without having the option for a request error callback.

@damonearp
Copy link

Basically it would be nice to be able to differentiate between timeouts, parsing errors, client disconnects, etc so they can be logged. If that's achievable with one error callback go for it.

@NathanFrench
Copy link
Collaborator Author

Basically it would be nice to be able to differentiate between timeouts, parsing
errors, client disconnects, etc so they can be logged. If that's achievable with one error callback go for it.

I'm on it. Thanks for the feedback!

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants