circuituse.c 118 KB
Newer Older
Roger Dingledine's avatar
Roger Dingledine committed
1
2
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
Nick Mathewson's avatar
Nick Mathewson committed
4
 * Copyright (c) 2007-2019, The Tor Project, Inc. */
5
6
7
8
/* See LICENSE for licensing information */

/**
 * \file circuituse.c
9
10
11
12
13
14
15
16
 * \brief Launch the right sort of circuits and attach the right streams to
 * them.
 *
 * As distinct from circuitlist.c, which manages lookups to find circuits, and
 * circuitbuild.c, which handles the logistics of circuit construction, this
 * module keeps track of which streams can be attached to which circuits (in
 * circuit_get_best()), and attaches streams to circuits (with
 * circuit_try_attaching_streams(), connection_ap_handshake_attach_circuit(),
17
 * and connection_ap_handshake_attach_chosen_circuit() ).
18
19
20
21
22
23
24
25
26
27
 *
 * This module also makes sure that we are building circuits for all of the
 * predicted ports, using circuit_remove_handled_ports(),
 * circuit_stream_is_being_handled(), and circuit_build_needed_cirs().  It
 * handles launching circuits for specific targets using
 * circuit_launch_by_extend_info().
 *
 * This is also where we handle expiring circuits that have been around for
 * too long without actually completing, along with the circuit_build_timeout
 * logic in circuitstats.c.
28
29
 **/

30
#include "core/or/or.h"
31
32
#include "app/config/config.h"
#include "core/mainloop/connection.h"
33
34
35
36
37
38
#include "core/or/channel.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitstats.h"
#include "core/or/circuituse.h"
#include "core/or/connection_edge.h"
39
40
41
42
43
#include "core/or/policies.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
#include "feature/client/entrynodes.h"
44
#include "feature/control/control.h"
45
#include "feature/dircommon/directory.h"
46
#include "feature/hs/hs_circuit.h"
47
48
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
49
50
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_stats.h"
51
#include "feature/nodelist/describe.h"
52
#include "feature/nodelist/networkstatus.h"
53
54
55
56
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/routermode.h"
#include "feature/relay/selftest.h"
57
58
59
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
60
#include "feature/stats/predict_ports.h"
61
#include "lib/math/fp.h"
62
#include "lib/time/tvdiff.h"
63

64
65
66
67
68
69
70
#include "core/or/cpath_build_state_st.h"
#include "feature/dircommon/dir_connection_st.h"
#include "core/or/entry_connection_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
#include "core/or/socks_request_st.h"
71

72
static void circuit_expire_old_circuits_clientside(void);
73
74
static void circuit_increment_failure_count(void);

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/** Check whether the hidden service destination of the stream at
 *  <b>edge_conn</b> is the same as the destination of the circuit at
 *  <b>origin_circ</b>. */
static int
circuit_matches_with_rend_stream(const edge_connection_t *edge_conn,
                                 const origin_circuit_t *origin_circ)
{
  /* Check if this is a v2 rendezvous circ/stream */
  if ((edge_conn->rend_data && !origin_circ->rend_data) ||
      (!edge_conn->rend_data && origin_circ->rend_data) ||
      (edge_conn->rend_data && origin_circ->rend_data &&
       rend_cmp_service_ids(rend_data_get_address(edge_conn->rend_data),
                            rend_data_get_address(origin_circ->rend_data)))) {
    /* this circ is not for this conn */
    return 0;
  }

  /* Check if this is a v3 rendezvous circ/stream */
  if ((edge_conn->hs_ident && !origin_circ->hs_ident) ||
      (!edge_conn->hs_ident && origin_circ->hs_ident) ||
      (edge_conn->hs_ident && origin_circ->hs_ident &&
       !ed25519_pubkey_eq(&edge_conn->hs_ident->identity_pk,
                          &origin_circ->hs_ident->identity_pk))) {
    /* this circ is not for this conn */
    return 0;
  }

  return 1;
}

105
/** Return 1 if <b>circ</b> could be returned by circuit_get_best().
106
107
 * Else return 0.
 */
108
static int
Nick Mathewson's avatar
Nick Mathewson committed
109
circuit_is_acceptable(const origin_circuit_t *origin_circ,
110
                      const entry_connection_t *conn,
111
112
                      int must_be_open, uint8_t purpose,
                      int need_uptime, int need_internal,
113
                      time_t now)
114
{
Nick Mathewson's avatar
Nick Mathewson committed
115
  const circuit_t *circ = TO_CIRCUIT(origin_circ);
116
  const node_t *exitnode;
117
  cpath_build_state_t *build_state;
118
119
120
  tor_assert(circ);
  tor_assert(conn);
  tor_assert(conn->socks_request);
121

122
  if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_chan))
123
124
125
126
127
    return 0; /* ignore non-open circs */
  if (circ->marked_for_close)
    return 0;

  /* if this circ isn't our purpose, skip. */
128
129
  if (purpose == CIRCUIT_PURPOSE_C_REND_JOINED && !must_be_open) {
    if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
130
131
132
        circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
        circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED &&
        circ->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)
133
      return 0;
134
135
  } else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT &&
             !must_be_open) {
136
137
138
139
    if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCING &&
        circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
      return 0;
  } else {
140
    if (purpose != circ->purpose)
141
142
143
      return 0;
  }

144
145
146
147
148
  /* If this is a timed-out hidden service circuit, skip it. */
  if (origin_circ->hs_circ_has_timed_out) {
    return 0;
  }

149
  if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
150
151
      purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
      purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
152
      purpose == CIRCUIT_PURPOSE_HS_VANGUARDS ||
153
      purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
