connection.c 32.4 KB
Newer Older
1
/* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
2
3
/* See LICENSE for licensing information */
/* $Id$ */
Roger Dingledine's avatar
Roger Dingledine committed
4
5
6
7
8

#include "or.h"

/********* START VARIABLES **********/

9
10
extern or_options_t options; /* command-line and config-file options */

Roger Dingledine's avatar
Roger Dingledine committed
11
char *conn_type_to_string[] = {
12
13
14
15
16
17
18
  "",            /* 0 */
  "OP listener", /* 1 */
  "OP",          /* 2 */
  "OR listener", /* 3 */
  "OR",          /* 4 */
  "Exit",        /* 5 */
  "App listener",/* 6 */
19
20
21
  "App",         /* 7 */
  "Dir listener",/* 8 */
  "Dir",         /* 9 */
Roger Dingledine's avatar
Roger Dingledine committed
22
23
  "DNS worker",  /* 10 */
  "CPU worker",  /* 11 */
Roger Dingledine's avatar
Roger Dingledine committed
24
25
};

26
char *conn_state_to_string[][_CONN_TYPE_MAX+1] = {
27
28
29
  { NULL }, /* no type associated with 0 */
  { NULL }, /* op listener, obsolete */
  { NULL }, /* op, obsolete */
Roger Dingledine's avatar
Roger Dingledine committed
30
  { "ready" }, /* or listener, 0 */
31
32
33
34
35
36
37
  { "",                         /* OR, 0 */
    "connect()ing",                 /* 1 */
    "handshaking",                  /* 2 */
    "open" },                       /* 3 */
  { "",                          /* exit, 0 */
    "waiting for dest info",           /* 1 */
    "connecting",                      /* 2 */
38
    "open",                            /* 3 */
39
    "resolve failed" },                /* 4 */
40
  { "ready" }, /* app listener, 0 */
41
42
43
  { "", /* 0 */
    "", /* 1 */
    "", /* 2 */
44
    "", /* 3 */
45
46
    "", /* 4 */
    "awaiting dest info",         /* app, 5 */
47
48
49
50
    "waiting for rendezvous desc",     /* 6 */
    "waiting for safe circuit",        /* 7 */
    "waiting for connected",           /* 8 */
    "open" },                          /* 9 */
51
  { "ready" }, /* dir listener, 0 */
52
  { "",                           /* dir, 0 */
Roger Dingledine's avatar
Roger Dingledine committed
53
54
55
56
57
    "connecting",                      /* 1 */
    "client sending",                  /* 2 */
    "client reading",                  /* 3 */
    "awaiting command",                /* 4 */
    "writing" },                       /* 5 */
58
59
60
61
62
63
64
  { "",                    /* dns worker, 0 */
    "idle",                            /* 1 */
    "busy" },                          /* 2 */
  { "",                    /* cpu worker, 0 */
    "idle",                            /* 1 */
    "busy with onion",                 /* 2 */
    "busy with handshake" },           /* 3 */
Roger Dingledine's avatar
Roger Dingledine committed
65
66
67
68
};

/********* END VARIABLES ************/

69
static int connection_init_accepted_conn(connection_t *conn);
Nick Mathewson's avatar
Nick Mathewson committed
70
static int connection_handle_listener_read(connection_t *conn, int new_type);
71
static int connection_receiver_bucket_should_increase(connection_t *conn);
72
73
74

/**************************************************************/

Roger Dingledine's avatar
Roger Dingledine committed
75
76
connection_t *connection_new(int type) {
  connection_t *conn;
77
  time_t now = time(NULL);
Roger Dingledine's avatar
Roger Dingledine committed
78

79
  conn = tor_malloc_zero(sizeof(connection_t));
80
  conn->magic = CONNECTION_MAGIC;
81
  conn->s = -1; /* give it a default of 'not used' */
Roger Dingledine's avatar
Roger Dingledine committed
82
83

  conn->type = type;
84
85
86
87
  if(!connection_is_listener(conn)) { /* listeners never use their buf */
    conn->inbuf = buf_new();
    conn->outbuf = buf_new();
  }
88
  if (type == CONN_TYPE_AP) {
89
    conn->socks_request = tor_malloc_zero(sizeof(socks_request_t));
90
  }
Roger Dingledine's avatar
Roger Dingledine committed
91

92
93
  conn->next_circ_id = crypto_pseudo_rand_int(1<<15);

94
95
96
  conn->timestamp_created = now;
  conn->timestamp_lastread = now;
  conn->timestamp_lastwritten = now;
97

Roger Dingledine's avatar
Roger Dingledine committed
98
99
100
101
  return conn;
}

void connection_free(connection_t *conn) {
Roger Dingledine's avatar
Roger Dingledine committed
102
103
  tor_assert(conn);
  tor_assert(conn->magic == CONNECTION_MAGIC);
Roger Dingledine's avatar
Roger Dingledine committed
104

105
106
107
108
  if(!connection_is_listener(conn)) {
    buf_free(conn->inbuf);
    buf_free(conn->outbuf);
  }
109
  tor_free(conn->address);
Roger Dingledine's avatar
Roger Dingledine committed
110

111
  if(connection_speaks_cells(conn)) {
112
    directory_set_dirty();
Roger Dingledine's avatar
Roger Dingledine committed
113
114
    if (conn->tls)
      tor_tls_free(conn->tls);
Roger Dingledine's avatar
Roger Dingledine committed
115
116
  }

117
118
  if (conn->identity_pkey)
    crypto_free_pk_env(conn->identity_pkey);
119
  tor_free(conn->nickname);
120
  tor_free(conn->socks_request);
121

122
  if(conn->s >= 0) {
123
    log_fn(LOG_INFO,"closing fd %d.",conn->s);
Roger Dingledine's avatar
Roger Dingledine committed
124
    close(conn->s);
125
  }
126
  memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */
Roger Dingledine's avatar
Roger Dingledine committed
127
128
129
  free(conn);
}

