Commit f34e6da3 authored by Roger Dingledine's avatar Roger Dingledine
Browse files

now circuit_get_newest returns an appropriate circ for your purpose

connection_ap_handshake_attach_circuit attaches to a circ of the
right purpose

add a skeletal rendclient.c


svn:r1441
parent 4cb21bab
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -7,8 +7,8 @@ bin_PROGRAMS = tor
tor_SOURCES = buffers.c circuit.c command.c config.c \
	connection.c connection_edge.c connection_or.c \
	cpuworker.c directory.c dirserv.c dns.c main.c \
	onion.c rendcommon.c rendmid.c rendservice.c rephist.c \
	router.c routerlist.c \
	onion.c rendcommon.c rendclient.c rendmid.c \
	rendservice.c rephist.c router.c routerlist.c \
	tor_main.c

tor_LDADD = ../common/libor.a
@@ -16,8 +16,8 @@ tor_LDADD = ../common/libor.a
test_SOURCES = buffers.c circuit.c command.c config.c \
	connection.c connection_edge.c connection_or.c \
	cpuworker.c directory.c dirserv.c dns.c main.c \
	onion.c rendcommon.c rendmid.c rendservice.c rephist.c \
	router.c routerlist.c \
	onion.c rendcommon.c rendclient.c rendmid.c \
	rendservice.c rephist.c router.c routerlist.c \
	test.c

