mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-23 20:03:31 +01:00
r11741@Kushana: nickm | 2006-12-28 22:41:29 -0500
Count TLS bytes accurately: previously, we counted only the number of bytes read or transmitted via tls, not the number of extra bytes used to do so. This has been a lonstanding wart. The fix "Works for me". svn:r9207
This commit is contained in:
parent
7cfdac1bf6
commit
361998d0f3
@ -16,6 +16,9 @@ Changes in version 0.1.2.5-xxxx - 200?-??-??
|
||||
same directory as tor.exe (Bug #356) and default to using the torrc
|
||||
located in the %appdata%\Tor\ of the user who installed the service.
|
||||
Patch from Matt Edman.
|
||||
- Include TLS overhead when counting bandwidth usage; previously, we
|
||||
would count only the bytes sent over TLS, but not the bytes used to
|
||||
send them.
|
||||
|
||||
o Minor features:
|
||||
- Start using the state file to store bandwidth accounting data:
|
||||
|
2
doc/TODO
2
doc/TODO
@ -296,7 +296,7 @@ P - Figure out why openssl 0.9.8d "make test" fails at sha256t test.
|
||||
- a way to pick entry guards based wholly on extend_info equivalent;
|
||||
a way to export extend_info equivalent.
|
||||
|
||||
- Count TLS bandwidth more accurately
|
||||
o Count TLS bandwidth more accurately
|
||||
|
||||
- Better estimates in the directory of whether servers have good uptime
|
||||
(high expected time to failure) or good guard qualities (high
|
||||
|
@ -53,9 +53,11 @@ struct tor_tls_t {
|
||||
TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED
|
||||
} state; /**< The current SSL state, depending on which operations have
|
||||
* completed successfully. */
|
||||
int isServer;
|
||||
int isServer; /**< True iff this is a server-side connection */
|
||||
size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
|
||||
* time. */
|
||||
unsigned long last_write_count;
|
||||
unsigned long last_read_count;
|
||||
};
|
||||
|
||||
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
@ -339,7 +341,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = tor_malloc(sizeof(tor_tls_context_t));
|
||||
result = tor_malloc_zero(sizeof(tor_tls_context_t));
|
||||
#ifdef EVERYONE_HAS_AES
|
||||
/* Tell OpenSSL to only use TLS1 */
|
||||
if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
|
||||
@ -415,7 +417,7 @@ tor_tls_t *
|
||||
tor_tls_new(int sock, int isServer)
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
tor_tls_t *result = tor_malloc(sizeof(tor_tls_t));
|
||||
tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
|
||||
|
||||
tor_assert(global_tls_context); /* make sure somebody made it first */
|
||||
if (!(result->ssl = SSL_new(global_tls_context->ctx))) {
|
||||
@ -860,19 +862,23 @@ tor_tls_get_forced_write_size(tor_tls_t *tls)
|
||||
return tls->wantwrite_n;
|
||||
}
|
||||
|
||||
/** Return the number of bytes read across the underlying socket. */
|
||||
unsigned long
|
||||
tor_tls_get_n_bytes_read(tor_tls_t *tls)
|
||||
/** Sets n_read and n_written to the number of bytes read and written,
|
||||
* respectivey, on the raw socket used by <b>tls</b> since the last time this
|
||||
* function was called on <b>tls</b>. */
|
||||
void
|
||||
tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written)
|
||||
{
|
||||
tor_assert(tls);
|
||||
return BIO_number_read(SSL_get_rbio(tls->ssl));
|
||||
}
|
||||
/** Return the number of bytes written across the underlying socket. */
|
||||
unsigned long
|
||||
tor_tls_get_n_bytes_written(tor_tls_t *tls)
|
||||
{
|
||||
tor_assert(tls);
|
||||
return BIO_number_written(SSL_get_wbio(tls->ssl));
|
||||
unsigned long r, w;
|
||||
r = BIO_number_read(SSL_get_rbio(tls->ssl));
|
||||
w = BIO_number_written(SSL_get_wbio(tls->ssl));
|
||||
/* If we wrapped around, this should still give us the right answer, unless
|
||||
* we wrapped around by more than ULONG_MAX since the last time we called
|
||||
* this function.
|
||||
*/
|
||||
*n_read = (size_t)(r - tls->last_read_count);
|
||||
*n_written = (size_t)(w - tls->last_write_count);
|
||||
tls->last_read_count = r;
|
||||
tls->last_write_count = w;
|
||||
}
|
||||
|
||||
/** Implement check_no_tls_errors: If there are any pending OpenSSL
|
||||
|
@ -43,8 +43,8 @@ int tor_tls_shutdown(tor_tls_t *tls);
|
||||
int tor_tls_get_pending_bytes(tor_tls_t *tls);
|
||||
size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
|
||||
|
||||
unsigned long tor_tls_get_n_bytes_read(tor_tls_t *tls);
|
||||
unsigned long tor_tls_get_n_bytes_written(tor_tls_t *tls);
|
||||
void tor_tls_get_n_raw_bytes(tor_tls_t *tls,
|
||||
size_t *n_read, size_t *n_written);
|
||||
|
||||
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
|
||||
*/
|
||||
|
@ -1418,6 +1418,7 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
||||
{
|
||||
int result, at_most = *max_to_read;
|
||||
size_t bytes_in_buf, more_to_read;
|
||||
size_t n_read = 0, n_written = 0;
|
||||
|
||||
if (at_most == -1) { /* we need to initialize it */
|
||||
/* how many bytes are we allowed to read? */
|
||||
@ -1475,7 +1476,7 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
||||
}
|
||||
pending = tor_tls_get_pending_bytes(or_conn->tls);
|
||||
if (pending) {
|
||||
/* XXXX012 If we have any pending bytes, read them now. This *can*
|
||||
/* If we have any pending bytes, we read them now. This *can*
|
||||
* take us over our read allotment, but really we shouldn't be
|
||||
* believing that SSL bytes are the same as TCP bytes anyway. */
|
||||
int r2 = read_to_buf_tls(or_conn->tls, pending, conn->inbuf);
|
||||
@ -1487,6 +1488,9 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
||||
}
|
||||
}
|
||||
|
||||
tor_tls_get_n_raw_bytes(or_conn->tls, &n_read, &n_written);
|
||||
log_debug(LD_GENERAL, "After TLS read of %d: %ld read, %ld written",
|
||||
result, (long)n_read, (long)n_written);
|
||||
} else {
|
||||
int reached_eof = 0;
|
||||
CONN_LOG_PROTECT(conn,
|
||||
@ -1498,15 +1502,24 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
||||
|
||||
if (result < 0)
|
||||
return -1;
|
||||
n_read = (size_t) result;
|
||||
}
|
||||
|
||||
if (result > 0) { /* change *max_to_read */
|
||||
*max_to_read = at_most - result;
|
||||
if (n_read > 0) { /* change *max_to_read */
|
||||
*max_to_read = at_most - n_read;
|
||||
}
|
||||
|
||||
if (result > 0 && !is_internal_IP(conn->addr, 0)) { /* remember it */
|
||||
rep_hist_note_bytes_read(result, time(NULL));
|
||||
connection_read_bucket_decrement(conn, result);
|
||||
if (!is_internal_IP(conn->addr, 0)) {
|
||||
/* For non-local IPs, remember if we flushed any bytes over the wire. */
|
||||
time_t now = time(NULL);
|
||||
if (n_read > 0) {
|
||||
rep_hist_note_bytes_read(n_read, now);
|
||||
connection_read_bucket_decrement(conn, n_read);
|
||||
}
|
||||
if (n_written > 0) {
|
||||
rep_hist_note_bytes_written(n_written, now);
|
||||
global_write_bucket -= n_written;
|
||||
}
|
||||
}
|
||||
|
||||
if (more_to_read && result == at_most) {
|
||||
@ -1520,6 +1533,8 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
||||
* have reached 0 on a different conn, and this guy needs to
|
||||
* know to stop reading. */
|
||||
connection_consider_empty_read_buckets(conn);
|
||||
if (n_written > 0)
|
||||
connection_consider_empty_write_buckets(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1571,6 +1586,7 @@ connection_handle_write(connection_t *conn)
|
||||
int result;
|
||||
int max_to_write;
|
||||
time_t now = time(NULL);
|
||||
size_t n_read = 0, n_written = 0;
|
||||
|
||||
tor_assert(!connection_is_listener(conn));
|
||||
|
||||
@ -1664,6 +1680,10 @@ connection_handle_write(connection_t *conn)
|
||||
* is empty, so we can stop writing.
|
||||
*/
|
||||
}
|
||||
|
||||
tor_tls_get_n_raw_bytes(or_conn->tls, &n_read, &n_written);
|
||||
log_debug(LD_GENERAL, "After TLS write of %d: %ld read, %ld written",
|
||||
result, (long)n_read, (long)n_written);
|
||||
} else {
|
||||
CONN_LOG_PROTECT(conn,
|
||||
result = flush_buf(conn->s, conn->outbuf,
|
||||
@ -1677,13 +1697,25 @@ connection_handle_write(connection_t *conn)
|
||||
connection_mark_for_close(conn);
|
||||
return -1;
|
||||
}
|
||||
n_written = (size_t) result;
|
||||
}
|
||||
|
||||
if (!is_internal_IP(conn->addr, 0)) {
|
||||
/* For non-local IPs, remember if we flushed any bytes over the wire. */
|
||||
time_t now = time(NULL);
|
||||
if (n_written > 0) {
|
||||
rep_hist_note_bytes_written(n_written, now);
|
||||
global_write_bucket -= n_written;
|
||||
}
|
||||
if (n_read > 0) {
|
||||
rep_hist_note_bytes_read(n_read, now);
|
||||
global_read_bucket -= n_read;
|
||||
}
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
if (!is_internal_IP(conn->addr, 0)) { /* remember it */
|
||||
rep_hist_note_bytes_written(result, time(NULL));
|
||||
global_write_bucket -= result;
|
||||
}
|
||||
/* If we wrote any bytes from our buffer, then call the appropriate
|
||||
* functions. */
|
||||
if (connection_flushed_some(conn) < 0)
|
||||
connection_mark_for_close(conn);
|
||||
}
|
||||
@ -1700,6 +1732,9 @@ connection_handle_write(connection_t *conn)
|
||||
* have reached 0 on a different conn, and this guy needs to
|
||||
* know to stop writing. */
|
||||
connection_consider_empty_write_buckets(conn);
|
||||
if (n_read > 0)
|
||||
connection_consider_empty_read_buckets(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user