130
131
132
133
134
135
136
137
138
void connection_free_all(void) {
  int i, n;
  connection_t **carray;

  get_connection_array(&carray,&n);
  for(i=0;i<n;i++)
    connection_free(carray[i]);
}

139
/* Close the underlying socket for conn, so we don't try to flush it.
Roger Dingledine's avatar
Roger Dingledine committed
140
 * Must be used in conjunction with (right before) connection_mark_for_close
141
142
143
144
145
146
147
148
 */
void connection_close_immediate(connection_t *conn)
{
  assert_connection_ok(conn,0);
  if (conn->s < 0) {
    log_fn(LOG_WARN,"Attempt to close already-closed connection.");
    return;
  }
149
  if (conn->outbuf_flushlen) {
150
151
    log_fn(LOG_INFO,"Closing connection (fd %d, type %s, state %d) with data on outbuf.",
           conn->s, CONN_TYPE_TO_STRING(conn->type), conn->state);
152
  }
153
154
  close(conn->s);
  conn->s = -1;
155
156
157
158
  if(!connection_is_listener(conn)) {
    buf_clear(conn->outbuf);
    conn->outbuf_flushlen = 0;
  }
159
160
}

161
162
163
int
_connection_mark_for_close(connection_t *conn, char reason)
{
164
  int retval = 0;
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  assert_connection_ok(conn,0);

  if (conn->marked_for_close) {
    log(LOG_WARN, "Double mark-for-close on connection.");
    return -1;
  }

  switch (conn->type)
    {
    case CONN_TYPE_OR_LISTENER:
    case CONN_TYPE_AP_LISTENER:
    case CONN_TYPE_DIR_LISTENER:
    case CONN_TYPE_CPUWORKER:
      /* No special processing needed. */
      break;
180
181
182
183
    case CONN_TYPE_DIR:
      if(conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
        rend_client_desc_fetched(conn->rend_query, 0);
      break;
184
    case CONN_TYPE_OR:
185
186
      /* Remember why we're closing this connection. */
      if (conn->state != OR_CONN_STATE_OPEN) {
187
188
189
190
191
        /* XXX Nick: this still isn't right, because it might be
         * dying even though we didn't initiate the connect. Can
         * you look at this more? -RD */
        if(conn->nickname)
          rep_hist_note_connect_failed(conn->nickname, time(NULL));
192
193
194
195
196
197
      } else if (reason == CLOSE_REASON_UNUSED_OR_CONN) {
        rep_hist_note_disconnect(conn->nickname, time(NULL));
      } else {
        rep_hist_note_connection_died(conn->nickname, time(NULL));
      }
      /* No special processing needed. */
198
199
      break;
    case CONN_TYPE_AP:
Roger Dingledine's avatar
Roger Dingledine committed
200
201
202
203
      if (conn->socks_request->has_finished == 0) {
        log_fn(LOG_INFO,"Cleaning up AP -- sending socks reject.");
        connection_ap_handshake_socks_reply(conn, NULL, 0, 0);
        conn->socks_request->has_finished = 1;
204
        conn->hold_open_until_flushed = 1;
Roger Dingledine's avatar
Roger Dingledine committed
205
206
207
      }
      /* fall through, to do things for both ap and exit */
    case CONN_TYPE_EXIT:
208
      if (conn->state == EXIT_CONN_STATE_RESOLVING)
209
        connection_dns_remove(conn);
210
      if (!conn->has_sent_end && reason &&
211
          connection_edge_end(conn, reason, conn->cpath_layer) < 0)
212
        retval = -1;
213
214
215
      break;
    case CONN_TYPE_DNSWORKER:
      if (conn->state == DNSWORKER_STATE_BUSY) {
216
        dns_cancel_pending_resolve(conn->address);
217
218
219
220
221
222
223
      }
      break;
    default:
      log(LOG_ERR, "Unknown connection type %d", conn->type);
      ;
    }
  conn->marked_for_close = 1;
224
225
226
227
228
229

  /* in case we're going to be held-open-til-flushed, reset
   * the number of seconds since last successful write, so
   * we get our whole 15 seconds */
  conn->timestamp_lastwritten = time(NULL);

230
  return retval;
231
232
}

233
234
235
236
237
238
239
240
241
242
243
244
245
246
void connection_expire_held_open(void)
{
  connection_t **carray, *conn;
  int n, i;
  time_t now;

  now = time(NULL);

  get_connection_array(&carray, &n);
  for (i = 0; i < n; ++i) {
    conn = carray[i];
    /* If we've been holding the connection open, but we haven't written
     * for 15 seconds...
     */
247
    if (conn->hold_open_until_flushed) {
Roger Dingledine's avatar
Roger Dingledine committed
248
      tor_assert(conn->marked_for_close);
249
      if (now - conn->timestamp_lastwritten >= 15) {
250
        log_fn(LOG_WARN,"Giving up on marked_for_close conn that's been flushing for 15s (fd %d, type %s, state %d).",
Roger Dingledine's avatar
Roger Dingledine committed
251
               conn->s, CONN_TYPE_TO_STRING(conn->type), conn->state);
252
253
        conn->hold_open_until_flushed = 0;
      }
254
255
256
257
    }
  }
}

258
259
260
int connection_create_listener(char *bindaddress, uint16_t bindport, int type) {
  struct sockaddr_in bindaddr; /* where to bind */
  struct hostent *rent;
Roger Dingledine's avatar
Roger Dingledine committed
261
  connection_t *conn;
262
  int s; /* the socket we're going to make */
Roger Dingledine's avatar
Roger Dingledine committed
263
264
  int one=1;

265
266
267
268
269
270
271
272
273
274
275
276
  memset(&bindaddr,0,sizeof(struct sockaddr_in));
  bindaddr.sin_family = AF_INET;
  bindaddr.sin_port = htons(bindport);
  rent = gethostbyname(bindaddress);
  if (!rent) {
    log_fn(LOG_WARN,"Can't resolve BindAddress %s",bindaddress);
    return -1;
  }
  if(rent->h_length != 4)
    return -1; /* XXX complain */
  memcpy(&(bindaddr.sin_addr.s_addr),rent->h_addr,rent->h_length);

Roger Dingledine's avatar
Roger Dingledine committed
277
  s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
Roger Dingledine's avatar
Roger Dingledine committed
278
  if (s < 0) {
Roger Dingledine's avatar
Roger Dingledine committed
279
    log_fn(LOG_WARN,"Socket creation failed.");
Roger Dingledine's avatar
Roger Dingledine committed
280
281
282
    return -1;
  }

283
  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one));
Roger Dingledine's avatar
Roger Dingledine committed
284

285
286
  if(bind(s,(struct sockaddr *)&bindaddr,sizeof(bindaddr)) < 0) {
    log_fn(LOG_WARN,"Could not bind to port %u: %s",bindport,strerror(errno));
Roger Dingledine's avatar
Roger Dingledine committed
287
288
289
290
    return -1;
  }

  if(listen(s,SOMAXCONN) < 0) {
291
    log_fn(LOG_WARN,"Could not listen on port %u: %s",bindport,strerror(errno));
Roger Dingledine's avatar
Roger Dingledine committed
292
293
294
    return -1;
  }

295
  set_socket_nonblocking(s);
Roger Dingledine's avatar
Roger Dingledine committed
296
297
298
299
300

  conn = connection_new(type);
  conn->s = s;

  if(connection_add(conn) < 0) { /* no space, forget it */
Roger Dingledine's avatar
Roger Dingledine committed
301
    log_fn(LOG_WARN,"connection_add failed. Giving up.");
Roger Dingledine's avatar
Roger Dingledine committed
302
303
304
305
    connection_free(conn);
    return -1;
  }

306
  log_fn(LOG_DEBUG,"%s listening on port %u.",conn_type_to_string[type], bindport);
Roger Dingledine's avatar
Roger Dingledine committed
307
308

  conn->state = LISTENER_STATE_READY;
309
  connection_start_reading(conn);
Roger Dingledine's avatar
Roger Dingledine committed
310
311
312
313

  return 0;
}

Nick Mathewson's avatar
Nick Mathewson committed
314
static int connection_handle_listener_read(connection_t *conn, int new_type) {
Roger Dingledine's avatar
Roger Dingledine committed
315
316
317
318
  int news; /* the new socket */
  connection_t *newconn;
  struct sockaddr_in remote; /* information about the remote peer when connecting to other routers */
  int remotelen = sizeof(struct sockaddr_in); /* length of the remote address */
319
320
321
#ifdef MS_WINDOWS
  int e;
#endif
Roger Dingledine's avatar
Roger Dingledine committed
322
323
324

  news = accept(conn->s,(struct sockaddr *)&remote,&remotelen);
  if (news == -1) { /* accept() error */
325
326
327
328
329
330
    if(ERRNO_EAGAIN(errno)) {
#ifdef MS_WINDOWS
      e = correct_socket_errno(conn->s);
      if (ERRNO_EAGAIN(e))
        return 0;
#else
Roger Dingledine's avatar
Roger Dingledine committed
331
      return 0; /* he hung up before we could accept(). that's fine. */
332
333
#endif
    }
Roger Dingledine's avatar
Roger Dingledine committed
334
    /* else there was a real error. */
Roger Dingledine's avatar
Roger Dingledine committed
335
    log_fn(LOG_WARN,"accept() failed. Closing listener.");
336
    connection_mark_for_close(conn,0);
Roger Dingledine's avatar
Roger Dingledine committed
337
338
    return -1;
  }
339
  log(LOG_INFO,"Connection accepted on socket %d (child of fd %d).",news, conn->s);
Roger Dingledine's avatar
Roger Dingledine committed
340

341
  set_socket_nonblocking(news);
342

Roger Dingledine's avatar
Roger Dingledine committed
343
344
345
  newconn = connection_new(new_type);
  newconn->s = news;

346
  newconn->address = tor_strdup(inet_ntoa(remote.sin_addr)); /* remember the remote address */
347
348
  newconn->addr = ntohl(remote.sin_addr.s_addr);
  newconn->port = ntohs(remote.sin_port);
Roger Dingledine's avatar
Roger Dingledine committed
349
350
351

  if(connection_add(newconn) < 0) { /* no space, forget it */
    connection_free(newconn);
352
    return 0; /* no need to tear down the parent */
Roger Dingledine's avatar
Roger Dingledine committed
353
354
  }

355
  if(connection_init_accepted_conn(newconn) < 0) {
356
    connection_mark_for_close(newconn,0);
357
358
359
360
361
362
363
364
365
366
367
    return 0;
  }
  return 0;
}