154
    if (circ->timestamp_dirty &&
155
       circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
156
      return 0;
157
158
159
160
  }

  if (origin_circ->unusable_for_new_conns)
    return 0;
161

162
  /* decide if this circ is suitable for this conn */
163

164
  /* for rend circs, circ->cpath->prev is not the last router in the
165
   * circuit, it's the magical extra service hop. so just check the nickname
166
167
   * of the one we meant to finish at.
   */
Nick Mathewson's avatar
Nick Mathewson committed
168
  build_state = origin_circ->build_state;
169
  exitnode = build_state_get_exit_node(build_state);
170

171
  if (need_uptime && !build_state->need_uptime)
172
    return 0;
173
  if (need_internal != build_state->is_internal)
174
    return 0;
175

176
177
178
  if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
      purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
      purpose == CIRCUIT_PURPOSE_C_HSDIR_GET) {
179
180
    tor_addr_t addr;
    const int family = tor_addr_parse(&addr, conn->socks_request->address);
181
    if (!exitnode && !build_state->onehop_tunnel) {
182
      log_debug(LD_CIRC,"Not considering circuit with unknown router.");
183
184
185
      return 0; /* this circuit is screwed and doesn't know it yet,
                 * or is a rendezvous circuit. */
    }
186
    if (build_state->onehop_tunnel) {
187
      if (!conn->want_onehop) {
188
189
190
        log_debug(LD_CIRC,"Skipping one-hop circuit.");
        return 0;
      }
191
192
193
      tor_assert(conn->chosen_exit_name);
      if (build_state->chosen_exit) {
        char digest[DIGEST_LEN];
194
195
        if (hexdigest_to_digest(conn->chosen_exit_name, digest) < 0)
          return 0; /* broken digest, we don't want it */
196
        if (tor_memneq(digest, build_state->chosen_exit->identity_digest,
197
                          DIGEST_LEN))
198
          return 0; /* this is a circuit to somewhere else */
199
200
        if (tor_digest_is_zero(digest)) {
          /* we don't know the digest; have to compare addr:port */
201
          if (family < 0 ||
202
              !tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
203
204
205
              build_state->chosen_exit->port != conn->socks_request->port)
            return 0;
        }
206
      }
207
    } else {
208
      if (conn->want_onehop) {
209
210
211
212
        /* don't use three-hop circuits -- that could hurt our anonymity. */
        return 0;
      }
    }
213
214
215
216
217
218
219
    if (origin_circ->prepend_policy && family != -1) {
      int r = compare_tor_addr_to_addr_policy(&addr,
                                              conn->socks_request->port,
                                              origin_circ->prepend_policy);
      if (r == ADDR_POLICY_REJECTED)
        return 0;
    }
220
    if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
221
222
223
      /* can't exit from this router */
      return 0;
    }
224
  } else { /* not general: this might be a rend circuit */
225
    const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
226
    if (!circuit_matches_with_rend_stream(edge_conn, origin_circ)) {
227
      return 0;
228
229
    }
  }
Nick Mathewson's avatar
Nick Mathewson committed
230
231
232
233
234
235
236

  if (!connection_edge_compatible_with_circuit(conn, origin_circ)) {
    /* conn needs to be isolated from other conns that have already used
     * origin_circ */
    return 0;
  }

237
238
239
  return 1;
}

240
/** Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for
Nick Mathewson's avatar
Nick Mathewson committed
241
 * <b>conn</b>, and return 0 otherwise. Used by circuit_get_best.
242
 */
243
static int
Nick Mathewson's avatar
Nick Mathewson committed
244
circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
245
                  const entry_connection_t *conn)
246
{
Nick Mathewson's avatar
Nick Mathewson committed
247
248
  const circuit_t *a = TO_CIRCUIT(oa);
  const circuit_t *b = TO_CIRCUIT(ob);
249
  const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose;
Nick Mathewson's avatar
Nick Mathewson committed
250
  int a_bits, b_bits;
Nick Mathewson's avatar
Nick Mathewson committed
251

252
253
254
255
256
257
258
  /* If one of the circuits was allowed to live due to relaxing its timeout,
   * it is definitely worse (it's probably a much slower path). */
  if (oa->relaxed_timeout && !ob->relaxed_timeout)
    return 0; /* ob is better. It's not relaxed. */
  if (!oa->relaxed_timeout && ob->relaxed_timeout)
    return 1; /* oa is better. It's not relaxed. */

259
  switch (purpose) {
260
261
    case CIRCUIT_PURPOSE_S_HSDIR_POST:
    case CIRCUIT_PURPOSE_C_HSDIR_GET:
262
263
264
265
    case CIRCUIT_PURPOSE_C_GENERAL:
      /* if it's used but less dirty it's best;
       * else if it's more recently created it's best
       */
266
267
      if (b->timestamp_dirty) {
        if (a->timestamp_dirty &&
268
            a->timestamp_dirty > b->timestamp_dirty)
269
270
          return 1;
      } else {
271
        if (a->timestamp_dirty ||
272
            timercmp(&a->timestamp_began, &b->timestamp_began, OP_GT))
273
          return 1;
Nick Mathewson's avatar
Nick Mathewson committed
274
        if (ob->build_state->is_internal)
275
          /* XXXX++ what the heck is this internal thing doing here. I
Roger Dingledine's avatar
Roger Dingledine committed
276
277
278
           * think we can get rid of it. circuit_is_acceptable() already
           * makes sure that is_internal is exactly what we need it to
           * be. -RD */
279
          return 1;
280
281
282
283
      }
      break;
    case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
      /* the closer it is to ack_wait the better it is */
284
      if (a->purpose > b->purpose)
285
286
287
288
        return 1;
      break;
    case CIRCUIT_PURPOSE_C_REND_JOINED:
      /* the closer it is to rend_joined the better it is */
289
      if (a->purpose > b->purpose)
290
291
292
        return 1;
      break;
  }
Nick Mathewson's avatar
Nick Mathewson committed
293

294
  /* XXXX Maybe this check should get a higher priority to avoid
Nick Mathewson's avatar
Nick Mathewson committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
   *   using up circuits too rapidly. */

  a_bits = connection_edge_update_circuit_isolation(conn,
                                                    (origin_circuit_t*)oa, 1);
  b_bits = connection_edge_update_circuit_isolation(conn,
                                                    (origin_circuit_t*)ob, 1);
  /* if x_bits < 0, then we have not used x for anything; better not to dirty
   * a connection if we can help it. */
  if (a_bits < 0) {
    return 0;
  } else if (b_bits < 0) {
    return 1;
  }
  a_bits &= ~ oa->isolation_flags_mixed;
  a_bits &= ~ ob->isolation_flags_mixed;
  if (n_bits_set_u8(a_bits) < n_bits_set_u8(b_bits)) {
    /* The fewer new restrictions we need to make on a circuit for stream
     * isolation, the better. */
    return 1;
  }

316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  return 0;
}

