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

Commit

Permalink
Merge pull request #46 from sftwrngnr/bug-fix/issue42
Browse files Browse the repository at this point in the history
Fix for issue #42. (and some refactoring)
  • Loading branch information
NathanFrench authored Nov 1, 2017
2 parents c56bd4f + 49abc00 commit 9650124
Showing 1 changed file with 105 additions and 33 deletions.
138 changes: 105 additions & 33 deletions evhtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2158,22 +2158,70 @@ htp__connection_readcb_(struct bufferevent * bev, void * arg)
static void
htp__connection_writecb_(struct bufferevent * bev, void * arg)
{
evhtp_connection_t * c;
evhtp_connection_t * conn;
uint64_t keepalive_max;
const char * errstr;

evhtp_assert(bev != NULL);

if (evhtp_unlikely(arg == NULL))
{
log_error("No data associated with the bufferevent %p", bev);

bufferevent_free(bev);
return;
}

errstr = NULL;
conn = (evhtp_connection_t *)arg;

do {
if (evhtp_unlikely(conn->request == NULL))
{
errstr = "no request associated with connection";
break;
}

if (evhtp_unlikely(conn->parser == NULL))
{
errstr = "no parser registered with connection";
break;
}

if (evhtp_likely(conn->type == evhtp_type_server))
{
if (evhtp_unlikely(conn->htp == NULL))
{
errstr = "no context associated with the server-connection";
break;
}

c = arg;
keepalive_max = conn->htp->max_keepalive_requests;
} else {
keepalive_max = 0;
}
} while (0);

evhtp_assert(c && c->htp && c->request && c->parser && bev);
if (evhtp_unlikely(errstr != NULL))
{
log_error("shutting down connection: %s", errstr);

evhtp_safe_free(conn, evhtp_connection_free);
return;
}

htp__hook_connection_write_(c);
/* run user-hook for on_write callback before further analysis */
htp__hook_connection_write_(conn);

if (evhtp_unlikely(c->flags & EVHTP_CONN_FLAG_PAUSED))
/* connection is in a paused state, no further processing yet */
if ((conn->flags & EVHTP_CONN_FLAG_PAUSED))
{
return;
}

if (c->flags & EVHTP_CONN_FLAG_WAITING)
if (conn->flags & EVHTP_CONN_FLAG_WAITING)
{
HTP_FLAG_OFF(c, EVHTP_CONN_FLAG_WAITING);
HTP_FLAG_OFF(conn, EVHTP_CONN_FLAG_WAITING);

bufferevent_enable(bev, EV_READ);

Expand All @@ -2185,7 +2233,12 @@ htp__connection_writecb_(struct bufferevent * bev, void * arg)
return;
}

if (!(c->request->flags & EVHTP_REQ_FLAG_FINISHED)
/* if the connection is not finished, OR there is data ready to output
* (can only happen if a user-defined connection_write hook added data
* manually, since this is called only when all data has been flushed)
* just return and wait.
*/
if (!(conn->request->flags & EVHTP_REQ_FLAG_FINISHED)
|| evbuffer_get_length(bufferevent_get_output(bev)))
{
return;
Expand All @@ -2196,55 +2249,66 @@ htp__connection_writecb_(struct bufferevent * bev, void * arg)
* to make sure we are not over it. If we have gone over the max we set the
* keepalive bit to 0, thus closing the connection.
*/
if (c->htp->max_keepalive_requests)
if (keepalive_max > 0)
{
if (++c->num_requests >= c->htp->max_keepalive_requests)
conn->num_requests += 1;

if (conn->num_requests >= keepalive_max)
{
HTP_FLAG_OFF(c->request, EVHTP_REQ_FLAG_KEEPALIVE);
HTP_FLAG_OFF(conn->request, EVHTP_REQ_FLAG_KEEPALIVE);
}
}

if (c->request->flags & EVHTP_REQ_FLAG_KEEPALIVE)
if (conn->request->flags & EVHTP_REQ_FLAG_KEEPALIVE)
{
htp_type type;

htp__request_free_(c->request);
/* free up the current request, set it to NULL, making
* way for the next request.
*/
evhtp_safe_free(conn->request, htp__request_free_);

HTP_FLAG_ON(c, EVHTP_CONN_FLAG_KEEPALIVE);
/* since the request is keep-alive, assure that the connection
* is aware of the same.
*/
HTP_FLAG_ON(conn, EVHTP_CONN_FLAG_KEEPALIVE);

c->request = NULL;
c->body_bytes_read = 0;
conn->body_bytes_read = 0;

if (c->htp->parent && c->flags & EVHTP_CONN_FLAG_VHOST_VIA_SNI)
if (conn->type == evhtp_type_server)
{
/* this request was servied by a virtual host evhtp_t structure
* which was *NOT* found via SSL SNI lookup. In this case we want to
* reset our connections evhtp_t structure back to the original so
* that subsequent requests can have a different Host: header.
*/
evhtp_t * orig_htp = c->htp->parent;

c->htp = orig_htp;
if (conn->htp->parent != NULL
&& !(conn->flags & EVHTP_CONN_FLAG_VHOST_VIA_SNI))
{
/* this request was served by a virtual host evhtp_t structure
* which was *NOT* found via SSL SNI lookup. In this case we want to
* reset our connections evhtp_t structure back to the original so
* that subsequent requests can have a different 'Host' header.
*/
conn->htp = conn->htp->parent;
}
}

switch (c->type) {
switch (conn->type) {
case evhtp_type_client:
type = htp_type_response;
break;
case evhtp_type_server:
type = htp_type_request;
break;
default:
evhtp_connection_free(c);
log_error("Unknown connection type");

evhtp_safe_free(conn, evhtp_connection_free);
return;
}

htparser_init(c->parser, type);
htparser_set_userdata(c->parser, c);
htparser_init(conn->parser, type);
htparser_set_userdata(conn->parser, conn);

return;
} else {
evhtp_connection_free(c);
evhtp_safe_free(conn, evhtp_connection_free);

return;
}
Expand Down Expand Up @@ -2680,6 +2744,10 @@ htp__ssl_add_scache_ent_(evhtp_ssl_t * ssl, evhtp_ssl_sess_t * sess)
int slen;

connection = (evhtp_connection_t *)SSL_get_app_data(ssl);
if (connection->htp == NULL)
{
return 0; /* We cannot get the ssl_cfg */
}
cfg = connection->htp->ssl_cfg;

sid = sess->session_id;
Expand All @@ -2703,6 +2771,10 @@ htp__ssl_get_scache_ent_(evhtp_ssl_t * ssl, unsigned char * sid, int sid_len, in
evhtp_ssl_sess_t * sess;

connection = (evhtp_connection_t * )SSL_get_app_data(ssl);
if (connection->htp == NULL)
{
return NULL; /* We have no way of getting ssl_cfg */
}
cfg = connection->htp->ssl_cfg;
sess = NULL;

Expand Down Expand Up @@ -4001,7 +4073,7 @@ evhtp_callback_new(const char * path, evhtp_callback_type type, evhtp_callback_c
} /* switch */

return hcb;
} /* evhtp_callback_new */
} /* evhtp_callback_new */

void
evhtp_callback_free(evhtp_callback_t * callback)
Expand Down Expand Up @@ -4121,7 +4193,7 @@ htp__set_hook_(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void
} /* switch */

return 0;
} /* htp__set_hook_ */
} /* htp__set_hook_ */

int
evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg)
Expand Down Expand Up @@ -5280,7 +5352,7 @@ evhtp_connection_ssl_new(struct event_base * evbase,
evhtp_assert(rc == 0);

return conn;
} /* evhtp_connection_ssl_new */
} /* evhtp_connection_ssl_new */

#endif

Expand Down

0 comments on commit 9650124

Please sign in to comment.