static int connection_init_accepted_conn(connection_t *conn) {

  connection_start_reading(conn);

  switch(conn->type) {
    case CONN_TYPE_OR:
368
      return connection_tls_start_handshake(conn, 1);
369
370
371
372
    case CONN_TYPE_AP:
      conn->state = AP_CONN_STATE_SOCKS_WAIT;
      break;
    case CONN_TYPE_DIR:
Roger Dingledine's avatar
Roger Dingledine committed
373
      conn->purpose = DIR_PURPOSE_SERVER;
374
      conn->state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
375
376
377
378
379
      break;
  }
  return 0;
}

Roger Dingledine's avatar
Roger Dingledine committed
380
/* take conn, make a nonblocking socket; try to connect to
381
382
383
384
385
386
387
388
389
390
 * addr:port (they arrive in *host order*). If fail, return -1. Else
 * assign s to conn->s: if connected return 1, if eagain return 0.
 * address is used to make the logs useful.
 */
int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_t port) {
  int s;
  struct sockaddr_in dest_addr;

  s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  if (s < 0) {
Roger Dingledine's avatar
Roger Dingledine committed
391
    log_fn(LOG_WARN,"Error creating network socket.");
392
393
394
395
    return -1;
  }
  set_socket_nonblocking(s);

396
  memset(&dest_addr,0,sizeof(dest_addr));
397
398
399
400
401
402
403
404
405
  dest_addr.sin_family = AF_INET;
  dest_addr.sin_port = htons(port);
  dest_addr.sin_addr.s_addr = htonl(addr);

  log_fn(LOG_DEBUG,"Connecting to %s:%u.",address,port);

  if(connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) {
    if(!ERRNO_CONN_EINPROGRESS(errno)) {
      /* yuck. kill it. */
406
      log_fn(LOG_INFO,"Connect() to %s:%u failed: %s",address,port,strerror(errno));
407
      close(s);
408
409
410
411
412
413
414
415
416
417
      return -1;
    } else {
      /* it's in progress. set state appropriately and return. */
      conn->s = s;
      log_fn(LOG_DEBUG,"connect in progress, socket %d.",s);
      return 0;
    }
  }

  /* it succeeded. we're connected. */
418
  log_fn(LOG_INFO,"Connection to %s:%u established.",address,port);
419
420
421
422
  conn->s = s;
  return 1;
}

423
static void listener_close_if_present(int type) {
424
  connection_t *conn;
Roger Dingledine's avatar
Roger Dingledine committed
425
426
427
  tor_assert(type == CONN_TYPE_OR_LISTENER ||
             type == CONN_TYPE_AP_LISTENER ||
             type == CONN_TYPE_DIR_LISTENER);
428
  conn = connection_get_by_type(type);
429
  if (conn) {
430
    connection_close_immediate(conn);
431
    connection_mark_for_close(conn,0);
432
433
434
  }
}

Roger Dingledine's avatar
Roger Dingledine committed
435
/* start all connections that should be up but aren't */
436
int retry_all_connections(void) {
437

438
  if(options.ORPort) {
439
    router_retry_connections();
Roger Dingledine's avatar
Roger Dingledine committed
440
441
  }

442
443
  if(options.ORPort) {
    listener_close_if_present(CONN_TYPE_OR_LISTENER);
Roger Dingledine's avatar
Roger Dingledine committed
444
445
    if(connection_create_listener(options.ORBindAddress,
                                  (uint16_t) options.ORPort,
446
447
                                  CONN_TYPE_OR_LISTENER) < 0)
      return -1;
Roger Dingledine's avatar
Roger Dingledine committed
448
  }
449

450
451
  if(options.DirPort) {
    listener_close_if_present(CONN_TYPE_DIR_LISTENER);
452
    if(connection_create_listener(options.DirBindAddress,
Roger Dingledine's avatar
Roger Dingledine committed
453
                                  (uint16_t) options.DirPort,
454
455
                                  CONN_TYPE_DIR_LISTENER) < 0)
      return -1;
456
  }
457
458
459

  if(options.SocksPort) {
    listener_close_if_present(CONN_TYPE_AP_LISTENER);
460
    if(connection_create_listener(options.SocksBindAddress,
Roger Dingledine's avatar
Roger Dingledine committed
461
                                  (uint16_t) options.SocksPort,
462
463
                                  CONN_TYPE_AP_LISTENER) < 0)
      return -1;
464
465
  }

Roger Dingledine's avatar
Roger Dingledine committed
466
467
468
  return 0;
}

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
extern int global_read_bucket;

/* how many bytes at most can we read onto this connection? */
int connection_bucket_read_limit(connection_t *conn) {
  int at_most;

  if(options.LinkPadding) {
    at_most = global_read_bucket;
  } else {
    /* do a rudimentary round-robin so one circuit can't hog a connection */
    if(connection_speaks_cells(conn)) {
      at_most = 32*(CELL_NETWORK_SIZE);
    } else {
      at_most = 32*(RELAY_PAYLOAD_SIZE);
    }

    if(at_most > global_read_bucket)
      at_most = global_read_bucket;
  }

  if(connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN)
    if(at_most > conn->receiver_bucket)
      at_most = conn->receiver_bucket;

  return at_most;
}

/* we just read num_read onto conn. Decrement buckets appropriately. */
void connection_bucket_decrement(connection_t *conn, int num_read) {
Roger Dingledine's avatar
Roger Dingledine committed
498
  global_read_bucket -= num_read; tor_assert(global_read_bucket >= 0);
499
  if(connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) {
Roger Dingledine's avatar
Roger Dingledine committed
500
    conn->receiver_bucket -= num_read; tor_assert(conn->receiver_bucket >= 0);
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  }
  if(global_read_bucket == 0) {
    log_fn(LOG_DEBUG,"global bucket exhausted. Pausing.");
    conn->wants_to_read = 1;
    connection_stop_reading(conn);
    return;
  }
  if(connection_speaks_cells(conn) &&
     conn->state == OR_CONN_STATE_OPEN &&
     conn->receiver_bucket == 0) {
      log_fn(LOG_DEBUG,"receiver bucket exhausted. Pausing.");
      conn->wants_to_read = 1;
      connection_stop_reading(conn);
  }
}

