mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
Refactor directory servers
* read all the time (before we would ignore eof sometimes, oops) * we can handle different urls now * send back 404 for an un-handled url * commands initiated by the client can handle payloads now * introduce conn->purpose to avoid exponential state-space explosion svn:r1400
This commit is contained in:
parent
919a8f236e
commit
2d3ac08633
@ -49,14 +49,11 @@ char *conn_state_to_string[][_CONN_TYPE_MAX+1] = {
|
||||
"open" }, /* 8 */
|
||||
{ "ready" }, /* dir listener, 0 */
|
||||
{ "", /* dir, 0 */
|
||||
"connecting (fetch)", /* 1 */
|
||||
"connecting (upload)", /* 2 */
|
||||
"client sending fetch", /* 3 */
|
||||
"client sending upload", /* 4 */
|
||||
"client reading fetch", /* 5 */
|
||||
"client reading upload", /* 6 */
|
||||
"awaiting command", /* 7 */
|
||||
"writing" }, /* 8 */
|
||||
"connecting", /* 1 */
|
||||
"client sending", /* 2 */
|
||||
"client reading", /* 3 */
|
||||
"awaiting command", /* 4 */
|
||||
"writing" }, /* 5 */
|
||||
{ "", /* dns worker, 0 */
|
||||
"idle", /* 1 */
|
||||
"busy" }, /* 2 */
|
||||
@ -373,6 +370,7 @@ static int connection_init_accepted_conn(connection_t *conn) {
|
||||
conn->state = AP_CONN_STATE_SOCKS_WAIT;
|
||||
break;
|
||||
case CONN_TYPE_DIR:
|
||||
conn->purpose = DIR_PURPOSE_SERVER;
|
||||
conn->state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
|
||||
break;
|
||||
}
|
||||
@ -599,8 +597,7 @@ int connection_handle_read(connection_t *conn) {
|
||||
|
||||
if(connection_read_to_buf(conn) < 0) {
|
||||
if(conn->type == CONN_TYPE_DIR &&
|
||||
(conn->state == DIR_CONN_STATE_CONNECTING_FETCH ||
|
||||
conn->state == DIR_CONN_STATE_CONNECTING_UPLOAD)) {
|
||||
conn->state == DIR_CONN_STATE_CONNECTING) {
|
||||
/* it's a directory server and connecting failed: forget about this router */
|
||||
/* XXX I suspect pollerr may make Windows not get to this point. :( */
|
||||
router_mark_as_down(conn->nickname);
|
||||
@ -1029,6 +1026,9 @@ void assert_connection_ok(connection_t *conn, time_t now)
|
||||
} else {
|
||||
assert(!conn->socks_request);
|
||||
}
|
||||
if(conn->type != CONN_TYPE_DIR) {
|
||||
assert(!conn->purpose); /* only used for dir types currently */
|
||||
}
|
||||
|
||||
switch(conn->type)
|
||||
{
|
||||
@ -1053,6 +1053,8 @@ void assert_connection_ok(connection_t *conn, time_t now)
|
||||
case CONN_TYPE_DIR:
|
||||
assert(conn->state >= _DIR_CONN_STATE_MIN &&
|
||||
conn->state <= _DIR_CONN_STATE_MAX);
|
||||
assert(conn->purpose >= _DIR_PURPOSE_MIN &&
|
||||
conn->purpose <= _DIR_PURPOSE_MAX);
|
||||
break;
|
||||
case CONN_TYPE_DNSWORKER:
|
||||
assert(conn->state == DNSWORKER_STATE_IDLE ||
|
||||
|
@ -4,7 +4,8 @@
|
||||
|
||||
#include "or.h"
|
||||
|
||||
static int directory_send_command(connection_t *conn, int command);
|
||||
static void directory_send_command(connection_t *conn,
|
||||
int purpose, const char *payload);
|
||||
static int directory_handle_command(connection_t *conn);
|
||||
|
||||
/********* START VARIABLES **********/
|
||||
@ -17,20 +18,26 @@ extern int has_fetched_directory;
|
||||
|
||||
/********* END VARIABLES ************/
|
||||
|
||||
void directory_initiate_command(routerinfo_t *router, int command) {
|
||||
void directory_initiate_command(routerinfo_t *router, int purpose, const char *payload) {
|
||||
connection_t *conn;
|
||||
|
||||
switch(command) {
|
||||
case DIR_CONN_STATE_CONNECTING_FETCH:
|
||||
switch(purpose) {
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
log_fn(LOG_DEBUG,"initiating directory fetch");
|
||||
break;
|
||||
case DIR_CONN_STATE_CONNECTING_UPLOAD:
|
||||
log_fn(LOG_DEBUG,"initiating directory upload");
|
||||
case DIR_PURPOSE_FETCH_HIDSERV:
|
||||
log_fn(LOG_DEBUG,"initiating hidden-service descriptor fetch");
|
||||
break;
|
||||
case DIR_PURPOSE_UPLOAD_DIR:
|
||||
log_fn(LOG_DEBUG,"initiating server descriptor upload");
|
||||
break;
|
||||
case DIR_PURPOSE_UPLOAD_HIDSERV:
|
||||
log_fn(LOG_DEBUG,"initiating hidden-service descriptor upload");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!router) { /* i guess they didn't have one in mind for me to use */
|
||||
log_fn(LOG_WARN,"No running dirservers known. Not trying.");
|
||||
log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -44,57 +51,99 @@ void directory_initiate_command(routerinfo_t *router, int command) {
|
||||
assert(router->identity_pkey);
|
||||
conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
|
||||
|
||||
conn->state = command;
|
||||
conn->purpose = purpose;
|
||||
|
||||
if(connection_add(conn) < 0) { /* no space, forget it */
|
||||
connection_free(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(connection_connect(conn, router->address, router->addr, router->dir_port)) {
|
||||
/* queue the command on the outbuf */
|
||||
directory_send_command(conn, purpose, payload);
|
||||
|
||||
if(purpose == DIR_PURPOSE_FETCH_DIR ||
|
||||
purpose == DIR_PURPOSE_UPLOAD_DIR) {
|
||||
|
||||
/* then we want to connect directly */
|
||||
conn->state = DIR_CONN_STATE_CONNECTING;
|
||||
|
||||
switch(connection_connect(conn, conn->address, conn->addr, conn->port)) {
|
||||
case -1:
|
||||
router_mark_as_down(conn->nickname); /* don't try him again */
|
||||
connection_mark_for_close(conn, 0);
|
||||
return;
|
||||
case 1:
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
|
||||
/* fall through */
|
||||
case 0:
|
||||
connection_set_poll_socket(conn);
|
||||
connection_watch_events(conn, POLLIN | POLLOUT | POLLERR);
|
||||
/* writable indicates finish, readable indicates broken link,
|
||||
error indicates broken link in windowsland. */
|
||||
return;
|
||||
/* case 1: fall through */
|
||||
}
|
||||
} else { /* we want to connect via tor */
|
||||
/* make an AP connection
|
||||
* populate it and add it at the right state
|
||||
* socketpair and hook up both sides
|
||||
*/
|
||||
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING;
|
||||
connection_set_poll_socket(conn);
|
||||
if(directory_send_command(conn, command) < 0) {
|
||||
connection_mark_for_close(conn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int directory_send_command(connection_t *conn, int command) {
|
||||
static void directory_send_command(connection_t *conn,
|
||||
int purpose, const char *payload) {
|
||||
char fetchstring[] = "GET / HTTP/1.0\r\n\r\n";
|
||||
const char *s;
|
||||
char tmp[8192];
|
||||
|
||||
assert(conn && conn->type == CONN_TYPE_DIR);
|
||||
|
||||
switch(command) {
|
||||
case DIR_CONN_STATE_CONNECTING_FETCH:
|
||||
switch(purpose) {
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
assert(payload == NULL);
|
||||
connection_write_to_buf(fetchstring, strlen(fetchstring), conn);
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING_FETCH;
|
||||
break;
|
||||
case DIR_CONN_STATE_CONNECTING_UPLOAD:
|
||||
s = router_get_my_descriptor();
|
||||
if(!s) {
|
||||
log_fn(LOG_WARN,"Failed to get my descriptor.");
|
||||
return -1;
|
||||
}
|
||||
case DIR_PURPOSE_UPLOAD_DIR:
|
||||
assert(payload);
|
||||
snprintf(tmp, sizeof(tmp), "POST / HTTP/1.0\r\nContent-Length: %d\r\n\r\n%s",
|
||||
(int)strlen(s), s);
|
||||
(int)strlen(payload), payload);
|
||||
connection_write_to_buf(tmp, strlen(tmp), conn);
|
||||
break;
|
||||
case DIR_PURPOSE_FETCH_HIDSERV:
|
||||
assert(payload);
|
||||
snprintf(tmp, sizeof(tmp), "GET /hidserv/%s HTTP/1.0\r\n\r\n", payload);
|
||||
connection_write_to_buf(tmp, strlen(tmp), conn);
|
||||
break;
|
||||
case DIR_PURPOSE_UPLOAD_HIDSERV:
|
||||
assert(payload);
|
||||
snprintf(tmp, sizeof(tmp),
|
||||
"POST /hidserv/ HTTP/1.0\r\nContent-Length: %d\r\n\r\n%s",
|
||||
(int)strlen(payload), payload);
|
||||
connection_write_to_buf(tmp, strlen(tmp), conn);
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING_UPLOAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse "%s %s HTTP/1..."
|
||||
* If it's well-formed, point *url to the second %s,
|
||||
* null-terminate it (this modifies headers!) and return 0.
|
||||
* Otherwise, return -1.
|
||||
*/
|
||||
int parse_http_url(char *headers, char **url) {
|
||||
char *s, *tmp;
|
||||
|
||||
s = (char *)eat_whitespace_no_nl(headers);
|
||||
if (!*s) return -1;
|
||||
s = (char *)find_whitespace(s); /* get past GET/POST */
|
||||
if (!*s) return -1;
|
||||
s = (char *)eat_whitespace_no_nl(s);
|
||||
if (!*s) return -1;
|
||||
tmp = s; /* this is it, assuming it's valid */
|
||||
s = (char *)find_whitespace(s);
|
||||
if (!*s) return -1;
|
||||
*s = 0;
|
||||
*url = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -131,8 +180,7 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
assert(conn && conn->type == CONN_TYPE_DIR);
|
||||
|
||||
if(conn->inbuf_reached_eof) {
|
||||
if(conn->state != DIR_CONN_STATE_CLIENT_READING_FETCH &&
|
||||
conn->state != DIR_CONN_STATE_CLIENT_READING_UPLOAD) {
|
||||
if(conn->state != DIR_CONN_STATE_CLIENT_READING) {
|
||||
log_fn(LOG_INFO,"conn reached eof, not reading. Closing.");
|
||||
connection_close_immediate(conn); /* it was an error; give up on flushing */
|
||||
connection_mark_for_close(conn,0);
|
||||
@ -160,7 +208,7 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(conn->state == DIR_CONN_STATE_CLIENT_READING_FETCH) {
|
||||
if(conn->purpose == DIR_PURPOSE_FETCH_DIR) {
|
||||
/* fetch/process the directory to learn about new routers. */
|
||||
int directorylen;
|
||||
directorylen = strlen(directory);
|
||||
@ -192,7 +240,7 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(conn->state == DIR_CONN_STATE_CLIENT_READING_UPLOAD) {
|
||||
if(conn->purpose == DIR_PURPOSE_UPLOAD_DIR) {
|
||||
switch(status_code) {
|
||||
case 200:
|
||||
log_fn(LOG_INFO,"eof (status 200) while reading upload response: finished.");
|
||||
@ -203,16 +251,36 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
case 403:
|
||||
log_fn(LOG_WARN,"http status 403 (unapproved server) response from dirserver. Is your clock skewed? Have you mailed arma your identity fingerprint? Are you using the right key?");
|
||||
|
||||
break;
|
||||
default:
|
||||
log_fn(LOG_WARN,"http status %d response unrecognized.", status_code);
|
||||
break;
|
||||
}
|
||||
free(directory); free(headers);
|
||||
connection_mark_for_close(conn,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(conn->purpose == DIR_PURPOSE_FETCH_HIDSERV) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT)
|
||||
return directory_handle_command(conn);
|
||||
if(conn->purpose == DIR_PURPOSE_UPLOAD_HIDSERV) {
|
||||
|
||||
|
||||
}
|
||||
assert(0); /* never reached */
|
||||
}
|
||||
|
||||
if(conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
|
||||
if (directory_handle_command(conn) < 0) {
|
||||
connection_mark_for_close(conn,0);
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX for READ states, might want to make sure inbuf isn't too big */
|
||||
|
||||
@ -223,38 +291,69 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
static char answer200[] = "HTTP/1.0 200 OK\r\n\r\n";
|
||||
static char answer400[] = "HTTP/1.0 400 Bad request\r\n\r\n";
|
||||
static char answer403[] = "HTTP/1.0 403 Unapproved server\r\n\r\n";
|
||||
static char answer404[] = "HTTP/1.0 404 Not found\r\n\r\n";
|
||||
static char answer503[] = "HTTP/1.0 503 Directory unavailable\r\n\r\n";
|
||||
|
||||
/* always returns 0 */
|
||||
static int directory_handle_command_get(connection_t *conn,
|
||||
char *headers, char *body) {
|
||||
size_t dlen;
|
||||
const char *cp;
|
||||
char *url;
|
||||
|
||||
/* XXX should check url and http version */
|
||||
log_fn(LOG_DEBUG,"Received GET command.");
|
||||
|
||||
conn->state = DIR_CONN_STATE_SERVER_WRITING;
|
||||
|
||||
if (parse_http_url(headers, &url) < 0) {
|
||||
connection_write_to_buf(answer400, strlen(answer400), conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!strcmp(url,"/")) { /* directory fetch */
|
||||
dlen = dirserv_get_directory(&cp);
|
||||
|
||||
if(dlen == 0) {
|
||||
log_fn(LOG_WARN,"My directory is empty. Closing.");
|
||||
connection_write_to_buf(answer503, strlen(answer503), conn);
|
||||
conn->state = DIR_CONN_STATE_SERVER_WRITING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_fn(LOG_DEBUG,"Dumping directory to client.");
|
||||
connection_write_to_buf(answer200, strlen(answer200), conn);
|
||||
connection_write_to_buf(cp, dlen, conn);
|
||||
conn->state = DIR_CONN_STATE_SERVER_WRITING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!strncmp(url,"/hidserv/",9)) { /* hidserv descriptor fetch */
|
||||
/* ask back-end for the hidden-services descriptor in
|
||||
* url+9, and return it with a 200 if valid, or give a 404
|
||||
* otherwise
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/* we didn't recognize the url */
|
||||
connection_write_to_buf(answer404, strlen(answer404), conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* always returns 0 */
|
||||
static int directory_handle_command_post(connection_t *conn,
|
||||
char *headers, char *body) {
|
||||
const char *cp;
|
||||
char *url;
|
||||
|
||||
/* XXX should check url and http version */
|
||||
log_fn(LOG_DEBUG,"Received POST command.");
|
||||
|
||||
conn->state = DIR_CONN_STATE_SERVER_WRITING;
|
||||
|
||||
if (parse_http_url(headers, &url) < 0) {
|
||||
connection_write_to_buf(answer400, strlen(answer400), conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!strcmp(url,"/")) { /* server descriptor post */
|
||||
cp = body;
|
||||
switch(dirserv_add_descriptor(&cp)) {
|
||||
case -1:
|
||||
@ -270,7 +369,16 @@ static int directory_handle_command_post(connection_t *conn,
|
||||
connection_write_to_buf(answer200, strlen(answer200), conn);
|
||||
break;
|
||||
}
|
||||
conn->state = DIR_CONN_STATE_SERVER_WRITING;
|
||||
}
|
||||
|
||||
if(!strncmp(url,"/hidserv/",9)) { /* hidserv descriptor post */
|
||||
/* pass 'body' to the backend */
|
||||
/* return 400, 403, or 200 as appropriate */
|
||||
|
||||
}
|
||||
|
||||
/* we didn't recognize the url */
|
||||
connection_write_to_buf(answer404, strlen(answer404), conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -312,8 +420,7 @@ int connection_dir_finished_flushing(connection_t *conn) {
|
||||
assert(conn && conn->type == CONN_TYPE_DIR);
|
||||
|
||||
switch(conn->state) {
|
||||
case DIR_CONN_STATE_CONNECTING_FETCH:
|
||||
case DIR_CONN_STATE_CONNECTING_UPLOAD:
|
||||
case DIR_CONN_STATE_CONNECTING:
|
||||
if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0) { /* not yet */
|
||||
if(!ERRNO_CONN_EINPROGRESS(errno)) {
|
||||
log_fn(LOG_DEBUG,"in-progress connect failed. Removing.");
|
||||
@ -329,16 +436,12 @@ int connection_dir_finished_flushing(connection_t *conn) {
|
||||
log_fn(LOG_INFO,"Dir connection to router %s:%u established.",
|
||||
conn->address,conn->port);
|
||||
|
||||
return directory_send_command(conn, conn->state);
|
||||
case DIR_CONN_STATE_CLIENT_SENDING_FETCH:
|
||||
log_fn(LOG_DEBUG,"client finished sending fetch command.");
|
||||
conn->state = DIR_CONN_STATE_CLIENT_READING_FETCH;
|
||||
connection_watch_events(conn, POLLIN);
|
||||
conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
|
||||
return 0;
|
||||
case DIR_CONN_STATE_CLIENT_SENDING_UPLOAD:
|
||||
log_fn(LOG_DEBUG,"client finished sending upload command.");
|
||||
conn->state = DIR_CONN_STATE_CLIENT_READING_UPLOAD;
|
||||
connection_watch_events(conn, POLLIN);
|
||||
case DIR_CONN_STATE_CLIENT_SENDING:
|
||||
log_fn(LOG_DEBUG,"client finished sending command.");
|
||||
conn->state = DIR_CONN_STATE_CLIENT_READING;
|
||||
connection_stop_writing(conn);
|
||||
return 0;
|
||||
case DIR_CONN_STATE_SERVER_WRITING:
|
||||
log_fn(LOG_INFO,"Finished writing server response. Closing.");
|
||||
|
@ -329,7 +329,7 @@ static void run_scheduled_events(time_t now) {
|
||||
/* NOTE directory servers do not currently fetch directories.
|
||||
* Hope this doesn't bite us later. */
|
||||
directory_initiate_command(router_pick_directory_server(),
|
||||
DIR_CONN_STATE_CONNECTING_FETCH);
|
||||
DIR_PURPOSE_FETCH_DIR, NULL);
|
||||
} else {
|
||||
/* We're a directory; dump any old descriptors. */
|
||||
dirserv_remove_old_servers();
|
||||
@ -519,7 +519,8 @@ static int do_hup(void) {
|
||||
}
|
||||
} else {
|
||||
/* fetch a new directory */
|
||||
directory_initiate_command(router_pick_directory_server(), DIR_CONN_STATE_CONNECTING_FETCH);
|
||||
directory_initiate_command(router_pick_directory_server(),
|
||||
DIR_PURPOSE_FETCH_DIR, NULL);
|
||||
}
|
||||
if(options.ORPort) {
|
||||
router_rebuild_descriptor();
|
||||
|
26
src/or/or.h
26
src/or/or.h
@ -171,15 +171,20 @@
|
||||
#define _AP_CONN_STATE_MAX 8
|
||||
|
||||
#define _DIR_CONN_STATE_MIN 1
|
||||
#define DIR_CONN_STATE_CONNECTING_FETCH 1
|
||||
#define DIR_CONN_STATE_CONNECTING_UPLOAD 2
|
||||
#define DIR_CONN_STATE_CLIENT_SENDING_FETCH 3
|
||||
#define DIR_CONN_STATE_CLIENT_SENDING_UPLOAD 4
|
||||
#define DIR_CONN_STATE_CLIENT_READING_FETCH 5
|
||||
#define DIR_CONN_STATE_CLIENT_READING_UPLOAD 6
|
||||
#define DIR_CONN_STATE_SERVER_COMMAND_WAIT 7
|
||||
#define DIR_CONN_STATE_SERVER_WRITING 8
|
||||
#define _DIR_CONN_STATE_MAX 8
|
||||
#define DIR_CONN_STATE_CONNECTING 1
|
||||
#define DIR_CONN_STATE_CLIENT_SENDING 2
|
||||
#define DIR_CONN_STATE_CLIENT_READING 3
|
||||
#define DIR_CONN_STATE_SERVER_COMMAND_WAIT 4
|
||||
#define DIR_CONN_STATE_SERVER_WRITING 5
|
||||
#define _DIR_CONN_STATE_MAX 5
|
||||
|
||||
#define _DIR_PURPOSE_MIN 1
|
||||
#define DIR_PURPOSE_FETCH_DIR 1
|
||||
#define DIR_PURPOSE_FETCH_HIDSERV 2
|
||||
#define DIR_PURPOSE_UPLOAD_DIR 3
|
||||
#define DIR_PURPOSE_UPLOAD_HIDSERV 4
|
||||
#define DIR_PURPOSE_SERVER 5
|
||||
#define _DIR_PURPOSE_MAX 5
|
||||
|
||||
#define CIRCUIT_STATE_BUILDING 0 /* I'm the OP, still haven't done all my handshakes */
|
||||
#define CIRCUIT_STATE_ONIONSKIN_PENDING 1 /* waiting to process the onionskin */
|
||||
@ -331,6 +336,7 @@ struct connection_t {
|
||||
|
||||
uint8_t type;
|
||||
uint8_t state;
|
||||
uint8_t purpose; /* only used for DIR types currently */
|
||||
uint8_t wants_to_read; /* should we start reading again once
|
||||
* the bandwidth throttler allows it?
|
||||
*/
|
||||
@ -830,7 +836,7 @@ int assign_to_cpuworker(connection_t *cpuworker, unsigned char question_type,
|
||||
|
||||
/********************************* directory.c ***************************/
|
||||
|
||||
void directory_initiate_command(routerinfo_t *router, int command);
|
||||
void directory_initiate_command(routerinfo_t *router, int purpose, const char *payload);
|
||||
int connection_dir_process_inbuf(connection_t *conn);
|
||||
int connection_dir_finished_flushing(connection_t *conn);
|
||||
|
||||
|
@ -236,12 +236,14 @@ void router_upload_desc_to_dirservers(void) {
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
routerlist_t *rl;
|
||||
const char *s;
|
||||
|
||||
router_get_routerlist(&rl);
|
||||
if(!rl)
|
||||
return;
|
||||
|
||||
if (!router_get_my_descriptor()) {
|
||||
s = router_get_my_descriptor();
|
||||
if (!s) {
|
||||
log_fn(LOG_WARN, "No descriptor; skipping upload");
|
||||
return;
|
||||
}
|
||||
@ -249,7 +251,7 @@ void router_upload_desc_to_dirservers(void) {
|
||||
for(i=0;i<rl->n_routers;i++) {
|
||||
router = rl->routers[i];
|
||||
if(router->dir_port > 0)
|
||||
directory_initiate_command(router, DIR_CONN_STATE_CONNECTING_UPLOAD);
|
||||
directory_initiate_command(router, DIR_PURPOSE_UPLOAD_DIR, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user