[or-cvs] introduced a periodic keepalive padding cell
Roger Dingledine
arma at seul.org
Tue Oct 1 23:37:33 UTC 2002
Update of /home/or/cvsroot/src/or
In directory moria.seul.org:/home/arma/work/onion/cvs/src/or
Modified Files:
config.c connection.c main.c or.h
Log Message:
introduced a periodic keepalive padding cell
now tor can be run safely inside nat'ed areas that kill idle
connections; and the proxy can handle when you suspend your laptop
and then emerge hours later from a new domain.
Index: config.c
===================================================================
RCS file: /home/or/cvsroot/src/or/config.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- config.c 28 Sep 2002 00:52:59 -0000 1.18
+++ config.c 1 Oct 2002 23:37:31 -0000 1.19
@@ -99,6 +99,8 @@
0, "how many seconds between directory rebuilds", "<rebuildperiod>" },
{ "DirFetchPeriod", 'F', POPT_ARG_INT, &options->DirFetchPeriod,
0, "how many seconds between directory fetches", "<fetchperiod>" },
+ { "KeepalivePeriod", 'K', POPT_ARG_INT, &options->KeepalivePeriod,
+ 0, "how many seconds between keepalives", "<keepaliveperiod>" },
// { "ReconnectPeriod", 'e', POPT_ARG_INT, &options->ReconnectPeriod,
// 0, "how many seconds between retrying all OR connections", "<reconnectperiod>" },
{ "Role", 'R', POPT_ARG_INT, &options->Role,
@@ -122,6 +124,7 @@
options->LinkPadding = 0;
options->DirRebuildPeriod = 600;
options->DirFetchPeriod = 6000;
+ options->KeepalivePeriod = 300;
// options->ReconnectPeriod = 6001;
options->Role = ROLE_OR_LISTEN | ROLE_OR_CONNECT_ALL | ROLE_OP_LISTEN | ROLE_AP_LISTEN;
@@ -170,9 +173,10 @@
options->MaxConn,
options->TrafficShaping,
options->LinkPadding);
- printf("DirRebuildPeriod=%d, DirFetchPeriod=%d\n",
+ printf("DirRebuildPeriod=%d, DirFetchPeriod=%d KeepalivePeriod=%d\n",
options->DirRebuildPeriod,
- options->DirFetchPeriod);
+ options->DirFetchPeriod,
+ options->KeepalivePeriod);
}
/* Validate options */
@@ -284,6 +288,12 @@
if ( options->DirFetchPeriod < 1)
{
log(LOG_ERR,"DirFetchPeriod option must be positive.");
+ code = -1;
+ }
+
+ if ( options->KeepalivePeriod < 1)
+ {
+ log(LOG_ERR,"KeepalivePeriod option must be positive.");
code = -1;
}
Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- connection.c 28 Sep 2002 05:53:00 -0000 1.27
+++ connection.c 1 Oct 2002 23:37:31 -0000 1.28
@@ -86,6 +86,10 @@
connection_t *connection_new(int type) {
connection_t *conn;
+ struct timeval now;
+
+ if(gettimeofday(&now,NULL) < 0)
+ return NULL;
conn = (connection_t *)malloc(sizeof(connection_t));
if(!conn)
@@ -99,6 +103,7 @@
conn->receiver_bucket = 10240; /* should be enough to do the handshake */
conn->bandwidth = conn->receiver_bucket / 10; /* give it a default */
+ conn->timestamp_created = now.tv_sec;
if (connection_speaks_cells(conn)) {
conn->f_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
@@ -320,6 +325,7 @@
int connection_read_to_buf(connection_t *conn) {
int read_result;
+ struct timeval now;
if(connection_speaks_cells(conn)) {
assert(conn->receiver_bucket >= 0);
@@ -327,6 +333,11 @@
if(!connection_speaks_cells(conn)) {
assert(conn->receiver_bucket < 0);
}
+
+ if(gettimeofday(&now,NULL) < 0)
+ return -1;
+ conn->timestamp_lastread = now.tv_sec;
+
read_result = read_to_buf(conn->s, conn->receiver_bucket, &conn->inbuf, &conn->inbuflen,
&conn->inbuf_datalen, &conn->inbuf_reached_eof);
// log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);
@@ -369,8 +380,15 @@
}
int connection_write_to_buf(char *string, int len, connection_t *conn) {
+ struct timeval now;
+
+ if(gettimeofday(&now,NULL) < 0)
+ return -1;
+
if(!len)
return 0;
+
+ conn->timestamp_lastwritten = now.tv_sec;
if( (!connection_speaks_cells(conn)) ||
(!connection_state_is_open(conn)) ||
Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- main.c 28 Sep 2002 01:40:11 -0000 1.28
+++ main.c 1 Oct 2002 23:37:31 -0000 1.29
@@ -310,20 +310,11 @@
connection_t *conn = NULL;
connection_t *tmpconn;
struct timeval now, soonest;
- static int current_second = 0; /* from previous calls to gettimeofday */
- static int time_to_rebuild_directory = 0;
- static int time_to_fetch_directory = 0;
+ static long current_second = 0; /* from previous calls to gettimeofday */
+ static long time_to_rebuild_directory = 0;
+ static long time_to_fetch_directory = 0;
int ms_until_conn;
-
- *timeout = -1; /* set it to never timeout, possibly overridden below */
-
- /* first check if we need to refill buckets */
- for(i=0;i<nfds;i++) {
- if(connection_receiver_bucket_should_increase(connection_array[i])) {
- need_to_refill_buckets = 1;
- break;
- }
- }
+ cell_t cell;
if(gettimeofday(&now,NULL) < 0)
return -1;
@@ -356,6 +347,50 @@
*timeout = 1000*(time_to_fetch_directory - now.tv_sec) + (1000 - (now.tv_usec / 1000));
}
+ /* check connections to see whether we should send a keepalive, expire, or wait */
+ for(i=0;i<nfds;i++) {
+ tmpconn = connection_array[i];
+ if(!connection_speaks_cells(tmpconn))
+ continue; /* this conn type doesn't send cells */
+ if(!connection_state_is_open(tmpconn)) {
+ continue; /* only conns in state 'open' need a keepalive */
+ /* XXX should time-out unfinished connections someday too */
+ }
+ if(now.tv_sec >= tmpconn->timestamp_lastwritten + options.KeepalivePeriod) {
+ if(!(options.Role & ROLE_OR_CONNECT_ALL) && !circuit_get_by_conn(tmpconn)) {
+ /* we're an onion proxy, with no circuits. kill it. */
+ log(LOG_DEBUG,"prepare_for_poll(): Expiring connection to %d (%s:%d).",
+ i,tmpconn->address, tmpconn->port);
+ tmpconn->marked_for_close = 1;
+ } else {
+ /* either a full router, or we've got a circuit. send a padding cell. */
+// log(LOG_DEBUG,"prepare_for_poll(): Sending keepalive to (%s:%d)",
+// tmpconn->address, tmpconn->port);
+ memset(&cell,0,sizeof(cell_t));
+ cell.command = CELL_PADDING;
+ connection_write_cell_to_buf(&cell, tmpconn);
+ }
+ }
+ if(!tmpconn->marked_for_close &&
+ *timeout > 1000*(tmpconn->timestamp_lastwritten + options.KeepalivePeriod - now.tv_sec)) {
+ *timeout = 1000*(tmpconn->timestamp_lastwritten + options.KeepalivePeriod - now.tv_sec);
+ }
+ }
+ assert(*timeout >= 0);
+ /* blow away any connections that need to die. can't do this later
+ * because we might open up a circuit and not realize it.
+ */
+ for(i=0;i<nfds;i++)
+ check_conn_marked(i);
+
+ /* check if we need to refill buckets */
+ for(i=0;i<nfds;i++) {
+ if(connection_receiver_bucket_should_increase(connection_array[i])) {
+ need_to_refill_buckets = 1;
+ break;
+ }
+ }
+
if(need_to_refill_buckets) {
if(now.tv_sec > current_second) { /* the second has already rolled over! */
// log(LOG_DEBUG,"prepare_for_poll(): The second has rolled over, immediately refilling.");
@@ -363,7 +398,7 @@
connection_increment_receiver_bucket(connection_array[i]);
current_second = now.tv_sec; /* remember which second it is, for next time */
}
- /* this timeout is definitely sooner than either of the above two */
+ /* this timeout is definitely sooner than any of the above ones */
*timeout = 1000 - (now.tv_usec / 1000); /* how many milliseconds til the next second? */
}
@@ -394,7 +429,7 @@
ms_until_conn = (soonest.tv_sec - now.tv_sec)*1000 +
(soonest.tv_usec - now.tv_usec)/1000;
// log(LOG_DEBUG,"prepare_for_poll(): conn %d times out in %d ms.",conn->s, ms_until_conn);
- if(*timeout == -1 || ms_until_conn < *timeout) { /* use the new one */
+ if(ms_until_conn < *timeout) { /* use the new one */
// log(LOG_DEBUG,"prepare_for_poll(): conn %d soonest, in %d ms.",conn->s,ms_until_conn);
*timeout = ms_until_conn;
}
@@ -517,18 +552,25 @@
void dumpstats (void) { /* dump stats to stdout */
int i;
connection_t *conn;
+ struct timeval now;
extern char *conn_type_to_string[];
extern char *conn_state_to_string[][15];
printf("Dumping stats:\n");
+ if(gettimeofday(&now,NULL) < 0)
+ return ;
for(i=0;i<nfds;i++) {
conn = connection_array[i];
- printf("Conn %d (socket %d) type %d (%s), state %d (%s)\n",
+ printf("Conn %d (socket %d) type %d (%s), state %d (%s), created %ld secs ago\n",
i, conn->s, conn->type, conn_type_to_string[conn->type],
- conn->state, conn_state_to_string[conn->type][conn->state]);
+ conn->state, conn_state_to_string[conn->type][conn->state], now.tv_sec - conn->timestamp_created);
if(!connection_is_listener(conn)) {
printf("Conn %d is to '%s:%d'.\n",i,conn->address, conn->port);
+ printf("Conn %d: %d bytes waiting on inbuf (last read %ld secs ago)\n",i,conn->inbuf_datalen,
+ now.tv_sec - conn->timestamp_lastread);
+ printf("Conn %d: %d bytes waiting on outbuf (last written %ld secs ago)\n",i,conn->outbuf_datalen,
+ now.tv_sec - conn->timestamp_lastwritten);
}
circuit_dump_by_conn(conn); /* dump info about all the circuits using this conn */
printf("\n");
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- or.h 28 Sep 2002 05:53:00 -0000 1.31
+++ or.h 1 Oct 2002 23:37:31 -0000 1.32
@@ -188,11 +188,15 @@
int inbuflen;
int inbuf_datalen;
int inbuf_reached_eof;
+ long timestamp_lastread;
char *outbuf;
int outbuflen; /* how many bytes are allocated for the outbuf? */
int outbuf_flushlen; /* how much data should we try to flush from the outbuf? */
int outbuf_datalen; /* how much data is there total on the outbuf? */
+ long timestamp_lastwritten;
+
+ long timestamp_created;
// uint16_t aci; /* anonymous connection identifier */
@@ -357,6 +361,7 @@
int LinkPadding;
int DirRebuildPeriod;
int DirFetchPeriod;
+ int KeepalivePeriod;
int Role;
int loglevel;
} or_options_t;
More information about the tor-commits
mailing list