/** Find the best circ that conn can use, preferably one which is
 * dirty. Circ must not be too old.
 *
 * Conn must be defined.
 *
 * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
 *
 * circ_purpose specifies what sort of circuit we must have.
 * It can be C_GENERAL, C_INTRODUCE_ACK_WAIT, or C_REND_JOINED.
 *
 * If it's REND_JOINED and must_be_open==0, then return the closest
 * rendezvous-purposed circuit that you can find.
 *
 * If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
 * closest introduce-purposed circuit that you can find.
 */
335
static origin_circuit_t *
336
circuit_get_best(const entry_connection_t *conn,
Nick Mathewson's avatar
Nick Mathewson committed
337
                 int must_be_open, uint8_t purpose,
338
                 int need_uptime, int need_internal)
339
{
Nick Mathewson's avatar
Nick Mathewson committed
340
  origin_circuit_t *best=NULL;
341
  struct timeval now;
342
  int intro_going_on_but_too_old = 0;
343
344
345
346

  tor_assert(conn);

  tor_assert(purpose == CIRCUIT_PURPOSE_C_GENERAL ||
347
             purpose == CIRCUIT_PURPOSE_HS_VANGUARDS ||
348
349
             purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
             purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
350
351
352
             purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT ||
             purpose == CIRCUIT_PURPOSE_C_REND_JOINED);

353
354
  tor_gettimeofday(&now);

355
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
Nick Mathewson's avatar
Nick Mathewson committed
356
357
358
359
    origin_circuit_t *origin_circ;
    if (!CIRCUIT_IS_ORIGIN(circ))
      continue;
    origin_circ = TO_ORIGIN_CIRCUIT(circ);
360

Mike Perry's avatar
Mike Perry committed
361
362
    /* Log an info message if we're going to launch a new intro circ in
     * parallel */
363
    if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT &&
364
365
        !must_be_open && origin_circ->hs_circ_has_timed_out &&
        !circ->marked_for_close) {
Mike Perry's avatar
Mike Perry committed
366
367
        intro_going_on_but_too_old = 1;
        continue;
368
369
    }

Mike Perry's avatar
Mike Perry committed
370
    if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose,
371
                               need_uptime,need_internal, (time_t)now.tv_sec))
Mike Perry's avatar
Mike Perry committed
372
373
      continue;

374
375
376
    /* now this is an acceptable circ to hand back. but that doesn't
     * mean it's the *best* circ to hand back. try to decide.
     */
Nick Mathewson's avatar
Nick Mathewson committed
377
    if (!best || circuit_is_better(origin_circ,best,conn))
Nick Mathewson's avatar
Nick Mathewson committed
378
      best = origin_circ;
379
  }
380
  SMARTLIST_FOREACH_END(circ);
381

382
383
384
385
386
  if (!best && intro_going_on_but_too_old)
    log_info(LD_REND|LD_CIRC, "There is an intro circuit being created "
             "right now, but it has already taken quite a while. Starting "
             "one in parallel.");

Nick Mathewson's avatar
Nick Mathewson committed
387
  return best;
388
389
}

390
391
392
393
394
395
/** Return the number of not-yet-open general-purpose origin circuits. */
static int
count_pending_general_client_circuits(void)
{
  int count = 0;

396
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
397
398
    if (circ->marked_for_close ||
        circ->state == CIRCUIT_STATE_OPEN ||
399
        !CIRCUIT_PURPOSE_COUNTS_TOWARDS_MAXPENDING(circ->purpose) ||
400
401
402
403
404
        !CIRCUIT_IS_ORIGIN(circ))
      continue;

    ++count;
  }
405
  SMARTLIST_FOREACH_END(circ);
406
407
408
409

  return count;
}

410
#if 0
411
/** Check whether, according to the policies in <b>options</b>, the
412
 * circuit <b>circ</b> makes sense. */
413
414
415
/* XXXX currently only checks Exclude{Exit}Nodes; it should check more.
 * Also, it doesn't have the right definition of an exit circuit. Also,
 * it's never called. */
416
417
418
419
420
421
int
circuit_conforms_to_options(const origin_circuit_t *circ,
                            const or_options_t *options)
{
  const crypt_path_t *cpath, *cpath_next = NULL;

422
423
  /* first check if it includes any excluded nodes */
  for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) {
424
425
426
427
    cpath_next = cpath->next;
    if (routerset_contains_extendinfo(options->ExcludeNodes,
                                      cpath->extend_info))
      return 0;
428
  }
429

