| 
					
				 | 
			
			
				@@ -2027,31 +2027,23 @@ entry_guards_note_internet_connectivity(guard_selection_t *gs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Get a guard for use with a circuit.  Prefer to pick a running primary 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * guard; then a non-pending running filtered confirmed guard; then a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * non-pending runnable filtered guard.  Update the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Pick a primary guard for use with a circuit, if available. Update the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * <b>last_tried_to_connect</b> time and the <b>is_pending</b> fields of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * guard as appropriate.  Set <b>state_out</b> to the new guard-state 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * of the circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-STATIC entry_guard_t * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-select_entry_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                               guard_usage_t usage, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                               const entry_guard_restriction_t *rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                               unsigned *state_out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static entry_guard_t * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+select_primary_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 guard_usage_t usage, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 const entry_guard_restriction_t *rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 unsigned *state_out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  tor_assert(gs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  tor_assert(state_out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!gs->primary_guards_up_to_date) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    entry_guards_update_primary(gs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  entry_guard_t *chosen_guard = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int num_entry_guards = get_n_primary_guards_to_use(usage); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_t *usable_primary_guards = smartlist_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* "If any entry in PRIMARY_GUARDS has {is_reachable} status of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      <maybe> or <yes>, return the first such guard." */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     entry_guard_consider_retry(guard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (! entry_guard_obeys_restriction(guard, rst)) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2069,18 +2061,30 @@ select_entry_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } SMARTLIST_FOREACH_END(guard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (smartlist_len(usable_primary_guards)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    entry_guard_t *guard = smartlist_choose(usable_primary_guards); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    chosen_guard = smartlist_choose(usable_primary_guards); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     smartlist_free(usable_primary_guards); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     log_info(LD_GUARD, "Selected primary guard %s for circuit.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             entry_guard_describe(guard)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             entry_guard_describe(chosen_guard)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_free(usable_primary_guards); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return chosen_guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * For use with a circuit, pick a non-pending running filtered confirmed guard, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * if one is available. Update the <b>last_tried_to_connect</b> time and the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <b>is_pending</b> fields of the guard as appropriate. Set <b>state_out</b> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * to the new guard-state of the circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static entry_guard_t * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+select_confirmed_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  guard_usage_t usage, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  const entry_guard_restriction_t *rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  unsigned *state_out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      and {USABLE_FILTERED_GUARDS} is nonempty, return the first 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      entry in that intersection that has {is_pending} set to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      false." */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SMARTLIST_FOREACH_BEGIN(gs->confirmed_entry_guards, entry_guard_t *, guard) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (guard->is_primary) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       continue; /* we already considered this one. */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2101,34 +2105,93 @@ select_entry_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } SMARTLIST_FOREACH_END(guard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * For use with a circuit, pick a confirmed usable filtered guard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * at random. Update the <b>last_tried_to_connect</b> time and the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <b>is_pending</b> fields of the guard as appropriate. Set <b>state_out</b> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * to the new guard-state of the circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static entry_guard_t * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+select_filtered_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  guard_usage_t usage, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  const entry_guard_restriction_t *rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  unsigned *state_out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  entry_guard_t *chosen_guard = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  unsigned flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (need_descriptor) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  chosen_guard = sample_reachable_filtered_entry_guards(gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                 rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                 SAMPLE_EXCLUDE_CONFIRMED | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                 SAMPLE_EXCLUDE_PRIMARY | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                 SAMPLE_EXCLUDE_PENDING | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                 flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!chosen_guard) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  chosen_guard->is_pending = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  chosen_guard->last_tried_to_connect = approx_time(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  log_info(LD_GUARD, "No primary or confirmed guards available. Selected " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           "random guard %s for circuit. Will try other guards before " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           "using this circuit.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           entry_guard_describe(chosen_guard)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return chosen_guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Get a guard for use with a circuit.  Prefer to pick a running primary 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * guard; then a non-pending running filtered confirmed guard; then a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * non-pending runnable filtered guard.  Update the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <b>last_tried_to_connect</b> time and the <b>is_pending</b> fields of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * guard as appropriate.  Set <b>state_out</b> to the new guard-state 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * of the circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+STATIC entry_guard_t * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+select_entry_guard_for_circuit(guard_selection_t *gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               guard_usage_t usage, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               const entry_guard_restriction_t *rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               unsigned *state_out) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  entry_guard_t *chosen_guard = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(gs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(state_out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!gs->primary_guards_up_to_date) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    entry_guards_update_primary(gs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* "If any entry in PRIMARY_GUARDS has {is_reachable} status of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <maybe> or <yes>, return the first such guard." */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  chosen_guard = select_primary_guard_for_circuit(gs, usage, rst, state_out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (chosen_guard) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return chosen_guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      and {USABLE_FILTERED_GUARDS} is nonempty, return the first 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      entry in that intersection that has {is_pending} set to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      false." */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  chosen_guard = select_confirmed_guard_for_circuit(gs, usage, rst, state_out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (chosen_guard) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return chosen_guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* "Otherwise, if there is no such entry, select a member at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       random from {USABLE_FILTERED_GUARDS}." */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    entry_guard_t *guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    unsigned flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (need_descriptor) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    guard = sample_reachable_filtered_entry_guards(gs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                   rst, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                   SAMPLE_EXCLUDE_CONFIRMED | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                   SAMPLE_EXCLUDE_PRIMARY | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                   SAMPLE_EXCLUDE_PENDING | 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                   flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (guard == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      log_info(LD_GUARD, "Absolutely no sampled guards were available. " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               "Marking all guards for retry and starting from top again."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      mark_all_guards_maybe_reachable(gs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    guard->is_pending = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    guard->last_tried_to_connect = approx_time(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    log_info(LD_GUARD, "No primary or confirmed guards available. Selected " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             "random guard %s for circuit. Will try other guards before " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             "using this circuit.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             entry_guard_describe(guard)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  chosen_guard = select_filtered_guard_for_circuit(gs, usage, rst, state_out); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (chosen_guard == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    log_info(LD_GUARD, "Absolutely no sampled guards were available. " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "Marking all guards for retry and starting from top again."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mark_all_guards_maybe_reachable(gs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return chosen_guard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 |