From 087e9a77269af5c10a6945c3b48755e82eeab3fd Mon Sep 17 00:00:00 2001 From: Nathan French Date: Mon, 22 May 2017 16:20:00 -0700 Subject: [PATCH] EVHTP_CONN flags - The following bitflags have been replaced with the following bitmasks inside the connection context. error : EVHTP_CONN_FLAG_ERROR owner : EVHTP_CONN_FLAG_OWNER vhost_via : EVHTP_CONN_FLAG_VHOST_VIA_SNI paused : EVHTP_CONN_FLAG_PAUSED connected : EVHTP_CONN_FLAG_CONNECTED waiting : EVHTP_CONN_FLAG_WAITING free : EVHTP_CONN_FLAG_FREE_CONN keepalive : EVHTP_CONN_FLAG_KEEPALIVE - Side effects: users should not notice any changes, these are mostly internal flags. --- evhtp.c | 105 +++++++++++++++++++++++++++++--------------------------- evhtp.h | 30 ++++++++-------- 2 files changed, 71 insertions(+), 64 deletions(-) diff --git a/evhtp.c b/evhtp.c index c8a6a7c..34136c2 100644 --- a/evhtp.c +++ b/evhtp.c @@ -1114,7 +1114,7 @@ htp__request_parse_start_(htparser * p) return 0; } - if (evhtp_unlikely(c->paused == 1)) + if (c->flags & EVHTP_CONN_FLAG_PAUSED) { return -1; } @@ -1432,7 +1432,7 @@ htp__request_parse_hostname_(htparser * p, const char * data, size_t len) evhtp_t * evhtp_vhost; #ifndef EVHTP_DISABLE_SSL - if (c->vhost_via_sni == 1 && c->ssl != NULL) + if ((c->flags & EVHTP_CONN_FLAG_VHOST_VIA_SNI) && c->ssl != NULL) { /* use the SNI set hostname instead of the header hostname */ const char * host; @@ -1636,7 +1636,7 @@ htp__request_parse_body_(htparser * p, const char * data, size_t len) if (c->max_body_size > 0 && c->body_bytes_read + len >= c->max_body_size) { - c->error = 1; + c->flags |= EVHTP_CONN_FLAG_ERROR; c->request->status = EVHTP_RES_DATA_TOO_LONG; return -1; @@ -1645,7 +1645,6 @@ htp__request_parse_body_(htparser * p, const char * data, size_t len) buf = c->scratch_buf; evhtp_assert(buf != NULL); - evbuffer_add(buf, data, len); if ((c->request->status = htp__hook_body_(c->request, buf)) != EVHTP_RES_OK) @@ -1761,7 +1760,7 @@ htp__request_parse_fini_(htparser * p) { evhtp_connection_t * c = htparser_get_userdata(p); - if (c->paused == 1) + if (c->flags & EVHTP_CONN_FLAG_PAUSED) { return -1; } @@ -1802,7 +1801,7 @@ htp__request_parse_fini_(htparser * p) (c->request->cb)(c->request, c->request->cbarg); } - if (c->paused == 1) + if (c->flags & EVHTP_CONN_FLAG_PAUSED) { return -1; } @@ -1955,14 +1954,15 @@ htp__connection_resumecb_(int fd, short events, void * arg) { evhtp_connection_t * c = arg; - c->paused = 0; + /* unset the pause flag */ + c->flags &= ~EVHTP_CONN_FLAG_PAUSED; if (c->request) { c->request->status = EVHTP_RES_OK; } - if (c->free_connection == 1) + if (c->flags & EVHTP_CONN_FLAG_FREE_CONN) { evhtp_connection_free(c); @@ -1978,8 +1978,9 @@ htp__connection_resumecb_(int fd, short events, void * arg) if (evbuffer_get_length(bufferevent_get_output(c->bev))) { + c->flags |= EVHTP_CONN_FLAG_WAITING; + bufferevent_enable(c->bev, EV_WRITE); - c->waiting = 1; } else { bufferevent_enable(c->bev, EV_READ | EV_WRITE); htp__connection_readcb_(c->bev, c); @@ -2010,7 +2011,7 @@ htp__connection_readcb_(evbev_t * bev, void * arg) c->request->status = EVHTP_RES_OK; } - if (c->paused == 1) + if (c->flags & EVHTP_CONN_FLAG_PAUSED) { return; } @@ -2023,7 +2024,7 @@ htp__connection_readcb_(evbev_t * bev, void * arg) htp_log_debug("nread = %zu", nread); - if (evhtp_unlikely(c->owner != 1)) + if (!(c->flags & EVHTP_CONN_FLAG_OWNER)) { /* * someone has taken the ownership of this connection, we still need to @@ -2061,7 +2062,7 @@ htp__connection_readcb_(evbev_t * bev, void * arg) /* we still have more data to read (piped request probably) */ evhtp_connection_resume(c); } -} /* htp__connection_readcb_ */ +} /* htp__connection_readcb_ */ static void htp__connection_writecb_(evbev_t * bev, void * arg) @@ -2077,14 +2078,14 @@ htp__connection_writecb_(evbev_t * bev, void * arg) htp__hook_connection_write_(c); - if (evhtp_unlikely(c->paused == 1)) + if (evhtp_unlikely(c->flags & EVHTP_CONN_FLAG_PAUSED)) { return; } - if (evhtp_unlikely(c->waiting == 1)) + if (c->flags & EVHTP_CONN_FLAG_WAITING) { - c->waiting = 0; + c->flags &= ~EVHTP_CONN_FLAG_WAITING; bufferevent_enable(bev, EV_READ); @@ -2119,11 +2120,11 @@ htp__connection_writecb_(evbev_t * bev, void * arg) { htp__request_free_(c->request); - c->keepalive = 1; + c->flags |= EVHTP_CONN_FLAG_KEEPALIVE; c->request = NULL; c->body_bytes_read = 0; - if (c->htp->parent && c->vhost_via_sni == 0) + if (c->htp->parent && c->flags & EVHTP_CONN_FLAG_VHOST_VIA_SNI) { /* 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 @@ -2146,7 +2147,7 @@ htp__connection_writecb_(evbev_t * bev, void * arg) } return; -} /* htp__connection_writecb_ */ +} /* htp__connection_writecb_ */ static void htp__connection_eventcb_(evbev_t * bev, short events, void * arg) @@ -2162,7 +2163,8 @@ htp__connection_eventcb_(evbev_t * bev, short events, void * arg) { if (evhtp_likely(c->type == evhtp_type_client)) { - c->connected = 1; + c->flags |= EVHTP_CONN_FLAG_CONNECTED; + bufferevent_setcb(bev, htp__connection_readcb_, htp__connection_writecb_, @@ -2176,7 +2178,7 @@ htp__connection_eventcb_(evbev_t * bev, short events, void * arg) if (c->ssl && !(events & BEV_EVENT_EOF)) { /* XXX need to do better error handling for SSL specific errors */ - c->error = 1; + c->flags |= EVHTP_CONN_FLAG_ERROR; if (c->request) { @@ -2204,21 +2206,24 @@ htp__connection_eventcb_(evbev_t * bev, short events, void * arg) } } - c->error = 1; - c->connected = 0; + /* set the error mask */ + c->flags |= EVHTP_CONN_FLAG_ERROR; + + /* unset connected flag */ + c->flags &= ~EVHTP_CONN_FLAG_CONNECTED; htp__hook_connection_error_(c, events); - if (c->paused == 1) + if (c->flags & EVHTP_CONN_FLAG_PAUSED) { /* we are currently paused, so we don't want to free just yet, let's * wait till the next loop. */ - c->free_connection = 1; + c->flags |= EVHTP_CONN_FLAG_FREE_CONN; } else { evhtp_connection_free((evhtp_connection_t *)arg); } -} /* htp__connection_eventcb_ */ +} /* htp__connection_eventcb_ */ static int htp__run_pre_accept_(evhtp_t * htp, evhtp_connection_t * conn) @@ -2347,10 +2352,7 @@ htp__connection_new_(evhtp_t * htp, evutil_socket_t sock, evhtp_type type) connection->scratch_buf = evbuffer_new(); evhtp_alloc_assert(connection->scratch_buf); - connection->error = 0; - connection->owner = 1; - connection->paused = 0; - connection->connected = 0; + connection->flags = EVHTP_CONN_FLAG_OWNER; connection->sock = sock; connection->htp = htp; connection->type = type; @@ -2366,7 +2368,7 @@ htp__connection_new_(evhtp_t * htp, evutil_socket_t sock, evhtp_type type) #endif return connection; -} /* htp__connection_new_ */ +} /* htp__connection_new_ */ #ifdef LIBEVENT_HAS_SHUTDOWN #ifndef EVHTP_DISABLE_SSL @@ -2475,7 +2477,7 @@ htp__accept_cb_(evserv_t * serv, int fd, struct sockaddr * s, int sl, void * arg return; } -} /* htp__accept_cb_ */ +} /* htp__accept_cb_ */ #ifndef EVHTP_DISABLE_SSL #ifndef EVHTP_DISABLE_EVTHR @@ -2596,8 +2598,8 @@ htp__ssl_servername_(evhtp_ssl_t * ssl, int * unused, void * arg) if ((evhtp_vhost = htp__request_find_vhost_(evhtp, sname))) { - connection->htp = evhtp_vhost; - connection->vhost_via_sni = 1; + connection->htp = evhtp_vhost; + connection->flags |= EVHTP_CONN_FLAG_VHOST_VIA_SNI; SSL_set_SSL_CTX(ssl, evhtp_vhost->ssl_ctx); SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx)); @@ -2613,7 +2615,7 @@ htp__ssl_servername_(evhtp_ssl_t * ssl, int * unused, void * arg) } return SSL_TLSEXT_ERR_NOACK; -} /* htp__ssl_servername_ */ +} /* htp__ssl_servername_ */ #endif @@ -2641,7 +2643,7 @@ evhtp_connection_pause(evhtp_connection_t * c) { evhtp_assert(c != NULL); - c->paused = 1; + c->flags |= EVHTP_CONN_FLAG_PAUSED; bufferevent_disable(c->bev, EV_READ | EV_WRITE); @@ -2658,7 +2660,7 @@ evhtp_connection_resume(evhtp_connection_t * c) { evhtp_assert(c != NULL); - c->paused = 0; + c->flags &= ~EVHTP_CONN_FLAG_PAUSED; event_active(c->resume_ev, EV_WRITE, 1); @@ -3010,7 +3012,7 @@ evhtp_is_hex_query_char(unsigned char ch) default: return 0; - } /* switch */ + } /* switch */ } enum unscape_state { @@ -3204,7 +3206,7 @@ evhtp_parse_query_wflags(const char * query, size_t len, int flags) key_buf[key_idx++] = ch; key_buf[key_idx] = '\0'; break; - } /* switch */ + } /* switch */ break; case s_query_key_hex_1: if (!evhtp_is_hex_query_char(ch)) @@ -3483,7 +3485,7 @@ evhtp_send_reply_chunk_start(evhtp_request_t * request, evhtp_res code) default: request->flags &= ~EVHTP_REQ_FLAG_CHUNKED; break; - } /* switch */ + } /* switch */ } else { request->flags &= ~EVHTP_REQ_FLAG_CHUNKED; } @@ -3519,7 +3521,7 @@ evhtp_send_reply_chunk_start(evhtp_request_t * request, evhtp_res code) end: evhtp_send_reply_start(request, code); -} /* evhtp_send_reply_chunk_start */ +} /* evhtp_send_reply_chunk_start */ void evhtp_send_reply_chunk(evhtp_request_t * request, evbuf_t * buf) @@ -3647,7 +3649,7 @@ evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog) } return 0; -} /* evhtp_accept_socket */ +} /* evhtp_accept_socket */ int evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr * sa, size_t sin_len, int backlog) @@ -3724,7 +3726,7 @@ evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr * sa, size_t sin_len, int bac } return 0; -} /* evhtp_bind_sockaddr */ +} /* evhtp_bind_sockaddr */ int evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog) @@ -3781,7 +3783,7 @@ evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog) } return evhtp_bind_sockaddr(htp, sa, sin_len, backlog); -} /* evhtp_bind_socket */ +} /* evhtp_bind_socket */ void evhtp_callbacks_free(evhtp_callbacks_t * callbacks) @@ -3841,7 +3843,7 @@ evhtp_callback_new(const char * path, evhtp_callback_type type, evhtp_callback_c evhtp_safe_free(hcb, free); return NULL; - } /* switch */ + } /* switch */ return hcb; } @@ -4053,7 +4055,7 @@ evhtp_unset_all_hooks(evhtp_hooks_t ** hooks) } return res; -} /* evhtp_unset_all_hooks */ +} /* evhtp_unset_all_hooks */ evhtp_callback_t * evhtp_set_cb(evhtp_t * htp, const char * path, evhtp_callback_cb cb, void * arg) @@ -4389,7 +4391,7 @@ evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg) SSL_CTX_set_tmp_ecdh(htp->ssl_ctx, ecdh); EC_KEY_free(ecdh); } -#endif /* OPENSSL_NO_ECDH */ +#endif /* OPENSSL_NO_ECDH */ #ifndef OPENSSL_NO_DH if (cfg->dhparams != NULL) { @@ -4412,7 +4414,7 @@ evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg) fprintf(stderr, "DH initialization failed: unable to open file %s\n", cfg->dhparams); } } -#endif /* OPENSSL_NO_DH */ +#endif /* OPENSSL_NO_DH */ if (cfg->ciphers != NULL) { @@ -4523,7 +4525,10 @@ evhtp_connection_take_ownership(evhtp_connection_t * connection) evhtp_connection_set_bev(connection, NULL); - connection->owner = 0; + /* relinquish ownership of this connection, unset + * the ownership flag. + */ + connection->flags &= ~EVHTP_CONN_FLAG_OWNER; bufferevent_disable(bev, EV_READ); bufferevent_setcb(bev, NULL, NULL, NULL, NULL); @@ -4920,7 +4925,7 @@ evhtp_free(evhtp_t * evhtp) } evhtp_safe_free(evhtp, free); -} /* evhtp_free */ +} /* evhtp_free */ /***************************************************************** * client request functions * @@ -5001,7 +5006,7 @@ evhtp_connection_new_dns(evbase_t * evbase, struct evdns_base * dns_base, } return conn; -} /* evhtp_connection_new_dns */ +} /* evhtp_connection_new_dns */ #ifndef EVHTP_DISABLE_SSL evhtp_connection_t * diff --git a/evhtp.h b/evhtp.h index cc9952c..e591ac1 100644 --- a/evhtp.h +++ b/evhtp.h @@ -476,26 +476,28 @@ struct evhtp_connection_s { htparser * parser; event_t * resume_ev; struct sockaddr * saddr; - struct timeval recv_timeo; /**< conn read timeouts (overrides global) */ - struct timeval send_timeo; /**< conn write timeouts (overrides global) */ + struct timeval recv_timeo; /**< conn read timeouts (overrides global) */ + struct timeval send_timeo; /**< conn write timeouts (overrides global) */ evutil_socket_t sock; - evhtp_request_t * request; /**< the request currently being processed */ + evhtp_request_t * request; /**< the request currently being processed */ uint64_t max_body_size; uint64_t body_bytes_read; uint64_t num_requests; - evhtp_type type; /**< server or client */ - uint8_t error : 1, - owner : 1, /**< set to 1 if this structure owns the bufferevent */ - vhost_via_sni : 1, /**< set to 1 if the vhost was found via SSL SNI */ - paused : 1, /**< this connection has been marked as paused */ - connected : 1, /**< client specific - set after successful connection */ - waiting : 1, /**< used to make sure resuming happens AFTER sending a reply */ - free_connection : 1, - keepalive : 1; /**< set to 1 after the first request has been processed and the connection is kept open */ - struct evbuffer * scratch_buf; /**< always zero'd out after used */ + evhtp_type type; /**< server or client */ + #define EVHTP_CONN_FLAG_ERROR (1 << 1) + #define EVHTP_CONN_FLAG_OWNER (1 << 2) /**< set to 1 if this structure owns the bufferevent */ + #define EVHTP_CONN_FLAG_VHOST_VIA_SNI (1 << 3) /**< set to 1 if the vhost was found via SSL SNI */ + #define EVHTP_CONN_FLAG_PAUSED (1 << 4) /**< this connection has been marked as paused */ + #define EVHTP_CONN_FLAG_CONNECTED (1 << 5) /**< client specific - set after successful connection */ + #define EVHTP_CONN_FLAG_WAITING (1 << 6) /**< used to make sure resuming happens AFTER sending a reply */ + #define EVHTP_CONN_FLAG_FREE_CONN (1 << 7) + #define EVHTP_CONN_FLAG_KEEPALIVE (1 << 8) /**< set to 1 after the first request has been processed and the connection is kept open */ + uint16_t flags; + + struct evbuffer * scratch_buf; /**< always zero'd out after used */ #ifdef EVHTP_FUTURE_USE - TAILQ_HEAD(, evhtp_request_s) pending; /**< client pending data */ + TAILQ_HEAD(, evhtp_request_s) pending; /**< client pending data */ #endif };