TOR源码阅读(二)

今天阅读的内容是一段时间浏览后觉得有必要详细理解的部分,这里由于项目原因不进行具体的技术和语法等等分析,只做功能逻辑分析。

line 1008 in file main.c

run_connection_housekeeping(int i,time_t now) 函数,用于长期的单个连接上的持久性任务,被run_scheduled_ecents()每秒钟周期性调用。

我们来看它做了什么 获取第i个连接,获取当前配置选项结构体,判断当前时间是否超过连接生存周期,查看连接输出缓冲区是否已为空,若为空则进行标记,若连接标记为关闭,结束当前函数。

{
cell_t cell;
connection_t *conn = smartlist_get(connection_array, i);
const or_options_t *options = get_options();
or_connection_t *or_conn;
channel_t *chan = NULL;
int have_any_circuits;
int past_keepalive =
now >= conn-> timestamp_lastwritten + options-> KeepalivePeriod;

if (conn-> outbuf && ! connection_get_outbuf_len(conn) &&
conn-> type == CONN_TYPE_OR)
TO_OR_CONN(conn)-> timestamp_lastempty = now;

if (conn-> marked_for_close) {
/* nothing to do here */
return;
}

。若连接类型为目录连接,连接活动超时(如果是服务器则为发送,如果为客户端则为接收),打印日志。判断连接目的是否为获取服务器的文件描述符,且读入缓冲已大于1024字节,若是则该连接已满,若不是,则标记连接为已关闭。若连接既非目录连接也非OR连接,则退出函数。

if (conn-> type == CONN_TYPE_DIR &&
(( DIR_CONN_IS_SERVER(conn) &&
conn-> timestamp_lastwritten
+ options-> TestingDirConnectionMaxStall < now) ||
(! DIR_CONN_IS_SERVER(conn) &&
conn-> timestamp_lastread
+ options-> TestingDirConnectionMaxStall < now))) {
log_info(LD_DIR, "Expiring wedged directory conn (fd %d, purpose %d)",
( int)conn-> s, conn-> purpose);
/* This check is temporary; it's to let us know whether we should consider
* parsing partial serverdesc responses. */
if (conn-> purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
connection_get_inbuf_len(conn) >= 1024) {
log_info(LD_DIR, "Trying to extract information from wedged server desc "
"download.");
connection_dir_reached_eof( TO_DIR_CONN(conn));
} else {
connection_mark_for_close(conn);
}
return;
}

if (! connection_speaks_cells(conn))
return;

连接为OR连接时,若通道上存在链路,则设置当前时间戳为有链路存在的最新时间。若通道上不适合产生新链路,且当前并无链路在其上,则标记之,且若连接状态为已连接,则放弃该连接。若连接并未打开,则连接正常关闭。若连接空闲,且无链路,输出缓冲区为空,则关闭之。若连接超时,也关闭之。若连接仍在生存期内但无数据待发送,则发送一个填充数据元保持链路可用。若均不是,即正常可用通道,则进行通道填充。

if ( channel_is_bad_for_new_circs( TLS_CHAN_TO_BASE(or_conn-> chan)) &&
! have_any_circuits) {
/* It's bad for new circuits, and has no unmarked circuits on it:
* mark it now. */
log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Too old].",
( int)conn-> s, conn-> address, conn-> port);
if (conn-> state == OR_CONN_STATE_CONNECTING)
connection_or_connect_failed( TO_OR_CONN(conn),
END_OR_CONN_REASON_TIMEOUT,
"Tor gave up on the connection");
connection_or_close_normally( TO_OR_CONN(conn), 1);
} else if (! connection_state_is_open(conn)) {
if (past_keepalive) {
/* We never managed to actually get this connection open and happy. */
log_info(LD_OR, "Expiring non-open OR connection to fd %d (%s:%d).",
( int)conn-> s,conn-> address, conn-> port);
connection_or_close_normally( TO_OR_CONN(conn), 0);
}
} else if ( we_are_hibernating() &&
! have_any_circuits &&
! connection_get_outbuf_len(conn)) {
/* We're hibernating, there's no circuits, and nothing to flush.*/
log_info(LD_OR, "Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
( int)conn-> s,conn-> address, conn-> port);
connection_or_close_normally( TO_OR_CONN(conn), 1);
} else if (!have_any_circuits &&
now - or_conn-> idle_timeout >=
chan-> timestamp_last_had_circuits) {
log_info(LD_OR, "Expiring non-used OR connection "U64_FORMAT " to fd %d "
"(%s:%d) [no circuits for %d; timeout %d; %scanonical].",
U64_PRINTF_ARG(chan-> global_identifier),
( int)conn-> s, conn-> address, conn-> port,
( int)(now - chan-> timestamp_last_had_circuits),
or_conn-> idle_timeout,
or_conn-> is_canonical ? "" : "non");
connection_or_close_normally( TO_OR_CONN(conn), 0);
} else if (
now >= or_conn-> timestamp_lastempty + options-> KeepalivePeriod* 10 &&
now >= conn-> timestamp_lastwritten + options-> KeepalivePeriod* 10) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
"Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
"flush; %d seconds since last write)",
( int)conn-> s, conn-> address, conn-> port,
( int) connection_get_outbuf_len(conn),
( int)(now-conn-> timestamp_lastwritten));
connection_or_close_normally( TO_OR_CONN(conn), 0);
} else if (past_keepalive && ! connection_get_outbuf_len(conn)) {
/* send a padding cell */
log_fn(LOG_DEBUG,LD_OR, "Sending keepalive to (%s:%d)",
conn-> address, conn-> port);
memset(&cell, 0, sizeof( cell_t));
cell. command = CELL_PADDING;
connection_or_write_cell_to_buf(&cell, or_conn);
} else {
channelpadding_decide_to_pad_channel(chan);
}
开发者思维之缜密再一次使我惊叹,我们所关注的数据填充部分可以下移到channelpadding_decide_to_pad_channel(chan)上。因为我们可以探究若为可用OR连接时,他们会怎么进行通道的填充。


猜你喜欢

转载自blog.csdn.net/LHF_debug/article/details/79697704
今日推荐