/* keep a timeval to know when time has passed enough to refill buckets */
static struct timeval current_time;

520
void connection_bucket_init(void) {
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
  tor_gettimeofday(&current_time);
  global_read_bucket = options.BandwidthBurst; /* start it at max traffic */
}

/* some time has passed; increment buckets appropriately. */
void connection_bucket_refill(struct timeval *now) {
  int i, n;
  connection_t *conn;
  connection_t **carray;

  if(now->tv_sec <= current_time.tv_sec)
    return; /* wait until the second has rolled over */

  current_time.tv_sec = now->tv_sec; /* update current_time */
  /* (ignore usecs for now) */

  /* refill the global bucket */
  if(global_read_bucket < options.BandwidthBurst) {
    global_read_bucket += options.BandwidthRate;
    log_fn(LOG_DEBUG,"global_read_bucket now %d.", global_read_bucket);
  }

  /* refill the per-connection buckets */
  get_connection_array(&carray,&n);
  for(i=0;i<n;i++) {
    conn = carray[i];

    if(connection_receiver_bucket_should_increase(conn)) {
      conn->receiver_bucket += conn->bandwidth;
      //log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, conn->receiver_bucket);
    }

    if(conn->wants_to_read == 1 /* it's marked to turn reading back on now */
       && global_read_bucket > 0 /* and we're allowed to read */
       && (!connection_speaks_cells(conn) ||
           conn->state != OR_CONN_STATE_OPEN ||
           conn->receiver_bucket > 0)) {
      /* and either a non-cell conn or a cell conn with non-empty bucket */
559
      log_fn(LOG_DEBUG,"waking up conn (fd %d)",conn->s);
560
561
562
563
564
565
566
567
568
569
570
      conn->wants_to_read = 0;
      connection_start_reading(conn);
      if(conn->wants_to_write == 1) {
        conn->wants_to_write = 0;
        connection_start_writing(conn);
      }
    }
  }
}

static int connection_receiver_bucket_should_increase(connection_t *conn) {
Roger Dingledine's avatar
Roger Dingledine committed
571
  tor_assert(conn);
572
573
574
575
576
577

  if(!connection_speaks_cells(conn))
    return 0; /* edge connections don't use receiver_buckets */
  if(conn->state != OR_CONN_STATE_OPEN)
    return 0; /* only open connections play the rate limiting game */

Roger Dingledine's avatar
Roger Dingledine committed
578
  tor_assert(conn->bandwidth > 0);
579
580
581
582
583
584
  if(conn->receiver_bucket > 9*conn->bandwidth)
    return 0;

  return 1;
}

585
586
int connection_handle_read(connection_t *conn) {

587
  conn->timestamp_lastread = time(NULL);
588
589
590

  switch(conn->type) {
    case CONN_TYPE_OR_LISTENER:
591
      return connection_handle_listener_read(conn, CONN_TYPE_OR);
592
    case CONN_TYPE_AP_LISTENER:
593
      return connection_handle_listener_read(conn, CONN_TYPE_AP);
594
    case CONN_TYPE_DIR_LISTENER:
595
596
      return connection_handle_listener_read(conn, CONN_TYPE_DIR);
  }
597

598
  if(connection_read_to_buf(conn) < 0) {
Roger Dingledine's avatar
Roger Dingledine committed
599
    if(conn->type == CONN_TYPE_DIR &&
Roger Dingledine's avatar
Roger Dingledine committed
600
       conn->state == DIR_CONN_STATE_CONNECTING) {
601
602
       /* it's a directory server and connecting failed: forget about this router */
       /* XXX I suspect pollerr may make Windows not get to this point. :( */
603
       router_mark_as_down(conn->nickname);
604
    }
605
    /* There's a read error; kill the connection.*/
606
    connection_close_immediate(conn); /* Don't flush; connection is dead. */
607
    connection_mark_for_close(conn, END_STREAM_REASON_MISC);
608
609
610
    return -1;
  }
  if(connection_process_inbuf(conn) < 0) {
611
//    log_fn(LOG_DEBUG,"connection_process_inbuf returned -1.");
612
613
    return -1;
  }
Roger Dingledine's avatar
Roger Dingledine committed
614
  return 0;
615
616
}

