Merge remote-tracking branch 'origin/patches-2.0'

This commit is contained in:
Nick Mathewson 2012-08-23 10:13:26 -04:00
commit e3d010c8f6

View File

@ -559,15 +559,20 @@ decrement_buckets(struct bufferevent_openssl *bev_ssl)
bev_ssl->counts.n_read = num_r; bev_ssl->counts.n_read = num_r;
} }
/* returns -1 on internal error, 0 on stall, 1 on progress */ #define OP_MADE_PROGRESS 1
static int #define OP_BLOCKED 2
do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) #define OP_ERR 4
{
/* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if
we're now blocked); and OP_ERR (if an error occurred). */
static int
do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) {
/* Requires lock */ /* Requires lock */
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
struct evbuffer *input = bev->input; struct evbuffer *input = bev->input;
int r, n, i, n_used = 0, blocked = 0, atmost; int r, n, i, n_used = 0, atmost;
struct evbuffer_iovec space[2]; struct evbuffer_iovec space[2];
int result = 0;
atmost = bufferevent_get_read_max_(&bev_ssl->bev); atmost = bufferevent_get_read_max_(&bev_ssl->bev);
if (n_to_read > atmost) if (n_to_read > atmost)
@ -575,16 +580,17 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read)
n = evbuffer_reserve_space(input, n_to_read, space, 2); n = evbuffer_reserve_space(input, n_to_read, space, 2);
if (n < 0) if (n < 0)
return -1; return OP_ERR;
for (i=0; i<n; ++i) { for (i=0; i<n; ++i) {
if (bev_ssl->bev.read_suspended) if (bev_ssl->bev.read_suspended)
break; break;
r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len); r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
if (r>0) { if (r>0) {
result |= OP_MADE_PROGRESS;
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
if (clear_rbow(bev_ssl) < 0) if (clear_rbow(bev_ssl) < 0)
return -1; return OP_ERR | result;
++n_used; ++n_used;
space[i].iov_len = r; space[i].iov_len = r;
decrement_buckets(bev_ssl); decrement_buckets(bev_ssl);
@ -596,20 +602,20 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read)
/* Can't read until underlying has more data. */ /* Can't read until underlying has more data. */
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
if (clear_rbow(bev_ssl) < 0) if (clear_rbow(bev_ssl) < 0)
return -1; return OP_ERR | result;
break; break;
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
/* This read operation requires a write, and the /* This read operation requires a write, and the
* underlying is full */ * underlying is full */
if (!bev_ssl->read_blocked_on_write) if (!bev_ssl->read_blocked_on_write)
if (set_rbow(bev_ssl) < 0) if (set_rbow(bev_ssl) < 0)
return -1; return OP_ERR | result;
break; break;
default: default:
conn_closed(bev_ssl, BEV_EVENT_READING, err, r); conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
break; break;
} }
blocked = 1; result |= OP_BLOCKED;
break; /* out of the loop */ break; /* out of the loop */
} }
} }
@ -620,16 +626,19 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read)
BEV_RESET_GENERIC_READ_TIMEOUT(bev); BEV_RESET_GENERIC_READ_TIMEOUT(bev);
} }
return blocked ? 0 : 1; return result;
} }
/* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if
we're now blocked); and OP_ERR (if an error occurred). */
static int static int
do_write(struct bufferevent_openssl *bev_ssl, int atmost) do_write(struct bufferevent_openssl *bev_ssl, int atmost)
{ {
int i, r, n, n_written = 0, blocked=0; int i, r, n, n_written = 0;
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
struct evbuffer *output = bev->output; struct evbuffer *output = bev->output;
struct evbuffer_iovec space[8]; struct evbuffer_iovec space[8];
int result = 0;
if (bev_ssl->last_write > 0) if (bev_ssl->last_write > 0)
atmost = bev_ssl->last_write; atmost = bev_ssl->last_write;
@ -638,7 +647,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
n = evbuffer_peek(output, atmost, NULL, space, 8); n = evbuffer_peek(output, atmost, NULL, space, 8);
if (n < 0) if (n < 0)
return -1; return OP_ERR | result;
if (n > 8) if (n > 8)
n = 8; n = 8;
@ -655,9 +664,10 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
r = SSL_write(bev_ssl->ssl, space[i].iov_base, r = SSL_write(bev_ssl->ssl, space[i].iov_base,
space[i].iov_len); space[i].iov_len);
if (r > 0) { if (r > 0) {
result |= OP_MADE_PROGRESS;
if (bev_ssl->write_blocked_on_read) if (bev_ssl->write_blocked_on_read)
if (clear_wbor(bev_ssl) < 0) if (clear_wbor(bev_ssl) < 0)
return -1; return OP_ERR | result;
n_written += r; n_written += r;
bev_ssl->last_write = -1; bev_ssl->last_write = -1;
decrement_buckets(bev_ssl); decrement_buckets(bev_ssl);
@ -669,7 +679,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
/* Can't read until underlying has more data. */ /* Can't read until underlying has more data. */
if (bev_ssl->write_blocked_on_read) if (bev_ssl->write_blocked_on_read)
if (clear_wbor(bev_ssl) < 0) if (clear_wbor(bev_ssl) < 0)
return -1; return OP_ERR | result;
bev_ssl->last_write = space[i].iov_len; bev_ssl->last_write = space[i].iov_len;
break; break;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
@ -677,7 +687,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
* underlying is full */ * underlying is full */
if (!bev_ssl->write_blocked_on_read) if (!bev_ssl->write_blocked_on_read)
if (set_wbor(bev_ssl) < 0) if (set_wbor(bev_ssl) < 0)
return -1; return OP_ERR | result;
bev_ssl->last_write = space[i].iov_len; bev_ssl->last_write = space[i].iov_len;
break; break;
default: default:
@ -685,7 +695,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
bev_ssl->last_write = -1; bev_ssl->last_write = -1;
break; break;
} }
blocked = 1; result |= OP_BLOCKED;
break; break;
} }
} }
@ -697,7 +707,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
if (evbuffer_get_length(output) <= bev->wm_write.low) if (evbuffer_get_length(output) <= bev->wm_write.low)
bufferevent_run_writecb_(bev); bufferevent_run_writecb_(bev);
} }
return blocked ? 0 : 1; return result;
} }
#define WRITE_FRAME 15000 #define WRITE_FRAME 15000
@ -757,11 +767,11 @@ consider_reading(struct bufferevent_openssl *bev_ssl)
{ {
int r; int r;
int n_to_read; int n_to_read;
int read_data = 0; int all_result_flags = 0;
while (bev_ssl->write_blocked_on_read) { while (bev_ssl->write_blocked_on_read) {
r = do_write(bev_ssl, WRITE_FRAME); r = do_write(bev_ssl, WRITE_FRAME);
if (r <= 0) if (r & (OP_BLOCKED|OP_ERR))
break; break;
} }
if (bev_ssl->write_blocked_on_read) if (bev_ssl->write_blocked_on_read)
@ -770,10 +780,11 @@ consider_reading(struct bufferevent_openssl *bev_ssl)
n_to_read = bytes_to_read(bev_ssl); n_to_read = bytes_to_read(bev_ssl);
while (n_to_read) { while (n_to_read) {
if (do_read(bev_ssl, n_to_read) <= 0) r = do_read(bev_ssl, n_to_read);
break; all_result_flags |= r;
read_data = 1; if (r & (OP_BLOCKED|OP_ERR))
break;
/* Read all pending data. This won't hit the network /* Read all pending data. This won't hit the network
* again, and will (most importantly) put us in a state * again, and will (most importantly) put us in a state
@ -803,7 +814,7 @@ consider_reading(struct bufferevent_openssl *bev_ssl)
n_to_read = bytes_to_read(bev_ssl); n_to_read = bytes_to_read(bev_ssl);
} }
if (read_data == 1) { if (all_result_flags & OP_MADE_PROGRESS) {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
struct evbuffer *input = bev->input; struct evbuffer *input = bev->input;
@ -831,9 +842,7 @@ consider_writing(struct bufferevent_openssl *bev_ssl)
while (bev_ssl->read_blocked_on_write) { while (bev_ssl->read_blocked_on_write) {
r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */ r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */
if (r <= 0) if (r & OP_MADE_PROGRESS) {
break;
else {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
struct evbuffer *input = bev->input; struct evbuffer *input = bev->input;
@ -841,6 +850,8 @@ consider_writing(struct bufferevent_openssl *bev_ssl)
bufferevent_run_readcb_(bev); bufferevent_run_readcb_(bev);
} }
} }
if (r & (OP_ERR|OP_BLOCKED))
break;
} }
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
return; return;
@ -858,7 +869,7 @@ consider_writing(struct bufferevent_openssl *bev_ssl)
else else
n_to_write = WRITE_FRAME; n_to_write = WRITE_FRAME;
r = do_write(bev_ssl, n_to_write); r = do_write(bev_ssl, n_to_write);
if (r <= 0) if (r & (OP_BLOCKED|OP_ERR))
break; break;
} }