mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-14 14:54:49 -04:00
Merge branch 'be-openssl-drop-fd_is_set-v4'
This must fix some issues with bufferevent openssl layer + some cleanups. * be-openssl-drop-fd_is_set-v4: be_openssl: don't use *_auto() in do_handshake() we can't have fd == -1 there be_openssl: don't call set_open_callbacks() if fd == -1 be_openssl: introduce be_openssl_auto_fd() helper be_openssl: introduce set_open_callbacks_auto() be_openssl: get rid off hackish "fd_is_set", to fix some corner cases
This commit is contained in:
commit
620aae969c
@ -320,8 +320,6 @@ struct bufferevent_openssl {
|
||||
unsigned write_blocked_on_read : 1;
|
||||
/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
|
||||
unsigned allow_dirty_shutdown : 1;
|
||||
/* XXXX */
|
||||
unsigned fd_is_set : 1;
|
||||
/* XXX */
|
||||
unsigned n_errors : 2;
|
||||
|
||||
@ -957,6 +955,18 @@ be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||
{
|
||||
@ -968,30 +978,36 @@ 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 (fd < 0 && bev_ssl->fd_is_set)
|
||||
fd = event_get_fd(&bev->ev_read);
|
||||
if (bev_ssl->fd_is_set) {
|
||||
|
||||
if (event_initialized(&bev->ev_read)) {
|
||||
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);
|
||||
event_assign(&bev->ev_write, bev->ev_base, fd,
|
||||
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
||||
be_openssl_writeeventcb, bev_ssl);
|
||||
|
||||
if (rpending)
|
||||
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
||||
if (wpending)
|
||||
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;
|
||||
}
|
||||
}
|
||||
static int
|
||||
set_open_callbacks_auto(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||
{
|
||||
fd = be_openssl_auto_fd(bev_ssl, fd);
|
||||
return set_open_callbacks(bev_ssl, fd);
|
||||
}
|
||||
|
||||
static int
|
||||
do_handshake(struct bufferevent_openssl *bev_ssl)
|
||||
@ -1011,9 +1027,10 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
|
||||
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, -1); /* XXXX handle failure */
|
||||
set_open_callbacks(bev_ssl, fd); /* 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,
|
||||
@ -1074,12 +1091,12 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||
} else {
|
||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||
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) {
|
||||
|
||||
if (event_initialized(&bev->ev_read)) {
|
||||
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);
|
||||
@ -1089,12 +1106,18 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
set_handshake_callbacks_auto(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||
{
|
||||
fd = be_openssl_auto_fd(bev_ssl, fd);
|
||||
return set_handshake_callbacks(bev_ssl, fd);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_ssl_renegotiate(struct bufferevent *bev)
|
||||
{
|
||||
@ -1104,7 +1127,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, -1) < 0)
|
||||
if (set_handshake_callbacks_auto(bev_ssl, -1) < 0)
|
||||
return -1;
|
||||
if (!bev_ssl->underlying)
|
||||
return do_handshake(bev_ssl);
|
||||
@ -1162,8 +1185,6 @@ 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);
|
||||
@ -1274,25 +1295,16 @@ be_openssl_ctrl(struct bufferevent *bev,
|
||||
BIO *bio;
|
||||
bio = BIO_new_socket(data->fd, 0);
|
||||
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
||||
bev_ssl->fd_is_set = 1;
|
||||
}
|
||||
if (data->fd == -1)
|
||||
bev_ssl->fd_is_set = 0;
|
||||
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
|
||||
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN && data->fd >= 0)
|
||||
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:
|
||||
@ -1360,16 +1372,16 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
||||
switch (state) {
|
||||
case BUFFEREVENT_SSL_ACCEPTING:
|
||||
SSL_set_accept_state(bev_ssl->ssl);
|
||||
if (set_handshake_callbacks(bev_ssl, fd) < 0)
|
||||
if (set_handshake_callbacks_auto(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)
|
||||
if (set_handshake_callbacks_auto(bev_ssl, fd) < 0)
|
||||
goto err;
|
||||
break;
|
||||
case BUFFEREVENT_SSL_OPEN:
|
||||
if (set_open_callbacks(bev_ssl, fd) < 0)
|
||||
if (set_open_callbacks_auto(bev_ssl, fd) < 0)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
@ -1383,15 +1395,15 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
||||
bufferevent_suspend_read_(underlying,
|
||||
BEV_SUSPEND_FILT_READ);
|
||||
} else {
|
||||
bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE;
|
||||
if (bev_ssl->fd_is_set) {
|
||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||
bev->enabled = EV_READ|EV_WRITE;
|
||||
if (state != BUFFEREVENT_SSL_OPEN)
|
||||
if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0)
|
||||
if (event_add(&bev->ev_read, NULL) < 0)
|
||||
goto err;
|
||||
if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0)
|
||||
if (event_initialized(&bev->ev_write))
|
||||
if (event_add(&bev->ev_write, NULL) < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return &bev_ssl->bev.bev;
|
||||
err:
|
||||
|
Loading…
x
Reference in New Issue
Block a user