Roger Dingledine's avatar
Roger Dingledine committed
617
/* return -1 if we want to break conn, else return 0 */
Roger Dingledine's avatar
Roger Dingledine committed
618
int connection_read_to_buf(connection_t *conn) {
Roger Dingledine's avatar
Roger Dingledine committed
619
  int result;
Roger Dingledine's avatar
Roger Dingledine committed
620
  int at_most;
621

622
623
  /* how many bytes are we allowed to read? */
  at_most = connection_bucket_read_limit(conn);
624

Roger Dingledine's avatar
Roger Dingledine committed
625
  if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) {
626
627
    if(conn->state == OR_CONN_STATE_HANDSHAKING) {
      /* continue handshaking even if global token bucket is empty */
628
      return connection_tls_continue_handshake(conn);
629
    }
630
631

    /* else open, or closing */
632
    result = read_to_buf_tls(conn->tls, at_most, conn->inbuf);
Roger Dingledine's avatar
Roger Dingledine committed
633
634
635
636

    switch(result) {
      case TOR_TLS_ERROR:
      case TOR_TLS_CLOSE:
637
        log_fn(LOG_INFO,"tls error. breaking.");
Roger Dingledine's avatar
Roger Dingledine committed
638
        return -1; /* XXX deal with close better */
639
      case TOR_TLS_WANTWRITE:
Roger Dingledine's avatar
Roger Dingledine committed
640
641
        connection_start_writing(conn);
        return 0;
642
      case TOR_TLS_WANTREAD: /* we're already reading */
Roger Dingledine's avatar
Roger Dingledine committed
643
      case TOR_TLS_DONE: /* no data read, so nothing to process */
644
645
        result = 0;
        break; /* so we call bucket_decrement below */
646
    }
647
  } else {
648
649
650
    result = read_to_buf(conn->s, at_most, conn->inbuf,
                         &conn->inbuf_reached_eof);

Roger Dingledine's avatar
Roger Dingledine committed
651
652
653
654
//  log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);

    if(result < 0)
      return -1;
655
656
  }

657
  connection_bucket_decrement(conn, result);
Roger Dingledine's avatar
Roger Dingledine committed
658
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
659
660
661
}

int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
662
  return fetch_from_buf(string, len, conn->inbuf);
Roger Dingledine's avatar
Roger Dingledine committed
663
664
}

665
int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
666
  return find_on_inbuf(string, len, conn->inbuf);
667
668
}

669
670
671
672
673
674
675
676
int connection_wants_to_flush(connection_t *conn) {
  return conn->outbuf_flushlen;
}

int connection_outbuf_too_full(connection_t *conn) {
  return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE);
}

Roger Dingledine's avatar
Roger Dingledine committed
677
/* return -1 if you want to break the conn, else return 0 */
678
679
int connection_handle_write(connection_t *conn) {

Roger Dingledine's avatar
Roger Dingledine committed
680
  tor_assert(!connection_is_listener(conn));
681

682
  conn->timestamp_lastwritten = time(NULL);
683

684
685
686
  if (connection_speaks_cells(conn) &&
      conn->state != OR_CONN_STATE_CONNECTING) {
    if (conn->state == OR_CONN_STATE_HANDSHAKING) {
687
      connection_stop_writing(conn);
688
689
690
691
692
693
      if(connection_tls_continue_handshake(conn) < 0) {
        connection_close_immediate(conn); /* Don't flush; connection is dead. */
        connection_mark_for_close(conn, 0);
        return -1;
      }
      return 0;
694
    }
695

696
    /* else open, or closing */
697
    switch(flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen)) {
Roger Dingledine's avatar
Roger Dingledine committed
698
699
      case TOR_TLS_ERROR:
      case TOR_TLS_CLOSE:
700
        log_fn(LOG_INFO,"tls error. breaking.");
701
        connection_close_immediate(conn); /* Don't flush; connection is dead. */
702
        connection_mark_for_close(conn, 0);
Roger Dingledine's avatar
Roger Dingledine committed
703
        return -1; /* XXX deal with close better */
704
      case TOR_TLS_WANTWRITE:
705
        log_fn(LOG_DEBUG,"wanted write.");
Roger Dingledine's avatar
Roger Dingledine committed
706
707
        /* we're already writing */
        return 0;
708
      case TOR_TLS_WANTREAD:
Roger Dingledine's avatar
Roger Dingledine committed
709
        /* Make sure to avoid a loop if the receive buckets are empty. */
710
        log_fn(LOG_DEBUG,"wanted read.");
Roger Dingledine's avatar
Roger Dingledine committed
711
712
713
714
715
716
717
718
719
        if(!connection_is_reading(conn)) {
          connection_stop_writing(conn);
          conn->wants_to_write = 1;
          /* we'll start reading again when the next second arrives,
           * and then also start writing again.
           */
        }
        /* else no problem, we're already reading */
        return 0;
720
721
      /* case TOR_TLS_DONE:
       * for TOR_TLS_DONE, fall through to check if the flushlen
Roger Dingledine's avatar
Roger Dingledine committed
722
       * is empty, so we can stop writing.
Roger Dingledine's avatar
Roger Dingledine committed
723
       */
Roger Dingledine's avatar
Roger Dingledine committed
724
    }
725
  } else {
726
    if (flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen) < 0) {
727
      connection_close_immediate(conn); /* Don't flush; connection is dead. */
728
      connection_mark_for_close(conn, END_STREAM_REASON_MISC);
Roger Dingledine's avatar
Roger Dingledine committed
729
      return -1;
730
    }
Roger Dingledine's avatar
Roger Dingledine committed
731
    /* conns in CONNECTING state will fall through... */
732
733
  }

Roger Dingledine's avatar
Roger Dingledine committed
734
735
736
737
738
  if(!connection_wants_to_flush(conn)) /* it's done flushing */
    if(connection_finished_flushing(conn) < 0) /* ...and get handled here. */
      return -1;

  return 0;
739
740
}

