[or-cvs] divorce circuit building from user connections

Roger Dingledine arma at seul.org
Wed Apr 16 06:18:33 UTC 2003


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home/arma/work/onion/cvs/src/or

Modified Files:
	circuit.c config.c connection_ap.c connection_or.c main.c 
	onion.c or.h test.c 
Log Message:
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.


Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- circuit.c	11 Apr 2003 22:11:11 -0000	1.29
+++ circuit.c	16 Apr 2003 06:18:30 -0000	1.30
@@ -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 @@
 
 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 @@
   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 @@
 
 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 @@
   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);
 }
 
@@ -608,6 +628,210 @@
       }
     }
   }
+}
+
+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;
 }
 
 /*

Index: config.c
===================================================================
RCS file: /home/or/cvsroot/src/or/config.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- config.c	7 Apr 2003 02:12:02 -0000	1.29
+++ config.c	16 Apr 2003 06:18:30 -0000	1.30
@@ -187,6 +187,7 @@
     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 @@
   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 */

Index: connection_ap.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_ap.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- connection_ap.c	11 Apr 2003 22:11:11 -0000	1.34
+++ connection_ap.c	16 Apr 2003 06:18:30 -0000	1.35
@@ -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 @@
   }
 
   /* 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);
-    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 */
+  if(!circ) {
+    log(LOG_INFO,"ap_handshake_process_socks(): No circuit ready. Closing.");
     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);
+  /* 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(ap_conn, circ) < 0) {
+  if(ap_handshake_send_begin(conn, circ) < 0) {
+    circuit_close(circ);
     return -1;
   }
-
-  circ->state = CIRCUIT_STATE_OPEN;
-  /* FIXME should set circ->expire to something here */
 
   return 0;
 }

Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- connection_or.c	8 Apr 2003 22:31:48 -0000	1.25
+++ connection_or.c	16 Apr 2003 06:18:30 -0000	1.26
@@ -334,7 +334,7 @@
   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;
 }
 

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- main.c	8 Apr 2003 06:44:38 -0000	1.47
+++ main.c	16 Apr 2003 06:18:30 -0000	1.48
@@ -302,8 +302,10 @@
   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 @@
       }
     }
 
+    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 @@
   }
 }
 
-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 daemonize() {
+void daemonize(void) {
   /* Fork; parent exits. */
   if (fork())
     exit(0);

Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- onion.c	8 Apr 2003 06:44:38 -0000	1.32
+++ onion.c	16 Apr 2003 06:18:30 -0000	1.33
@@ -337,9 +337,9 @@
 {
   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 @@
 
   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 @@
 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)) {

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- or.h	15 Apr 2003 19:10:18 -0000	1.62
+++ or.h	16 Apr 2003 06:18:30 -0000	1.63
@@ -341,7 +341,7 @@
   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 @@
   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 *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 @@
    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 @@
 
 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 @@
 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_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 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);

Index: test.c
===================================================================
RCS file: /home/or/cvsroot/src/or/test.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- test.c	15 Apr 2003 19:10:18 -0000	1.3
+++ test.c	16 Apr 2003 06:18:31 -0000	1.4
@@ -182,7 +182,7 @@
   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) {



More information about the tor-commits mailing list