summaryrefslogtreecommitdiff
path: root/bufferevent_openssl.c
diff options
context:
space:
mode:
authorAzat Khuzhin <a3at.mail@gmail.com>2016-12-07 02:53:07 +0300
committerAzat Khuzhin <a3at.mail@gmail.com>2017-01-19 20:53:05 +0300
commit8939676706b8e2a125c5e3344f8672ddfadeb4e1 (patch)
treeed992f9150d6acb56f0ea3d5b9fa581b2818b400 /bufferevent_openssl.c
parentd77fcea15fe8ebb166853597cfff934fd5a47b0f (diff)
downloadlibevent-8939676706b8e2a125c5e3344f8672ddfadeb4e1.tar.gz
be_openssl: Fix writing into filted openssl bufferevent after connected
The main problems was due to when bufferevent_openssl has underlying (i.e. created with bufferevent_openssl_filter_new()) some events was disabled/suspended, while with openssl, READ can require WRITE and vice-versa hence this issues. The BEV_CTRL_GET_FD hunk to fix http subsystem, since it depends from what bufferevent_getfd() returns. Fixes: #428 Fixes: ssl/bufferevent_filter_write_after_connect Fixes: http/https_filter_chunk_out Fixes: da52933550fd4736aa1c213b6de497e2ffc31e34 ("be_openssl: don't call do_write() directly from outbuf_cb")
Diffstat (limited to 'bufferevent_openssl.c')
-rw-r--r--bufferevent_openssl.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c
index cbb7f8a5..da3963af 100644
--- a/bufferevent_openssl.c
+++ b/bufferevent_openssl.c
@@ -404,7 +404,10 @@ 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);
@@ -435,7 +438,8 @@ 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);
@@ -716,7 +720,7 @@ 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, 0);
+ bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS);
}
return result;
}
@@ -1040,17 +1044,11 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
print_err(err);
switch (err) {
case SSL_ERROR_WANT_WRITE:
- if (!bev_ssl->underlying) {
- stop_reading(bev_ssl);
- return start_writing(bev_ssl);
- }
- return 0;
+ stop_reading(bev_ssl);
+ return start_writing(bev_ssl);
case SSL_ERROR_WANT_READ:
- if (!bev_ssl->underlying) {
- stop_writing(bev_ssl);
- return start_reading(bev_ssl);
- }
- return 0;
+ stop_writing(bev_ssl);
+ return start_reading(bev_ssl);
default:
conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
return -1;
@@ -1086,6 +1084,13 @@ 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;
@@ -1131,10 +1136,13 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
int r = 0;
/* XXX need to hold a reference here. */
- if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN &&
- cbinfo->orig_size == 0) {
- r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
- &bev_ssl->bev.bev.timeout_write);
+ 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,
+ &bev_ssl->bev.bev.timeout_write);
+
+ if (bev_ssl->underlying)
+ consider_writing(bev_ssl);
}
/* XXX Handle r < 0 */
(void)r;
@@ -1286,17 +1294,24 @@ be_openssl_ctrl(struct bufferevent *bev,
struct bufferevent_openssl *bev_ssl = upcast(bev);
switch (op) {
case BEV_CTRL_SET_FD:
- if (bev_ssl->underlying)
- return -1;
- {
+ if (!bev_ssl->underlying) {
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);
}
return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd);
case BEV_CTRL_GET_FD:
- data->fd = event_get_fd(&bev->ev_read);
+ if (bev_ssl->underlying) {
+ data->fd = event_get_fd(&bev_ssl->underlying->ev_read);
+ } else {
+ data->fd = event_get_fd(&bev->ev_read);
+ }
return 0;
case BEV_CTRL_GET_UNDERLYING:
data->ptr = bev_ssl->underlying;