741
void connection_write_to_buf(const char *string, int len, connection_t *conn) {
742

743
744
  if(!len || conn->marked_for_close)
    return;
745

746
  if(write_to_buf(string, len, conn->outbuf) < 0) {
Roger Dingledine's avatar
Roger Dingledine committed
747
    log_fn(LOG_WARN,"write_to_buf failed. Closing connection (fd %d).", conn->s);
748
    connection_mark_for_close(conn,0);
749
    return;
750
  }
751
752

  connection_start_writing(conn);
753
#define MIN_TLS_FLUSHLEN 15872
754
755
756
757
/* openssl tls record size is 16383, this is close. The goal here is to
 * push data out as soon as we know there's enough for a tls record, so
 * during periods of high load we won't read the entire megabyte from
 * input before pushing any data out. */
758
759
  if(connection_speaks_cells(conn) &&
     conn->outbuf_flushlen < MIN_TLS_FLUSHLEN &&
760
761
762
763
764
     conn->outbuf_flushlen+len >= MIN_TLS_FLUSHLEN) {
    len -= (MIN_TLS_FLUSHLEN - conn->outbuf_flushlen);
    conn->outbuf_flushlen = MIN_TLS_FLUSHLEN;
    if(connection_handle_write(conn) < 0) {
      log_fn(LOG_WARN,"flushing failed.");
765
      connection_mark_for_close(conn,0);
766
767
    }
  }
768
769
770
771
772
  if(len > 0) { /* if there's any left over */
    conn->outbuf_flushlen += len;
    connection_start_writing(conn);
    /* because connection_handle_write() above might have stopped writing */
  }
Roger Dingledine's avatar
Roger Dingledine committed
773
774
}

775
/* get the conn to addr/port that has the most recent timestamp_created */
776
777
connection_t *connection_exact_get_by_addr_port(uint32_t addr, uint16_t port) {
  int i, n;
778
  connection_t *conn, *best=NULL;
779
  connection_t **carray;
Roger Dingledine's avatar
Roger Dingledine committed
780

781
782
783
  get_connection_array(&carray,&n);
  for(i=0;i<n;i++) {
    conn = carray[i];
784
785
786
    if(conn->addr == addr && conn->port == port && !conn->marked_for_close &&
       (!best || best->timestamp_created < conn->timestamp_created))
      best = conn;
787
  }
788
  return best;
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
}

connection_t *connection_twin_get_by_addr_port(uint32_t addr, uint16_t port) {
  /* Find a connection to the router described by addr and port,
   *   or alternately any router which knows its key.
   * This connection *must* be in 'open' state.
   * If not, return NULL.
   */
  int i, n;
  connection_t *conn;
  routerinfo_t *router;
  connection_t **carray;

  /* first check if it's there exactly */
  conn = connection_exact_get_by_addr_port(addr,port);
  if(conn && connection_state_is_open(conn)) {
805
    log(LOG_DEBUG,"connection_twin_get_by_addr_port(): Found exact match.");
806
807
    return conn;
  }
Roger Dingledine's avatar
Roger Dingledine committed
808

809
  /* now check if any of the other open connections are a twin for this one */
Roger Dingledine's avatar
Roger Dingledine committed
810

811
812
813
  router = router_get_by_addr_port(addr,port);
  if(!router)
    return NULL;
Roger Dingledine's avatar
Roger Dingledine committed
814

815
816
817
  get_connection_array(&carray,&n);
  for(i=0;i<n;i++) {
    conn = carray[i];
Roger Dingledine's avatar
Roger Dingledine committed
818
    tor_assert(conn);
819
    if(connection_state_is_open(conn) &&
820
       !crypto_pk_cmp_keys(conn->identity_pkey, router->identity_pkey)) {
821
      log(LOG_DEBUG,"connection_twin_get_by_addr_port(): Found twin (%s).",conn->address);
822
823
824
825
826
827
828
829
830
831
      return conn;
    }
  }
  return NULL;
}

connection_t *connection_get_by_type(int type) {
  int i, n;
  connection_t *conn;
  connection_t **carray;
Roger Dingledine's avatar
Roger Dingledine committed
832

833
834
835
836
837
838
839
840
841
842
843
844
845
  get_connection_array(&carray,&n);
  for(i=0;i<n;i++) {
    conn = carray[i];
    if(conn->type == type && !conn->marked_for_close)
      return conn;
  }
  return NULL;
}

connection_t *connection_get_by_type_state(int type, int state) {
  int i, n;
  connection_t *conn;
  connection_t **carray;
Roger Dingledine's avatar
Roger Dingledine committed
846

847
  get_connection_array(&carray,&n);
848
849
850
851
852
853
854
855
856
857
858
859
  for(i=0;i<n;i++) {
    conn = carray[i];
    if(conn->type == type && conn->state == state && !conn->marked_for_close)
      return conn;
  }
  return NULL;
}

connection_t *connection_get_by_type_state_lastwritten(int type, int state) {
  int i, n;
  connection_t *conn, *best=NULL;
  connection_t **carray;
Roger Dingledine's avatar
Roger Dingledine committed
860

861
  get_connection_array(&carray,&n);
862
863
864
865
866
867
868
869
870
  for(i=0;i<n;i++) {
    conn = carray[i];
    if(conn->type == type && conn->state == state && !conn->marked_for_close)
      if(!best || conn->timestamp_lastwritten < best->timestamp_lastwritten)
        best = conn;
  }
  return best;
}

871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
connection_t *connection_get_by_type_rendquery(int type, char *rendquery) {
  int i, n;
  connection_t *conn;
  connection_t **carray;

  get_connection_array(&carray,&n);
  for(i=0;i<n;i++) {
    conn = carray[i];
    if(conn->type == type &&
       !conn->marked_for_close &&
       !rend_cmp_service_ids(rendquery, conn->rend_query))
      return conn;
  }
  return NULL;
}

887
int connection_is_listener(connection_t *conn) {
888
  if(conn->type == CONN_TYPE_OR_LISTENER ||
889
890
     conn->type == CONN_TYPE_AP_LISTENER ||
     conn->type == CONN_TYPE_DIR_LISTENER)
891
892
893
894
    return 1;
  return 0;
}

