diff options
author | Roger Dingledine <arma@torproject.org> | 2002-11-27 04:08:20 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2002-11-27 04:08:20 +0000 |
commit | 8f18647a33eedb1f579d67563fa29fefdb52400a (patch) | |
tree | cf70437a4865057c57d655db32066c7577580739 /src/or/command.c | |
parent | 147879ab17801d44098d19ec94e705f890070a81 (diff) | |
download | tor-8f18647a33eedb1f579d67563fa29fefdb52400a.tar.gz tor-8f18647a33eedb1f579d67563fa29fefdb52400a.zip |
create cells are now queued and processed only when idle
we also queue data cells destined for a circuit that is
pending, and process them once the circuit opens
destroys reach into the queue and remove the pending onion,
along with its collected data cells
svn:r142
Diffstat (limited to 'src/or/command.c')
-rw-r--r-- | src/or/command.c | 142 |
1 files changed, 26 insertions, 116 deletions
diff --git a/src/or/command.c b/src/or/command.c index c4f5251068..c725b22808 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -70,7 +70,6 @@ void command_process_cell(cell_t *cell, connection_t *conn) { /* do nothing */ break; case CELL_CREATE: - log(LOG_INFO,"Starting to process create cell."); command_time_process_cell(cell, conn, &num_create, &create_time, command_process_create_cell); break; @@ -96,61 +95,19 @@ void command_process_cell(cell_t *cell, connection_t *conn) { } } -/* helper function for command_process_create_cell */ -static int deliver_onion_to_conn(aci_t aci, unsigned char *onion, uint32_t onionlen, connection_t *conn) { - char *buf; - int buflen, dataleft; - cell_t cell; - - assert(aci && onion && onionlen); - - buflen = onionlen+4; - buf = malloc(buflen); - if(!buf) - return -1; - - log(LOG_DEBUG,"deliver_onion_to_conn(): Setting onion length to %u.",onionlen); - *(uint32_t*)buf = htonl(onionlen); - memcpy((void *)(buf+4),(void *)onion,onionlen); - - dataleft = buflen; - while(dataleft > 0) { - memset(&cell,0,sizeof(cell_t)); - cell.command = CELL_CREATE; - cell.aci = aci; - if(dataleft >= CELL_PAYLOAD_SIZE) - cell.length = CELL_PAYLOAD_SIZE; - else - cell.length = dataleft; - memcpy(cell.payload, buf+buflen-dataleft, cell.length); - dataleft -= cell.length; - - log(LOG_DEBUG,"deliver_onion_to_conn(): Delivering create cell, payload %d bytes.",cell.length); - if(connection_write_cell_to_buf(&cell, conn) < 0) { - log(LOG_DEBUG,"deliver_onion_to_conn(): Could not buffer new create cells. Closing."); - free(buf); - return -1; - } - } - free(buf); - return 0; -} - void command_process_create_cell(cell_t *cell, connection_t *conn) { circuit_t *circ; - connection_t *n_conn; - int retval; circ = circuit_get_by_aci_conn(cell->aci, conn); - if(circ && circ->state != CIRCUIT_STATE_OPEN_WAIT) { - log(LOG_DEBUG,"command_process_create_cell(): received CREATE cell, not in open_wait. Dropping."); + if(circ && circ->state != CIRCUIT_STATE_ONION_WAIT) { + log(LOG_DEBUG,"command_process_create_cell(): received CREATE cell, not in onion_wait. Dropping."); return; } if(!circ) { /* if it's not there, create it */ circ = circuit_new(cell->aci, conn); - circ->state = CIRCUIT_STATE_OPEN_WAIT; + circ->state = CIRCUIT_STATE_ONION_WAIT; circ->onionlen = ntohl(*(int*)cell->payload); log(LOG_DEBUG,"command_process_create_cell(): Onion length is %u.",circ->onionlen); if(circ->onionlen > 50000 || circ->onionlen < 1) { /* too big or too small */ @@ -191,9 +148,17 @@ void command_process_create_cell(cell_t *cell, connection_t *conn) { return; } - /* we're all ready to go now. */ - circ->state = CIRCUIT_STATE_OPEN; + /* add it to the pending onions queue, and then return */ + circ->state = CIRCUIT_STATE_ONION_PENDING; + + if(onion_pending_add(circ) < 0) { + log(LOG_DEBUG,"command_process_create_cell(): Failed to queue onion. Closing."); + circuit_close(circ); + } + return; +} +#if 0 conn->onions_handled_this_second++; log(LOG_DEBUG,"command_process_create_cell(): Processing onion %d for this second.",conn->onions_handled_this_second); if(conn->onions_handled_this_second > options.OnionsPerSecond) { @@ -201,69 +166,7 @@ void command_process_create_cell(cell_t *cell, connection_t *conn) { circuit_close(circ); return; } - - if(process_onion(circ, conn) < 0) { - log(LOG_DEBUG,"command_process_create_cell(): Onion processing failed. Closing."); - circuit_close(circ); - return; - } - - if(circ->n_addr && circ->n_port) { /* must send create cells to the next router */ - n_conn = connection_twin_get_by_addr_port(circ->n_addr,circ->n_port); - if(!n_conn || n_conn->type != CONN_TYPE_OR) { - /* i've disabled making connections through OPs, but it's definitely - * possible here. I'm not sure if it would be a bug or a feature. -RD - */ - /* note also that this will close circuits where the onion has the same - * router twice in a row in the path. i think that's ok. -RD - */ - log(LOG_DEBUG,"command_process_create_cell(): Next router not connected. Closing."); - circuit_close(circ); - return; - } - - circ->n_addr = n_conn->addr; /* these are different if we found a twin instead */ - circ->n_port = n_conn->port; - - circ->n_conn = n_conn; - log(LOG_DEBUG,"command_process_create_cell(): n_conn is %s:%u",n_conn->address,n_conn->port); - - /* send the CREATE cells on to the next hop */ - pad_onion(circ->onion,circ->onionlen, sizeof(onion_layer_t)); - log(LOG_DEBUG,"command_process_create_cell(): Padded the onion with random data."); - - retval = deliver_onion_to_conn(circ->n_aci, circ->onion, circ->onionlen, n_conn); -// retval = pack_create(circ->n_aci, circ->onion, circ->onionlen, &cellbuf, &cellbuflen); - free((void *)circ->onion); - circ->onion = NULL; - if (retval == -1) { - log(LOG_DEBUG,"command_process_create_cell(): Could not deliver the onion to next conn. Closing."); - circuit_close(circ); - } - return; - - } else { /* this is destined for an exit */ - log(LOG_DEBUG,"command_process_create_cell(): Creating new exit connection."); - n_conn = connection_new(CONN_TYPE_EXIT); - if(!n_conn) { - log(LOG_DEBUG,"command_process_create_cell(): connection_new failed. Closing."); - circuit_close(circ); - return; - } - n_conn->state = EXIT_CONN_STATE_CONNECTING_WAIT; - n_conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */ - n_conn->bandwidth = -1; - n_conn->s = -1; /* not yet valid */ - if(connection_add(n_conn) < 0) { /* no space, forget it */ - log(LOG_DEBUG,"command_process_create_cell(): connection_add failed. Closing."); - connection_free(n_conn); - circuit_close(circ); - return; - } - circ->n_conn = n_conn; - return; - } -} +#endif void command_process_sendme_cell(cell_t *cell, connection_t *conn) { circuit_t *circ; @@ -275,8 +178,8 @@ void command_process_sendme_cell(cell_t *cell, connection_t *conn) { return; } - if(circ->state == CIRCUIT_STATE_OPEN_WAIT) { - log(LOG_DEBUG,"command_process_sendme_cell(): circuit in open_wait. Dropping."); + if(circ->state == CIRCUIT_STATE_ONION_WAIT) { + log(LOG_DEBUG,"command_process_sendme_cell(): circuit in onion_wait. Dropping."); return; } if(circ->state == CIRCUIT_STATE_OR_WAIT) { @@ -330,15 +233,19 @@ void command_process_data_cell(cell_t *cell, connection_t *conn) { return; } - if(circ->state == CIRCUIT_STATE_OPEN_WAIT) { - log(LOG_DEBUG,"command_process_data_cell(): circuit in open_wait. Dropping data cell."); + if(circ->state == CIRCUIT_STATE_ONION_WAIT) { + log(LOG_DEBUG,"command_process_data_cell(): circuit in onion_wait. Dropping data cell."); return; } if(circ->state == CIRCUIT_STATE_OR_WAIT) { log(LOG_DEBUG,"command_process_data_cell(): circuit in or_wait. Dropping data cell."); return; } - + if(circ->state == CIRCUIT_STATE_ONION_PENDING) { + log(LOG_DEBUG,"command_process_data_cell(): circuit in create_wait. Queueing data cell."); + onion_pending_data_add(circ, cell); + return; + } /* at this point both circ->n_conn and circ->p_conn are guaranteed to be set */ if(cell->aci == circ->p_aci) { /* it's an outgoing cell */ @@ -389,6 +296,9 @@ void command_process_destroy_cell(cell_t *cell, connection_t *conn) { } log(LOG_DEBUG,"command_process_destroy_cell(): Received for aci %d.",cell->aci); + if(circ->state == CIRCUIT_STATE_ONION_PENDING) { + onion_pending_remove(circ); + } circuit_remove(circ); if(cell->aci == circ->p_aci) /* the destroy came from behind */ connection_send_destroy(circ->n_aci, circ->n_conn); |