test_LDADD = ../common/libor.a
+32 −13
Original line number Diff line number Diff line
@@ -255,34 +255,56 @@ circuit_t *circuit_get_by_conn(connection_t *conn) {
 * If !conn, return newest.
 *
 * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
 * If must_be_clean, ignore circs that have been used before.
 *
 * circ_purpose specifies what sort of circuit we must have.
 * If circ_purpose is not GENERAL, then conn must be defined.
 */
circuit_t *circuit_get_newest(connection_t *conn,
                              int must_be_open, int must_be_clean) {
                              int must_be_open, uint8_t circ_purpose) {
  circuit_t *circ, *newest=NULL, *leastdirty=NULL;
  routerinfo_t *exitrouter;

  for (circ=global_circuitlist;circ;circ = circ->next) {
    if (!circ->cpath)
      continue; /* this circ doesn't start at us */
    if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
      continue; /* don't pick rendezvous circuits */
    if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
      continue; /* ignore non-open circs */
    if (circ->marked_for_close)
      continue;

    if (circ->purpose != circ_purpose)
      continue;

#if 0
    if (must_be_clean && circ->timestamp_dirty)
      continue; /* ignore dirty circs */
#endif

    if(conn) {
      /* decide if this circ is suitable for this conn */

      if(circ->state == CIRCUIT_STATE_OPEN && circ->n_conn) /* open */
        exitrouter = router_get_by_addr_port(circ->cpath->prev->addr, circ->cpath->prev->port);
        exitrouter = router_get_by_addr_port(circ->cpath->prev->addr,
                                             circ->cpath->prev->port);
      else /* not open */
        exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
      if(!exitrouter || connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {

      if(!exitrouter)
        continue; /* this circuit is screwed and doesn't know it yet */

      if(circ_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
        if(connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {
          /* can't exit from this router */
          continue;
        }
      } else { /* not general */
        if(rend_cmp_service_ids(conn->socks_request->address, circ->rend_service)) {
          /* this circ is not for this conn */
          continue;
        }
      }
    }

    if(!newest || newest->timestamp_created < circ->timestamp_created) {
      newest = circ;
    }
@@ -1033,11 +1055,11 @@ static void circuit_is_ready(circuit_t *circ) {
      break;
    case CIRCUIT_PURPOSE_C_INTRODUCING:
      /* at Alice, connecting to intro point */
      // alice sends introduce1 relay cell
      rend_client_intro_is_ready(circ);
      break;
    case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
      /* at Alice, waiting for Bob */
      // alice launches a circuit to bob's intro point
      rend_client_rendezvous_is_ready(circ);
      break;
    case CIRCUIT_PURPOSE_S_CONNECT_REND:
      /* at Bob, connecting to rend point */
@@ -1246,9 +1268,6 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
      }
      circuit_rep_hist_note_result(circ);
      circuit_is_ready(circ); /* do other actions as necessary */
      /* Tell any AP connections that have been waiting for a new
       * circuit that one is ready. */
      connection_ap_attach_pending();
      return 0;
    } else if (r<0) {
      log_fn(LOG_INFO,"Unable to extend circuit path.");
+61 −58
Original line number Diff line number Diff line
@@ -9,10 +9,7 @@ extern or_options_t options; /* command-line and config-file options */
extern char *conn_state_to_string[][_CONN_TYPE_MAX+1];

static int connection_ap_handshake_process_socks(connection_t *conn);
static int connection_ap_handshake_attach_circuit(connection_t *conn,
                                                  int must_be_clean);
static int connection_ap_handshake_attach_circuit_helper(connection_t *conn,
                                                         int must_be_clean);
static int connection_ap_handshake_attach_circuit(connection_t *conn);
static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);

static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
@@ -377,9 +374,10 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
        memcpy(&addr, cell->payload+RELAY_HEADER_SIZE+1, 4);
        addr = ntohl(addr);
        client_dns_set_entry(conn->socks_request->address, addr);
        /* conn->purpose is still set to general */
        conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
        /* attaching to a dirty circuit is fine */
        if(connection_ap_handshake_attach_circuit(conn, 0) >= 0)
        if(connection_ap_handshake_attach_circuit(conn) >= 0)
          return 0;
        /* else, conn will get closed below */
      }
@@ -639,6 +637,7 @@ void connection_ap_expire_beginning(void) {
      conn->has_sent_end = 0;
      /* move it back into 'pending' state. */
      conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
      /* conn->purpose is still set to general */
      circuit_detach_stream(circ, conn);
      /* kludge to make us not try this circuit again, yet to allow
       * current streams on it to survive if they can: make it
@@ -648,7 +647,7 @@ void connection_ap_expire_beginning(void) {
      /* give our stream another 15 seconds to try */
      conn->timestamp_lastread += 15;
      /* attaching to a dirty circuit is fine */
      if(connection_ap_handshake_attach_circuit(conn,0)<0) {
      if(connection_ap_handshake_attach_circuit(conn)<0) {
        /* it will never work */
        /* Don't need to send end -- we're not connected */
        connection_mark_for_close(conn, 0);
@@ -672,7 +671,7 @@ void connection_ap_attach_pending(void)
        conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
      continue;
    /* attaching to a dirty circuit is fine */
    if(connection_ap_handshake_attach_circuit(conn,0) < 0) {
    if(connection_ap_handshake_attach_circuit(conn) < 0) {
      /* -1 means it will never work */
      /* Don't send end; there is no 'other side' yet */
      connection_mark_for_close(conn,0);
@@ -738,8 +737,9 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
  if (rend_parse_rendezvous_address(socks->address) < 0) {
    /* normal request */
    conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
    conn->purpose = AP_PURPOSE_GENERAL;
    /* attaching to a dirty circuit is fine */
    return connection_ap_handshake_attach_circuit(conn,0);
    return connection_ap_handshake_attach_circuit(conn);
  } else {
    /* it's a hidden-service request */
    const char *descp;
@@ -747,59 +747,59 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {

    /* see if we already have it cached */
    if (rend_cache_lookup(socks->address, &descp, &desc_len) == 1) {
      if(0){ //if a circuit already exists to this place, use it

      } else {
        /* go into some other state maybe? */
        /* then launch a rendezvous circuit */
        circuit_launch_new(CIRCUIT_PURPOSE_C_ESTABLISH_REND, NULL);
      }
      conn->purpose = AP_PURPOSE_RENDPOINT_WAIT;
      return connection_ap_handshake_attach_circuit(conn);
      //circuit_launch_new(CIRCUIT_PURPOSE_C_ESTABLISH_REND, NULL);
    } else {
      conn->purpose = AP_PURPOSE_RENDDESC_WAIT;
      /* initiate a dir hidserv desc lookup */
      /* go into a state where you'll be notified of the answer */
    }
  }
      directory_initiate_command(router_pick_directory_server(),
                                 DIR_PURPOSE_FETCH_RENDDESC,
                                 socks->address, strlen(socks->address));
      return 0;
    }

static int connection_ap_handshake_attach_circuit(connection_t *conn,
                                                  int must_be_clean) {
  /* try attaching. launch new circuit if needed.
   * return -1 if conn needs to die, else 0. */
  switch(connection_ap_handshake_attach_circuit_helper(conn, must_be_clean)) {
    case -1: /* it will never work */
      return -1;
    case 0: /* no useful circuits available */
      if(!circuit_get_newest(conn, 0, must_be_clean)) {
        /* is one already on the way? */
        circuit_launch_new(CIRCUIT_PURPOSE_C_GENERAL, NULL);
  }
  return 0;
    default: /* case 1, it succeeded, great */
      return 0;
  }
}

/* Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
 * we don't find one: if conn cannot be handled by any known nodes,
 * warn and return -1; else tell conn to stop reading and return 0.
 * Otherwise, associate conn with a safe live circuit, start
 * sending a BEGIN cell down the circuit, and return 1.
 * warn and return -1 (conn needs to die);
 * else launch new circuit and return 0.
 * Otherwise, associate conn with a safe live circuit, do the
 * right next step, and return 1.
 */
static int connection_ap_handshake_attach_circuit_helper(connection_t *conn,
                                                         int must_be_clean) {
static int connection_ap_handshake_attach_circuit(connection_t *conn) {
  circuit_t *circ;
  uint32_t addr;
  int must_be_clean;
  uint8_t desired_circuit_purpose;

  assert(conn);
  assert(conn->type == CONN_TYPE_AP);
  assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
  assert(conn->socks_request);

  switch(conn->purpose) {
    case AP_PURPOSE_GENERAL:
    case AP_PURPOSE_RENDDESC_WAIT:
      desired_circuit_purpose = CIRCUIT_PURPOSE_C_GENERAL;
      break;
    case AP_PURPOSE_RENDPOINT_WAIT:
      desired_circuit_purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
      break;
    case AP_PURPOSE_INTROPOINT_WAIT:
      desired_circuit_purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
      break;
    default:
      assert(0); /* never reached */
  }

  /* find the circuit that we should use, if there is one. */
  circ = circuit_get_newest(conn, 1, must_be_clean);
  circ = circuit_get_newest(conn, 1, desired_circuit_purpose);

  if(!circ) {
//XXX
    log_fn(LOG_INFO,"No safe circuit ready for edge connection; delaying.");
    addr = client_dns_lookup_entry(conn->socks_request->address);
    if(router_exit_policy_all_routers_reject(addr, conn->socks_request->port)) {
@@ -807,18 +807,22 @@ static int connection_ap_handshake_attach_circuit_helper(connection_t *conn,
             conn->socks_request->address, conn->socks_request->port);
      return -1;
    }
    connection_stop_reading(conn); /* don't read until the connected cell arrives */
    if(!circuit_get_newest(conn, 0, desired_circuit_purpose)) {
      /* is one already on the way? */
      circuit_launch_new(desired_circuit_purpose, NULL);
    }
    return 0;
  }

  connection_start_reading(conn);

  /* here, print the circ's path. so people can figure out which circs are sucking. */
  circuit_log_path(LOG_INFO,circ);

  if(!circ->timestamp_dirty)
    circ->timestamp_dirty = time(NULL);

  switch(conn->purpose) {
    case AP_PURPOSE_GENERAL:
    case AP_PURPOSE_RENDDESC_WAIT:
      /* add it into the linked list of streams on this circuit */
      log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
      conn->next_stream = circ->p_streams;
@@ -830,6 +834,10 @@ static int connection_ap_handshake_attach_circuit_helper(connection_t *conn,
      conn->cpath_layer = circ->cpath->prev;

      connection_ap_handshake_send_begin(conn, circ);
      break;
    case AP_PURPOSE_RENDPOINT_WAIT:
    case AP_PURPOSE_INTROPOINT_WAIT:
  }

  return 1;
}
@@ -894,11 +902,6 @@ static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t
  ap_conn->package_window = STREAMWINDOW_START;
  ap_conn->deliver_window = STREAMWINDOW_START;
  ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
  /* XXX Right now, we rely on the socks client not to send us any data
   * XXX until we've sent back a socks reply.  (If it does, we could wind
   * XXX up packaging that data and sending it to the exit, then later having
   * XXX the exit refuse us.)
   */
  log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn->s,circ->n_circ_id);
  return;
}
@@ -947,7 +950,7 @@ int connection_ap_make_bridge(char *address, uint16_t port) {
  connection_start_reading(conn);

  /* attaching to a dirty circuit is fine */
  if (connection_ap_handshake_attach_circuit(conn, 0) < 0) {
  if (connection_ap_handshake_attach_circuit(conn) < 0) {
    connection_mark_for_close(conn, 0);
    close(fd[1]);
    return -1;
+2 −2
Original line number Diff line number Diff line
@@ -275,11 +275,11 @@ int connection_dir_process_inbuf(connection_t *conn) {
            /* alice's ap_stream is just going to have to time out. */
          } else {
            /* success. notify pending connections about this. */
            //alice_notify_desc_fetched(conn->rend_query);
            rend_client_desc_fetched(conn->rend_query);
          }
          break;
        case 404:
          //alice_notify_desc_not_fetched(conn->rend_query);
          rend_client_desc_not_fetched(conn->rend_query);
          break;
        case 400:
          log_fn(LOG_WARN,"http status 400 (bad request). Dirserver didn't like our rendezvous query?");
+1 −1
Original line number Diff line number Diff line
@@ -384,7 +384,7 @@ static void run_scheduled_events(time_t now) {
/* Build a new test circuit every 5 minutes */
#define TESTING_CIRCUIT_INTERVAL 300

    circ = circuit_get_newest(NULL, 1, 0);
    circ = circuit_get_newest(NULL, 1, CIRCUIT_PURPOSE_C_GENERAL);
    if(time_to_new_circuit < now) {
      client_dns_clean();
      circuit_expire_unused_circuits();
Loading