|  | @@ -371,6 +371,7 @@ circuit_predict_and_launch_new(void)
 | 
	
		
			
				|  |  |    int hidserv_needs_uptime=0, hidserv_needs_capacity=1;
 | 
	
		
			
				|  |  |    int port_needs_uptime=0, port_needs_capacity=1;
 | 
	
		
			
				|  |  |    time_t now = time(NULL);
 | 
	
		
			
				|  |  | +  int flags = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* First, count how many of each type of circuit we have already. */
 | 
	
		
			
				|  |  |    for (circ=global_circuitlist;circ;circ = circ->next) {
 | 
	
	
		
			
				|  | @@ -402,22 +403,26 @@ circuit_predict_and_launch_new(void)
 | 
	
		
			
				|  |  |     * and no circuit is currently available that can handle it. */
 | 
	
		
			
				|  |  |    if (!circuit_all_predicted_ports_handled(now, &port_needs_uptime,
 | 
	
		
			
				|  |  |                                             &port_needs_capacity)) {
 | 
	
		
			
				|  |  | +    if (port_needs_uptime)
 | 
	
		
			
				|  |  | +      flags |= CIRCLAUNCH_NEED_UPTIME;
 | 
	
		
			
				|  |  | +    if (port_needs_capacity)
 | 
	
		
			
				|  |  | +      flags |= CIRCLAUNCH_NEED_CAPACITY;
 | 
	
		
			
				|  |  |      log_info(LD_CIRC,
 | 
	
		
			
				|  |  |               "Have %d clean circs (%d internal), need another exit circ.",
 | 
	
		
			
				|  |  |               num, num_internal);
 | 
	
		
			
				|  |  | -    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL,
 | 
	
		
			
				|  |  | -                             port_needs_uptime, port_needs_capacity, 0);
 | 
	
		
			
				|  |  | +    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* Third, see if we need any more hidden service (server) circuits. */
 | 
	
		
			
				|  |  |    if (num_rend_services() && num_uptime_internal < 3) {
 | 
	
		
			
				|  |  | +    flags = (CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_NEED_UPTIME |
 | 
	
		
			
				|  |  | +             CIRCLAUNCH_IS_INTERNAL);
 | 
	
		
			
				|  |  |      log_info(LD_CIRC,
 | 
	
		
			
				|  |  |               "Have %d clean circs (%d internal), need another internal "
 | 
	
		
			
				|  |  |               "circ for my hidden service.",
 | 
	
		
			
				|  |  |               num, num_internal);
 | 
	
		
			
				|  |  | -    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL,
 | 
	
		
			
				|  |  | -                             1, 1, 1);
 | 
	
		
			
				|  |  | +    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -426,12 +431,16 @@ circuit_predict_and_launch_new(void)
 | 
	
		
			
				|  |  |                                        &hidserv_needs_capacity) &&
 | 
	
		
			
				|  |  |        ((num_uptime_internal<2 && hidserv_needs_uptime) ||
 | 
	
		
			
				|  |  |          num_internal<2)) {
 | 
	
		
			
				|  |  | +    if (hidserv_needs_uptime)
 | 
	
		
			
				|  |  | +      flags |= CIRCLAUNCH_NEED_UPTIME;
 | 
	
		
			
				|  |  | +    if (hidserv_needs_capacity)
 | 
	
		
			
				|  |  | +      flags |= CIRCLAUNCH_NEED_CAPACITY;
 | 
	
		
			
				|  |  | +    flags |= CIRCLAUNCH_IS_INTERNAL;
 | 
	
		
			
				|  |  |      log_info(LD_CIRC,
 | 
	
		
			
				|  |  |               "Have %d clean circs (%d uptime-internal, %d internal), need"
 | 
	
		
			
				|  |  |               " another hidserv circ.",
 | 
	
		
			
				|  |  |               num, num_uptime_internal, num_internal);
 | 
	
		
			
				|  |  | -    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL,
 | 
	
		
			
				|  |  | -                             hidserv_needs_uptime, hidserv_needs_capacity, 1);
 | 
	
		
			
				|  |  | +    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -469,7 +478,7 @@ circuit_build_needed_circs(time_t now)
 | 
	
		
			
				|  |  |          circ &&
 | 
	
		
			
				|  |  |          circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
 | 
	
		
			
				|  |  |        log_fn(LOG_INFO,"Creating a new testing circuit.");
 | 
	
		
			
				|  |  | -      circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL, 0, 0, 0);
 | 
	
		
			
				|  |  | +      circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -798,34 +807,33 @@ static int did_circs_fail_last_period = 0;
 | 
	
		
			
				|  |  |  /** Launch a new circuit; see circuit_launch_by_extend_info() for
 | 
	
		
			
				|  |  |   * details on arguments. */
 | 
	
		
			
				|  |  |  origin_circuit_t *
 | 
	
		
			
				|  |  | -circuit_launch_by_router(uint8_t purpose, int onehop_tunnel,
 | 
	
		
			
				|  |  | -                         routerinfo_t *exit, int need_uptime,
 | 
	
		
			
				|  |  | -                         int need_capacity, int internal)
 | 
	
		
			
				|  |  | +circuit_launch_by_router(uint8_t purpose,
 | 
	
		
			
				|  |  | +                         routerinfo_t *exit, int flags)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    origin_circuit_t *circ;
 | 
	
		
			
				|  |  |    extend_info_t *info = NULL;
 | 
	
		
			
				|  |  |    if (exit)
 | 
	
		
			
				|  |  |      info = extend_info_from_router(exit);
 | 
	
		
			
				|  |  | -  circ = circuit_launch_by_extend_info(
 | 
	
		
			
				|  |  | -    purpose, onehop_tunnel, info, need_uptime, need_capacity, internal);
 | 
	
		
			
				|  |  | +  circ = circuit_launch_by_extend_info(purpose, info, flags);
 | 
	
		
			
				|  |  |    if (info)
 | 
	
		
			
				|  |  |      extend_info_free(info);
 | 
	
		
			
				|  |  |    return circ;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Launch a new circuit with purpose <b>purpose</b> and exit node
 | 
	
		
			
				|  |  | - * <b>extend_info</b> (or NULL to select a random exit node).
 | 
	
		
			
				|  |  | - * If <b>need_uptime</b> is true,
 | 
	
		
			
				|  |  | - * choose among routers with high uptime.  If <b>need_capacity</b> is true,
 | 
	
		
			
				|  |  | - * choose among routers with high bandwidth.  If <b>internal</b> is true, the
 | 
	
		
			
				|  |  | - * last hop need not be an exit node. Return the newly allocated circuit on
 | 
	
		
			
				|  |  | - * success, or NULL on failure. */
 | 
	
		
			
				|  |  | + * <b>extend_info</b> (or NULL to select a random exit node).  If flags
 | 
	
		
			
				|  |  | + * contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime.  If
 | 
	
		
			
				|  |  | + * CIRCLAUNCH_NEED_CAPACITY is set, choose among routers with high bandwidth.
 | 
	
		
			
				|  |  | + * If CIRCLAUNCH_IS_INTERNAL is true, the last hop need not be an exit node.
 | 
	
		
			
				|  |  | + * If CIRCLAUNCH_ONEHOP_TUNNEL is set, the circuit will have only one hop.
 | 
	
		
			
				|  |  | + * Return the newly allocated circuit on success, or NULL on failure. */
 | 
	
		
			
				|  |  |  origin_circuit_t *
 | 
	
		
			
				|  |  | -circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
 | 
	
		
			
				|  |  | -                              extend_info_t *extend_info, int need_uptime,
 | 
	
		
			
				|  |  | -                              int need_capacity, int internal)
 | 
	
		
			
				|  |  | +circuit_launch_by_extend_info(uint8_t purpose,
 | 
	
		
			
				|  |  | +                              extend_info_t *extend_info,
 | 
	
		
			
				|  |  | +                              int flags)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    origin_circuit_t *circ;
 | 
	
		
			
				|  |  | +  int onehop_tunnel = flags & CIRCLAUNCH_ONEHOP_TUNNEL;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (!onehop_tunnel && !router_have_minimum_dir_info()) {
 | 
	
		
			
				|  |  |      log_debug(LD_CIRC,"Haven't fetched enough directory info yet; canceling "
 | 
	
	
		
			
				|  | @@ -838,8 +846,7 @@ circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
 | 
	
		
			
				|  |  |      /* see if there are appropriate circs available to cannibalize. */
 | 
	
		
			
				|  |  |      /* XXX020 if we're planning to add a hop, perhaps we want to look for
 | 
	
		
			
				|  |  |       * internal circs rather than exit circs? -RD */
 | 
	
		
			
				|  |  | -    circ = circuit_find_to_cannibalize(purpose, extend_info,
 | 
	
		
			
				|  |  | -                                       need_uptime, need_capacity, internal);
 | 
	
		
			
				|  |  | +    circ = circuit_find_to_cannibalize(purpose, extend_info, flags);
 | 
	
		
			
				|  |  |      if (circ) {
 | 
	
		
			
				|  |  |        log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d",
 | 
	
		
			
				|  |  |                 build_state_get_exit_nickname(circ->build_state), purpose);
 | 
	
	
		
			
				|  | @@ -881,16 +888,14 @@ circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* try a circ. if it fails, circuit_mark_for_close will increment
 | 
	
		
			
				|  |  |     * n_circuit_failures */
 | 
	
		
			
				|  |  | -  return circuit_establish_circuit(purpose, onehop_tunnel, extend_info,
 | 
	
		
			
				|  |  | -                                   need_uptime, need_capacity, internal);
 | 
	
		
			
				|  |  | +  return circuit_establish_circuit(purpose, extend_info, flags);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Launch a new circuit; see circuit_launch_by_extend_info() for
 | 
	
		
			
				|  |  |   * details on arguments. */
 | 
	
		
			
				|  |  |  origin_circuit_t *
 | 
	
		
			
				|  |  | -circuit_launch_by_nickname(uint8_t purpose, int onehop_tunnel,
 | 
	
		
			
				|  |  | -                           const char *exit_nickname,
 | 
	
		
			
				|  |  | -                           int need_uptime, int need_capacity, int internal)
 | 
	
		
			
				|  |  | +circuit_launch_by_nickname(uint8_t purpose,
 | 
	
		
			
				|  |  | +                           const char *exit_nickname, int flags)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    routerinfo_t *router = NULL;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -902,8 +907,7 @@ circuit_launch_by_nickname(uint8_t purpose, int onehop_tunnel,
 | 
	
		
			
				|  |  |        return NULL;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return circuit_launch_by_router(purpose, onehop_tunnel, router,
 | 
	
		
			
				|  |  | -                                  need_uptime, need_capacity, internal);
 | 
	
		
			
				|  |  | +  return circuit_launch_by_router(purpose, router, flags);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Record another failure at opening a general circuit. When we have
 | 
	
	
		
			
				|  | @@ -1085,9 +1089,15 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
 | 
	
		
			
				|  |  |      else
 | 
	
		
			
				|  |  |        new_circ_purpose = desired_circuit_purpose;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    circ = circuit_launch_by_extend_info(
 | 
	
		
			
				|  |  | -              new_circ_purpose, want_onehop, extend_info,
 | 
	
		
			
				|  |  | -              need_uptime, 1, need_internal);
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +      int flags = CIRCLAUNCH_NEED_CAPACITY;
 | 
	
		
			
				|  |  | +      if (want_onehop) flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
 | 
	
		
			
				|  |  | +      if (need_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
 | 
	
		
			
				|  |  | +      if (need_internal) flags |= CIRCLAUNCH_IS_INTERNAL;
 | 
	
		
			
				|  |  | +      circ = circuit_launch_by_extend_info(new_circ_purpose, extend_info,
 | 
	
		
			
				|  |  | +                                           flags);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (extend_info)
 | 
	
		
			
				|  |  |        extend_info_free(extend_info);
 | 
	
		
			
				|  |  |  
 |