aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dircache
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/dircache')
-rw-r--r--src/feature/dircache/directory.c3
-rw-r--r--src/feature/dircache/dirserv.c69
-rw-r--r--src/feature/dircache/dirserv.h14
3 files changed, 65 insertions, 21 deletions
diff --git a/src/feature/dircache/directory.c b/src/feature/dircache/directory.c
index 230fa69a1e..de0bcdbfa7 100644
--- a/src/feature/dircache/directory.c
+++ b/src/feature/dircache/directory.c
@@ -5208,6 +5208,9 @@ connection_dir_finished_flushing(dir_connection_t *conn)
tor_assert(conn);
tor_assert(conn->base_.type == CONN_TYPE_DIR);
+ if (conn->base_.marked_for_close)
+ return 0;
+
/* Note that we have finished writing the directory response. For direct
* connections this means we're done; for tunneled connections it's only
* an intermediate step. */
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index c5286b0cbf..b85db8324f 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -51,6 +51,7 @@
#include "lib/crypt_ops/crypto_format.h"
#include "lib/encoding/confline.h"
+#include "lib/encoding/keyval.h"
/**
* \file dirserv.c
* \brief Directory server core implementation. Manages directory
@@ -2599,14 +2600,15 @@ measured_bw_line_apply(measured_bw_line_t *parsed_line,
}
/**
- * Read the measured bandwidth file and apply it to the list of
- * vote_routerstatus_t. Returns -1 on error, 0 otherwise.
+ * Read the measured bandwidth list file, apply it to the list of
+ * vote_routerstatus_t and store all the headers in <b>bw_file_headers</b>.
+ * Returns -1 on error, 0 otherwise.
*/
int
dirserv_read_measured_bandwidths(const char *from_file,
- smartlist_t *routerstatuses)
+ smartlist_t *routerstatuses,
+ smartlist_t *bw_file_headers)
{
- char line[512];
FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
time_t file_time, now;
@@ -2616,28 +2618,28 @@ dirserv_read_measured_bandwidths(const char *from_file,
* if there are additional header lines, as introduced in Bandwidth List spec
* version 1.1.0 */
int line_is_after_headers = 0;
+ int rv = -1;
+ char *line = NULL;
+ size_t n = 0;
/* Initialise line, so that we can't possibly run off the end. */
- memset(line, 0, sizeof(line));
if (fp == NULL) {
log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
from_file);
- return -1;
+ goto err;
}
/* If fgets fails, line is either unmodified, or indeterminate. */
- if (!fgets(line, sizeof(line), fp)) {
+ if (tor_getline(&line,&n,fp) <= 0) {
log_warn(LD_DIRSERV, "Empty bandwidth file");
- fclose(fp);
- return -1;
+ goto err;
}
if (!strlen(line) || line[strlen(line)-1] != '\n') {
log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s",
escaped(line));
- fclose(fp);
- return -1;
+ goto err;
}
line[strlen(line)-1] = '\0';
@@ -2645,24 +2647,28 @@ dirserv_read_measured_bandwidths(const char *from_file,
if (!ok) {
log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s",
escaped(line));
- fclose(fp);
- return -1;
+ goto err;
}
now = time(NULL);
if ((now - file_time) > MAX_MEASUREMENT_AGE) {
log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
(unsigned)(time(NULL) - file_time));
- fclose(fp);
- return -1;
+ goto err;
}
+ /* If timestamp was correct and bw_file_headers is not NULL,
+ * add timestamp to bw_file_headers */
+ if (bw_file_headers)
+ smartlist_add_asprintf(bw_file_headers, "timestamp=%lu",
+ (unsigned long)file_time);
+
if (routerstatuses)
smartlist_sort(routerstatuses, compare_vote_routerstatus_entries);
while (!feof(fp)) {
measured_bw_line_t parsed_line;
- if (fgets(line, sizeof(line), fp) && strlen(line)) {
+ if (tor_getline(&line, &n, fp) >= 0) {
if (measured_bw_line_parse(&parsed_line, line,
line_is_after_headers) != -1) {
/* This condition will be true when the first complete valid bw line
@@ -2672,18 +2678,43 @@ dirserv_read_measured_bandwidths(const char *from_file,
dirserv_cache_measured_bw(&parsed_line, file_time);
if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
applied_lines++;
- }
+ /* if the terminator is found, it is the end of header lines, set the
+ * flag but do not store anything */
+ } else if (strcmp(line, BW_FILE_HEADERS_TERMINATOR) == 0) {
+ line_is_after_headers = 1;
+ /* if the line was not a correct relay line nor the terminator and
+ * the end of the header lines has not been detected yet
+ * and it is key_value and bw_file_headers did not reach the maximum
+ * number of headers,
+ * then assume this line is a header and add it to bw_file_headers */
+ } else if (bw_file_headers &&
+ (line_is_after_headers == 0) &&
+ string_is_key_value(LOG_DEBUG, line) &&
+ !strchr(line, ' ') &&
+ (smartlist_len(bw_file_headers)
+ < MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) {
+ line[strlen(line)-1] = '\0';
+ smartlist_add_strdup(bw_file_headers, line);
+ };
}
}
/* Now would be a nice time to clean the cache, too */
dirserv_expire_measured_bw_cache(now);
- fclose(fp);
log_info(LD_DIRSERV,
"Bandwidth measurement file successfully read. "
"Applied %d measurements.", applied_lines);
- return 0;
+ rv = 0;
+
+ err:
+ if (line) {
+ // we need to raw_free this buffer because we got it from tor_getdelim()
+ raw_free(line);
+ }
+ if (fp)
+ fclose(fp);
+ return rv;
}
/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h
index 3b4a646094..9be4bf9db2 100644
--- a/src/feature/dircache/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -49,6 +49,13 @@ typedef enum {
/** Maximum allowable length of a version line in a networkstatus. */
#define MAX_V_LINE_LEN 128
+/** Maximum allowable length of bandwidth headers in a bandwidth file */
+#define MAX_BW_FILE_HEADER_COUNT_IN_VOTE 50
+
+/** Terminatore that separates bandwidth file headers from bandwidth file
+ * relay lines */
+#define BW_FILE_HEADERS_TERMINATOR "=====\n"
+
/** Ways to convert a spoolable_resource_t to a bunch of bytes. */
typedef enum dir_spool_source_t {
DIR_SPOOL_SERVER_BY_DIGEST=1, DIR_SPOOL_SERVER_BY_FP,
@@ -180,7 +187,9 @@ char *routerstatus_format_entry(
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
cached_dir_t *new_cached_dir(char *s, time_t published);
-
+struct config_line_t;
+char *format_recommended_version_list(const struct config_line_t *line,
+ int warn);
int validate_recommended_package_line(const char *line);
int dirserv_query_measured_bw_cache_kb(const char *node_id,
long *bw_out,
@@ -215,7 +224,8 @@ dirserv_read_guardfraction_file_from_str(const char *guardfraction_file_str,
#endif /* defined(DIRSERV_PRIVATE) */
int dirserv_read_measured_bandwidths(const char *from_file,
- smartlist_t *routerstatuses);
+ smartlist_t *routerstatuses,
+ smartlist_t *bw_file_headers);
int dirserv_read_guardfraction_file(const char *fname,
smartlist_t *vote_routerstatuses);