Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
David Goulet
Tor
Commits
682a8050
Commit
682a8050
authored
May 05, 2004
by
Nick Mathewson
🥄
Browse files
Comments for nearly all non-tricky files
svn:r1796
parent
6cfdc90d
Changes
11
Hide whitespace changes
Inline
Side-by-side
src/or/buffers.c
View file @
682a8050
...
...
@@ -219,8 +219,9 @@ int read_to_buf_tls(tor_tls *tls, size_t at_most, buf_t *buf) {
tor_assert
(
tls
);
assert_buf_ok
(
buf
);
log_fn
(
LOG_DEBUG
,
"start: %d on buf, %d pending, at_most %d."
,(
int
)
buf_datalen
(
buf
),
tor_tls_get_pending_bytes
(
tls
),
at_most
);
log_fn
(
LOG_DEBUG
,
"start: %d on buf, %d pending, at_most %d."
,
(
int
)
buf_datalen
(
buf
),
(
int
)
tor_tls_get_pending_bytes
(
tls
),
(
int
)
at_most
);
if
(
buf_ensure_capacity
(
buf
,
at_most
+
buf
->
datalen
))
return
TOR_TLS_ERROR
;
...
...
@@ -231,8 +232,9 @@ int read_to_buf_tls(tor_tls *tls, size_t at_most, buf_t *buf) {
if
(
at_most
==
0
)
return
0
;
log_fn
(
LOG_DEBUG
,
"before: %d on buf, %d pending, at_most %d."
,(
int
)
buf_datalen
(
buf
),
tor_tls_get_pending_bytes
(
tls
),
at_most
);
log_fn
(
LOG_DEBUG
,
"before: %d on buf, %d pending, at_most %d."
,
(
int
)
buf_datalen
(
buf
),
(
int
)
tor_tls_get_pending_bytes
(
tls
),
(
int
)
at_most
);
assert_no_tls_errors
();
r
=
tor_tls_read
(
tls
,
buf
->
mem
+
buf
->
datalen
,
at_most
);
...
...
src/or/cpuworker.c
View file @
682a8050
...
...
@@ -2,6 +2,13 @@
/* See LICENSE for licensing information */
/* $Id$ */
/*****
* cpuworker.c: Run computation-intensive tasks (generally for crypto) in
* a separate execution context. [OR only.]
*
* Right now, we only use this for processing onionskins.
*****/
#include
"or.h"
extern
or_options_t
options
;
/* command-line and config-file options */
...
...
@@ -14,6 +21,9 @@ extern or_options_t options; /* command-line and config-file options */
static
int
num_cpuworkers
=
0
;
static
int
num_cpuworkers_busy
=
0
;
/* We need to spawn new cpuworkers whenever we rotate the onion keys
* on platforms where execution contexts==processes. This variable stores
* the last time we got a key rotation event.*/
static
time_t
last_rotation_time
=
0
;
int
cpuworker_main
(
void
*
data
);
...
...
@@ -21,34 +31,45 @@ static int spawn_cpuworker(void);
static
void
spawn_enough_cpuworkers
(
void
);
static
void
process_pending_task
(
connection_t
*
cpuworker
);
/* Initialize the cpuworker subsystem.
*/
void
cpu_init
(
void
)
{
last_rotation_time
=
time
(
NULL
);
spawn_enough_cpuworkers
();
}
/* Called when we're done sending a request to a cpuworker. */
int
connection_cpu_finished_flushing
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
type
==
CONN_TYPE_CPUWORKER
);
connection_stop_writing
(
conn
);
return
0
;
}
/* Pack addr,port,and circ_id; set *tag to the result. (See note on
* cpuworker_main for wire format.) */
static
void
tag_pack
(
char
*
tag
,
uint32_t
addr
,
uint16_t
port
,
uint16_t
circ_id
)
{
*
(
uint32_t
*
)
tag
=
addr
;
*
(
uint16_t
*
)(
tag
+
4
)
=
port
;
*
(
uint16_t
*
)(
tag
+
6
)
=
circ_id
;
}
static
void
tag_unpack
(
char
*
tag
,
uint32_t
*
addr
,
uint16_t
*
port
,
uint16_t
*
circ_id
)
{
/* Unpack 'tag' into addr, port, and circ_id.
*/
static
void
tag_unpack
(
const
char
*
tag
,
uint32_t
*
addr
,
uint16_t
*
port
,
uint16_t
*
circ_id
)
{
struct
in_addr
in
;
*
addr
=
*
(
uint32_t
*
)
tag
;
*
port
=
*
(
uint16_t
*
)(
tag
+
4
);
*
circ_id
=
*
(
uint16_t
*
)(
tag
+
6
);
*
addr
=
*
(
const
uint32_t
*
)
tag
;
*
port
=
*
(
const
uint16_t
*
)(
tag
+
4
);
*
circ_id
=
*
(
const
uint16_t
*
)(
tag
+
6
);
in
.
s_addr
=
htonl
(
*
addr
);
log_fn
(
LOG_DEBUG
,
"onion was from %s:%d, circ_id %d."
,
inet_ntoa
(
in
),
*
port
,
*
circ_id
);
}
/* Called when the onion key has changed and we need to spawn new
* cpuworkers. Close all currently idle cpuworkers, and mark the last
* rotation time as now.
*/
void
cpuworkers_rotate
(
void
)
{
connection_t
*
cpuworker
;
...
...
@@ -61,6 +82,11 @@ void cpuworkers_rotate(void)
spawn_enough_cpuworkers
();
}
/* Called when we get data from a cpuworker. If the answer is not complete,
* wait for a complete answer. If the cpuworker closes the connection,
* mark it as closed and spawn a new one as needed. If the answer is complete,
* process it as appropriate.
*/
int
connection_cpu_process_inbuf
(
connection_t
*
conn
)
{
char
success
;
unsigned
char
buf
[
LEN_ONION_RESPONSE
];
...
...
@@ -136,6 +162,20 @@ done_processing:
return
0
;
}
/* Implement a cpuworker. 'data' is an fdarray as returned by socketpair.
* Read and writes from fdarray[1]. Reads requests, writes answers.
*
* Request format:
* Task type [1 byte, always ONIONSKIN_CHALLENGE_LEN]
* Opaque tag TAG_LEN
* Onionskin challenge ONIONSKIN_CHALLENGE_LEN
* Response format:
* Success/failure [1 byte, boolean.]
* Opaque tag TAG_LEN
* Onionskin challenge ONIONSKIN_REPLY_LEN
* Negotiated keys KEY_LEN*2+DIGEST_LEN*2
*/
int
cpuworker_main
(
void
*
data
)
{
unsigned
char
question
[
ONIONSKIN_CHALLENGE_LEN
];
unsigned
char
question_type
;
...
...
@@ -209,6 +249,8 @@ int cpuworker_main(void *data) {
return
0
;
/* windows wants this function to return an int */
}
/* Launch a new cpuworker.
*/
static
int
spawn_cpuworker
(
void
)
{
int
fd
[
2
];
connection_t
*
conn
;
...
...
@@ -243,6 +285,9 @@ static int spawn_cpuworker(void) {
return
0
;
/* success */
}
/* If we have too few or too many active cpuworkers, try to spawn new ones
* or kill idle ones.
*/
static
void
spawn_enough_cpuworkers
(
void
)
{
int
num_cpuworkers_needed
=
options
.
NumCpus
;
...
...
@@ -260,6 +305,7 @@ static void spawn_enough_cpuworkers(void) {
}
}
/* Take a pending task from the queue and assign it to 'cpuworker' */
static
void
process_pending_task
(
connection_t
*
cpuworker
)
{
circuit_t
*
circ
;
...
...
src/or/dns.c
View file @
682a8050
...
...
@@ -2,6 +2,10 @@
/* See LICENSE for licensing information */
/* $Id$ */
/*****
* dns.c: Resolve hostnames in separate processes.
*****/
/* See http://elvin.dstc.com/ListArchive/elvin-dev/archive/2001/09/msg00027.html
* for some approaches to asynchronous dns. We will want to switch once one of
* them becomes more commonly available.
...
...
@@ -12,12 +16,19 @@
extern
or_options_t
options
;
/* command-line and config-file options */
/* Longest hostname we're willing to resolve. */
#define MAX_ADDRESSLEN 256
/* Maximum DNS processes to spawn. */
#define MAX_DNSWORKERS 50
/* Minimum DNS processes to spawn. */
#define MIN_DNSWORKERS 3
/* If more than this many processes are idle, shut down the extras. */
#define MAX_IDLE_DNSWORKERS 10
/* Possible outcomes from hostname lookup: permanent failure,
* transient (retryable) failure, and success */
#define DNS_RESOLVE_FAILED_TRANSIENT 1
#define DNS_RESOLVE_FAILED_PERMANENT 2
#define DNS_RESOLVE_SUCCEEDED 3
...
...
@@ -25,11 +36,16 @@ extern or_options_t options; /* command-line and config-file options */
int
num_dnsworkers
=
0
;
int
num_dnsworkers_busy
=
0
;
/* Linked list of connections waiting for a DNS answer. */
struct
pending_connection_t
{
struct
connection_t
*
conn
;
struct
pending_connection_t
*
next
;
};
/* A DNS request: possibly completed, possibly pending; cached_resolve
* structs are stored at the OR side in a splay tree, and as a linked
* list from oldest to newest.
*/
struct
cached_resolve
{
SPLAY_ENTRY
(
cached_resolve
)
node
;
char
address
[
MAX_ADDRESSLEN
];
/* the hostname to be resolved */
...
...
@@ -38,7 +54,7 @@ struct cached_resolve {
#define CACHE_STATE_PENDING 0
#define CACHE_STATE_VALID 1
#define CACHE_STATE_FAILED 2
uint32_t
expire
;
/* remove
untouched
items from cache after
some
time
?
*/
uint32_t
expire
;
/* remove items from cache after
this
time */
struct
pending_connection_t
*
pending_connections
;
struct
cached_resolve
*
next
;
};
...
...
@@ -51,8 +67,11 @@ int dnsworker_main(void *data);
static
int
spawn_dnsworker
(
void
);
static
void
spawn_enough_dnsworkers
(
void
);
/* Splay tree of cached_resolve objects */
static
SPLAY_HEAD
(
cache_tree
,
cached_resolve
)
cache_root
;
/* Function to compare hashed resolves on their addresses; used to
* implement splay trees. */
static
int
compare_cached_resolves
(
struct
cached_resolve
*
a
,
struct
cached_resolve
*
b
)
{
/* make this smarter one day? */
...
...
@@ -62,10 +81,12 @@ static int compare_cached_resolves(struct cached_resolve *a,
SPLAY_PROTOTYPE
(
cache_tree
,
cached_resolve
,
node
,
compare_cached_resolves
);
SPLAY_GENERATE
(
cache_tree
,
cached_resolve
,
node
,
compare_cached_resolves
);
/* Initialize the DNS cache */
static
void
init_cache_tree
(
void
)
{
SPLAY_INIT
(
&
cache_root
);
}
/* Initialize the DNS subsystem; called by the OR process. */
void
dns_init
(
void
)
{
init_cache_tree
();
spawn_enough_dnsworkers
();
...
...
@@ -74,6 +95,8 @@ void dns_init(void) {
static
struct
cached_resolve
*
oldest_cached_resolve
=
NULL
;
/* linked list, */
static
struct
cached_resolve
*
newest_cached_resolve
=
NULL
;
/* oldest to newest */
/* Remove every cached_resolve whose 'expire' time is before 'now'
* from the cache. */
static
void
purge_expired_resolves
(
uint32_t
now
)
{
struct
cached_resolve
*
resolve
;
...
...
@@ -178,6 +201,9 @@ int dns_resolve(connection_t *exitconn) {
return
assign_to_dnsworker
(
exitconn
);
}
/* Find or spawn a dns worker process to handle resolving
* exitconn->address; tell that dns worker to begin resolving.
*/
static
int
assign_to_dnsworker
(
connection_t
*
exitconn
)
{
connection_t
*
dnsconn
;
unsigned
char
len
;
...
...
@@ -210,6 +236,8 @@ static int assign_to_dnsworker(connection_t *exitconn) {
return
0
;
}
/* Remove 'conn' from the list of connections waiting for conn->address.
*/
void
connection_dns_remove
(
connection_t
*
conn
)
{
struct
pending_connection_t
*
pend
,
*
victim
;
...
...
@@ -251,6 +279,8 @@ void connection_dns_remove(connection_t *conn)
}
}
/* Log an error and abort if conn is waiting for a DNS resolve.
*/
void
assert_connection_edge_not_dns_pending
(
connection_t
*
conn
)
{
struct
pending_connection_t
*
pend
;
struct
cached_resolve
*
resolve
;
...
...
@@ -264,6 +294,8 @@ void assert_connection_edge_not_dns_pending(connection_t *conn) {
}
}
/* Log an error and abort if any connection waiting for a DNS resolve is
* corrupted. */
void
assert_all_pending_dns_resolves_ok
(
void
)
{
struct
pending_connection_t
*
pend
;
struct
cached_resolve
*
resolve
;
...
...
@@ -277,8 +309,9 @@ void assert_all_pending_dns_resolves_ok(void) {
}
}
/* Cancel all pending connections. Then cancel the resolve itself,
* and remove the 'struct cached_resolve' from the cache.
/* Mark all connections waiting for 'address' for close. Then cancel
* the resolve for 'address' itself, and remove any cached results for
* 'address' from the cache.
*/
void
dns_cancel_pending_resolve
(
char
*
address
)
{
struct
pending_connection_t
*
pend
;
...
...
@@ -314,6 +347,8 @@ void dns_cancel_pending_resolve(char *address) {
dns_purge_resolve
(
resolve
);
}
/* Remove 'resolve' from the cache.
*/
static
void
dns_purge_resolve
(
struct
cached_resolve
*
resolve
)
{
struct
cached_resolve
*
tmp
;
...
...
@@ -338,6 +373,12 @@ static void dns_purge_resolve(struct cached_resolve *resolve) {
tor_free
(
resolve
);
}
/* Called on the OR side when a DNS worker tells us the outcome of a DNS
* resolve: tell all pending connections about the result of the lookup, and
* cache the value. ('address' is a NUL-terminated string containing the
* address to look up; 'addr' is an IPv4 address in host order; 'outcome' is
* one of DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
*/
static
void
dns_found_answer
(
char
*
address
,
uint32_t
addr
,
char
outcome
)
{
struct
pending_connection_t
*
pend
;
struct
cached_resolve
search
;
...
...
@@ -356,6 +397,8 @@ static void dns_found_answer(char *address, uint32_t addr, char outcome) {
}
if
(
resolve
->
state
!=
CACHE_STATE_PENDING
)
{
/* XXXX Maybe update addr? or check addr for consistency? Or let
* VALID replace FAILED? */
log_fn
(
LOG_WARN
,
"Resolved '%s' which was already resolved; ignoring"
,
address
);
tor_assert
(
resolve
->
pending_connections
==
NULL
);
...
...
@@ -401,12 +444,21 @@ static void dns_found_answer(char *address, uint32_t addr, char outcome) {
/******************************************************************/
/*****
* Connection between OR and dnsworker
*****/
/* Write handler: called when we've pushed a request to a dnsworker. */
int
connection_dns_finished_flushing
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
type
==
CONN_TYPE_DNSWORKER
);
connection_stop_writing
(
conn
);
return
0
;
}
/* Read handler: called when we get data from a dnsworker. If the
* connection is closed, mark the dnsworker as dead. Otherwise, see
* if we have a complete answer. If so, call dns_found_answer on the
* result. If not, wait. Returns 0. */
int
connection_dns_process_inbuf
(
connection_t
*
conn
)
{
char
success
;
uint32_t
addr
;
...
...
@@ -447,6 +499,23 @@ int connection_dns_process_inbuf(connection_t *conn) {
return
0
;
}
/* Implementation for DNS workers; this code runs in a separate
* execution context. It takes as its argument an fdarray as returned
* by socketpair(), and communicates via fdarray[1]. The protocol is
* as follows:
* The OR says:
* ADDRESSLEN [1 byte]
* ADDRESS [ADDRESSLEN bytes]
* The DNS worker does the lookup, and replies:
* OUTCOME [1 byte]
* IP [4 bytes]
*
* OUTCOME is one of DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
* IP is in host order.
*
* The dnsworker runs indefinitely, until its connection is closed or an error
* occurs.
*/
int
dnsworker_main
(
void
*
data
)
{
char
address
[
MAX_ADDRESSLEN
];
unsigned
char
address_len
;
...
...
@@ -498,6 +567,8 @@ int dnsworker_main(void *data) {
return
0
;
/* windows wants this function to return an int */
}
/* Launch a new DNS worker; return 0 on success, -1 on failure.
*/
static
int
spawn_dnsworker
(
void
)
{
int
fd
[
2
];
connection_t
*
conn
;
...
...
@@ -532,6 +603,8 @@ static int spawn_dnsworker(void) {
return
0
;
/* success */
}
/* If we have too many or too few DNS workers, spawn or kill some.
*/
static
void
spawn_enough_dnsworkers
(
void
)
{
int
num_dnsworkers_needed
;
/* aim to have 1 more than needed,
* but no less than min and no more than max */
...
...
src/or/main.c
View file @
682a8050
...
...
@@ -2,6 +2,10 @@
/* See LICENSE for licensing information */
/* $Id$ */
/*****
* main.c: Tor main loop and startup functions.
*****/
#include
"or.h"
/********* PROTOTYPES **********/
...
...
@@ -11,18 +15,26 @@ static int init_from_config(int argc, char **argv);
/********* START VARIABLES **********/
/* declared in connection.c */
extern
char
*
conn_state_to_string
[][
_CONN_TYPE_MAX
+
1
];
or_options_t
options
;
/* command-line and config-file options */
int
global_read_bucket
;
/* max number of bytes I can read this second */
/* What was the read bucket before the last call to prepare_for_pool?
* (used to determine how many bytes we've read). */
static
int
stats_prev_global_read_bucket
;
/* How many bytes have we read since we started the process? */
static
uint64_t
stats_n_bytes_read
=
0
;
/* How many seconds have we been running? */
static
long
stats_n_seconds_reading
=
0
;
/* Array of all open connections; each element corresponds to the element of
* poll_array in the same position. The first nfds elements are valid. */
static
connection_t
*
connection_array
[
MAXCONNECTIONS
]
=
{
NULL
};
/* Array of pollfd objects for calls to poll(). */
static
struct
pollfd
poll_array
[
MAXCONNECTIONS
];
static
int
nfds
=
0
;
/* number of connections currently active */
...
...
@@ -33,14 +45,14 @@ static int please_reset=0; /* whether we just got a sighup */
static
int
please_reap_children
=
0
;
/* whether we should waitpid for exited children */
#endif
/* signal stuff */
int
has_fetched_directory
=
0
;
/* we set this to 1 when we've fetched a dir, to know whether to complain
* yet about unrecognized nicknames in entrynodes, exitnodes, etc.
* Also, we don't try building circuits unless this is 1. */
int
has_fetched_directory
=
0
;
int
has_completed_circuit
=
0
;
/* we set this to 1 when we've opened a circuit, so we can print a log
* entry to inform the user that Tor is working. */
int
has_completed_circuit
=
0
;
/********* END VARIABLES ************/
...
...
@@ -52,6 +64,10 @@ int has_completed_circuit=0;
*
****************************************************************************/
/* Add 'conn' to the array of connections that we can poll on. The
* connection's socket must be set; the connection starts out
* non-reading and non-writing.
*/
int
connection_add
(
connection_t
*
conn
)
{
tor_assert
(
conn
);
tor_assert
(
conn
->
s
>=
0
);
...
...
@@ -112,11 +128,17 @@ int connection_remove(connection_t *conn) {
return
0
;
}
/* Set *array to an array of all connections, and *n to the length
* of the array. *array and *n must not be modified.
*/
void
get_connection_array
(
connection_t
***
array
,
int
*
n
)
{
*
array
=
connection_array
;
*
n
=
nfds
;
}
/* Set the event mask on 'conn' to 'events'. (The form of the event mask is
* as for poll().)
*/
void
connection_watch_events
(
connection_t
*
conn
,
short
events
)
{
tor_assert
(
conn
&&
conn
->
poll_index
<
nfds
);
...
...
@@ -124,10 +146,12 @@ void connection_watch_events(connection_t *conn, short events) {
poll_array
[
conn
->
poll_index
].
events
=
events
;
}
/* Return true iff the 'conn' is listening for read events. */
int
connection_is_reading
(
connection_t
*
conn
)
{
return
poll_array
[
conn
->
poll_index
].
events
&
POLLIN
;
}
/* Tell the main loop to stop notifying 'conn' of any read events. */
void
connection_stop_reading
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
poll_index
<
nfds
);
...
...
@@ -137,6 +161,7 @@ void connection_stop_reading(connection_t *conn) {
poll_array
[
conn
->
poll_index
].
events
-=
POLLIN
;
}
/* Tell the main loop to start notifying 'conn' of any read events. */
void
connection_start_reading
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
poll_index
<
nfds
);
...
...
@@ -144,10 +169,12 @@ void connection_start_reading(connection_t *conn) {
poll_array
[
conn
->
poll_index
].
events
|=
POLLIN
;
}
/* Return true iff the 'conn' is listening for write events. */
int
connection_is_writing
(
connection_t
*
conn
)
{
return
poll_array
[
conn
->
poll_index
].
events
&
POLLOUT
;
}
/* Tell the main loop to stop notifying 'conn' of any write events. */
void
connection_stop_writing
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
poll_index
<
nfds
);
...
...
@@ -156,6 +183,7 @@ void connection_stop_writing(connection_t *conn) {
poll_array
[
conn
->
poll_index
].
events
-=
POLLOUT
;
}
/* Tell the main loop to start notifying 'conn' of any write events. */
void
connection_start_writing
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
poll_index
<
nfds
);
...
...
@@ -163,6 +191,10 @@ void connection_start_writing(connection_t *conn) {
poll_array
[
conn
->
poll_index
].
events
|=
POLLOUT
;
}
/* Called when the connection at connection_array[i] has a read event:
* checks for validity, catches numerous errors, and dispatches to
* connection_handle_read.
*/
static
void
conn_read
(
int
i
)
{
connection_t
*
conn
=
connection_array
[
i
];
...
...
@@ -200,6 +232,10 @@ static void conn_read(int i) {
assert_all_pending_dns_resolves_ok
();
}
/* Called when the connection at connection_array[i] has a write event:
* checks for validity, catches numerous errors, and dispatches to
* connection_handle_write.
*/
static
void
conn_write
(
int
i
)
{
connection_t
*
conn
;
...
...
@@ -227,6 +263,15 @@ static void conn_write(int i) {
assert_all_pending_dns_resolves_ok
();
}
/* If the connection at connection_array[i] is marked for close, then:
* - If it has data that it wants to flush, try to flush it.
* - If it _still_ has data to flush, and conn->hold_open_until_flushed is
* true, then leave the connection open and return.
* - Otherwise, remove the connection from connection_array and from
* all other lists, close it, and free it.
* If we remove the connection, then call conn_closed_if_marked at the new
* connection at position i.
*/
static
void
conn_close_if_marked
(
int
i
)
{
connection_t
*
conn
;
int
retval
;
...
...
@@ -280,8 +325,7 @@ static void conn_close_if_marked(int i) {
}
}
/* This function is called whenever we successfully pull
* down a directory */
/* This function is called whenever we successfully pull down a directory */
void
directory_has_arrived
(
void
)
{
log_fn
(
LOG_INFO
,
"A directory has arrived."
);
...
...
@@ -304,11 +348,13 @@ static void run_connection_housekeeping(int i, time_t now) {
cell_t
cell
;
connection_t
*
conn
=
connection_array
[
i
];
/* Expire any directory connections that haven't sent anything for 5 min */
if
(
conn
->
type
==
CONN_TYPE_DIR
&&
!
conn
->
marked_for_close
&&
conn
->
timestamp_lastwritten
+
5
*
60
<
now
)
{
log_fn
(
LOG_WARN
,
"Expiring wedged directory conn (purpose %d)"
,
conn
->
purpose
);
connection_mark_for_close
(
conn
,
0
);
/* XXXX Does this next part make sense, really? */
conn
->
hold_open_until_flushed
=
1
;
/* give it a last chance */
return
;
}
...
...
@@ -317,6 +363,8 @@ static void run_connection_housekeeping(int i, time_t now) {
if
(
!
connection_speaks_cells
(
conn
))
return
;
/* If we haven't written to an OR connection for a while, then either nuke
the connection or send a keepalive, depending. */
if
(
now
>=
conn
->
timestamp_lastwritten
+
options
.
KeepalivePeriod
)
{
if
((
!
options
.
ORPort
&&
!
circuit_get_by_conn
(
conn
))
||
(
!
connection_state_is_open
(
conn
)))
{
...
...
@@ -450,6 +498,10 @@ static void run_scheduled_events(time_t now) {
conn_close_if_marked
(
i
);
}
/* Called every time we're about to call tor_poll. Increments statistics,
* and adjusts token buckets. Returns the number of milliseconds to use for
* the poll() timeout.
*/
static
int
prepare_for_poll
(
void
)
{
static
long
current_second
=
0
;
/* from previous calls to gettimeofday */
connection_t
*
conn
;
...
...
@@ -458,8 +510,8 @@ static int prepare_for_poll(void) {
tor_gettimeofday
(
&
now
);
/* Check how much bandwidth we've consumed,
*
and increment the token
buckets. */
/* Check how much bandwidth we've consumed,
and increment the token
* buckets. */
stats_n_bytes_read
+=
stats_prev_global_read_bucket
-
global_read_bucket
;
connection_bucket_refill
(
&
now
);
stats_prev_global_read_bucket
=
global_read_bucket
;
...
...
@@ -486,23 +538,30 @@ static int prepare_for_poll(void) {
return
(
1000
-
(
now
.
tv_usec
/
1000
));
/* how many milliseconds til the next second? */
}
/* Configure the Tor process from the command line arguments and from the
* configuration file.
*/
static
int
init_from_config
(
int
argc
,
char
**
argv
)
{
/* read the configuration file. */
if
(
getconfig
(
argc
,
argv
,
&
options
))
{
log_fn
(
LOG_ERR
,
"Reading config failed. For usage, try -h."
);
return
-
1
;
}
close_logs
();
/* we'll close, then open with correct loglevel if necessary */
/* Setuid/setgid as appropriate */
if
(
options
.
User
||
options
.
Group
)
{
if
(
switch_id
(
options
.
User
,
options
.
Group
)
!=
0
)
{
return
-
1
;
}
}
/* Start backgrounding the process, if requested. */
if
(
options
.
RunAsDaemon
)
{
start_daemon
(
options
.
DataDirectory
);
}
/* Configure the log(s) */
if
(
!
options
.
LogFile
&&
!
options
.
RunAsDaemon
)
add_stream_log
(
options
.
loglevel
,
"<stdout>"
,
stdout
);
if
(
options
.
LogFile
)
{
...
...
@@ -520,21 +579,26 @@ static int init_from_config(int argc, char **argv) {
log_fn
(
LOG_DEBUG
,
"Successfully opened DebugLogFile '%s'."
,
options
.
DebugLogFile
);
}
/* Set up our buckets */
connection_bucket_init
();
stats_prev_global_read_bucket
=
global_read_bucket
;
/* Finish backgrounding the process */
if
(
options
.
RunAsDaemon
)
{
/* XXXX Can we delay this any more? */
finish_daemon
();
}
/* write our pid to the pid file, if we do not have write permissions we will log a warning */
/* Write our pid to the pid file. if we do not have write permissions we
* will log a warning */
if
(
options
.
PidFile
)
write_pidfile
(
options
.
PidFile
);
return
0
;
}
/* Called when we get a SIGHUP: reload configuration files and keys,
* retry all connections, re-upload all descriptors, and so on. */
static
int
do_hup
(
void
)
{
char
keydir
[
512
];
...
...
@@ -580,6 +644,7 @@ static int do_hup(void) {
return
0
;
}
/* Tor main loop. */
static
int
do_main_loop
(
void
)
{
int
i
;
int
timeout
;
...
...
@@ -675,6 +740,7 @@ static int do_main_loop(void) {
}
}