430
431
432
433
  /* then consider the final hop */
  if (routerset_contains_extendinfo(options->ExcludeExitNodes,
                                    circ->cpath->prev->extend_info))
    return 0;
434
435
436

  return 1;
}
437
#endif /* 0 */
438

439
440
/**
 * Close all circuits that start at us, aren't open, and were born
441
 * at least CircuitBuildTimeout seconds ago.
442
443
444
445
446
447
448
449
 *
 * TODO: This function is now partially redundant to
 * circuit_build_times_handle_completed_hop(), but that function only
 * covers circuits up to and including 3 hops that are still actually
 * completing hops. However, circuit_expire_building() also handles longer
 * circuits, as well as circuits that are completely stalled.
 * In the future (after prop247/other path selection revamping), we probably
 * want to eliminate this rats nest in favor of a simpler approach.
450
 */
451
void
452
circuit_expire_building(void)
453
{
454
455
456
  /* circ_times.timeout_ms and circ_times.close_ms are from
   * circuit_build_times_get_initial_timeout() if we haven't computed
   * custom timeouts yet */
457
  struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff,
Mike Perry's avatar
Mike Perry committed
458
459
    close_cutoff, extremely_old_cutoff, hs_extremely_old_cutoff,
    cannibalized_cutoff, c_intro_cutoff, s_intro_cutoff, stream_cutoff;
460
  const or_options_t *options = get_options();
461
  struct timeval now;
462
  cpath_build_state_t *build_state;
463
  int any_opened_circs = 0;
464

465
  tor_gettimeofday(&now);
466
467
468
469
470

  /* Check to see if we have any opened circuits. If we don't,
   * we want to be more lenient with timeouts, in case the
   * user has relocated and/or changed network connections.
   * See bug #3443. */
471
  any_opened_circs = circuit_any_opened_circuits();
472

473
474
475
476
#define SET_CUTOFF(target, msec) do {                       \
    long ms = tor_lround(msec);                             \
    struct timeval diff;                                    \
    diff.tv_sec = ms / 1000;                                \
477
    diff.tv_usec = (int)((ms % 1000) * 1000);               \
478
479
480
    timersub(&now, &diff, &target);                         \
  } while (0)

Mike Perry's avatar
Mike Perry committed
481
  /**
Mike Perry's avatar
Mike Perry committed
482
483
484
485
486
487
488
489
490
   * Because circuit build timeout is calculated only based on 3 hop
   * general purpose circuit construction, we need to scale the timeout
   * to make it properly apply to longer circuits, and circuits of
   * certain usage types. The following diagram illustrates how we
   * derive the scaling below. In short, we calculate the number
   * of times our telescoping-based circuit construction causes cells
   * to traverse each link for the circuit purpose types in question,
   * and then assume each link is equivalent.
   *
Mike Perry's avatar
Mike Perry committed
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
   * OP --a--> A --b--> B --c--> C
   * OP --a--> A --b--> B --c--> C --d--> D
   *
   * Let h = a = b = c = d
   *
   * Three hops (general_cutoff)
   *   RTTs = 3a + 2b + c
   *   RTTs = 6h
   * Cannibalized:
   *   RTTs = a+b+c+d
   *   RTTs = 4h
   * Four hops:
   *   RTTs = 4a + 3b + 2c + d
   *   RTTs = 10h
   * Client INTRODUCE1+ACK: // XXX: correct?
   *   RTTs = 5a + 4b + 3c + 2d
   *   RTTs = 14h
   * Server intro:
   *   RTTs = 4a + 3b + 2c
   *   RTTs = 9h
   */
512
513
  SET_CUTOFF(general_cutoff, get_circuit_build_timeout_ms());
  SET_CUTOFF(begindir_cutoff, get_circuit_build_timeout_ms());
Mike Perry's avatar
Mike Perry committed
514

515
516
517
518
  // TODO: We should probably use route_len_for_purpose() here instead,
  // except that does not count the extra round trip for things like server
  // intros and rends.

Mike Perry's avatar
Mike Perry committed
519
520
  /* > 3hop circs seem to have a 1.0 second delay on their cannibalized
   * 4th hop. */
521
  SET_CUTOFF(fourhop_cutoff, get_circuit_build_timeout_ms() * (10/6.0) + 1000);
Mike Perry's avatar
Mike Perry committed
522
523
524
525
526
527

  /* CIRCUIT_PURPOSE_C_ESTABLISH_REND behaves more like a RELAY cell.
   * Use the stream cutoff (more or less). */
  SET_CUTOFF(stream_cutoff, MAX(options->CircuitStreamTimeout,15)*1000 + 1000);

  /* Be lenient with cannibalized circs. They already survived the official
Roger Dingledine's avatar
Roger Dingledine committed
528
   * CBT, and they're usually not performance-critical. */
Mike Perry's avatar
Mike Perry committed
529
  SET_CUTOFF(cannibalized_cutoff,
530
             MAX(get_circuit_build_close_time_ms()*(4/6.0),
Mike Perry's avatar
Mike Perry committed
531
532
                 options->CircuitStreamTimeout * 1000) + 1000);

Roger Dingledine's avatar
Roger Dingledine committed
533
  /* Intro circs have an extra round trip (and are also 4 hops long) */
534
  SET_CUTOFF(c_intro_cutoff, get_circuit_build_timeout_ms() * (14/6.0) + 1000);
Mike Perry's avatar
Mike Perry committed
535

Roger Dingledine's avatar
Roger Dingledine committed
536
  /* Server intro circs have an extra round trip */
537
  SET_CUTOFF(s_intro_cutoff, get_circuit_build_timeout_ms() * (9/6.0) + 1000);
Mike Perry's avatar
Mike Perry committed
538

539
540
  SET_CUTOFF(close_cutoff, get_circuit_build_close_time_ms());
  SET_CUTOFF(extremely_old_cutoff, get_circuit_build_close_time_ms()*2 + 1000);
541

542
  SET_CUTOFF(hs_extremely_old_cutoff,
543
             MAX(get_circuit_build_close_time_ms()*2 + 1000,
544
545
                 options->SocksTimeout * 1000));

546
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *,victim) {
547
    struct timeval cutoff;
548
549
    bool fixed_time = circuit_build_times_disabled(get_options());

550
    if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */
551
552
553
554
555
556
557
558
559
560
561
562
        victim->marked_for_close)     /* don't mess with marked circs */
      continue;

    /* If we haven't yet started the first hop, it means we don't have
     * any orconns available, and thus have not started counting time yet
     * for this circuit. See circuit_deliver_create_cell() and uses of
     * timestamp_began.
     *
     * Continue to wait in this case. The ORConn should timeout
     * independently and kill us then.
     */
    if (TO_ORIGIN_CIRCUIT(victim)->cpath->state == CPATH_STATE_CLOSED) {
563
      continue;
564
    }
565

566
    build_state = TO_ORIGIN_CIRCUIT(victim)->build_state;
567
568
    if (build_state && build_state->onehop_tunnel)
      cutoff = begindir_cutoff;
569
570
    else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
      cutoff = close_cutoff;
571
    else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
