Loading src/or/buffers.c +4 −2 Original line number Diff line number Diff line Loading @@ -129,6 +129,7 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale // log_fn(LOG_DEBUG,"flushed %d bytes, %d ready to flush, %d remain.", // write_result,*buf_flushlen,*buf_datalen); return *buf_flushlen; /* XXX USE_TLS should change to return write_result like any sane function would */ } } Loading @@ -136,8 +137,9 @@ int flush_buf_tls(tor_tls *tls, char **buf, int *buflen, int *buf_flushlen, int { int r; assert(tls && *buf && buflen && buf_datalen); if (*buf_flushlen == 0) return 0; /* we want to let tls write even if flushlen is zero, because it might * have a partial record pending */ r = tor_tls_write(tls, *buf, *buf_flushlen); if (r < 0) { return r; Loading src/or/connection.c +112 −50 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ connection_t *connection_new(int type) { conn->timestamp_lastread = now.tv_sec; conn->timestamp_lastwritten = now.tv_sec; #ifndef TOR_TLS #ifndef USE_TLS if (connection_speaks_cells(conn)) { conn->f_crypto = crypto_new_cipher_env(CONNECTION_CIPHER); if (!conn->f_crypto) { Loading @@ -107,7 +107,6 @@ connection_t *connection_new(int type) { } } #endif conn->done_sending = conn->done_receiving = 0; return conn; } Loading @@ -123,9 +122,9 @@ void connection_free(connection_t *conn) { if(connection_speaks_cells(conn)) { directory_set_dirty(); #ifdef TOR_TLS if (conn->SSL) crypt_SSL_free(conn->SSL); #ifdef USE_TLS if (conn->tls) tor_tls_free(conn->tls); #else if (conn->f_crypto) crypto_free_cipher_env(conn->f_crypto); Loading Loading @@ -245,10 +244,8 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st return 0; } int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { /* start all connections that should be up but aren't */ int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { struct sockaddr_in bindaddr; /* where to bind */ if(or_listenport) { Loading Loading @@ -316,12 +313,13 @@ int connection_handle_read(connection_t *conn) { log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing."); return -1; } return 0; } /* end switch */ return 0; } /* return -1 if we want to break conn, else return 0 */ int connection_read_to_buf(connection_t *conn) { int read_result; int result; int at_most; assert((connection_speaks_cells(conn) && conn->receiver_bucket >= 0) || Loading @@ -344,27 +342,51 @@ int connection_read_to_buf(connection_t *conn) { if(conn->receiver_bucket >= 0 && at_most > conn->receiver_bucket) at_most = conn->receiver_bucket; read_result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen, #ifdef USE_TLS if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) { if(conn->state == OR_CONN_STATE_HANDSHAKING) { result = tor_tls_handshake(conn->tls) if(result == TOR_TLS_DONE) { conn->state = OR_CONN_STATE_OPEN; log_fn(LOG_DEBUG,"tls handshake done, now open."); } } else { /* open, or closing */ result = read_to_buf_tls(conn->tls, at_most, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen); } switch(result) { case TOR_TLS_ERROR: case TOR_TLS_CLOSE: log_fn(LOG_DEBUG,"tls error. breaking."); return -1; /* XXX deal with close better */ case TOR_TLS_WANT_WRITE: connection_start_writing(conn); return 0; case TOR_TLS_WANT_READ: /* we're already reading */ case TOR_TLS_DONE: /* no data read, so nothing to process */ return 0; } } else #endif { result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen, &conn->inbuf_reached_eof); // log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result); if(read_result >= 0) { global_read_bucket -= read_result; assert(global_read_bucket >= 0); if(result < 0) return -1; } global_read_bucket -= result; assert(global_read_bucket >= 0); if(connection_speaks_cells(conn)) conn->receiver_bucket -= read_result; conn->receiver_bucket -= result; if(conn->receiver_bucket == 0 || global_read_bucket == 0) { log_fn(LOG_DEBUG,"buckets (%d, %d) exhausted. Pausing.", global_read_bucket, conn->receiver_bucket); conn->wants_to_read = 1; connection_stop_reading(conn); /* If we're not in 'open' state here, then we're never going to finish the * handshake, because we'll never increment the receiver_bucket. But we * can't check for that here, because the buf we just read might have enough * on it to finish the handshake. So we check for that in connection_handle_read(). */ } } return read_result; return 0; } int connection_fetch_from_buf(char *string, int len, connection_t *conn) { Loading @@ -388,9 +410,10 @@ int connection_flush_buf(connection_t *conn) { &conn->outbuf_flushlen, &conn->outbuf_datalen); } /* return -1 if you want to break the conn, else return 0 */ int connection_handle_write(connection_t *conn) { struct timeval now; int retval; int result; if(connection_is_listener(conn)) { log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!"); Loading @@ -400,25 +423,57 @@ int connection_handle_write(connection_t *conn) { my_gettimeofday(&now); conn->timestamp_lastwritten = now.tv_sec; #ifdef TOR_TLS if(connection_speaks_cells(conn)) { retval = flush_buf_SSL(conn->SSL, &conn->outbuf, &conn->outbuflen, #ifdef USE_TLS if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) { if(conn->state == OR_CONN_STATE_HANDSHAKING) { result = tor_tls_handshake(conn->tls) if(result == TOR_TLS_DONE) { conn->state = OR_CONN_STATE_OPEN; log_fn(LOG_DEBUG,"tls handshake done, now open."); } } else { /* open, or closing */ result = flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen); ... } switch(result) { case TOR_TLS_ERROR: case TOR_TLS_CLOSE: log_fn(LOG_DEBUG,"tls error. breaking."); return -1; /* XXX deal with close better */ case TOR_TLS_WANT_WRITE: /* we're already writing */ return 0; case TOR_TLS_WANT_READ: /* Make sure to avoid a loop if the receive buckets are empty. */ if(!connection_is_reading(conn)) { connection_stop_writing(conn); conn->wants_to_write = 1; /* we'll start reading again when the next second arrives, * and then also start writing again. */ } /* else no problem, we're already reading */ return 0; case TOR_TLS_DONE: /* for TOR_TLS_DONE, fall through to check if the flushlen * is empty, so we can stop writing. */ } } else #endif { retval = flush_buf(conn->s, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen); if(flush_buf(conn->s, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen) < 0) return -1; /* conns in CONNECTING state will fall through... */ if(retval == 0) { /* it's done flushing */ retval = connection_finished_flushing(conn); /* ...and get handled here. */ } } return retval; if(!connection_wants_to_flush(conn)) /* it's done flushing */ if(connection_finished_flushing(conn) < 0) /* ...and get handled here. */ return -1; return 0; } int connection_write_to_buf(char *string, int len, connection_t *conn) { Loading Loading @@ -496,13 +551,16 @@ int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn) { cell_pack(n, cellp); #ifndef USE_TLS if(connection_encrypt_cell(n,conn)<0) { return -1; } #endif return connection_write_to_buf(n, CELL_NETWORK_SIZE, conn); } #ifndef USE_TLS int connection_encrypt_cell(char *cellp, connection_t *conn) { char cryptcell[CELL_NETWORK_SIZE]; #if 0 Loading Loading @@ -535,6 +593,7 @@ int connection_encrypt_cell(char *cellp, connection_t *conn) { memcpy(cellp,cryptcell,CELL_NETWORK_SIZE); return 0; } #endif int connection_process_inbuf(connection_t *conn) { Loading Loading @@ -705,18 +764,20 @@ int connection_finished_flushing(connection_t *conn) { int connection_process_cell_from_inbuf(connection_t *conn) { /* check if there's a whole cell there. * if yes, pull it off, decrypt it, and process it. * if yes, pull it off, decrypt it if we're not doing TLS, and process it. */ char crypted[CELL_NETWORK_SIZE]; char outbuf[1024]; char networkcell[CELL_NETWORK_SIZE]; char buf[CELL_NETWORK_SIZE]; // int x; cell_t cell; if(conn->inbuf_datalen < CELL_NETWORK_SIZE) /* entire response available? */ return 0; /* not yet */ connection_fetch_from_buf(crypted,CELL_NETWORK_SIZE,conn); #ifdef USE_TLS connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn); #else connection_fetch_from_buf(networkcell, CELL_NETWORK_SIZE, conn); #if 0 printf("Cell header crypttext: "); for(x=0;x<8;x++) { Loading @@ -725,7 +786,7 @@ int connection_process_cell_from_inbuf(connection_t *conn) { printf("\n"); #endif /* decrypt */ if(crypto_cipher_decrypt(conn->b_crypto,crypted,CELL_NETWORK_SIZE,outbuf)) { if(crypto_cipher_decrypt(conn->b_crypto, networkcell, CELL_NETWORK_SIZE, buf)) { log_fn(LOG_ERR,"Decryption failed, dropping."); return connection_process_inbuf(conn); /* process the remainder of the buffer */ } Loading @@ -736,10 +797,11 @@ int connection_process_cell_from_inbuf(connection_t *conn) { printf("%u ",outbuf[x]); } printf("\n"); #endif #endif /* retrieve cell info from outbuf (create the host-order struct from the network-order string) */ cell_unpack(&cell, outbuf); /* retrieve cell info from buf (create the host-order struct from the network-order string) */ cell_unpack(&cell, buf); // log_fn(LOG_DEBUG,"Decrypted cell is of type %u (ACI %u).",cellp->command,cellp->aci); command_process_cell(&cell, conn); Loading src/or/connection_or.c +16 −10 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ extern or_options_t options; /* command-line and config-file options */ #ifndef TOR_TLS #ifndef USE_TLS static int or_handshake_op_send_keys(connection_t *conn); static int or_handshake_op_finished_sending_keys(connection_t *conn); Loading Loading @@ -35,17 +35,18 @@ int connection_or_process_inbuf(connection_t *conn) { return -1; } #ifdef USE_TLS assert(conn->state == OR_CONN_STATE_OPEN); return connection_process_cell_from_inbuf(conn); #else // log(LOG_DEBUG,"connection_or_process_inbuf(): state %d.",conn->state); switch(conn->state) { #ifndef TOR_TLS case OR_CONN_STATE_CLIENT_AUTH_WAIT: return or_handshake_client_process_auth(conn); case OR_CONN_STATE_SERVER_AUTH_WAIT: return or_handshake_server_process_auth(conn); case OR_CONN_STATE_SERVER_NONCE_WAIT: return or_handshake_server_process_nonce(conn); #endif case OR_CONN_STATE_OPEN: return connection_process_cell_from_inbuf(conn); default: Loading @@ -53,6 +54,7 @@ int connection_or_process_inbuf(connection_t *conn) { } return 0; #endif } int connection_or_finished_flushing(connection_t *conn) { Loading @@ -61,9 +63,13 @@ int connection_or_finished_flushing(connection_t *conn) { assert(conn && conn->type == CONN_TYPE_OR); switch(conn->state) { #ifndef USE_TLS case OR_CONN_STATE_OP_SENDING_KEYS: return or_handshake_op_finished_sending_keys(conn); case OR_CONN_STATE_CLIENT_CONNECTING: #else case OR_CONN_STATE_CONNECTING: #endif if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */ if(!ERRNO_CONN_EINPROGRESS(errno)){ /* yuck. kill it. */ Loading @@ -78,6 +84,9 @@ int connection_or_finished_flushing(connection_t *conn) { log_fn(LOG_DEBUG,"OR connection to router %s:%u established.", conn->address,conn->port); #ifdef USE_TLS call TLS new, and start the TLS handshake #else if(options.OnionRouter) return or_handshake_client_send_auth(conn); else Loading @@ -98,17 +107,14 @@ int connection_or_finished_flushing(connection_t *conn) { conn->state = OR_CONN_STATE_SERVER_NONCE_WAIT; connection_watch_events(conn, POLLIN); return 0; #endif case OR_CONN_STATE_OPEN: /* FIXME down the road, we'll clear out circuits that are pending to close */ connection_stop_writing(conn); return 0; default: log_fn(LOG_DEBUG,"BUG: called in unexpected state."); log_fn(LOG_ERR,"BUG: called in unexpected state."); return 0; } return 0; } /*********************/ Loading Loading @@ -659,7 +665,7 @@ connection_or_set_open(connection_t *conn) { connection_watch_events(conn, POLLIN); } #ifndef TOR_TLS #ifndef USE_TLS static void conn_or_init_crypto(connection_t *conn) { //int x; Loading src/or/main.c +30 −19 Original line number Diff line number Diff line Loading @@ -212,6 +212,10 @@ void connection_watch_events(connection_t *conn, short events) { poll_array[conn->poll_index].events = events; } int connection_is_reading(connection_t *conn) { return poll_array[conn->poll_index].events & POLLIN; } void connection_stop_reading(connection_t *conn) { assert(conn && conn->poll_index < nfds); Loading Loading @@ -312,8 +316,7 @@ static void check_conn_marked(int i) { static int prepare_for_poll(void) { int i; // connection_t *conn = NULL; connection_t *tmpconn; connection_t *conn; struct timeval now; //soonest; static long current_second = 0; /* from previous calls to gettimeofday */ static long time_to_fetch_directory = 0; Loading Loading @@ -355,37 +358,41 @@ static int prepare_for_poll(void) { /* do housekeeping for each connection */ for(i=0;i<nfds;i++) { tmpconn = connection_array[i]; if(connection_receiver_bucket_should_increase(tmpconn)) { tmpconn->receiver_bucket += tmpconn->bandwidth; // log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, tmpconn->receiver_bucket); conn = connection_array[i]; if(connection_receiver_bucket_should_increase(conn)) { conn->receiver_bucket += conn->bandwidth; // log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, conn->receiver_bucket); } if(tmpconn->wants_to_read == 1 /* it's marked to turn reading back on now */ if(conn->wants_to_read == 1 /* it's marked to turn reading back on now */ && global_read_bucket > 0 /* and we're allowed to read */ && tmpconn->receiver_bucket != 0) { /* and either an edge conn or non-empty bucket */ tmpconn->wants_to_read = 0; connection_start_reading(tmpconn); && conn->receiver_bucket != 0) { /* and either an edge conn or non-empty bucket */ conn->wants_to_read = 0; connection_start_reading(conn); if(conn->wants_to_write == 1) { conn->wants_to_write = 0; connection_start_writing(conn); } } /* check connections to see whether we should send a keepalive, expire, or wait */ if(!connection_speaks_cells(tmpconn)) if(!connection_speaks_cells(conn)) continue; /* this conn type doesn't send cells */ if(now.tv_sec >= tmpconn->timestamp_lastwritten + options.KeepalivePeriod) { if((!options.OnionRouter && !circuit_get_by_conn(tmpconn)) || (!connection_state_is_open(tmpconn))) { if(now.tv_sec >= conn->timestamp_lastwritten + options.KeepalivePeriod) { if((!options.OnionRouter && !circuit_get_by_conn(conn)) || (!connection_state_is_open(conn))) { /* we're an onion proxy, with no circuits; or our handshake has expired. kill it. */ log(LOG_DEBUG,"prepare_for_poll(): Expiring connection to %d (%s:%d).", i,tmpconn->address, tmpconn->port); tmpconn->marked_for_close = 1; i,conn->address, conn->port); conn->marked_for_close = 1; } else { /* either a full router, or we've got a circuit. send a padding cell. */ // log(LOG_DEBUG,"prepare_for_poll(): Sending keepalive to (%s:%d)", // tmpconn->address, tmpconn->port); // conn->address, conn->port); memset(&cell,0,sizeof(cell_t)); cell.command = CELL_PADDING; if(connection_write_cell_to_buf(&cell, tmpconn) < 0) tmpconn->marked_for_close = 1; if(connection_write_cell_to_buf(&cell, conn) < 0) conn->marked_for_close = 1; } } } Loading Loading @@ -442,6 +449,10 @@ static int do_main_loop(void) { set_signing_privatekey(prkey); } #ifdef USE_TLS make the tls context here #endif /* start up the necessary connections based on which ports are * non-zero. This is where we try to connect to all the other ORs, * and start the listeners. Loading src/or/or.h +6 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,9 @@ struct connection_t { uint8_t wants_to_read; /* should we start reading again once * the bandwidth throttler allows it? */ uint8_t wants_to_write; /* should we start writing again once * the bandwidth throttler allows reads? */ int s; /* our socket */ int poll_index; /* index of this conn into the poll_array */ int marked_for_close; /* should we close this conn on the next Loading Loading @@ -642,7 +645,9 @@ int connection_state_is_open(connection_t *conn); int connection_send_destroy(aci_t aci, connection_t *conn); int connection_send_connected(aci_t aci, connection_t *conn); #ifndef USE_TLS int connection_encrypt_cell(char *cellp, connection_t *conn); #endif int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn); int connection_process_inbuf(connection_t *conn); Loading Loading @@ -751,6 +756,7 @@ connection_t *connection_get_by_type_state(int type, int state); connection_t *connection_get_by_type_state_lastwritten(int type, int state); void connection_watch_events(connection_t *conn, short events); int connection_is_reading(connection_t *conn); void connection_stop_reading(connection_t *conn); void connection_start_reading(connection_t *conn); void connection_stop_writing(connection_t *conn); Loading Loading
src/or/buffers.c +4 −2 Original line number Diff line number Diff line Loading @@ -129,6 +129,7 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale // log_fn(LOG_DEBUG,"flushed %d bytes, %d ready to flush, %d remain.", // write_result,*buf_flushlen,*buf_datalen); return *buf_flushlen; /* XXX USE_TLS should change to return write_result like any sane function would */ } } Loading @@ -136,8 +137,9 @@ int flush_buf_tls(tor_tls *tls, char **buf, int *buflen, int *buf_flushlen, int { int r; assert(tls && *buf && buflen && buf_datalen); if (*buf_flushlen == 0) return 0; /* we want to let tls write even if flushlen is zero, because it might * have a partial record pending */ r = tor_tls_write(tls, *buf, *buf_flushlen); if (r < 0) { return r; Loading
src/or/connection.c +112 −50 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ connection_t *connection_new(int type) { conn->timestamp_lastread = now.tv_sec; conn->timestamp_lastwritten = now.tv_sec; #ifndef TOR_TLS #ifndef USE_TLS if (connection_speaks_cells(conn)) { conn->f_crypto = crypto_new_cipher_env(CONNECTION_CIPHER); if (!conn->f_crypto) { Loading @@ -107,7 +107,6 @@ connection_t *connection_new(int type) { } } #endif conn->done_sending = conn->done_receiving = 0; return conn; } Loading @@ -123,9 +122,9 @@ void connection_free(connection_t *conn) { if(connection_speaks_cells(conn)) { directory_set_dirty(); #ifdef TOR_TLS if (conn->SSL) crypt_SSL_free(conn->SSL); #ifdef USE_TLS if (conn->tls) tor_tls_free(conn->tls); #else if (conn->f_crypto) crypto_free_cipher_env(conn->f_crypto); Loading Loading @@ -245,10 +244,8 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st return 0; } int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { /* start all connections that should be up but aren't */ int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { struct sockaddr_in bindaddr; /* where to bind */ if(or_listenport) { Loading Loading @@ -316,12 +313,13 @@ int connection_handle_read(connection_t *conn) { log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing."); return -1; } return 0; } /* end switch */ return 0; } /* return -1 if we want to break conn, else return 0 */ int connection_read_to_buf(connection_t *conn) { int read_result; int result; int at_most; assert((connection_speaks_cells(conn) && conn->receiver_bucket >= 0) || Loading @@ -344,27 +342,51 @@ int connection_read_to_buf(connection_t *conn) { if(conn->receiver_bucket >= 0 && at_most > conn->receiver_bucket) at_most = conn->receiver_bucket; read_result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen, #ifdef USE_TLS if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) { if(conn->state == OR_CONN_STATE_HANDSHAKING) { result = tor_tls_handshake(conn->tls) if(result == TOR_TLS_DONE) { conn->state = OR_CONN_STATE_OPEN; log_fn(LOG_DEBUG,"tls handshake done, now open."); } } else { /* open, or closing */ result = read_to_buf_tls(conn->tls, at_most, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen); } switch(result) { case TOR_TLS_ERROR: case TOR_TLS_CLOSE: log_fn(LOG_DEBUG,"tls error. breaking."); return -1; /* XXX deal with close better */ case TOR_TLS_WANT_WRITE: connection_start_writing(conn); return 0; case TOR_TLS_WANT_READ: /* we're already reading */ case TOR_TLS_DONE: /* no data read, so nothing to process */ return 0; } } else #endif { result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen, &conn->inbuf_reached_eof); // log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result); if(read_result >= 0) { global_read_bucket -= read_result; assert(global_read_bucket >= 0); if(result < 0) return -1; } global_read_bucket -= result; assert(global_read_bucket >= 0); if(connection_speaks_cells(conn)) conn->receiver_bucket -= read_result; conn->receiver_bucket -= result; if(conn->receiver_bucket == 0 || global_read_bucket == 0) { log_fn(LOG_DEBUG,"buckets (%d, %d) exhausted. Pausing.", global_read_bucket, conn->receiver_bucket); conn->wants_to_read = 1; connection_stop_reading(conn); /* If we're not in 'open' state here, then we're never going to finish the * handshake, because we'll never increment the receiver_bucket. But we * can't check for that here, because the buf we just read might have enough * on it to finish the handshake. So we check for that in connection_handle_read(). */ } } return read_result; return 0; } int connection_fetch_from_buf(char *string, int len, connection_t *conn) { Loading @@ -388,9 +410,10 @@ int connection_flush_buf(connection_t *conn) { &conn->outbuf_flushlen, &conn->outbuf_datalen); } /* return -1 if you want to break the conn, else return 0 */ int connection_handle_write(connection_t *conn) { struct timeval now; int retval; int result; if(connection_is_listener(conn)) { log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!"); Loading @@ -400,25 +423,57 @@ int connection_handle_write(connection_t *conn) { my_gettimeofday(&now); conn->timestamp_lastwritten = now.tv_sec; #ifdef TOR_TLS if(connection_speaks_cells(conn)) { retval = flush_buf_SSL(conn->SSL, &conn->outbuf, &conn->outbuflen, #ifdef USE_TLS if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) { if(conn->state == OR_CONN_STATE_HANDSHAKING) { result = tor_tls_handshake(conn->tls) if(result == TOR_TLS_DONE) { conn->state = OR_CONN_STATE_OPEN; log_fn(LOG_DEBUG,"tls handshake done, now open."); } } else { /* open, or closing */ result = flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen); ... } switch(result) { case TOR_TLS_ERROR: case TOR_TLS_CLOSE: log_fn(LOG_DEBUG,"tls error. breaking."); return -1; /* XXX deal with close better */ case TOR_TLS_WANT_WRITE: /* we're already writing */ return 0; case TOR_TLS_WANT_READ: /* Make sure to avoid a loop if the receive buckets are empty. */ if(!connection_is_reading(conn)) { connection_stop_writing(conn); conn->wants_to_write = 1; /* we'll start reading again when the next second arrives, * and then also start writing again. */ } /* else no problem, we're already reading */ return 0; case TOR_TLS_DONE: /* for TOR_TLS_DONE, fall through to check if the flushlen * is empty, so we can stop writing. */ } } else #endif { retval = flush_buf(conn->s, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen); if(flush_buf(conn->s, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen) < 0) return -1; /* conns in CONNECTING state will fall through... */ if(retval == 0) { /* it's done flushing */ retval = connection_finished_flushing(conn); /* ...and get handled here. */ } } return retval; if(!connection_wants_to_flush(conn)) /* it's done flushing */ if(connection_finished_flushing(conn) < 0) /* ...and get handled here. */ return -1; return 0; } int connection_write_to_buf(char *string, int len, connection_t *conn) { Loading Loading @@ -496,13 +551,16 @@ int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn) { cell_pack(n, cellp); #ifndef USE_TLS if(connection_encrypt_cell(n,conn)<0) { return -1; } #endif return connection_write_to_buf(n, CELL_NETWORK_SIZE, conn); } #ifndef USE_TLS int connection_encrypt_cell(char *cellp, connection_t *conn) { char cryptcell[CELL_NETWORK_SIZE]; #if 0 Loading Loading @@ -535,6 +593,7 @@ int connection_encrypt_cell(char *cellp, connection_t *conn) { memcpy(cellp,cryptcell,CELL_NETWORK_SIZE); return 0; } #endif int connection_process_inbuf(connection_t *conn) { Loading Loading @@ -705,18 +764,20 @@ int connection_finished_flushing(connection_t *conn) { int connection_process_cell_from_inbuf(connection_t *conn) { /* check if there's a whole cell there. * if yes, pull it off, decrypt it, and process it. * if yes, pull it off, decrypt it if we're not doing TLS, and process it. */ char crypted[CELL_NETWORK_SIZE]; char outbuf[1024]; char networkcell[CELL_NETWORK_SIZE]; char buf[CELL_NETWORK_SIZE]; // int x; cell_t cell; if(conn->inbuf_datalen < CELL_NETWORK_SIZE) /* entire response available? */ return 0; /* not yet */ connection_fetch_from_buf(crypted,CELL_NETWORK_SIZE,conn); #ifdef USE_TLS connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn); #else connection_fetch_from_buf(networkcell, CELL_NETWORK_SIZE, conn); #if 0 printf("Cell header crypttext: "); for(x=0;x<8;x++) { Loading @@ -725,7 +786,7 @@ int connection_process_cell_from_inbuf(connection_t *conn) { printf("\n"); #endif /* decrypt */ if(crypto_cipher_decrypt(conn->b_crypto,crypted,CELL_NETWORK_SIZE,outbuf)) { if(crypto_cipher_decrypt(conn->b_crypto, networkcell, CELL_NETWORK_SIZE, buf)) { log_fn(LOG_ERR,"Decryption failed, dropping."); return connection_process_inbuf(conn); /* process the remainder of the buffer */ } Loading @@ -736,10 +797,11 @@ int connection_process_cell_from_inbuf(connection_t *conn) { printf("%u ",outbuf[x]); } printf("\n"); #endif #endif /* retrieve cell info from outbuf (create the host-order struct from the network-order string) */ cell_unpack(&cell, outbuf); /* retrieve cell info from buf (create the host-order struct from the network-order string) */ cell_unpack(&cell, buf); // log_fn(LOG_DEBUG,"Decrypted cell is of type %u (ACI %u).",cellp->command,cellp->aci); command_process_cell(&cell, conn); Loading
src/or/connection_or.c +16 −10 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ extern or_options_t options; /* command-line and config-file options */ #ifndef TOR_TLS #ifndef USE_TLS static int or_handshake_op_send_keys(connection_t *conn); static int or_handshake_op_finished_sending_keys(connection_t *conn); Loading Loading @@ -35,17 +35,18 @@ int connection_or_process_inbuf(connection_t *conn) { return -1; } #ifdef USE_TLS assert(conn->state == OR_CONN_STATE_OPEN); return connection_process_cell_from_inbuf(conn); #else // log(LOG_DEBUG,"connection_or_process_inbuf(): state %d.",conn->state); switch(conn->state) { #ifndef TOR_TLS case OR_CONN_STATE_CLIENT_AUTH_WAIT: return or_handshake_client_process_auth(conn); case OR_CONN_STATE_SERVER_AUTH_WAIT: return or_handshake_server_process_auth(conn); case OR_CONN_STATE_SERVER_NONCE_WAIT: return or_handshake_server_process_nonce(conn); #endif case OR_CONN_STATE_OPEN: return connection_process_cell_from_inbuf(conn); default: Loading @@ -53,6 +54,7 @@ int connection_or_process_inbuf(connection_t *conn) { } return 0; #endif } int connection_or_finished_flushing(connection_t *conn) { Loading @@ -61,9 +63,13 @@ int connection_or_finished_flushing(connection_t *conn) { assert(conn && conn->type == CONN_TYPE_OR); switch(conn->state) { #ifndef USE_TLS case OR_CONN_STATE_OP_SENDING_KEYS: return or_handshake_op_finished_sending_keys(conn); case OR_CONN_STATE_CLIENT_CONNECTING: #else case OR_CONN_STATE_CONNECTING: #endif if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */ if(!ERRNO_CONN_EINPROGRESS(errno)){ /* yuck. kill it. */ Loading @@ -78,6 +84,9 @@ int connection_or_finished_flushing(connection_t *conn) { log_fn(LOG_DEBUG,"OR connection to router %s:%u established.", conn->address,conn->port); #ifdef USE_TLS call TLS new, and start the TLS handshake #else if(options.OnionRouter) return or_handshake_client_send_auth(conn); else Loading @@ -98,17 +107,14 @@ int connection_or_finished_flushing(connection_t *conn) { conn->state = OR_CONN_STATE_SERVER_NONCE_WAIT; connection_watch_events(conn, POLLIN); return 0; #endif case OR_CONN_STATE_OPEN: /* FIXME down the road, we'll clear out circuits that are pending to close */ connection_stop_writing(conn); return 0; default: log_fn(LOG_DEBUG,"BUG: called in unexpected state."); log_fn(LOG_ERR,"BUG: called in unexpected state."); return 0; } return 0; } /*********************/ Loading Loading @@ -659,7 +665,7 @@ connection_or_set_open(connection_t *conn) { connection_watch_events(conn, POLLIN); } #ifndef TOR_TLS #ifndef USE_TLS static void conn_or_init_crypto(connection_t *conn) { //int x; Loading
src/or/main.c +30 −19 Original line number Diff line number Diff line Loading @@ -212,6 +212,10 @@ void connection_watch_events(connection_t *conn, short events) { poll_array[conn->poll_index].events = events; } int connection_is_reading(connection_t *conn) { return poll_array[conn->poll_index].events & POLLIN; } void connection_stop_reading(connection_t *conn) { assert(conn && conn->poll_index < nfds); Loading Loading @@ -312,8 +316,7 @@ static void check_conn_marked(int i) { static int prepare_for_poll(void) { int i; // connection_t *conn = NULL; connection_t *tmpconn; connection_t *conn; struct timeval now; //soonest; static long current_second = 0; /* from previous calls to gettimeofday */ static long time_to_fetch_directory = 0; Loading Loading @@ -355,37 +358,41 @@ static int prepare_for_poll(void) { /* do housekeeping for each connection */ for(i=0;i<nfds;i++) { tmpconn = connection_array[i]; if(connection_receiver_bucket_should_increase(tmpconn)) { tmpconn->receiver_bucket += tmpconn->bandwidth; // log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, tmpconn->receiver_bucket); conn = connection_array[i]; if(connection_receiver_bucket_should_increase(conn)) { conn->receiver_bucket += conn->bandwidth; // log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, conn->receiver_bucket); } if(tmpconn->wants_to_read == 1 /* it's marked to turn reading back on now */ if(conn->wants_to_read == 1 /* it's marked to turn reading back on now */ && global_read_bucket > 0 /* and we're allowed to read */ && tmpconn->receiver_bucket != 0) { /* and either an edge conn or non-empty bucket */ tmpconn->wants_to_read = 0; connection_start_reading(tmpconn); && conn->receiver_bucket != 0) { /* and either an edge conn or non-empty bucket */ conn->wants_to_read = 0; connection_start_reading(conn); if(conn->wants_to_write == 1) { conn->wants_to_write = 0; connection_start_writing(conn); } } /* check connections to see whether we should send a keepalive, expire, or wait */ if(!connection_speaks_cells(tmpconn)) if(!connection_speaks_cells(conn)) continue; /* this conn type doesn't send cells */ if(now.tv_sec >= tmpconn->timestamp_lastwritten + options.KeepalivePeriod) { if((!options.OnionRouter && !circuit_get_by_conn(tmpconn)) || (!connection_state_is_open(tmpconn))) { if(now.tv_sec >= conn->timestamp_lastwritten + options.KeepalivePeriod) { if((!options.OnionRouter && !circuit_get_by_conn(conn)) || (!connection_state_is_open(conn))) { /* we're an onion proxy, with no circuits; or our handshake has expired. kill it. */ log(LOG_DEBUG,"prepare_for_poll(): Expiring connection to %d (%s:%d).", i,tmpconn->address, tmpconn->port); tmpconn->marked_for_close = 1; i,conn->address, conn->port); conn->marked_for_close = 1; } else { /* either a full router, or we've got a circuit. send a padding cell. */ // log(LOG_DEBUG,"prepare_for_poll(): Sending keepalive to (%s:%d)", // tmpconn->address, tmpconn->port); // conn->address, conn->port); memset(&cell,0,sizeof(cell_t)); cell.command = CELL_PADDING; if(connection_write_cell_to_buf(&cell, tmpconn) < 0) tmpconn->marked_for_close = 1; if(connection_write_cell_to_buf(&cell, conn) < 0) conn->marked_for_close = 1; } } } Loading Loading @@ -442,6 +449,10 @@ static int do_main_loop(void) { set_signing_privatekey(prkey); } #ifdef USE_TLS make the tls context here #endif /* start up the necessary connections based on which ports are * non-zero. This is where we try to connect to all the other ORs, * and start the listeners. Loading
src/or/or.h +6 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,9 @@ struct connection_t { uint8_t wants_to_read; /* should we start reading again once * the bandwidth throttler allows it? */ uint8_t wants_to_write; /* should we start writing again once * the bandwidth throttler allows reads? */ int s; /* our socket */ int poll_index; /* index of this conn into the poll_array */ int marked_for_close; /* should we close this conn on the next Loading Loading @@ -642,7 +645,9 @@ int connection_state_is_open(connection_t *conn); int connection_send_destroy(aci_t aci, connection_t *conn); int connection_send_connected(aci_t aci, connection_t *conn); #ifndef USE_TLS int connection_encrypt_cell(char *cellp, connection_t *conn); #endif int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn); int connection_process_inbuf(connection_t *conn); Loading Loading @@ -751,6 +756,7 @@ connection_t *connection_get_by_type_state(int type, int state); connection_t *connection_get_by_type_state_lastwritten(int type, int state); void connection_watch_events(connection_t *conn, short events); int connection_is_reading(connection_t *conn); void connection_stop_reading(connection_t *conn); void connection_start_reading(connection_t *conn); void connection_stop_writing(connection_t *conn); Loading