895
int connection_state_is_open(connection_t *conn) {
Roger Dingledine's avatar
Roger Dingledine committed
896
  tor_assert(conn);
897

898
899
900
  if(conn->marked_for_close)
    return 0;

901
902
903
904
905
906
907
908
  if((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
     (conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
     (conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN))
    return 1;

  return 0;
}

909
int connection_send_destroy(uint16_t circ_id, connection_t *conn) {
Roger Dingledine's avatar
Roger Dingledine committed
910
911
  cell_t cell;

Roger Dingledine's avatar
Roger Dingledine committed
912
913
  tor_assert(conn);
  tor_assert(connection_speaks_cells(conn));
Roger Dingledine's avatar
Roger Dingledine committed
914

915
  memset(&cell, 0, sizeof(cell_t));
916
  cell.circ_id = circ_id;
Roger Dingledine's avatar
Roger Dingledine committed
917
  cell.command = CELL_DESTROY;
918
  log_fn(LOG_INFO,"Sending destroy (circID %d).", circ_id);
Nick Mathewson's avatar
Nick Mathewson committed
919
  connection_or_write_cell_to_buf(&cell, conn);
920
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
921
922
}

Roger Dingledine's avatar
Roger Dingledine committed
923
924
int connection_process_inbuf(connection_t *conn) {

Roger Dingledine's avatar
Roger Dingledine committed
925
  tor_assert(conn);
Roger Dingledine's avatar
Roger Dingledine committed
926
927
928
929

  switch(conn->type) {
    case CONN_TYPE_OR:
      return connection_or_process_inbuf(conn);
930
    case CONN_TYPE_EXIT:
931
    case CONN_TYPE_AP:
932
      return connection_edge_process_inbuf(conn);
933
934
    case CONN_TYPE_DIR:
      return connection_dir_process_inbuf(conn);
935
    case CONN_TYPE_DNSWORKER:
Roger Dingledine's avatar
Roger Dingledine committed
936
      return connection_dns_process_inbuf(conn);
Roger Dingledine's avatar
Roger Dingledine committed
937
    case CONN_TYPE_CPUWORKER:
Roger Dingledine's avatar
Roger Dingledine committed
938
      return connection_cpu_process_inbuf(conn);
Roger Dingledine's avatar
Roger Dingledine committed
939
    default:
Roger Dingledine's avatar
Roger Dingledine committed
940
      log_fn(LOG_WARN,"got unexpected conn->type %d.", conn->type);
Roger Dingledine's avatar
Roger Dingledine committed
941
942
943
944
945
946
      return -1;
  }
}

int connection_finished_flushing(connection_t *conn) {

Roger Dingledine's avatar
Roger Dingledine committed
947
  tor_assert(conn);
Roger Dingledine's avatar
Roger Dingledine committed
948

949
//  log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s);
Roger Dingledine's avatar
Roger Dingledine committed
950
951
952
953

  switch(conn->type) {
    case CONN_TYPE_OR:
      return connection_or_finished_flushing(conn);
954
    case CONN_TYPE_AP:
955
    case CONN_TYPE_EXIT:
956
      return connection_edge_finished_flushing(conn);
957
958
    case CONN_TYPE_DIR:
      return connection_dir_finished_flushing(conn);
959
    case CONN_TYPE_DNSWORKER:
960
      return connection_dns_finished_flushing(conn);
Roger Dingledine's avatar
Roger Dingledine committed
961
962
    case CONN_TYPE_CPUWORKER:
      return connection_cpu_finished_flushing(conn);
Roger Dingledine's avatar
Roger Dingledine committed
963
    default:
Roger Dingledine's avatar
Roger Dingledine committed
964
      log_fn(LOG_WARN,"got unexpected conn->type %d.", conn->type);
Roger Dingledine's avatar
Roger Dingledine committed
965
966
967
968
      return -1;
  }
}

969
970
void assert_connection_ok(connection_t *conn, time_t now)
{
Roger Dingledine's avatar
Roger Dingledine committed
971
972
973
974
  tor_assert(conn);
  tor_assert(conn->magic == CONNECTION_MAGIC);
  tor_assert(conn->type >= _CONN_TYPE_MIN);
  tor_assert(conn->type <= _CONN_TYPE_MAX);
975

976
  if(conn->outbuf_flushlen > 0) {
Roger Dingledine's avatar
Roger Dingledine committed
977
    tor_assert(connection_is_writing(conn) || conn->wants_to_write);
978
979
  }

980
  if(conn->hold_open_until_flushed)
Roger Dingledine's avatar
Roger Dingledine committed
981
    tor_assert(conn->marked_for_close);
982

983
984
  /* XXX check: wants_to_read, wants_to_write, s, poll_index,
   * marked_for_close. */
Roger Dingledine's avatar
Roger Dingledine committed
985

986
  /* buffers */
987
  if (!connection_is_listener(conn)) {
988
989
    assert_buf_ok(conn->inbuf);
    assert_buf_ok(conn->outbuf);
990
  }
991

992
#if 0 /* computers often go back in time; no way to know */
Roger Dingledine's avatar
Roger Dingledine committed
993
994
995
996
  tor_assert(!now || conn->timestamp_lastread <= now);
  tor_assert(!now || conn->timestamp_lastwritten <= now);
  tor_assert(conn->timestamp_created <= conn->timestamp_lastread);
  tor_assert(conn->timestamp_created <= conn->timestamp_lastwritten);
997
#endif
Roger Dingledine's avatar
Roger Dingledine committed
998

999
1000
  /* XXX Fix this; no longer so.*/
#if 0