divorce circuit building from user connections

now we rebuild the circuit periodically (but only if it's been used),
and we can further abstract it to do incremental circuit building, etc.


svn:r233
This commit is contained in:
Roger Dingledine 2003-04-16 06:18:31 +00:00
parent 1fa0fc1487
commit e1d37ed6ab
8 changed files with 289 additions and 245 deletions

View File

@ -4,6 +4,8 @@
#include "or.h"
extern or_options_t options; /* command-line and config-file options */
/********* START VARIABLES **********/
static circuit_t *global_circuitlist=NULL;
@ -49,12 +51,18 @@ void circuit_remove(circuit_t *circ) {
circuit_t *circuit_new(aci_t p_aci, connection_t *p_conn) {
circuit_t *circ;
struct timeval now;
if(gettimeofday(&now,NULL) < 0)
return NULL;
circ = (circuit_t *)malloc(sizeof(circuit_t));
if(!circ)
return NULL;
memset(circ,0,sizeof(circuit_t)); /* zero it out */
circ->timestamp_created = now.tv_sec;
circ->p_aci = p_aci;
circ->p_conn = p_conn;
@ -252,20 +260,24 @@ circuit_t *circuit_get_by_conn(connection_t *conn) {
return NULL;
}
circuit_t *circuit_get_by_edge_type(char edge_type) {
circuit_t *circ;
circuit_t *circuit_get_newest_by_edge_type(char edge_type) {
circuit_t *circ, *bestcirc=NULL;
for(circ=global_circuitlist;circ;circ = circ->next) {
if(edge_type == EDGE_AP && circ->n_conn && circ->n_conn->type == CONN_TYPE_OR) {
log(LOG_DEBUG,"circuit_get_by_edge_type(): Choosing n_aci %d.", circ->n_aci);
return circ;
if(edge_type == EDGE_AP && (!circ->p_conn || circ->p_conn->type == CONN_TYPE_AP)) {
if(!bestcirc ||
(circ->state == CIRCUIT_STATE_OPEN && bestcirc->timestamp_created < circ->timestamp_created)) {
log(LOG_DEBUG,"circuit_get_newest_by_edge_type(): Choosing n_aci %d.", circ->n_aci);
bestcirc = circ;
}
}
if(edge_type == EDGE_EXIT && circ->p_conn && circ->p_conn->type == CONN_TYPE_OR) {
return circ;
if(edge_type == EDGE_EXIT && (!circ->n_conn || circ->n_conn->type == CONN_TYPE_EXIT)) {
if(!bestcirc ||
(circ->state == CIRCUIT_STATE_OPEN && bestcirc->timestamp_created < circ->timestamp_created))
bestcirc = circ;
}
log(LOG_DEBUG,"circuit_get_by_edge_type(): Skipping p_aci %d / n_aci %d.", circ->p_aci, circ->n_aci);
}
return NULL;
return bestcirc;
}
int circuit_deliver_data_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type) {
@ -517,8 +529,11 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type) {
void circuit_close(circuit_t *circ) {
connection_t *conn;
circuit_t *youngest;
assert(circ);
if(options.APPort)
youngest = circuit_get_newest_by_edge_type(EDGE_AP);
circuit_remove(circ);
for(conn=circ->n_conn; conn; conn=conn->next_topic) {
connection_send_destroy(circ->n_aci, circ->n_conn);
@ -526,6 +541,11 @@ void circuit_close(circuit_t *circ) {
for(conn=circ->p_conn; conn; conn=conn->next_topic) {
connection_send_destroy(circ->p_aci, circ->p_conn);
}
if(options.APPort && youngest == circ) { /* check this after we've sent the destroys, to reduce races */
/* our current circuit just died. Launch another one pronto. */
log(LOG_INFO,"circuit_close(): Youngest circuit dying. Launching a replacement.");
circuit_launch_new(1);
}
circuit_free(circ);
}
@ -610,6 +630,210 @@ void circuit_dump_by_conn(connection_t *conn) {
}
}
void circuit_expire_unused_circuits(void) {
circuit_t *circ, *tmpcirc;
circuit_t *youngest;
youngest = circuit_get_newest_by_edge_type(EDGE_AP);
circ = global_circuitlist;
while(circ) {
tmpcirc = circ;
circ = circ->next;
if(tmpcirc != youngest && (!tmpcirc->p_conn || tmpcirc->p_conn->type == CONN_TYPE_AP)) {
log(LOG_DEBUG,"circuit_expire_unused_circuits(): Closing n_aci %d",tmpcirc->n_aci);
circuit_close(tmpcirc);
}
}
}
/* failure_status code: negative means reset failures to 0. Other values mean
* add that value to the current number of failures, then if we don't have too
* many failures on record, try to make a new circuit.
*/
void circuit_launch_new(int failure_status) {
static int failures=0;
if(failure_status == -1) { /* I was called because a circuit succeeded */
failures = 0;
return;
}
failures += failure_status;
retry_circuit:
if(failures > 5) {
log(LOG_INFO,"circuit_launch_new(): Giving up, %d failures.", failures);
return;
}
if(circuit_create_onion() < 0) {
failures++;
goto retry_circuit;
}
failures = 0;
return;
}
int circuit_create_onion(void) {
int i;
int routelen; /* length of the route */
unsigned int *route; /* hops in the route as an array of indexes into rarray */
unsigned char *onion; /* holds the onion */
int onionlen; /* onion length in host order */
crypt_path_t **cpath; /* defines the crypt operations that need to be performed on incoming/outgoing data */
/* choose a route */
route = (unsigned int *)router_new_route(&routelen);
if (!route) {
log(LOG_ERR,"circuit_create_onion(): Error choosing a route through the OR network.");
return -1;
}
log(LOG_DEBUG,"circuit_create_onion(): Chosen a route of length %u : ",routelen);
/* allocate memory for the crypt path */
cpath = malloc(routelen * sizeof(crypt_path_t *));
if (!cpath) {
log(LOG_ERR,"circuit_create_onion(): Error allocating memory for cpath.");
free(route);
return -1;
}
/* create an onion and calculate crypto keys */
onion = router_create_onion(route,routelen,&onionlen,cpath);
if (!onion) {
log(LOG_ERR,"circuit_create_onion(): Error creating an onion.");
free(route);
free(cpath); /* it's got nothing in it, since !onion */
return -1;
}
log(LOG_DEBUG,"circuit_create_onion(): Created an onion of size %u bytes.",onionlen);
log(LOG_DEBUG,"circuit_create_onion(): Crypt path :");
for (i=0;i<routelen;i++) {
log(LOG_DEBUG,"circuit_create_onion() : %u/%u",(cpath[i])->forwf, (cpath[i])->backf);
}
return circuit_establish_circuit(route, routelen, onion, onionlen, cpath);
}
int circuit_establish_circuit(unsigned int *route, int routelen, char *onion,
int onionlen, crypt_path_t **cpath) {
routerinfo_t *firsthop;
connection_t *n_conn;
circuit_t *circ;
/* now see if we're already connected to the first OR in 'route' */
firsthop = router_get_first_in_route(route, routelen);
assert(firsthop); /* should always be defined */
free(route); /* we don't need it anymore */
circ = circuit_new(0, NULL); /* sets circ->p_aci and circ->p_conn */
circ->state = CIRCUIT_STATE_OR_WAIT;
circ->onion = onion;
circ->onionlen = onionlen;
circ->cpath = cpath;
circ->cpathlen = routelen;
log(LOG_DEBUG,"circuit_establish_circuit(): Looking for firsthop '%s:%u'",
firsthop->address,firsthop->or_port);
n_conn = connection_twin_get_by_addr_port(firsthop->addr,firsthop->or_port);
if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) { /* not currently connected */
circ->n_addr = firsthop->addr;
circ->n_port = firsthop->or_port;
if(options.ORPort) { /* we would be connected if he were up. but he's not. */
log(LOG_DEBUG,"circuit_establish_circuit(): Route's firsthop isn't connected.");
circuit_close(circ);
return -1;
}
if(!n_conn) { /* launch the connection */
n_conn = connection_or_connect_as_op(firsthop);
if(!n_conn) { /* connect failed, forget the whole thing */
log(LOG_DEBUG,"circuit_establish_circuit(): connect to firsthop failed. Closing.");
circuit_close(circ);
return -1;
}
}
return 0; /* return success. The onion/circuit/etc will be taken care of automatically
* (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN.
*/
} else { /* it (or a twin) is already open. use it. */
circ->n_addr = n_conn->addr;
circ->n_port = n_conn->port;
return circuit_send_onion(n_conn, circ);
}
}
/* find circuits that are waiting on me, if any, and get them to send the onion */
void circuit_n_conn_open(connection_t *or_conn) {
circuit_t *circ;
log(LOG_DEBUG,"circuit_n_conn_open(): Starting.");
circ = circuit_enumerate_by_naddr_nport(NULL, or_conn->addr, or_conn->port);
for(;;) {
if(!circ)
return;
log(LOG_DEBUG,"circuit_n_conn_open(): Found circ, sending onion.");
if(circuit_send_onion(or_conn, circ) < 0) {
log(LOG_DEBUG,"circuit_n_conn_open(): circuit marked for closing.");
circuit_close(circ);
return; /* FIXME will want to try the other circuits too? */
}
circ = circuit_enumerate_by_naddr_nport(circ, or_conn->addr, or_conn->port);
}
}
int circuit_send_onion(connection_t *n_conn, circuit_t *circ) {
cell_t cell;
int tmpbuflen, dataleft;
char *tmpbuf;
circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, ACI_TYPE_BOTH);
circ->n_conn = n_conn;
log(LOG_DEBUG,"circuit_send_onion(): n_conn is %s:%u",n_conn->address,n_conn->port);
/* deliver the onion as one or more create cells */
cell.command = CELL_CREATE;
cell.aci = circ->n_aci;
tmpbuflen = circ->onionlen+4;
tmpbuf = malloc(tmpbuflen);
if(!tmpbuf)
return -1;
*(uint32_t*)tmpbuf = htonl(circ->onionlen);
memcpy(tmpbuf+4, circ->onion, circ->onionlen);
dataleft = tmpbuflen;
while(dataleft) {
cell.command = CELL_CREATE;
cell.aci = circ->n_aci;
log(LOG_DEBUG,"circuit_send_onion(): Sending a create cell for the onion...");
if(dataleft >= CELL_PAYLOAD_SIZE) {
cell.length = CELL_PAYLOAD_SIZE;
memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, CELL_PAYLOAD_SIZE);
connection_write_cell_to_buf(&cell, n_conn);
dataleft -= CELL_PAYLOAD_SIZE;
} else { /* last cell */
cell.length = dataleft;
memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, dataleft);
/* fill extra space with 0 bytes */
memset(cell.payload + dataleft, 0, CELL_PAYLOAD_SIZE - dataleft);
connection_write_cell_to_buf(&cell, n_conn);
dataleft = 0;
}
}
free(tmpbuf);
circ->state = CIRCUIT_STATE_OPEN;
/* FIXME should set circ->expire to something here */
return 0;
}
/*
Local Variables:
mode:c

View File

@ -187,6 +187,7 @@ void config_assign(or_options_t *options, struct config_line *list) {
config_compare(list, "DirFetchPeriod", CONFIG_TYPE_INT, &options->DirFetchPeriod) ||
config_compare(list, "KeepalivePeriod", CONFIG_TYPE_INT, &options->KeepalivePeriod) ||
config_compare(list, "MaxOnionsPending",CONFIG_TYPE_INT, &options->MaxOnionsPending) ||
config_compare(list, "NewCircuitPeriod",CONFIG_TYPE_INT, &options->NewCircuitPeriod) ||
config_compare(list, "Daemon", CONFIG_TYPE_BOOL, &options->Daemon) ||
config_compare(list, "TrafficShaping", CONFIG_TYPE_BOOL, &options->TrafficShaping) ||
@ -224,6 +225,7 @@ int getconfig(int argc, char **argv, or_options_t *options) {
options->DirFetchPeriod = 600;
options->KeepalivePeriod = 300;
options->MaxOnionsPending = 10;
options->NewCircuitPeriod = 60; /* once a minute */
// options->ReconnectPeriod = 6001;
/* get config lines from /etc/torrc and assign them */

View File

@ -4,8 +4,6 @@
#include "or.h"
extern or_options_t options; /* command-line and config-file options */
int ap_handshake_process_socks(connection_t *conn) {
char c;
socks4_t socks4_info;
@ -96,211 +94,25 @@ int ap_handshake_process_socks(connection_t *conn) {
}
/* find the circuit that we should use, if there is one. */
circ = circuit_get_by_edge_type(EDGE_AP);
circ = circuit_get_newest_by_edge_type(EDGE_AP);
circ->dirty = 1;
/* now we're all ready to make an onion or send a begin */
if(circ && circ->state == CIRCUIT_STATE_OPEN) {
/* FIXME if circ not yet open, figure out how to queue this begin? */
/* add it into the linked list of topics on this circuit */
log(LOG_DEBUG,"ap_handshake_process_socks(): attaching new conn to circ. n_aci %d.", circ->n_aci);
conn->next_topic = circ->p_conn;
circ->p_conn = conn;
if(ap_handshake_send_begin(conn, circ) < 0) {
circuit_close(circ);
return -1;
}
} else {
if(ap_handshake_create_onion(conn) < 0) {
if(circ)
circuit_close(circ);
return -1;
}
}
return 0;
}
int ap_handshake_create_onion(connection_t *conn) {
int i;
int routelen = 0; /* length of the route */
unsigned int *route = NULL; /* hops in the route as an array of indexes into rarray */
unsigned char *onion = NULL; /* holds the onion */
int onionlen = 0; /* onion length in host order */
crypt_path_t **cpath = NULL; /* defines the crypt operations that need to be performed on incoming/outgoing data */
assert(conn);
/* choose a route */
route = (unsigned int *)router_new_route(&routelen);
if (!route) {
log(LOG_ERR,"ap_handshake_create_onion(): Error choosing a route through the OR network.");
return -1;
}
log(LOG_DEBUG,"ap_handshake_create_onion(): Chosen a route of length %u : ",routelen);
#if 0
for (i=routelen-1;i>=0;i--)
{
log(LOG_DEBUG,"ap_handshake_process_ss() : %u : %s:%u, %u",routelen-i,(routerarray[route[i]])->address,ntohs((routerarray[route[i]])->port),RSA_size((routerarray[route[i]])->pkey));
}
#endif
/* allocate memory for the crypt path */
cpath = malloc(routelen * sizeof(crypt_path_t *));
if (!cpath) {
log(LOG_ERR,"ap_handshake_create_onion(): Error allocating memory for cpath.");
free(route);
if(!circ) {
log(LOG_INFO,"ap_handshake_process_socks(): No circuit ready. Closing.");
return -1;
}
/* create an onion and calculate crypto keys */
onion = router_create_onion(route,routelen,&onionlen,cpath);
if (!onion) {
log(LOG_ERR,"ap_handshake_create_onion(): Error creating an onion.");
free(route);
free(cpath); /* it's got nothing in it, since !onion */
/* add it into the linked list of topics on this circuit */
log(LOG_DEBUG,"ap_handshake_process_socks(): attaching new conn to circ. n_aci %d.", circ->n_aci);
conn->next_topic = circ->p_conn;
circ->p_conn = conn;
if(ap_handshake_send_begin(conn, circ) < 0) {
circuit_close(circ);
return -1;
}
log(LOG_DEBUG,"ap_handshake_create_onion(): Created an onion of size %u bytes.",onionlen);
log(LOG_DEBUG,"ap_handshake_create_onion(): Crypt path :");
for (i=0;i<routelen;i++) {
log(LOG_DEBUG,"ap_handshake_create_onion() : %u/%u",(cpath[i])->forwf, (cpath[i])->backf);
}
return ap_handshake_establish_circuit(conn, route, routelen, onion, onionlen, cpath);
}
int ap_handshake_establish_circuit(connection_t *conn, unsigned int *route, int routelen, char *onion,
int onionlen, crypt_path_t **cpath) {
routerinfo_t *firsthop;
connection_t *n_conn;
circuit_t *circ;
/* now see if we're already connected to the first OR in 'route' */
firsthop = router_get_first_in_route(route, routelen);
assert(firsthop); /* should always be defined */
free(route); /* we don't need it anymore */
circ = circuit_new(0, conn); /* sets circ->p_aci and circ->p_conn */
circ->state = CIRCUIT_STATE_OR_WAIT;
circ->onion = onion;
circ->onionlen = onionlen;
circ->cpath = cpath;
circ->cpathlen = routelen;
log(LOG_DEBUG,"ap_handshake_establish_circuit(): Looking for firsthop '%s:%u'",
firsthop->address,firsthop->or_port);
n_conn = connection_twin_get_by_addr_port(firsthop->addr,firsthop->or_port);
if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) { /* not currently connected */
circ->n_addr = firsthop->addr;
circ->n_port = firsthop->or_port;
if(options.ORPort) { /* we would be connected if he were up. but he's not. */
log(LOG_DEBUG,"ap_handshake_establish_circuit(): Route's firsthop isn't connected.");
circuit_close(circ);
return -1;
}
conn->state = AP_CONN_STATE_OR_WAIT;
connection_stop_reading(conn); /* Stop listening for input from the AP! */
if(!n_conn) { /* launch the connection */
n_conn = connection_or_connect_as_op(firsthop);
if(!n_conn) { /* connect failed, forget the whole thing */
log(LOG_DEBUG,"ap_handshake_establish_circuit(): connect to firsthop failed. Closing.");
circuit_close(circ);
return -1;
}
}
return 0; /* return success. The onion/circuit/etc will be taken care of automatically
* (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN.
*/
} else { /* it (or a twin) is already open. use it. */
circ->n_addr = n_conn->addr;
circ->n_port = n_conn->port;
return ap_handshake_send_onion(conn, n_conn, circ);
}
}
/* find circuits that are waiting on me, if any, and get them to send the onion */
void ap_handshake_n_conn_open(connection_t *or_conn) {
circuit_t *circ;
connection_t *p_conn;
log(LOG_DEBUG,"ap_handshake_n_conn_open(): Starting.");
circ = circuit_enumerate_by_naddr_nport(NULL, or_conn->addr, or_conn->port);
for(;;) {
if(!circ)
return;
p_conn = circ->p_conn;
if(p_conn->state != AP_CONN_STATE_OR_WAIT) {
log(LOG_WARNING,"Bug: ap_handshake_n_conn_open() got an ap_conn not in OR_WAIT state.");
}
connection_start_reading(p_conn); /* resume listening for reads */
log(LOG_DEBUG,"ap_handshake_n_conn_open(): Found circ, sending onion.");
if(ap_handshake_send_onion(p_conn, or_conn, circ) < 0) {
log(LOG_DEBUG,"ap_handshake_n_conn_open(): circuit marked for closing.");
circuit_close(circ);
return; /* FIXME will want to try the other circuits too? */
}
for(p_conn = p_conn->next_topic; p_conn; p_conn = p_conn->next_topic) { /* start up any other pending topics */
if(ap_handshake_send_begin(p_conn, circ) < 0) {
circuit_close(circ);
return;
}
}
circ = circuit_enumerate_by_naddr_nport(circ, or_conn->addr, or_conn->port);
}
}
int ap_handshake_send_onion(connection_t *ap_conn, connection_t *n_conn, circuit_t *circ) {
cell_t cell;
int tmpbuflen, dataleft;
char *tmpbuf;
circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, ACI_TYPE_BOTH);
circ->n_conn = n_conn;
log(LOG_DEBUG,"ap_handshake_send_onion(): n_conn is %s:%u",n_conn->address,n_conn->port);
/* deliver the onion as one or more create cells */
cell.command = CELL_CREATE;
cell.aci = circ->n_aci;
tmpbuflen = circ->onionlen+4;
tmpbuf = malloc(tmpbuflen);
if(!tmpbuf)
return -1;
*(uint32_t*)tmpbuf = htonl(circ->onionlen);
memcpy(tmpbuf+4, circ->onion, circ->onionlen);
dataleft = tmpbuflen;
while(dataleft) {
cell.command = CELL_CREATE;
cell.aci = circ->n_aci;
log(LOG_DEBUG,"ap_handshake_send_onion(): Sending a create cell for the onion...");
if(dataleft >= CELL_PAYLOAD_SIZE) {
cell.length = CELL_PAYLOAD_SIZE;
memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, CELL_PAYLOAD_SIZE);
connection_write_cell_to_buf(&cell, n_conn);
dataleft -= CELL_PAYLOAD_SIZE;
} else { /* last cell */
cell.length = dataleft;
memcpy(cell.payload, tmpbuf + tmpbuflen - dataleft, dataleft);
/* fill extra space with 0 bytes */
memset(cell.payload + dataleft, 0, CELL_PAYLOAD_SIZE - dataleft);
connection_write_cell_to_buf(&cell, n_conn);
dataleft = 0;
}
}
free(tmpbuf);
if(ap_handshake_send_begin(ap_conn, circ) < 0) {
return -1;
}
circ->state = CIRCUIT_STATE_OPEN;
/* FIXME should set circ->expire to something here */
return 0;
}

View File

@ -334,7 +334,7 @@ int or_handshake_op_finished_sending_keys(connection_t *conn) {
conn_or_init_crypto(conn);
connection_or_set_open(conn);
ap_handshake_n_conn_open(conn); /* send the pending onions */
circuit_n_conn_open(conn); /* send the pending onion(s) */
return 0;
}

View File

@ -302,8 +302,10 @@ int prepare_for_poll(int *timeout) {
struct timeval now; //soonest;
static long current_second = 0; /* from previous calls to gettimeofday */
static long time_to_fetch_directory = 0;
static long time_to_new_circuit = 0;
// int ms_until_conn;
cell_t cell;
circuit_t *circ;
if(gettimeofday(&now,NULL) < 0)
return -1;
@ -321,6 +323,17 @@ int prepare_for_poll(int *timeout) {
}
}
if(options.APPort && time_to_new_circuit < now.tv_sec) {
circuit_expire_unused_circuits();
circuit_launch_new(-1); /* tell it to forget about previous failures */
circ = circuit_get_newest_by_edge_type(EDGE_AP);
if(!circ || circ->dirty) {
log(LOG_INFO,"prepare_for_poll(): Youngest circuit missing or dirty; launching replacement.");
circuit_launch_new(0); /* make an onion and lay the circuit */
}
time_to_new_circuit = now.tv_sec + options.NewCircuitPeriod;
}
/* do housekeeping for each connection */
for(i=0;i<nfds;i++) {
tmpconn = connection_array[i];
@ -514,7 +527,7 @@ static void catch(int the_signal) {
}
}
void dumpstats (void) { /* dump stats to stdout */
void dumpstats(void) { /* dump stats to stdout */
int i;
connection_t *conn;
struct timeval now;
@ -638,7 +651,7 @@ void dump_directory_to_string(char *s, int maxlen) {
}
void daemonize() {
void daemonize(void) {
/* Fork; parent exits. */
if (fork())
exit(0);

View File

@ -337,9 +337,9 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r
{
int i, j;
int num_acceptable_routers;
unsigned int *route = NULL;
unsigned int *route;
unsigned int oldchoice, choice;
assert((cw >= 0) && (cw < 1) && (rarray) && (routelen) ); /* valid parameters */
*routelen = chooselen(cw);
@ -351,6 +351,11 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r
num_acceptable_routers = count_acceptable_routers(rarray, rarray_len);
if(num_acceptable_routers < 2) {
log(LOG_INFO,"new_route(): Not enough acceptable routers. Failing.");
return NULL;
}
if(num_acceptable_routers < *routelen) {
log(LOG_DEBUG,"new_route(): Cutting routelen from %d to %d.",*routelen, num_acceptable_routers);
*routelen = num_acceptable_routers;
@ -399,13 +404,16 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r
static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) {
int i, j;
int num=0;
connection_t *conn;
for(i=0;i<rarray_len;i++) {
log(LOG_DEBUG,"Contemplating whether router %d is a new option...",i);
if(options.ORPort &&
!connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port)) {
log(LOG_DEBUG,"Nope, %d is not connected.",i);
goto next_i_loop;
if(options.ORPort) {
conn = connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port);
if(!conn || conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN) {
log(LOG_DEBUG,"Nope, %d is not connected.",i);
goto next_i_loop;
}
}
for(j=0;j<i;j++) {
if(!crypto_pk_cmp_keys(rarray[i]->pkey, rarray[j]->pkey)) {

View File

@ -341,7 +341,7 @@ struct data_queue_t {
struct data_queue_t *next;
};
/* per-anonymous-connection struct */
/* struct for a path (circuit) through the network */
typedef struct {
uint32_t n_addr;
uint16_t n_port;
@ -365,6 +365,8 @@ typedef struct {
int cpathlen;
uint32_t expire; /* expiration time for the corresponding onion */
long timestamp_created;
char dirty; /* whether this circuit has been used yet */
int state;
@ -381,20 +383,6 @@ struct onion_queue_t {
struct onion_queue_t *next;
};
#if 0
typedef struct
{
int zero:1;
int version:7;
int backf:4;
int forwf:4;
uint16_t port;
uint32_t addr;
uint32_t expire;
unsigned char keyseed[16];
} onion_layer_t;
#endif
#define ONION_LAYER_SIZE 28
#define ONION_PADDING_SIZE (128-ONION_LAYER_SIZE)
@ -415,11 +403,11 @@ typedef struct {
int DirFetchPeriod;
int KeepalivePeriod;
int MaxOnionsPending;
int NewCircuitPeriod;
int Role;
int loglevel;
} or_options_t;
/* all the function prototypes go here */
/********************************* buffers.c ***************************/
@ -491,7 +479,7 @@ aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type);
circuit_t *circuit_get_by_aci_conn(aci_t aci, connection_t *conn);
circuit_t *circuit_get_by_conn(connection_t *conn);
circuit_t *circuit_get_by_edge_type(char edge_type);
circuit_t *circuit_get_newest_by_edge_type(char edge_type);
circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *start, uint32_t naddr, uint16_t nport);
int circuit_deliver_data_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type);
@ -506,8 +494,6 @@ int circuit_init(circuit_t *circ, int aci_type);
void circuit_free(circuit_t *circ);
void circuit_free_cpath(crypt_path_t **cpath, int cpathlen);
void circuit_close(circuit_t *circ);
void circuit_about_to_close_connection(connection_t *conn);
@ -515,6 +501,13 @@ void circuit_about_to_close_connection(connection_t *conn);
void circuit_dump_by_conn(connection_t *conn);
void circuit_launch_new(int failure_status);
int circuit_create_onion(void);
int circuit_establish_circuit(unsigned int *route, int routelen, char *onion,
int onionlen, crypt_path_t **cpath);
void circuit_n_conn_open(connection_t *or_conn);
int circuit_send_onion(connection_t *or_conn, circuit_t *circ);
/********************************* command.c ***************************/
void command_process_cell(cell_t *cell, connection_t *conn);
@ -611,14 +604,6 @@ int connection_finished_flushing(connection_t *conn);
int ap_handshake_process_socks(connection_t *conn);
int ap_handshake_create_onion(connection_t *conn);
int ap_handshake_establish_circuit(connection_t *conn, unsigned int *route, int routelen, char *onion,
int onionlen, crypt_path_t **cpath);
void ap_handshake_n_conn_open(connection_t *or_conn);
int ap_handshake_send_onion(connection_t *ap_conn, connection_t *or_conn, circuit_t *circ);
int ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
int ap_handshake_socks_reply(connection_t *conn, char result);

View File

@ -182,7 +182,7 @@ test_buffers() {
j = decompress_buf_to_buf(&buf, &buflen, &buf_datalen,
&buf2, &buf2len, &buf2_datalen,
decomp, 1);
/*XXXX check result *
/*XXXX check result */
/* Now compress more, into less room. */
for (i = 0; i < 20; ++i) {