Mike Perry's avatar
Mike Perry committed
572
573
574
575
576
      cutoff = c_intro_cutoff;
    else if (victim->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
      cutoff = s_intro_cutoff;
    else if (victim->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND)
      cutoff = stream_cutoff;
577
578
    else if (victim->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
      cutoff = close_cutoff;
Mike Perry's avatar
Mike Perry committed
579
580
581
582
583
    else if (TO_ORIGIN_CIRCUIT(victim)->has_opened &&
             victim->state != CIRCUIT_STATE_OPEN)
      cutoff = cannibalized_cutoff;
    else if (build_state && build_state->desired_path_len >= 4)
      cutoff = fourhop_cutoff;
584
585
    else
      cutoff = general_cutoff;
586

587
588
589
    if (TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)
      cutoff = hs_extremely_old_cutoff;

590
    if (timercmp(&victim->timestamp_began, &cutoff, OP_GT))
591
592
      continue; /* it's still young, leave it alone */

593
594
595
596
597
598
    /* We need to double-check the opened state here because
     * we don't want to consider opened 1-hop dircon circuits for
     * deciding when to relax the timeout, but we *do* want to relax
     * those circuits too if nothing else is opened *and* they still
     * aren't either. */
    if (!any_opened_circs && victim->state != CIRCUIT_STATE_OPEN) {
599
      /* It's still young enough that we wouldn't close it, right? */
600
      if (timercmp(&victim->timestamp_began, &close_cutoff, OP_GT)) {
601
602
603
        if (!TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout) {
          int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath->state
                                      == CPATH_STATE_OPEN;
604
605
606
607
608
609
610
611
612
613
614
615
616
          if (!fixed_time) {
            log_info(LD_CIRC,
                "No circuits are opened. Relaxing timeout for circuit %d "
                "(a %s %d-hop circuit in state %s with channel state %s).",
                TO_ORIGIN_CIRCUIT(victim)->global_identifier,
                circuit_purpose_to_string(victim->purpose),
                TO_ORIGIN_CIRCUIT(victim)->build_state ?
                  TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                  -1,
                circuit_state_to_string(victim->state),
                victim->n_chan ?
                   channel_state_to_string(victim->n_chan->state) : "none");
          }
617
618
619
620
621

          /* We count the timeout here for CBT, because technically this
           * was a timeout, and the timeout value needs to reset if we
           * see enough of them. Note this means we also need to avoid
           * double-counting below, too. */
622
          circuit_build_times_count_timeout(get_circuit_build_times_mutable(),
623
              first_hop_succeeded);
624
625
626
627
          TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout = 1;
        }
        continue;
      } else {
628
        static ratelim_t relax_timeout_limit = RATELIM_INIT(3600);
629
        const double build_close_ms = get_circuit_build_close_time_ms();
630
631
        if (!fixed_time) {
          log_fn_ratelim(&relax_timeout_limit, LOG_NOTICE, LD_CIRC,
632
633
634
                 "No circuits are opened. Relaxed timeout for circuit %d "
                 "(a %s %d-hop circuit in state %s with channel state %s) to "
                 "%ldms. However, it appears the circuit has timed out "
635
                 "anyway.",
636
637
                 TO_ORIGIN_CIRCUIT(victim)->global_identifier,
                 circuit_purpose_to_string(victim->purpose),
638
639
640
                 TO_ORIGIN_CIRCUIT(victim)->build_state ?
                   TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                   -1,
641
                 circuit_state_to_string(victim->state),
Mike Perry's avatar
Mike Perry committed
642
643
                 victim->n_chan ?
                    channel_state_to_string(victim->n_chan->state) : "none",
644
                 (long)build_close_ms);
645
        }
646
647
648
      }
    }

649
#if 0
650
    /* some debug logs, to help track bugs */
651
    if (victim->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING &&
652
        victim->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
653
      if (!victim->timestamp_dirty)
Nick Mathewson's avatar
Nick Mathewson committed
654
        log_fn(LOG_DEBUG,"Considering %sopen purpose %d to %s (circid %d)."
655
               "(clean).",
656
               victim->state == CIRCUIT_STATE_OPEN ? "" : "non",
Nick Mathewson's avatar
Nick Mathewson committed
657
               victim->purpose, victim->build_state->chosen_exit_name,
658
659
               victim->n_circ_id);
      else
Nick Mathewson's avatar
Nick Mathewson committed
660
        log_fn(LOG_DEBUG,"Considering %sopen purpose %d to %s (circid %d). "
661
               "%d secs since dirty.",
662
               victim->state == CIRCUIT_STATE_OPEN ? "" : "non",
Nick Mathewson's avatar
Nick Mathewson committed
663
               victim->purpose, victim->build_state->chosen_exit_name,
664
665
666
               victim->n_circ_id,
               (int)(now - victim->timestamp_dirty));
    }
667
#endif /* 0 */
668
669
670

    /* if circ is !open, or if it's open but purpose is a non-finished
     * intro or rend, then mark it for close */
671
672
    if (victim->state == CIRCUIT_STATE_OPEN) {
      switch (victim->purpose) {
673
        default: /* most open circuits can be left alone. */
674
675
          continue; /* yes, continue inside a switch refers to the nearest
                     * enclosing loop. C is smart. */
676
        case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
677
          break; /* too old, need to die */
678
679
        case CIRCUIT_PURPOSE_C_REND_READY:
          /* it's a rend_ready circ -- has it already picked a query? */
680
681
682
          /* c_rend_ready circs measure age since timestamp_dirty,
           * because that's set when they switch purposes
           */
683
          if (TO_ORIGIN_CIRCUIT(victim)->rend_data ||
684
              TO_ORIGIN_CIRCUIT(victim)->hs_ident ||
685
              victim->timestamp_dirty > cutoff.tv_sec)
686
687
            continue;
          break;
688
689
690
691
692
        case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
          /* Open path bias testing circuits are given a long
           * time to complete the test, but not forever */
          TO_ORIGIN_CIRCUIT(victim)->path_state = PATH_STATE_USE_FAILED;
          break;
Mike Perry's avatar
Mike Perry committed
693
        case CIRCUIT_PURPOSE_C_INTRODUCING:
694
          /* That purpose means that the intro point circuit has been opened
695
           * successfully but the INTRODUCE1 cell hasn't been sent yet because
696
697
698
699
700
           * the client is waiting for the rendezvous point circuit to open.
           * Keep this circuit open while waiting for the rendezvous circuit.
           * We let the circuit idle timeout take care of cleaning this
           * circuit if it never used. */
          continue;
Mike Perry's avatar
Mike Perry committed
701
        case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
702
703
704
705
706
707
        case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
        case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
          /* rend and intro circs become dirty each time they
           * make an introduction attempt. so timestamp_dirty
           * will reflect the time since the last attempt.
           */
708
          if (victim->timestamp_dirty > cutoff.tv_sec)
709
710
711
            continue;
          break;
      }
712
713
714
    } else { /* circuit not open, consider recording failure as timeout */
      int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath &&
            TO_ORIGIN_CIRCUIT(victim)->cpath->state == CPATH_STATE_OPEN;
715
716

      if (TO_ORIGIN_CIRCUIT(victim)->p_streams != NULL) {
717
        log_warn(LD_BUG, "Circuit %d (purpose %d, %s) has timed out, "
718
719
                 "yet has attached streams!",
                 TO_ORIGIN_CIRCUIT(victim)->global_identifier,
720
721
                 victim->purpose,
                 circuit_purpose_to_string(victim->purpose));
722
723
724
725
        tor_fragile_assert();
        continue;
      }

726
      if (circuit_timeout_want_to_count_circ(TO_ORIGIN_CIRCUIT(victim)) &&
727
          circuit_build_times_enough_to_compute(get_circuit_build_times())) {
728
729

        log_info(LD_CIRC,
730
731
                 "Deciding to count the timeout for circuit %"PRIu32"\n",
                 TO_ORIGIN_CIRCUIT(victim)->global_identifier);
732

733
734
735
        /* Circuits are allowed to last longer for measurement.
         * Switch their purpose and wait. */
        if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
736
737
          circuit_build_times_mark_circ_as_measurement_only(TO_ORIGIN_CIRCUIT(
                                                            victim));
738
739
          continue;
        }
740

741
742
743
744
745
        /*
         * If the circuit build time is much greater than we would have cut
         * it off at, we probably had a suspend event along this codepath,
         * and we should discard the value.
         */
746
        if (timercmp(&victim->timestamp_began, &extremely_old_cutoff, OP_LT)) {
747
748
          log_notice(LD_CIRC,
                     "Extremely large value for circuit build timeout: %lds. "
749
                     "Assuming clock jump. Purpose %d (%s)",
750
                     (long)(now.tv_sec - victim->timestamp_began.tv_sec),
751
                     victim->purpose,
752
                     circuit_purpose_to_string(victim->purpose));
753
        } else if (circuit_build_times_count_close(
754
755
756
            get_circuit_build_times_mutable(),
            first_hop_succeeded,
            (time_t)victim->timestamp_created.tv_sec)) {
757
          circuit_build_times_set_timeout(get_circuit_build_times_mutable());
758
        }
759
      }
760
    }
761

762
763
764
765
    /* If this is a hidden service client circuit which is far enough along in
     * connecting to its destination, and we haven't already flagged it as
     * 'timed out', flag it so we'll launch another intro or rend circ, but
     * don't mark it for close yet.
766
767
768
769
     *
     * (Circs flagged as 'timed out' are given a much longer timeout
     * period above, so we won't close them in the next call to
     * circuit_expire_building.) */
770
    if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)) {
771
772
773
774
775
776
777
778
      switch (victim->purpose) {
      case CIRCUIT_PURPOSE_C_REND_READY:
        /* We only want to spare a rend circ if it has been specified in
         * an INTRODUCE1 cell sent to a hidden service.  A circ's
         * pending_final_cpath field is non-NULL iff it is a rend circ
         * and we have tried to send an INTRODUCE1 cell specifying it.
         * Thus, if the pending_final_cpath field *is* NULL, then we
         * want to not spare it. */
779
780
        if (TO_ORIGIN_CIRCUIT(victim)->build_state &&
            TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
781
782
            NULL)
          break;
783
        FALLTHROUGH;
784
785
786
      case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
      case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
        /* If we have reached this line, we want to spare the circ for now. */
787
        log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) "
788
                 "as timed-out HS circ",
789
                 (unsigned)victim->n_circ_id,
790
791
792
793
794
795
796
797
798
                 victim->state, circuit_state_to_string(victim->state),
                 victim->purpose);
        TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1;
        continue;
      default:
        break;
      }
    }

