📄 directory.c
字号:
log_warn(LD_PROTOCOL,
"'fetch' response too large (server '%s:%d'). Closing.",
conn->_base.address, conn->_base.port);
return -1;
case 0:
log_info(LD_HTTP,
"'fetch' response not all here, but we're at eof. Closing.");
return -1;
/* case 1, fall through */
}
orig_len = body_len;
if (parse_http_response(headers, &status_code, &date_header,
&compression, &reason) < 0) {
log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers);
return -1;
}
if (!reason) reason = tor_strdup("[no reason given]");
log_debug(LD_DIR,
"Received response from directory server '%s:%d': %d %s",
conn->_base.address, conn->_base.port, status_code,
escaped(reason));
/* now check if it's got any hints for us about our IP address. */
if (conn->dirconn_direct) {
char *guess = http_get_header(headers, X_ADDRESS_HEADER);
if (guess) {
router_new_address_suggestion(guess, conn);
tor_free(guess);
}
}
if (date_header > 0) {
/* The date header was written very soon after we sent our request,
* so compute the skew as the difference between sending the request
* and the date header. (We used to check now-date_header, but that's
* inaccurate if we spend a lot of time downloading.)
*/
delta = conn->_base.timestamp_lastwritten - date_header;
if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
char dbuf[64];
int trusted = router_digest_is_trusted_dir(conn->identity_digest);
format_time_interval(dbuf, sizeof(dbuf), delta);
log_fn(trusted ? LOG_WARN : LOG_INFO,
LD_HTTP,
"Received directory with skewed time (server '%s:%d'): "
"It seems that our clock is %s by %s, or that theirs is %s. "
"Tor requires an accurate clock to work: please check your time "
"and date settings.",
conn->_base.address, conn->_base.port,
delta>0 ? "ahead" : "behind", dbuf,
delta>0 ? "behind" : "ahead");
skewed = 1; /* don't check the recommended-versions line */
control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
"CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d",
delta, conn->_base.address, conn->_base.port);
} else {
log_debug(LD_HTTP, "Time on received directory is within tolerance; "
"we are %ld seconds skewed. (That's okay.)", delta);
}
}
(void) skewed; /* skewed isn't used yet. */
if (status_code == 503 && body_len < 16) {
routerstatus_t *rs;
trusted_dir_server_t *ds;
log_info(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
rs->last_dir_503_at = now;
if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
ds->fake_status.last_dir_503_at = now;
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
} else if (status_code == 503) {
/* XXXX022 Remove this once every server with bug 539 is obsolete. */
log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
"a body anyway. We'll pretend it gave us a 200.",
conn->_base.address, conn->_base.port);
status_code = 200;
}
plausible = body_is_plausible(body, body_len, conn->_base.purpose);
if (compression != NO_METHOD || !plausible) {
char *new_body = NULL;
size_t new_len = 0;
compress_method_t guessed = detect_compression_method(body, body_len);
if (compression == UNKNOWN_METHOD || guessed != compression) {
/* Tell the user if we don't believe what we're told about compression.*/
const char *description1, *description2;
if (compression == ZLIB_METHOD)
description1 = "as deflated";
else if (compression == GZIP_METHOD)
description1 = "as gzipped";
else if (compression == NO_METHOD)
description1 = "as uncompressed";
else
description1 = "with an unknown Content-Encoding";
if (guessed == ZLIB_METHOD)
description2 = "deflated";
else if (guessed == GZIP_METHOD)
description2 = "gzipped";
else if (!plausible)
description2 = "confusing binary junk";
else
description2 = "uncompressed";
log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
"but it seems to be %s.%s",
conn->_base.address, conn->_base.port, description1,
description2,
(compression>0 && guessed>0)?" Trying both.":"");
}
/* Try declared compression first if we can. */
if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
!allow_partial, LOG_PROTOCOL_WARN);
/* Okay, if that didn't work, and we think that it was compressed
* differently, try that. */
if (!new_body &&
(guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
compression != guessed)
tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
!allow_partial, LOG_PROTOCOL_WARN);
/* If we're pretty sure that we have a compressed directory, and
* we didn't manage to uncompress it, then warn and bail. */
if (!plausible && !new_body) {
log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
"Unable to decompress HTTP body (server '%s:%d').",
conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
if (new_body) {
tor_free(body);
body = new_body;
body_len = new_len;
was_compressed = 1;
}
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
/* fetch/process the directory to cache it. */
log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
(int)body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) {
log_warn(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d' while fetching directory. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
if (router_parse_directory(body) < 0) {
log_notice(LD_DIR,"I failed to parse the directory I fetched from "
"'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
}
note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
/* just update our list of running routers, if this list is new info */
log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
if (status_code != 200) {
log_warn(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d' while fetching running-routers. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
if (router_parse_runningrouters(body)<0) {
log_warn(LD_DIR,
"Bad running-routers from server '%s:%d'. I'll try again soon.",
conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
note_request(was_compressed?"dl/running-routers.z":
"dl/running-routers", orig_len);
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
smartlist_t *which = NULL;
networkstatus_source_t source;
char *cp;
log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
"'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
"'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port, conn->requested_resource);
tor_free(body); tor_free(headers); tor_free(reason);
connection_dir_download_networkstatus_failed(conn, status_code);
return -1;
}
note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"fp/")) {
source = NS_FROM_DIR_BY_FP;
which = smartlist_create();
dir_split_resource_into_fingerprints(conn->requested_resource+3,
which, NULL, 0, 0);
} else if (conn->requested_resource &&
!strcmpstart(conn->requested_resource, "all")) {
source = NS_FROM_DIR_ALL;
which = smartlist_create();
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
char *hex = tor_malloc(HEX_DIGEST_LEN+1);
base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
smartlist_add(which, hex);
});
} else {
/* XXXX Can we even end up here? -- weasel*/
source = NS_FROM_DIR_BY_FP;
log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
"for it by fp, nor did we ask for all.");
}
cp = body;
while (*cp) {
char *next = strstr(cp, "\nnetwork-status-version");
if (next)
next[1] = '\0';
/* learn from it, and then remove it from 'which' */
if (router_set_networkstatus_v2(cp, now, source, which)<0)
break;
if (next) {
next[1] = 'n';
cp = next+1;
} else
break;
}
/* launches router downloads as needed */
routers_update_all_from_networkstatus(now, 2);
directory_info_has_arrived(now, 0);
if (which) {
if (smartlist_len(which)) {
dir_networkstatus_download_failed(which, status_code);
}
SMARTLIST_FOREACH(which, char *, s, tor_free(s));
smartlist_free(which);
}
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
int r;
if (status_code != 200) {
int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
log(severity, LD_DIR,
"Received http status code %d (%s) from server "
"'%s:%d' while fetching consensus directory.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
networkstatus_consensus_download_failed(status_code);
return -1;
}
log_info(LD_DIR,"Received consensus directory (size %d) from server "
"'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
if ((r=networkstatus_set_current_consensus(body, 0))<0) {
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
"Unable to load consensus directory downloaded from "
"server '%s:%d'. I'll try again soon.",
conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
networkstatus_consensus_download_failed(0);
return -1;
}
/* launches router downloads as needed */
routers_update_all_from_networkstatus(now, 3);
directory_info_has_arrived(now, 0);
log_info(LD_DIR, "Successfully loaded consensus.");
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
if (status_code != 200) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
"'%s:%d' while fetching \"/tor/keys/%s\".",
status_code, escaped(reason), conn->_base.address,
conn->_base.port, conn->requested_resource);
connection_dir_download_cert_failed(conn, status_code);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
log_info(LD_DIR,"Received authority certificates (size %d) from server "
"'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
log_warn(LD_DIR, "Unable to parse fetched certificates");
connection_dir_download_cert_failed(conn, status_code);
} else {
directory_info_has_arrived(now, 0);
log_info(LD_DIR, "Successfully loaded certificates from fetch.");
}
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
const char *msg;
int st;
log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
(int) body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
"'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
status_code, escaped(reason), conn->_base.address,
conn->_base.port, conn->requested_resource);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
dirvote_add_vote(body, &msg, &st);
if (st > 299) {
log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
} else {
log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
}
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
const char *msg = NULL;
log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
(int) body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) {
log_warn(LD_DIR,
"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -