diff options
author | Josh Gao <jmgao@google.com> | 2017-08-10 12:30:25 -0700 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2017-08-10 12:30:47 -0700 |
commit | 83a0c9c65a60a92d3ea5542596b3ba56db492c37 (patch) | |
tree | 64bb0c050c4db9ad9d721e05e3e199bfd02e60b0 /bufferevent_openssl.c | |
parent | af241a5c8c2cde0fab7d7d563276c1095b00e3b4 (diff) | |
download | libevent-83a0c9c65a60a92d3ea5542596b3ba56db492c37.tar.gz |
Revert "Upgrade to 2.1.8-stable (2017-01-22)." and "Probably Mac build fix?"android-o-iot-preview-5o-iot-preview-5
This reverts commits 2a572d125a91a4aafd3ad8ce87259fc640fa0763 and
af241a5c8c2cde0fab7d7d563276c1095b00e3b4, which break tombstoned.
Bug: http://b/64543673
Test: manual + treehugger
Diffstat (limited to 'bufferevent_openssl.c')
-rw-r--r-- | bufferevent_openssl.c | 455 |
1 files changed, 204 insertions, 251 deletions
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c index da3963a..7582d9b 100644 --- a/bufferevent_openssl.c +++ b/bufferevent_openssl.c @@ -24,17 +24,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Get rid of OSX 10.7 and greater deprecation warnings. -#if defined(__APPLE__) && defined(__clang__) -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif +#include <sys/types.h> #include "event2/event-config.h" -#include "evconfig-private.h" - -#include <sys/types.h> -#ifdef EVENT__HAVE_SYS_TIME_H +#ifdef _EVENT_HAVE_SYS_TIME_H #include <sys/time.h> #endif @@ -42,14 +36,14 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifdef EVENT__HAVE_STDARG_H +#ifdef _EVENT_HAVE_STDARG_H #include <stdarg.h> #endif -#ifdef EVENT__HAVE_UNISTD_H +#ifdef _EVENT_HAVE_UNISTD_H #include <unistd.h> #endif -#ifdef _WIN32 +#ifdef WIN32 #include <winsock2.h> #endif @@ -66,7 +60,6 @@ #include <openssl/bio.h> #include <openssl/ssl.h> #include <openssl/err.h> -#include "openssl-compat.h" /* * Define an OpenSSL bio that targets a bufferevent. @@ -110,8 +103,10 @@ print_err(int val) static int bio_bufferevent_new(BIO *b) { - BIO_set_init(b, 0); - BIO_set_data(b, NULL); /* We'll be putting the bufferevent in this field.*/ + b->init = 0; + b->num = -1; + b->ptr = NULL; /* We'll be putting the bufferevent in this field.*/ + b->flags = 0; return 1; } @@ -121,10 +116,12 @@ bio_bufferevent_free(BIO *b) { if (!b) return 0; - if (BIO_get_shutdown(b)) { - if (BIO_get_init(b) && BIO_get_data(b)) - bufferevent_free(BIO_get_data(b)); - BIO_free(b); + if (b->shutdown) { + if (b->init && b->ptr) + bufferevent_free(b->ptr); + b->init = 0; + b->flags = 0; + b->ptr = NULL; } return 1; } @@ -140,10 +137,10 @@ bio_bufferevent_read(BIO *b, char *out, int outlen) if (!out) return 0; - if (!BIO_get_data(b)) + if (!b->ptr) return -1; - input = bufferevent_get_input(BIO_get_data(b)); + input = bufferevent_get_input(b->ptr); if (evbuffer_get_length(input) == 0) { /* If there's no data to read, say so. */ BIO_set_retry_read(b); @@ -159,13 +156,13 @@ bio_bufferevent_read(BIO *b, char *out, int outlen) static int bio_bufferevent_write(BIO *b, const char *in, int inlen) { - struct bufferevent *bufev = BIO_get_data(b); + struct bufferevent *bufev = b->ptr; struct evbuffer *output; size_t outlen; BIO_clear_retry_flags(b); - if (!BIO_get_data(b)) + if (!b->ptr) return -1; output = bufferevent_get_output(bufev); @@ -191,15 +188,15 @@ bio_bufferevent_write(BIO *b, const char *in, int inlen) static long bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr) { - struct bufferevent *bufev = BIO_get_data(b); + struct bufferevent *bufev = b->ptr; long ret = 1; switch (cmd) { case BIO_CTRL_GET_CLOSE: - ret = BIO_get_shutdown(b); + ret = b->shutdown; break; case BIO_CTRL_SET_CLOSE: - BIO_set_shutdown(b, (int)num); + b->shutdown = (int)num; break; case BIO_CTRL_PENDING: ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0; @@ -228,24 +225,23 @@ bio_bufferevent_puts(BIO *b, const char *s) } /* Method table for the bufferevent BIO */ -static BIO_METHOD *methods_bufferevent; +static BIO_METHOD methods_bufferevent = { + BIO_TYPE_LIBEVENT, "bufferevent", + bio_bufferevent_write, + bio_bufferevent_read, + bio_bufferevent_puts, + NULL /* bio_bufferevent_gets */, + bio_bufferevent_ctrl, + bio_bufferevent_new, + bio_bufferevent_free, + NULL /* callback_ctrl */, +}; /* Return the method table for the bufferevents BIO */ static BIO_METHOD * BIO_s_bufferevent(void) { - if (methods_bufferevent == NULL) { - methods_bufferevent = BIO_meth_new(BIO_TYPE_LIBEVENT, "bufferevent"); - if (methods_bufferevent == NULL) - return NULL; - BIO_meth_set_write(methods_bufferevent, bio_bufferevent_write); - BIO_meth_set_read(methods_bufferevent, bio_bufferevent_read); - BIO_meth_set_puts(methods_bufferevent, bio_bufferevent_puts); - BIO_meth_set_ctrl(methods_bufferevent, bio_bufferevent_ctrl); - BIO_meth_set_create(methods_bufferevent, bio_bufferevent_new); - BIO_meth_set_destroy(methods_bufferevent, bio_bufferevent_free); - } - return methods_bufferevent; + return &methods_bufferevent; } /* Create a new BIO to wrap communication around a bufferevent. If close_flag @@ -258,9 +254,9 @@ BIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag) return NULL; if (!(result = BIO_new(BIO_s_bufferevent()))) return NULL; - BIO_set_init(result, 1); - BIO_set_data(result, bufferevent); - BIO_set_shutdown(result, close_flag ? 1 : 0); + result->init = 1; + result->ptr = bufferevent; + result->shutdown = close_flag ? 1 : 0; return result; } @@ -316,20 +312,19 @@ struct bufferevent_openssl { unsigned read_blocked_on_write : 1; /* When we next get data, we should say "write" instead of "read". */ unsigned write_blocked_on_read : 1; - /* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */ + /* XXX */ unsigned allow_dirty_shutdown : 1; + /* XXXX */ + unsigned fd_is_set : 1; /* XXX */ unsigned n_errors : 2; /* Are we currently connecting, accepting, or doing IO? */ unsigned state : 2; - /* If we reset fd, we sould reset state too */ - unsigned old_state : 2; }; static int be_openssl_enable(struct bufferevent *, short); static int be_openssl_disable(struct bufferevent *, short); -static void be_openssl_unlink(struct bufferevent *); static void be_openssl_destruct(struct bufferevent *); static int be_openssl_adj_timeouts(struct bufferevent *); static int be_openssl_flush(struct bufferevent *bufev, @@ -341,7 +336,6 @@ const struct bufferevent_ops bufferevent_ops_openssl = { evutil_offsetof(struct bufferevent_openssl, bev.bev), be_openssl_enable, be_openssl_disable, - be_openssl_unlink, be_openssl_destruct, be_openssl_adj_timeouts, be_openssl_flush, @@ -382,15 +376,15 @@ static int start_reading(struct bufferevent_openssl *bev_ssl) { if (bev_ssl->underlying) { - bufferevent_unsuspend_read_(bev_ssl->underlying, + bufferevent_unsuspend_read(bev_ssl->underlying, BEV_SUSPEND_FILT_READ); return 0; } else { struct bufferevent *bev = &bev_ssl->bev.bev; int r; - r = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read); + r = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); if (r == 0 && bev_ssl->read_blocked_on_write) - r = bufferevent_add_event_(&bev->ev_write, + r = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); return r; } @@ -404,15 +398,12 @@ start_writing(struct bufferevent_openssl *bev_ssl) { int r = 0; if (bev_ssl->underlying) { - if (bev_ssl->write_blocked_on_read) { - bufferevent_unsuspend_read_(bev_ssl->underlying, - BEV_SUSPEND_FILT_READ); - } + ; } else { struct bufferevent *bev = &bev_ssl->bev.bev; - r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write); + r = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); if (!r && bev_ssl->write_blocked_on_read) - r = bufferevent_add_event_(&bev->ev_read, + r = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); } return r; @@ -424,7 +415,7 @@ stop_reading(struct bufferevent_openssl *bev_ssl) if (bev_ssl->write_blocked_on_read) return; if (bev_ssl->underlying) { - bufferevent_suspend_read_(bev_ssl->underlying, + bufferevent_suspend_read(bev_ssl->underlying, BEV_SUSPEND_FILT_READ); } else { struct bufferevent *bev = &bev_ssl->bev.bev; @@ -438,8 +429,7 @@ stop_writing(struct bufferevent_openssl *bev_ssl) if (bev_ssl->read_blocked_on_write) return; if (bev_ssl->underlying) { - bufferevent_unsuspend_read_(bev_ssl->underlying, - BEV_SUSPEND_FILT_READ); + ; } else { struct bufferevent *bev = &bev_ssl->bev.bev; event_del(&bev->ev_write); @@ -492,7 +482,7 @@ clear_wbor(struct bufferevent_openssl *bev_ssl) } static void -conn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret) +conn_closed(struct bufferevent_openssl *bev_ssl, int errcode, int ret) { int event = BEV_EVENT_ERROR; int dirty_shutdown = 0; @@ -508,7 +498,7 @@ conn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret) break; case SSL_ERROR_SYSCALL: /* IO error; possibly a dirty shutdown. */ - if ((ret == 0 || ret == -1) && ERR_peek_error() == 0) + if (ret == 0 && ERR_peek_error() == 0) dirty_shutdown = 1; break; case SSL_ERROR_SSL: @@ -538,20 +528,16 @@ conn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret) stop_reading(bev_ssl); stop_writing(bev_ssl); - /* when is BEV_EVENT_{READING|WRITING} */ - event = when | event; - bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, event); } static void init_bio_counts(struct bufferevent_openssl *bev_ssl) { - BIO *rbio, *wbio; - - wbio = SSL_get_wbio(bev_ssl->ssl); - bev_ssl->counts.n_written = wbio ? BIO_number_written(wbio) : 0; - rbio = SSL_get_rbio(bev_ssl->ssl); - bev_ssl->counts.n_read = rbio ? BIO_number_read(rbio) : 0; + bev_ssl->counts.n_written = + BIO_number_written(SSL_get_wbio(bev_ssl->ssl)); + bev_ssl->counts.n_read = + BIO_number_read(SSL_get_rbio(bev_ssl->ssl)); } static inline void @@ -563,9 +549,9 @@ decrement_buckets(struct bufferevent_openssl *bev_ssl) unsigned long w = num_w - bev_ssl->counts.n_written; unsigned long r = num_r - bev_ssl->counts.n_read; if (w) - bufferevent_decrement_write_buckets_(&bev_ssl->bev, w); + _bufferevent_decrement_write_buckets(&bev_ssl->bev, w); if (r) - bufferevent_decrement_read_buckets_(&bev_ssl->bev, r); + _bufferevent_decrement_read_buckets(&bev_ssl->bev, r); bev_ssl->counts.n_written = num_w; bev_ssl->counts.n_read = num_r; } @@ -588,7 +574,7 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) { if (bev_ssl->bev.read_suspended) return 0; - atmost = bufferevent_get_read_max_(&bev_ssl->bev); + atmost = _bufferevent_get_read_max(&bev_ssl->bev); if (n_to_read > atmost) n_to_read = atmost; @@ -599,7 +585,6 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) { for (i=0; i<n; ++i) { if (bev_ssl->bev.read_suspended) break; - ERR_clear_error(); r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len); if (r>0) { result |= OP_MADE_PROGRESS; @@ -627,7 +612,7 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) { return OP_ERR | result; break; default: - conn_closed(bev_ssl, BEV_EVENT_READING, err, r); + conn_closed(bev_ssl, err, r); break; } result |= OP_BLOCKED; @@ -658,7 +643,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost) if (bev_ssl->last_write > 0) atmost = bev_ssl->last_write; else - atmost = bufferevent_get_write_max_(&bev_ssl->bev); + atmost = _bufferevent_get_write_max(&bev_ssl->bev); n = evbuffer_peek(output, atmost, NULL, space, 8); if (n < 0) @@ -676,7 +661,6 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost) if (space[i].iov_len == 0) continue; - ERR_clear_error(); r = SSL_write(bev_ssl->ssl, space[i].iov_base, space[i].iov_len); if (r > 0) { @@ -707,7 +691,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost) bev_ssl->last_write = space[i].iov_len; break; default: - conn_closed(bev_ssl, BEV_EVENT_WRITING, err, r); + conn_closed(bev_ssl, err, r); bev_ssl->last_write = -1; break; } @@ -720,7 +704,8 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost) if (bev_ssl->underlying) BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); - bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS); + if (evbuffer_get_length(output) <= bev->wm_write.low) + _bufferevent_run_writecb(bev); } return result; } @@ -764,7 +749,7 @@ bytes_to_read(struct bufferevent_openssl *bev) } /* Respect the rate limit */ - limit = bufferevent_get_read_max_(&bev->bev); + limit = _bufferevent_get_read_max(&bev->bev); if (result > limit) { result = limit; } @@ -834,8 +819,11 @@ consider_reading(struct bufferevent_openssl *bev_ssl) if (all_result_flags & OP_MADE_PROGRESS) { struct bufferevent *bev = &bev_ssl->bev.bev; + struct evbuffer *input = bev->input; - bufferevent_trigger_nolock_(bev, EV_READ, 0); + if (evbuffer_get_length(input) >= bev->wm_read.low) { + _bufferevent_run_readcb(bev); + } } if (!bev_ssl->underlying) { @@ -859,8 +847,11 @@ consider_writing(struct bufferevent_openssl *bev_ssl) r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */ if (r & OP_MADE_PROGRESS) { struct bufferevent *bev = &bev_ssl->bev.bev; + struct evbuffer *input = bev->input; - bufferevent_trigger_nolock_(bev, EV_READ, 0); + if (evbuffer_get_length(input) >= bev->wm_read.low) { + _bufferevent_run_readcb(bev); + } } if (r & (OP_ERR|OP_BLOCKED)) break; @@ -932,47 +923,35 @@ be_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx) eat it. */ } if (event) - bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, event); } static void be_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr) { struct bufferevent_openssl *bev_ssl = ptr; - bufferevent_incref_and_lock_(&bev_ssl->bev.bev); + _bufferevent_incref_and_lock(&bev_ssl->bev.bev); if (what == EV_TIMEOUT) { - bufferevent_run_eventcb_(&bev_ssl->bev.bev, - BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, + BEV_EVENT_TIMEOUT|BEV_EVENT_READING); } else { consider_reading(bev_ssl); } - bufferevent_decref_and_unlock_(&bev_ssl->bev.bev); + _bufferevent_decref_and_unlock(&bev_ssl->bev.bev); } static void be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr) { struct bufferevent_openssl *bev_ssl = ptr; - bufferevent_incref_and_lock_(&bev_ssl->bev.bev); + _bufferevent_incref_and_lock(&bev_ssl->bev.bev); if (what == EV_TIMEOUT) { - bufferevent_run_eventcb_(&bev_ssl->bev.bev, - BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING, 0); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, + BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING); } else { consider_writing(bev_ssl); } - bufferevent_decref_and_unlock_(&bev_ssl->bev.bev); -} - -static int -be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, int fd) -{ - if (!bev_ssl->underlying) { - struct bufferevent *bev = &bev_ssl->bev.bev; - if (event_initialized(&bev->ev_read) && fd < 0) { - fd = event_get_fd(&bev->ev_read); - } - } - return fd; + _bufferevent_decref_and_unlock(&bev_ssl->bev.bev); } static int @@ -986,27 +965,25 @@ set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) } else { struct bufferevent *bev = &bev_ssl->bev.bev; int rpending=0, wpending=0, r1=0, r2=0; - - if (event_initialized(&bev->ev_read)) { + if (fd < 0 && bev_ssl->fd_is_set) + fd = event_get_fd(&bev->ev_read); + if (bev_ssl->fd_is_set) { rpending = event_pending(&bev->ev_read, EV_READ, NULL); wpending = event_pending(&bev->ev_write, EV_WRITE, NULL); - event_del(&bev->ev_read); event_del(&bev->ev_write); } - event_assign(&bev->ev_read, bev->ev_base, fd, - EV_READ|EV_PERSIST|EV_FINALIZE, - be_openssl_readeventcb, bev_ssl); + EV_READ|EV_PERSIST, be_openssl_readeventcb, bev_ssl); event_assign(&bev->ev_write, bev->ev_base, fd, - EV_WRITE|EV_PERSIST|EV_FINALIZE, - be_openssl_writeeventcb, bev_ssl); - + EV_WRITE|EV_PERSIST, be_openssl_writeeventcb, bev_ssl); if (rpending) - r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read); + r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); if (wpending) - r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write); - + r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + if (fd >= 0) { + bev_ssl->fd_is_set = 1; + } return (r1<0 || r2<0) ? -1 : 0; } } @@ -1023,34 +1000,38 @@ do_handshake(struct bufferevent_openssl *bev_ssl) return -1; case BUFFEREVENT_SSL_CONNECTING: case BUFFEREVENT_SSL_ACCEPTING: - ERR_clear_error(); r = SSL_do_handshake(bev_ssl->ssl); break; } decrement_buckets(bev_ssl); if (r==1) { - int fd = event_get_fd(&bev_ssl->bev.bev.ev_read); /* We're done! */ bev_ssl->state = BUFFEREVENT_SSL_OPEN; - set_open_callbacks(bev_ssl, fd); /* XXXX handle failure */ + set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */ /* Call do_read and do_write as needed */ bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled); - bufferevent_run_eventcb_(&bev_ssl->bev.bev, - BEV_EVENT_CONNECTED, 0); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, + BEV_EVENT_CONNECTED); return 1; } else { int err = SSL_get_error(bev_ssl->ssl, r); print_err(err); switch (err) { case SSL_ERROR_WANT_WRITE: - stop_reading(bev_ssl); - return start_writing(bev_ssl); + if (!bev_ssl->underlying) { + stop_reading(bev_ssl); + return start_writing(bev_ssl); + } + return 0; case SSL_ERROR_WANT_READ: - stop_writing(bev_ssl); - return start_reading(bev_ssl); + if (!bev_ssl->underlying) { + stop_writing(bev_ssl); + return start_reading(bev_ssl); + } + return 0; default: - conn_closed(bev_ssl, BEV_EVENT_READING, err, r); + conn_closed(bev_ssl, err, r); return -1; } } @@ -1068,12 +1049,12 @@ be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr) { struct bufferevent_openssl *bev_ssl = ptr; - bufferevent_incref_and_lock_(&bev_ssl->bev.bev); + _bufferevent_incref_and_lock(&bev_ssl->bev.bev); if (what & EV_TIMEOUT) { - bufferevent_run_eventcb_(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT, 0); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT); } else do_handshake(bev_ssl);/* XXX handle failure */ - bufferevent_decref_and_unlock_(&bev_ssl->bev.bev); + _bufferevent_decref_and_unlock(&bev_ssl->bev.bev); } static int @@ -1084,31 +1065,26 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) be_openssl_handshakecb, be_openssl_handshakecb, be_openssl_eventcb, bev_ssl); - - if (fd < 0) - return 0; - - if (bufferevent_setfd(bev_ssl->underlying, fd)) - return 1; - return do_handshake(bev_ssl); } else { struct bufferevent *bev = &bev_ssl->bev.bev; - - if (event_initialized(&bev->ev_read)) { + int r1=0, r2=0; + if (fd < 0 && bev_ssl->fd_is_set) + fd = event_get_fd(&bev->ev_read); + if (bev_ssl->fd_is_set) { event_del(&bev->ev_read); event_del(&bev->ev_write); } - event_assign(&bev->ev_read, bev->ev_base, fd, - EV_READ|EV_PERSIST|EV_FINALIZE, - be_openssl_handshakeeventcb, bev_ssl); + EV_READ|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl); event_assign(&bev->ev_write, bev->ev_base, fd, - EV_WRITE|EV_PERSIST|EV_FINALIZE, - be_openssl_handshakeeventcb, bev_ssl); - if (fd >= 0) - bufferevent_enable(bev, bev->enabled); - return 0; + EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl); + if (fd >= 0) { + r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); + r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + bev_ssl->fd_is_set = 1; + } + return (r1<0 || r2<0) ? -1 : 0; } } @@ -1121,7 +1097,7 @@ bufferevent_ssl_renegotiate(struct bufferevent *bev) if (SSL_renegotiate(bev_ssl->ssl) < 0) return -1; bev_ssl->state = BUFFEREVENT_SSL_CONNECTING; - if (set_handshake_callbacks(bev_ssl, be_openssl_auto_fd(bev_ssl, -1)) < 0) + if (set_handshake_callbacks(bev_ssl, -1) < 0) return -1; if (!bev_ssl->underlying) return do_handshake(bev_ssl); @@ -1138,14 +1114,12 @@ be_openssl_outbuf_cb(struct evbuffer *buf, if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) { if (cbinfo->orig_size == 0) - r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write, + r = _bufferevent_add_event(&bev_ssl->bev.bev.ev_write, &bev_ssl->bev.bev.timeout_write); - - if (bev_ssl->underlying) - consider_writing(bev_ssl); + consider_writing(bev_ssl); } /* XXX Handle r < 0 */ - (void)r; + (void)r; } @@ -1155,6 +1129,9 @@ be_openssl_enable(struct bufferevent *bev, short events) struct bufferevent_openssl *bev_ssl = upcast(bev); int r1 = 0, r2 = 0; + if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) + return 0; + if (events & EV_READ) r1 = start_reading(bev_ssl); if (events & EV_WRITE) @@ -1178,6 +1155,8 @@ static int be_openssl_disable(struct bufferevent *bev, short events) { struct bufferevent_openssl *bev_ssl = upcast(bev); + if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) + return 0; if (events & EV_READ) stop_reading(bev_ssl); @@ -1194,10 +1173,17 @@ be_openssl_disable(struct bufferevent *bev, short events) } static void -be_openssl_unlink(struct bufferevent *bev) +be_openssl_destruct(struct bufferevent *bev) { struct bufferevent_openssl *bev_ssl = upcast(bev); + if (bev_ssl->underlying) { + _bufferevent_del_generic_timeout_cbs(bev); + } else { + event_del(&bev->ev_read); + event_del(&bev->ev_write); + } + if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) { if (bev_ssl->underlying) { if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) { @@ -1205,29 +1191,9 @@ be_openssl_unlink(struct bufferevent *bev) "bufferevent with too few references"); } else { bufferevent_free(bev_ssl->underlying); - /* We still have a reference to it, via our - * BIO. So we don't drop this. */ - // bev_ssl->underlying = NULL; + bev_ssl->underlying = NULL; } - } - } else { - if (bev_ssl->underlying) { - if (bev_ssl->underlying->errorcb == be_openssl_eventcb) - bufferevent_setcb(bev_ssl->underlying, - NULL,NULL,NULL,NULL); - bufferevent_unsuspend_read_(bev_ssl->underlying, - BEV_SUSPEND_FILT_READ); - } - } -} - -static void -be_openssl_destruct(struct bufferevent *bev) -{ - struct bufferevent_openssl *bev_ssl = upcast(bev); - - if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) { - if (! bev_ssl->underlying) { + } else { evutil_socket_t fd = -1; BIO *bio = SSL_get_wbio(bev_ssl->ssl); if (bio) @@ -1236,6 +1202,14 @@ be_openssl_destruct(struct bufferevent *bev) evutil_closesocket(fd); } SSL_free(bev_ssl->ssl); + } else { + if (bev_ssl->underlying) { + if (bev_ssl->underlying->errorcb == be_openssl_eventcb) + bufferevent_setcb(bev_ssl->underlying, + NULL,NULL,NULL,NULL); + bufferevent_unsuspend_read(bev_ssl->underlying, + BEV_SUSPEND_FILT_READ); + } } } @@ -1244,10 +1218,15 @@ be_openssl_adj_timeouts(struct bufferevent *bev) { struct bufferevent_openssl *bev_ssl = upcast(bev); - if (bev_ssl->underlying) { - return bufferevent_generic_adj_timeouts_(bev); - } else { - return bufferevent_generic_adj_existing_timeouts_(bev); + if (bev_ssl->underlying) + return _bufferevent_generic_adj_timeouts(bev); + else { + int r1=0, r2=0; + if (event_pending(&bev->ev_read, EV_READ, NULL)) + r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); + if (event_pending(&bev->ev_write, EV_WRITE, NULL)) + r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + return (r1<0 || r2<0) ? -1 : 0; } } @@ -1260,60 +1239,35 @@ be_openssl_flush(struct bufferevent *bufev, } static int -be_openssl_set_fd(struct bufferevent_openssl *bev_ssl, - enum bufferevent_ssl_state state, int fd) -{ - bev_ssl->state = state; - - switch (state) { - case BUFFEREVENT_SSL_ACCEPTING: - SSL_set_accept_state(bev_ssl->ssl); - if (set_handshake_callbacks(bev_ssl, fd) < 0) - return -1; - break; - case BUFFEREVENT_SSL_CONNECTING: - SSL_set_connect_state(bev_ssl->ssl); - if (set_handshake_callbacks(bev_ssl, fd) < 0) - return -1; - break; - case BUFFEREVENT_SSL_OPEN: - if (set_open_callbacks(bev_ssl, fd) < 0) - return -1; - break; - default: - return -1; - } - - return 0; -} - -static int be_openssl_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data) { struct bufferevent_openssl *bev_ssl = upcast(bev); switch (op) { case BEV_CTRL_SET_FD: - if (!bev_ssl->underlying) { + if (bev_ssl->underlying) + return -1; + { BIO *bio; bio = BIO_new_socket(data->fd, 0); SSL_set_bio(bev_ssl->ssl, bio, bio); - } else { - BIO *bio; - if (!(bio = BIO_new_bufferevent(bev_ssl->underlying, 0))) - return -1; - SSL_set_bio(bev_ssl->ssl, bio, bio); + bev_ssl->fd_is_set = 1; } - - return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd); - case BEV_CTRL_GET_FD: - if (bev_ssl->underlying) { - data->fd = event_get_fd(&bev_ssl->underlying->ev_read); - } else { - data->fd = event_get_fd(&bev->ev_read); + if (bev_ssl->state == BUFFEREVENT_SSL_OPEN) + return set_open_callbacks(bev_ssl, data->fd); + else { + return set_handshake_callbacks(bev_ssl, data->fd); } + case BEV_CTRL_GET_FD: + if (bev_ssl->underlying) + return -1; + if (!bev_ssl->fd_is_set) + return -1; + data->fd = event_get_fd(&bev->ev_read); return 0; case BEV_CTRL_GET_UNDERLYING: + if (!bev_ssl->underlying) + return -1; data->ptr = bev_ssl->underlying; return 0; case BEV_CTRL_CANCEL_ALL: @@ -1351,7 +1305,7 @@ bufferevent_openssl_new_impl(struct event_base *base, bev_p = &bev_ssl->bev; - if (bufferevent_init_common_(bev_p, base, + if (bufferevent_init_common(bev_p, base, &bufferevent_ops_openssl, tmp_options) < 0) goto err; @@ -1366,28 +1320,52 @@ bufferevent_openssl_new_impl(struct event_base *base, be_openssl_outbuf_cb, bev_ssl); if (options & BEV_OPT_THREADSAFE) - bufferevent_enable_locking_(&bev_ssl->bev.bev, NULL); + bufferevent_enable_locking(&bev_ssl->bev.bev, NULL); if (underlying) { - bufferevent_init_generic_timeout_cbs_(&bev_ssl->bev.bev); - bufferevent_incref_(underlying); + _bufferevent_init_generic_timeout_cbs(&bev_ssl->bev.bev); + bufferevent_incref(underlying); } - bev_ssl->old_state = state; + bev_ssl->state = state; bev_ssl->last_write = -1; init_bio_counts(bev_ssl); - fd = be_openssl_auto_fd(bev_ssl, fd); - if (be_openssl_set_fd(bev_ssl, state, fd)) + switch (state) { + case BUFFEREVENT_SSL_ACCEPTING: + SSL_set_accept_state(bev_ssl->ssl); + if (set_handshake_callbacks(bev_ssl, fd) < 0) + goto err; + break; + case BUFFEREVENT_SSL_CONNECTING: + SSL_set_connect_state(bev_ssl->ssl); + if (set_handshake_callbacks(bev_ssl, fd) < 0) + goto err; + break; + case BUFFEREVENT_SSL_OPEN: + if (set_open_callbacks(bev_ssl, fd) < 0) + goto err; + break; + default: goto err; + } if (underlying) { bufferevent_setwatermark(underlying, EV_READ, 0, 0); bufferevent_enable(underlying, EV_READ|EV_WRITE); if (state == BUFFEREVENT_SSL_OPEN) - bufferevent_suspend_read_(underlying, + bufferevent_suspend_read(underlying, BEV_SUSPEND_FILT_READ); + } else { + bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE; + if (bev_ssl->fd_is_set) { + if (state != BUFFEREVENT_SSL_OPEN) + if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0) + goto err; + if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0) + goto err; + } } return &bev_ssl->bev.bev; @@ -1461,31 +1439,6 @@ bufferevent_openssl_socket_new(struct event_base *base, base, NULL, fd, ssl, state, options); } -int -bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev) -{ - int allow_dirty_shutdown = -1; - struct bufferevent_openssl *bev_ssl; - BEV_LOCK(bev); - bev_ssl = upcast(bev); - if (bev_ssl) - allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown; - BEV_UNLOCK(bev); - return allow_dirty_shutdown; -} - -void -bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev, - int allow_dirty_shutdown) -{ - struct bufferevent_openssl *bev_ssl; - BEV_LOCK(bev); - bev_ssl = upcast(bev); - if (bev_ssl) - bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown; - BEV_UNLOCK(bev); -} - unsigned long bufferevent_get_openssl_error(struct bufferevent *bev) { |