799
800
801
    /* If this is a service-side rendezvous circuit which is far
     * enough along in connecting to its destination, consider sparing
     * it. */
802
    if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out) &&
803
        victim->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) {
804
      log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) "
805
               "as timed-out HS circ; relaunching rendezvous attempt.",
806
               (unsigned)victim->n_circ_id,
807
808
809
               victim->state, circuit_state_to_string(victim->state),
               victim->purpose);
      TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1;
810
      hs_circ_retry_service_rendezvous_point(TO_ORIGIN_CIRCUIT(victim));
811
812
813
      continue;
    }

814
    if (victim->n_chan)
Mike Perry's avatar
Mike Perry committed
815
      log_info(LD_CIRC,
816
               "Abandoning circ %u %s:%u (state %d,%d:%s, purpose %d, "
Mike Perry's avatar
Mike Perry committed
817
               "len %d)", TO_ORIGIN_CIRCUIT(victim)->global_identifier,
818
               channel_get_canonical_remote_descr(victim->n_chan),
819
               (unsigned)victim->n_circ_id,
Mike Perry's avatar
Mike Perry committed
820
               TO_ORIGIN_CIRCUIT(victim)->has_opened,
821
               victim->state, circuit_state_to_string(victim->state),
Mike Perry's avatar
Mike Perry committed
822
               victim->purpose,
823
824
825
               TO_ORIGIN_CIRCUIT(victim)->build_state ?
                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                 -1);
826
    else
Mike Perry's avatar
Mike Perry committed
827
      log_info(LD_CIRC,
828
               "Abandoning circ %u %u (state %d,%d:%s, purpose %d, len %d)",
Mike Perry's avatar
Mike Perry committed
829
               TO_ORIGIN_CIRCUIT(victim)->global_identifier,
830
831
               (unsigned)victim->n_circ_id,
               TO_ORIGIN_CIRCUIT(victim)->has_opened,
Mike Perry's avatar
Mike Perry committed
832
833
               victim->state,
               circuit_state_to_string(victim->state), victim->purpose,
834
835
836
               TO_ORIGIN_CIRCUIT(victim)->build_state ?
                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                 -1);
837

838
    circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
839
840
841
842
    if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
      circuit_mark_for_close(victim, END_CIRC_REASON_MEASUREMENT_EXPIRED);
    else
      circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT);
843
844

    pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim));
845
  } SMARTLIST_FOREACH_END(victim);
846
847
}

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
/**
 * Mark for close all circuits that start here, that were built through a
 * guard we weren't sure if we wanted to use, and that have been waiting
 * around for way too long.
 */
void
circuit_expire_waiting_for_better_guard(void)
{
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_origin_circuit_list(),
                          origin_circuit_t *, circ) {
    if (TO_CIRCUIT(circ)->marked_for_close)
      continue;
    if (circ->guard_state == NULL)
      continue;
    if (entry_guard_state_should_expire(circ->guard_state))
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NONE);
  } SMARTLIST_FOREACH_END(circ);
}

Nick Mathewson's avatar
Nick Mathewson committed
867
868
869
870
/** For debugging #8387: track when we last called
 * circuit_expire_old_circuits_clientside. */
static time_t last_expired_clientside_circuits = 0;

871
872
873
/**
 * As a diagnostic for bug 8387, log information about how many one-hop
 * circuits we have around that have been there for at least <b>age</b>
David Goulet's avatar
David Goulet committed
874
 * seconds. Log a few of them. Ignores Single Onion Service intro, it is
875
 * expected to be long-term one-hop circuits.
876
877
878
879
880
 */
void
circuit_log_ancient_one_hop_circuits(int age)
{
#define MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG 10
881
882
  time_t now = time(NULL);
  time_t cutoff = now - age;
883
884
  int n_found = 0;
  smartlist_t *log_these = smartlist_new();
885
  const or_options_t *options = get_options();
886

887
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
888
889
890
891
892
    const origin_circuit_t *ocirc;
    if (! CIRCUIT_IS_ORIGIN(circ))
      continue;
    if (circ->timestamp_created.tv_sec >= cutoff)
      continue;
893
    /* Single Onion Services deliberately make long term one-hop intro
894
     * and rendezvous connections. Don't log the established ones. */
895
    if (rend_service_allow_non_anonymous_connection(options) &&
896
897
        (circ->purpose == CIRCUIT_PURPOSE_S_INTRO ||
         circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED))
898
      continue;
899
900
901
902
903
904
905
906
907
    ocirc = CONST_TO_ORIGIN_CIRCUIT(circ);

    if (ocirc->build_state && ocirc->build_state->onehop_tunnel) {
      ++n_found;

      if (smartlist_len(log_these) < MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG)
        smartlist_add(log_these, (origin_circuit_t*) ocirc);
    }
  }
908
  SMARTLIST_FOREACH_END(circ);
