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) {
...
@@ -219,8 +219,9 @@ int read_to_buf_tls(tor_tls *tls, size_t at_most, buf_t *buf) {
tor_assert
(
tls
);
tor_assert
(
tls
);
assert_buf_ok
(
buf
);
assert_buf_ok
(
buf
);
log_fn
(
LOG_DEBUG
,
"start: %d on buf, %d pending, at_most %d."
,(
int
)
buf_datalen
(
buf
),
log_fn
(
LOG_DEBUG
,
"start: %d on buf, %d pending, at_most %d."
,
tor_tls_get_pending_bytes
(
tls
),
at_most
);
(
int
)
buf_datalen
(
buf
),
(
int
)
tor_tls_get_pending_bytes
(
tls
),
(
int
)
at_most
);
if
(
buf_ensure_capacity
(
buf
,
at_most
+
buf
->
datalen
))
if
(
buf_ensure_capacity
(
buf
,
at_most
+
buf
->
datalen
))
return
TOR_TLS_ERROR
;
return
TOR_TLS_ERROR
;
...
@@ -231,8 +232,9 @@ int read_to_buf_tls(tor_tls *tls, size_t at_most, buf_t *buf) {
...
@@ -231,8 +232,9 @@ int read_to_buf_tls(tor_tls *tls, size_t at_most, buf_t *buf) {
if
(
at_most
==
0
)
if
(
at_most
==
0
)
return
0
;
return
0
;
log_fn
(
LOG_DEBUG
,
"before: %d on buf, %d pending, at_most %d."
,(
int
)
buf_datalen
(
buf
),
log_fn
(
LOG_DEBUG
,
"before: %d on buf, %d pending, at_most %d."
,
tor_tls_get_pending_bytes
(
tls
),
at_most
);
(
int
)
buf_datalen
(
buf
),
(
int
)
tor_tls_get_pending_bytes
(
tls
),
(
int
)
at_most
);
assert_no_tls_errors
();
assert_no_tls_errors
();
r
=
tor_tls_read
(
tls
,
buf
->
mem
+
buf
->
datalen
,
at_most
);
r
=
tor_tls_read
(
tls
,
buf
->
mem
+
buf
->
datalen
,
at_most
);
...
...
src/or/cpuworker.c
View file @
682a8050
...
@@ -2,6 +2,13 @@
...
@@ -2,6 +2,13 @@
/* See LICENSE for licensing information */
/* See LICENSE for licensing information */
/* $Id$ */
/* $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"
#include
"or.h"
extern
or_options_t
options
;
/* command-line and config-file options */
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 */
...
@@ -14,6 +21,9 @@ extern or_options_t options; /* command-line and config-file options */
static
int
num_cpuworkers
=
0
;
static
int
num_cpuworkers
=
0
;
static
int
num_cpuworkers_busy
=
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
;
static
time_t
last_rotation_time
=
0
;
int
cpuworker_main
(
void
*
data
);
int
cpuworker_main
(
void
*
data
);
...
@@ -21,34 +31,45 @@ static int spawn_cpuworker(void);
...
@@ -21,34 +31,45 @@ static int spawn_cpuworker(void);
static
void
spawn_enough_cpuworkers
(
void
);
static
void
spawn_enough_cpuworkers
(
void
);
static
void
process_pending_task
(
connection_t
*
cpuworker
);
static
void
process_pending_task
(
connection_t
*
cpuworker
);
/* Initialize the cpuworker subsystem.
*/
void
cpu_init
(
void
)
{
void
cpu_init
(
void
)
{
last_rotation_time
=
time
(
NULL
);
last_rotation_time
=
time
(
NULL
);
spawn_enough_cpuworkers
();
spawn_enough_cpuworkers
();
}
}
/* Called when we're done sending a request to a cpuworker. */
int
connection_cpu_finished_flushing
(
connection_t
*
conn
)
{
int
connection_cpu_finished_flushing
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
type
==
CONN_TYPE_CPUWORKER
);
tor_assert
(
conn
&&
conn
->
type
==
CONN_TYPE_CPUWORKER
);
connection_stop_writing
(
conn
);
connection_stop_writing
(
conn
);
return
0
;
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
)
{
static
void
tag_pack
(
char
*
tag
,
uint32_t
addr
,
uint16_t
port
,
uint16_t
circ_id
)
{
*
(
uint32_t
*
)
tag
=
addr
;
*
(
uint32_t
*
)
tag
=
addr
;
*
(
uint16_t
*
)(
tag
+
4
)
=
port
;
*
(
uint16_t
*
)(
tag
+
4
)
=
port
;
*
(
uint16_t
*
)(
tag
+
6
)
=
circ_id
;
*
(
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
;
struct
in_addr
in
;
*
addr
=
*
(
uint32_t
*
)
tag
;
*
addr
=
*
(
const
uint32_t
*
)
tag
;
*
port
=
*
(
uint16_t
*
)(
tag
+
4
);
*
port
=
*
(
const
uint16_t
*
)(
tag
+
4
);
*
circ_id
=
*
(
uint16_t
*
)(
tag
+
6
);
*
circ_id
=
*
(
const
uint16_t
*
)(
tag
+
6
);
in
.
s_addr
=
htonl
(
*
addr
);
in
.
s_addr
=
htonl
(
*
addr
);
log_fn
(
LOG_DEBUG
,
"onion was from %s:%d, circ_id %d."
,
inet_ntoa
(
in
),
*
port
,
*
circ_id
);
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
)
void
cpuworkers_rotate
(
void
)
{
{
connection_t
*
cpuworker
;
connection_t
*
cpuworker
;
...
@@ -61,6 +82,11 @@ void cpuworkers_rotate(void)
...
@@ -61,6 +82,11 @@ void cpuworkers_rotate(void)
spawn_enough_cpuworkers
();
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
)
{
int
connection_cpu_process_inbuf
(
connection_t
*
conn
)
{
char
success
;
char
success
;
unsigned
char
buf
[
LEN_ONION_RESPONSE
];
unsigned
char
buf
[
LEN_ONION_RESPONSE
];
...
@@ -136,6 +162,20 @@ done_processing:
...
@@ -136,6 +162,20 @@ done_processing:
return
0
;
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
)
{
int
cpuworker_main
(
void
*
data
)
{
unsigned
char
question
[
ONIONSKIN_CHALLENGE_LEN
];
unsigned
char
question
[
ONIONSKIN_CHALLENGE_LEN
];
unsigned
char
question_type
;
unsigned
char
question_type
;
...
@@ -209,6 +249,8 @@ int cpuworker_main(void *data) {
...
@@ -209,6 +249,8 @@ int cpuworker_main(void *data) {
return
0
;
/* windows wants this function to return an int */
return
0
;
/* windows wants this function to return an int */
}
}
/* Launch a new cpuworker.
*/
static
int
spawn_cpuworker
(
void
)
{
static
int
spawn_cpuworker
(
void
)
{
int
fd
[
2
];
int
fd
[
2
];
connection_t
*
conn
;
connection_t
*
conn
;
...
@@ -243,6 +285,9 @@ static int spawn_cpuworker(void) {
...
@@ -243,6 +285,9 @@ static int spawn_cpuworker(void) {
return
0
;
/* success */
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
)
{
static
void
spawn_enough_cpuworkers
(
void
)
{
int
num_cpuworkers_needed
=
options
.
NumCpus
;
int
num_cpuworkers_needed
=
options
.
NumCpus
;
...
@@ -260,6 +305,7 @@ static void spawn_enough_cpuworkers(void) {
...
@@ -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
)
{
static
void
process_pending_task
(
connection_t
*
cpuworker
)
{
circuit_t
*
circ
;
circuit_t
*
circ
;
...
...
src/or/dns.c
View file @
682a8050
...
@@ -2,6 +2,10 @@
...
@@ -2,6 +2,10 @@
/* See LICENSE for licensing information */
/* See LICENSE for licensing information */
/* $Id$ */
/* $Id$ */
/*****
* dns.c: Resolve hostnames in separate processes.
*****/
/* See http://elvin.dstc.com/ListArchive/elvin-dev/archive/2001/09/msg00027.html
/* 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
* for some approaches to asynchronous dns. We will want to switch once one of
* them becomes more commonly available.
* them becomes more commonly available.
...
@@ -12,12 +16,19 @@
...
@@ -12,12 +16,19 @@
extern
or_options_t
options
;
/* command-line and config-file options */
extern
or_options_t
options
;
/* command-line and config-file options */
/* Longest hostname we're willing to resolve. */
#define MAX_ADDRESSLEN 256
#define MAX_ADDRESSLEN 256
/* Maximum DNS processes to spawn. */
#define MAX_DNSWORKERS 50
#define MAX_DNSWORKERS 50
/* Minimum DNS processes to spawn. */
#define MIN_DNSWORKERS 3
#define MIN_DNSWORKERS 3
/* If more than this many processes are idle, shut down the extras. */
#define MAX_IDLE_DNSWORKERS 10
#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_TRANSIENT 1
#define DNS_RESOLVE_FAILED_PERMANENT 2
#define DNS_RESOLVE_FAILED_PERMANENT 2
#define DNS_RESOLVE_SUCCEEDED 3
#define DNS_RESOLVE_SUCCEEDED 3
...
@@ -25,11 +36,16 @@ extern or_options_t options; /* command-line and config-file options */
...
@@ -25,11 +36,16 @@ extern or_options_t options; /* command-line and config-file options */
int
num_dnsworkers
=
0
;
int
num_dnsworkers
=
0
;
int
num_dnsworkers_busy
=
0
;
int
num_dnsworkers_busy
=
0
;
/* Linked list of connections waiting for a DNS answer. */
struct
pending_connection_t
{
struct
pending_connection_t
{
struct
connection_t
*
conn
;
struct
connection_t
*
conn
;
struct
pending_connection_t
*
next
;
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
{
struct
cached_resolve
{
SPLAY_ENTRY
(
cached_resolve
)
node
;
SPLAY_ENTRY
(
cached_resolve
)
node
;
char
address
[
MAX_ADDRESSLEN
];
/* the hostname to be resolved */
char
address
[
MAX_ADDRESSLEN
];
/* the hostname to be resolved */
...
@@ -38,7 +54,7 @@ struct cached_resolve {
...
@@ -38,7 +54,7 @@ struct cached_resolve {
#define CACHE_STATE_PENDING 0
#define CACHE_STATE_PENDING 0
#define CACHE_STATE_VALID 1
#define CACHE_STATE_VALID 1
#define CACHE_STATE_FAILED 2
#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
pending_connection_t
*
pending_connections
;
struct
cached_resolve
*
next
;
struct
cached_resolve
*
next
;
};
};
...
@@ -51,8 +67,11 @@ int dnsworker_main(void *data);
...
@@ -51,8 +67,11 @@ int dnsworker_main(void *data);
static
int
spawn_dnsworker
(
void
);
static
int
spawn_dnsworker
(
void
);
static
void
spawn_enough_dnsworkers
(
void
);
static
void
spawn_enough_dnsworkers
(
void
);
/* Splay tree of cached_resolve objects */
static
SPLAY_HEAD
(
cache_tree
,
cached_resolve
)
cache_root
;
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
,
static
int
compare_cached_resolves
(
struct
cached_resolve
*
a
,
struct
cached_resolve
*
b
)
{
struct
cached_resolve
*
b
)
{
/* make this smarter one day? */
/* make this smarter one day? */
...
@@ -62,10 +81,12 @@ static int compare_cached_resolves(struct cached_resolve *a,
...
@@ -62,10 +81,12 @@ static int compare_cached_resolves(struct cached_resolve *a,
SPLAY_PROTOTYPE
(
cache_tree
,
cached_resolve
,
node
,
compare_cached_resolves
);
SPLAY_PROTOTYPE
(
cache_tree
,
cached_resolve
,
node
,
compare_cached_resolves
);
SPLAY_GENERATE
(
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
)
{
static
void
init_cache_tree
(
void
)
{
SPLAY_INIT
(
&
cache_root
);
SPLAY_INIT
(
&
cache_root
);
}
}
/* Initialize the DNS subsystem; called by the OR process. */
void
dns_init
(
void
)
{
void
dns_init
(
void
)
{
init_cache_tree
();
init_cache_tree
();
spawn_enough_dnsworkers
();
spawn_enough_dnsworkers
();
...
@@ -74,6 +95,8 @@ void dns_init(void) {
...
@@ -74,6 +95,8 @@ void dns_init(void) {
static
struct
cached_resolve
*
oldest_cached_resolve
=
NULL
;
/* linked list, */
static
struct
cached_resolve
*
oldest_cached_resolve
=
NULL
;
/* linked list, */
static
struct
cached_resolve
*
newest_cached_resolve
=
NULL
;
/* oldest to newest */
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
)
{
static
void
purge_expired_resolves
(
uint32_t
now
)
{
struct
cached_resolve
*
resolve
;
struct
cached_resolve
*
resolve
;
...
@@ -178,6 +201,9 @@ int dns_resolve(connection_t *exitconn) {
...
@@ -178,6 +201,9 @@ int dns_resolve(connection_t *exitconn) {
return
assign_to_dnsworker
(
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
)
{
static
int
assign_to_dnsworker
(
connection_t
*
exitconn
)
{
connection_t
*
dnsconn
;
connection_t
*
dnsconn
;
unsigned
char
len
;
unsigned
char
len
;
...
@@ -210,6 +236,8 @@ static int assign_to_dnsworker(connection_t *exitconn) {
...
@@ -210,6 +236,8 @@ static int assign_to_dnsworker(connection_t *exitconn) {
return
0
;
return
0
;
}
}
/* Remove 'conn' from the list of connections waiting for conn->address.
*/
void
connection_dns_remove
(
connection_t
*
conn
)
void
connection_dns_remove
(
connection_t
*
conn
)
{
{
struct
pending_connection_t
*
pend
,
*
victim
;
struct
pending_connection_t
*
pend
,
*
victim
;
...
@@ -251,6 +279,8 @@ void connection_dns_remove(connection_t *conn)
...
@@ -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
)
{
void
assert_connection_edge_not_dns_pending
(
connection_t
*
conn
)
{
struct
pending_connection_t
*
pend
;
struct
pending_connection_t
*
pend
;
struct
cached_resolve
*
resolve
;
struct
cached_resolve
*
resolve
;
...
@@ -264,6 +294,8 @@ void assert_connection_edge_not_dns_pending(connection_t *conn) {
...
@@ -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
)
{
void
assert_all_pending_dns_resolves_ok
(
void
)
{
struct
pending_connection_t
*
pend
;
struct
pending_connection_t
*
pend
;
struct
cached_resolve
*
resolve
;
struct
cached_resolve
*
resolve
;
...
@@ -277,8 +309,9 @@ void assert_all_pending_dns_resolves_ok(void) {
...
@@ -277,8 +309,9 @@ void assert_all_pending_dns_resolves_ok(void) {
}
}
}
}
/* Cancel all pending connections. Then cancel the resolve itself,
/* Mark all connections waiting for 'address' for close. Then cancel
* and remove the 'struct cached_resolve' from the cache.
* the resolve for 'address' itself, and remove any cached results for
* 'address' from the cache.
*/
*/
void
dns_cancel_pending_resolve
(
char
*
address
)
{
void
dns_cancel_pending_resolve
(
char
*
address
)
{
struct
pending_connection_t
*
pend
;
struct
pending_connection_t
*
pend
;
...
@@ -314,6 +347,8 @@ void dns_cancel_pending_resolve(char *address) {
...
@@ -314,6 +347,8 @@ void dns_cancel_pending_resolve(char *address) {
dns_purge_resolve
(
resolve
);
dns_purge_resolve
(
resolve
);
}
}
/* Remove 'resolve' from the cache.
*/
static
void
dns_purge_resolve
(
struct
cached_resolve
*
resolve
)
{
static
void
dns_purge_resolve
(
struct
cached_resolve
*
resolve
)
{
struct
cached_resolve
*
tmp
;
struct
cached_resolve
*
tmp
;
...
@@ -338,6 +373,12 @@ static void dns_purge_resolve(struct cached_resolve *resolve) {
...
@@ -338,6 +373,12 @@ static void dns_purge_resolve(struct cached_resolve *resolve) {
tor_free
(
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
)
{
static
void
dns_found_answer
(
char
*
address
,
uint32_t
addr
,
char
outcome
)
{
struct
pending_connection_t
*
pend
;
struct
pending_connection_t
*
pend
;
struct
cached_resolve
search
;
struct
cached_resolve
search
;
...
@@ -356,6 +397,8 @@ static void dns_found_answer(char *address, uint32_t addr, char outcome) {
...
@@ -356,6 +397,8 @@ static void dns_found_answer(char *address, uint32_t addr, char outcome) {
}
}
if
(
resolve
->
state
!=
CACHE_STATE_PENDING
)
{
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"
,
log_fn
(
LOG_WARN
,
"Resolved '%s' which was already resolved; ignoring"
,
address
);
address
);
tor_assert
(
resolve
->
pending_connections
==
NULL
);
tor_assert
(
resolve
->
pending_connections
==
NULL
);
...
@@ -401,12 +444,21 @@ static void dns_found_answer(char *address, uint32_t addr, char outcome) {
...
@@ -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
)
{
int
connection_dns_finished_flushing
(
connection_t
*
conn
)
{
tor_assert
(
conn
&&
conn
->
type
==
CONN_TYPE_DNSWORKER
);
tor_assert
(
conn
&&
conn
->
type
==
CONN_TYPE_DNSWORKER
);
connection_stop_writing
(
conn
);
connection_stop_writing
(
conn
);
return
0
;
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
)
{
int
connection_dns_process_inbuf
(
connection_t
*
conn
)
{
char
success
;
char
success
;
uint32_t
addr
;
uint32_t
addr
;
...
@@ -447,6 +499,23 @@ int connection_dns_process_inbuf(connection_t *conn) {
...
@@ -447,6 +499,23 @@ int connection_dns_process_inbuf(connection_t *conn) {
return
0
;
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
)
{
int
dnsworker_main
(
void
*
data
)
{
char
address
[
MAX_ADDRESSLEN
];
char
address
[
MAX_ADDRESSLEN
];
unsigned
char
address_len
;
unsigned
char
address_len
;
...
@@ -498,6 +567,8 @@ int dnsworker_main(void *data) {
...
@@ -498,6 +567,8 @@ int dnsworker_main(void *data) {
return
0
;
/* windows wants this function to return an int */
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
)
{
static
int
spawn_dnsworker
(
void
)
{
int
fd
[
2
];
int
fd
[
2
];
connection_t
*
conn
;
connection_t
*
conn
;
...
@@ -532,6 +603,8 @@ static int spawn_dnsworker(void) {
...
@@ -532,6 +603,8 @@ static int spawn_dnsworker(void) {
return
0
;
/* success */
return
0
;
/* success */
}
}
/* If we have too many or too few DNS workers, spawn or kill some.
*/
static
void
spawn_enough_dnsworkers
(
void
)
{
static
void
spawn_enough_dnsworkers
(
void
)
{
int
num_dnsworkers_needed
;
/* aim to have 1 more than needed,
int
num_dnsworkers_needed
;
/* aim to have 1 more than needed,
* but no less than min and no more than max */
* but no less than min and no more than max */
...
...
src/or/main.c
View file @
682a8050
...
@@ -2,6 +2,10 @@
...
@@ -2,6 +2,10 @@
/* See LICENSE for licensing information */
/* See LICENSE for licensing information */
/* $Id$ */
/* $Id$ */
/*****
* main.c: Tor main loop and startup functions.
*****/
#include
"or.h"
#include
"or.h"
/********* PROTOTYPES **********/
/********* PROTOTYPES **********/
...
@@ -11,18 +15,26 @@ static int init_from_config(int argc, char **argv);
...
@@ -11,18 +15,26 @@ static int init_from_config(int argc, char **argv);
/********* START VARIABLES **********/
/********* START VARIABLES **********/
/* declared in connection.c */
extern
char
*
conn_state_to_string
[][
_CONN_TYPE_MAX
+
1
];
extern
char
*
conn_state_to_string
[][
_CONN_TYPE_MAX
+
1
];
or_options_t
options
;
/* command-line and config-file options */
or_options_t
options
;
/* command-line and config-file options */
int
global_read_bucket
;
/* max number of bytes I can read this second */
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
;
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
;
static
uint64_t
stats_n_bytes_read
=
0
;
/* How many seconds have we been running? */
static
long
stats_n_seconds_reading
=
0
;
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
]
=
static
connection_t
*
connection_array
[
MAXCONNECTIONS
]
=
{
NULL
};
{
NULL
};
/* Array of pollfd objects for calls to poll(). */
static
struct
pollfd
poll_array
[
MAXCONNECTIONS
];
static
struct
pollfd
poll_array
[
MAXCONNECTIONS
];
static
int
nfds
=
0
;
/* number of connections currently active */
static
int
nfds
=
0
;
/* number of connections currently active */
...
@@ -33,14 +45,14 @@ static int please_reset=0; /* whether we just got a sighup */
...
@@ -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 */
static
int
please_reap_children
=
0
;
/* whether we should waitpid for exited children */
#endif
/* signal stuff */
#endif
/* signal stuff */
int
has_fetched_directory
=
0
;
/* we set this to 1 when we've fetched a dir, to know whether to complain
/* we set this to 1 when we've fetched a dir, to know whether to complain
* yet about unrecognized nicknames in entrynodes, exitnodes, etc.
* yet about unrecognized nicknames in entrynodes, exitnodes, etc.
* Also, we don't try building circuits unless this is 1. */
* 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
/* 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. */
* entry to inform the user that Tor is working. */
int
has_completed_circuit
=
0
;
/********* END VARIABLES ************/
/********* END VARIABLES ************/
...
@@ -52,6 +64,10 @@ int has_completed_circuit=0;
...
@@ -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.