909
910
911
912
913

  if (n_found == 0)
    goto done;

  log_notice(LD_HEARTBEAT,
914
915
             "Diagnostic for issue 8387: Found %d one-hop circuits more "
             "than %d seconds old! Logging %d...",
916
917
918
919
             n_found, age, smartlist_len(log_these));

  SMARTLIST_FOREACH_BEGIN(log_these, const origin_circuit_t *, ocirc) {
    char created[ISO_TIME_LEN+1];
920
921
922
    int stream_num;
    const edge_connection_t *conn;
    char *dirty = NULL;
923
    const circuit_t *circ = TO_CIRCUIT(ocirc);
924

925
    format_local_iso_time(created,
926
                          (time_t)circ->timestamp_created.tv_sec);
927

928
929
930
931
932
933
    if (circ->timestamp_dirty) {
      char dirty_since[ISO_TIME_LEN+1];
      format_local_iso_time(dirty_since, circ->timestamp_dirty);

      tor_asprintf(&dirty, "Dirty since %s (%ld seconds vs %ld-second cutoff)",
                   dirty_since, (long)(now - circ->timestamp_dirty),
934
                   (long) options->MaxCircuitDirtiness);
935
936
937
938
    } else {
      dirty = tor_strdup("Not marked dirty");
    }

939
    log_notice(LD_HEARTBEAT, "  #%d created at %s. %s, %s. %s for close. "
940
               "Package window: %d. "
941
               "%s for new conns. %s.",
942
943
944
945
946
               ocirc_sl_idx,
               created,
               circuit_state_to_string(circ->state),
               circuit_purpose_to_string(circ->purpose),
               circ->marked_for_close ? "Marked" : "Not marked",
947
               circ->package_window,
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
               ocirc->unusable_for_new_conns ? "Not usable" : "usable",
               dirty);
    tor_free(dirty);

    stream_num = 0;
    for (conn = ocirc->p_streams; conn; conn = conn->next_stream) {
      const connection_t *c = TO_CONN(conn);
      char stream_created[ISO_TIME_LEN+1];
      if (++stream_num >= 5)
        break;

      format_local_iso_time(stream_created, c->timestamp_created);

      log_notice(LD_HEARTBEAT, "     Stream#%d created at %s. "
                 "%s conn in state %s. "
963
964
                 "It is %slinked and %sreading from a linked connection %p. "
                 "Package window %d. "
965
966
967
968
969
970
                 "%s for close (%s:%d). Hold-open is %sset. "
                 "Has %ssent RELAY_END. %s on circuit.",
                 stream_num,
                 stream_created,
                 conn_type_to_string(c->type),
                 conn_state_to_string(c->type, c->state),
971
972
973
974
                 c->linked ? "" : "not ",
                 c->reading_from_linked_conn ? "": "not",
                 c->linked_conn,
                 conn->package_window,
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
                 c->marked_for_close ? "Marked" : "Not marked",
                 c->marked_for_close_file ? c->marked_for_close_file : "--",
                 c->marked_for_close,
                 c->hold_open_until_flushed ? "" : "not ",
                 conn->edge_has_sent_end ? "" : "not ",
                 conn->edge_blocked_on_circ ? "Blocked" : "Not blocked");
      if (! c->linked_conn)
        continue;

      c = c->linked_conn;

      log_notice(LD_HEARTBEAT, "        Linked to %s connection in state %s "
                 "(Purpose %d). %s for close (%s:%d). Hold-open is %sset. ",
                 conn_type_to_string(c->type),
                 conn_state_to_string(c->type, c->state),
                 c->purpose,
                 c->marked_for_close ? "Marked" : "Not marked",
                 c->marked_for_close_file ? c->marked_for_close_file : "--",
                 c->marked_for_close,
                 c->hold_open_until_flushed ? "" : "not ");
    }
996
997
  } SMARTLIST_FOREACH_END(ocirc);

Nick Mathewson's avatar
Nick Mathewson committed
998
999
1000
1001
  log_notice(LD_HEARTBEAT, "It has been %ld seconds since I last called "
             "circuit_expire_old_circuits_clientside().",
             (long)(now - last_expired_clientside_circuits));

1002
1003
1004
1005
 done:
  smartlist_free(log_these);
}

1006
1007
/** Remove any elements in <b>needed_ports</b> that are handled by an
 * open or in-progress circuit.
1008
 */
1009
void
1010
1011
circuit_remove_handled_ports(smartlist_t *needed_ports)
{
1012
  int i;
Roger Dingledine's avatar
Roger Dingledine committed
1013
  uint16_t *port;
1014
1015

  for (i = 0; i < smartlist_len(needed_ports); ++i) {
Roger Dingledine's avatar
Roger Dingledine committed
1016
1017
    port = smartlist_get(needed_ports, i);
    tor_assert(*port);
1018
1019
    if (circuit_stream_is_being_handled(NULL, *port,
                                        MIN_CIRCUITS_HANDLING_STREAM)) {
1020
      log_debug(LD_CIRC,"Port %d is already being handled; removing.", *port);
1021
      smartlist_del(needed_ports, i--);
Roger Dingledine's avatar
Roger Dingledine committed
1022
      tor_free(port);
1023
    } else {
1024
      log_debug(LD_CIRC,"Port %d is not handled.", *port);
1025
1026
1027
    }
  }
}
1028

1029
1030
1031
/** Return 1 if at least <b>min</b> general-purpose non-internal circuits
 * will have an acceptable exit node for exit stream <b>conn</b> if it
 * is defined, else for "*:port".
1032
 * Else return 0.
1033
 */
1034
int
1035
circuit_stream_is_being_handled(entry_connection_t *conn,
1036
                                uint16_t port, int min)
1037
{
1038
  const node_t *exitnode;
1039
1040
  int num=0;