tor  0.4.1.0-alpha-dev
directory.c
Go to the documentation of this file.
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 #include "core/or/or.h"
7 
8 #include "app/config/config.h"
16 #include "lib/compress/compress.h"
17 
18 #include "feature/dircommon/dir_connection_st.h"
19 #include "feature/nodelist/routerinfo_st.h"
20 
57 /* In-points to directory.c:
58  *
59  * - directory_post_to_dirservers(), called from
60  * router_upload_dir_desc_to_dirservers() in router.c
61  * upload_service_descriptor() in rendservice.c
62  * - directory_get_from_dirserver(), called from
63  * rend_client_refetch_renddesc() in rendclient.c
64  * run_scheduled_events() in main.c
65  * do_hup() in main.c
66  * - connection_dir_process_inbuf(), called from
67  * connection_process_inbuf() in connection.c
68  * - connection_dir_finished_flushing(), called from
69  * connection_finished_flushing() in connection.c
70  * - connection_dir_finished_connecting(), called from
71  * connection_finished_connecting() in connection.c
72  */
73 
78 {
79  tor_assert(c->magic == DIR_CONNECTION_MAGIC);
80  return DOWNCAST(dir_connection_t, c);
81 }
82 
89 int
90 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
91  const char *resource)
92 {
93  if (get_options()->AllDirActionsPrivate)
94  return 1;
95 
96  if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
97  if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
98  && resource && !strcmp(resource, "authority.z")) {
99  /* We are asking a bridge for its own descriptor. That doesn't need
100  anonymity. */
101  return 0;
102  }
103  /* Assume all other bridge stuff needs anonymity. */
104  return 1; /* if no circuits yet, this might break bootstrapping, but it's
105  * needed to be safe. */
106  }
107 
108  switch (dir_purpose)
109  {
120  return 0;
127  return 1;
128  case DIR_PURPOSE_SERVER:
129  default:
130  log_warn(LD_BUG, "Called with dir_purpose=%d, router_purpose=%d",
131  dir_purpose, router_purpose);
132  tor_assert_nonfatal_unreached();
133  return 1; /* Assume it needs anonymity; better safe than sorry. */
134  }
135 }
136 
139 char *
141 {
142  char *result;
143  smartlist_t *lst = smartlist_new();
144  if (auth & V3_DIRINFO)
145  smartlist_add(lst, (void*)"V3");
146  if (auth & BRIDGE_DIRINFO)
147  smartlist_add(lst, (void*)"Bridge");
148  if (smartlist_len(lst)) {
149  result = smartlist_join_strings(lst, ", ", 0, NULL);
150  } else {
151  result = tor_strdup("[Not an authority]");
152  }
153  smartlist_free(lst);
154  return result;
155 }
156 
159 int
161 {
162  /* Right now it's sufficient to see if conn is or has been linked, since
163  * the only thing it could be linked to is an edge connection on a
164  * circuit, and the only way it could have been unlinked is at the edge
165  * connection getting closed.
166  */
167  return TO_CONN(conn)->linked;
168 }
169 
174 int
175 parse_http_command(const char *headers, char **command_out, char **url_out)
176 {
177  const char *command, *end_of_command;
178  char *s, *start, *tmp;
179 
180  s = (char *)eat_whitespace_no_nl(headers);
181  if (!*s) return -1;
182  command = s;
183  s = (char *)find_whitespace(s); /* get past GET/POST */
184  if (!*s) return -1;
185  end_of_command = s;
186  s = (char *)eat_whitespace_no_nl(s);
187  if (!*s) return -1;
188  start = s; /* this is the URL, assuming it's valid */
189  s = (char *)find_whitespace(start);
190  if (!*s) return -1;
191 
192  /* tolerate the http[s] proxy style of putting the hostname in the url */
193  if (s-start >= 4 && !strcmpstart(start,"http")) {
194  tmp = start + 4;
195  if (*tmp == 's')
196  tmp++;
197  if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
198  tmp = strchr(tmp+3, '/');
199  if (tmp && tmp < s) {
200  log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
201  start = tmp;
202  }
203  }
204  }
205 
206  /* Check if the header is well formed (next sequence
207  * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
208  {
209  unsigned minor_ver;
210  char ch;
211  char *e = (char *)eat_whitespace_no_nl(s);
212  if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
213  return -1;
214  }
215  if (ch != '\r')
216  return -1;
217  }
218 
219  *url_out = tor_memdup_nulterm(start, s-start);
220  *command_out = tor_memdup_nulterm(command, end_of_command - command);
221  return 0;
222 }
223 
228 char *
229 http_get_header(const char *headers, const char *which)
230 {
231  const char *cp = headers;
232  while (cp) {
233  if (!strcasecmpstart(cp, which)) {
234  char *eos;
235  cp += strlen(which);
236  if ((eos = strchr(cp,'\r')))
237  return tor_strndup(cp, eos-cp);
238  else
239  return tor_strdup(cp);
240  }
241  cp = strchr(cp, '\n');
242  if (cp)
243  ++cp;
244  }
245  return NULL;
246 }
263 int
264 parse_http_response(const char *headers, int *code, time_t *date,
265  compress_method_t *compression, char **reason)
266 {
267  unsigned n1, n2;
268  char datestr[RFC1123_TIME_LEN+1];
269  smartlist_t *parsed_headers;
270  tor_assert(headers);
271  tor_assert(code);
272 
273  while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
274 
275  if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
276  (n1 != 0 && n1 != 1) ||
277  (n2 < 100 || n2 >= 600)) {
278  log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
279  return -1;
280  }
281  *code = n2;
282 
283  parsed_headers = smartlist_new();
284  smartlist_split_string(parsed_headers, headers, "\n",
285  SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
286  if (reason) {
287  smartlist_t *status_line_elements = smartlist_new();
288  tor_assert(smartlist_len(parsed_headers));
289  smartlist_split_string(status_line_elements,
290  smartlist_get(parsed_headers, 0),
291  " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
292  tor_assert(smartlist_len(status_line_elements) <= 3);
293  if (smartlist_len(status_line_elements) == 3) {
294  *reason = smartlist_get(status_line_elements, 2);
295  smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
296  }
297  SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
298  smartlist_free(status_line_elements);
299  }
300  if (date) {
301  *date = 0;
302  SMARTLIST_FOREACH(parsed_headers, const char *, s,
303  if (!strcmpstart(s, "Date: ")) {
304  strlcpy(datestr, s+6, sizeof(datestr));
305  /* This will do nothing on failure, so we don't need to check
306  the result. We shouldn't warn, since there are many other valid
307  date formats besides the one we use. */
308  parse_rfc1123_time(datestr, date);
309  break;
310  });
311  }
312  if (compression) {
313  const char *enc = NULL;
314  SMARTLIST_FOREACH(parsed_headers, const char *, s,
315  if (!strcmpstart(s, "Content-Encoding: ")) {
316  enc = s+18; break;
317  });
318 
319  if (enc == NULL)
320  *compression = NO_METHOD;
321  else {
322  *compression = compression_method_get_by_name(enc);
323 
324  if (*compression == UNKNOWN_METHOD)
325  log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
326  escaped(enc));
327  }
328  }
329  SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
330  smartlist_free(parsed_headers);
331 
332  return 0;
333 }
334 
339 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
340 
341 #define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
342 
346 int
348 {
349  size_t max_size;
350  tor_assert(conn);
351  tor_assert(conn->base_.type == CONN_TYPE_DIR);
352 
353  /* Directory clients write, then read data until they receive EOF;
354  * directory servers read data until they get an HTTP command, then
355  * write their response (when it's finished flushing, they mark for
356  * close).
357  */
358 
359  /* If we're on the dirserver side, look for a command. */
360  if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
361  if (directory_handle_command(conn) < 0) {
362  connection_mark_for_close(TO_CONN(conn));
363  return -1;
364  }
365  return 0;
366  }
367 
368  max_size =
369  (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
370  MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
371 
372  if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
373  log_warn(LD_HTTP,
374  "Too much data received from directory connection (%s): "
375  "denial of service attempt, or you need to upgrade?",
376  conn->base_.address);
377  connection_mark_for_close(TO_CONN(conn));
378  return -1;
379  }
380 
381  if (!conn->base_.inbuf_reached_eof)
382  log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
383  return 0;
384 }
385 
388 void
390 {
391  connection_t *conn = TO_CONN(dir_conn);
392 
394  /* It's a directory connection and connecting or fetching
395  * failed: forget about this router, and maybe try again. */
397  }
398 
400 }
401 
406 int
408 {
409  tor_assert(conn);
410  tor_assert(conn->base_.type == CONN_TYPE_DIR);
411 
412  if (conn->base_.marked_for_close)
413  return 0;
414 
415  /* Note that we have finished writing the directory response. For direct
416  * connections this means we're done; for tunneled connections it's only
417  * an intermediate step. */
418  if (conn->dirreq_id)
419  geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
421  else
422  geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
423  DIRREQ_DIRECT,
425  switch (conn->base_.state) {
428  log_debug(LD_DIR,"client finished sending command.");
429  conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
430  return 0;
432  if (conn->spool) {
433  log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
434  connection_mark_for_close(TO_CONN(conn));
435  } else {
436  log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
437  connection_mark_for_close(TO_CONN(conn));
438  }
439  return 0;
440  default:
441  log_warn(LD_BUG,"called in unexpected state %d.",
442  conn->base_.state);
444  return -1;
445  }
446  return 0;
447 }
448 
452 int
454 {
455  tor_assert(conn);
456  tor_assert(conn->base_.type == CONN_TYPE_DIR);
458 
459  log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
460  conn->base_.address,conn->base_.port);
461 
462  /* start flushing conn */
463  conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
464  return 0;
465 }
466 
469 static int
470 compare_pairs_(const void **a, const void **b)
471 {
472  const fp_pair_t *fp1 = *a, *fp2 = *b;
473  int r;
474  if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
475  return r;
476  else
477  return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
478 }
479 
484 int
486  smartlist_t *pairs_out)
487 {
488  smartlist_t *pairs_tmp = smartlist_new();
489  smartlist_t *pairs_result = smartlist_new();
490 
491  smartlist_split_string(pairs_tmp, res, "+", 0, 0);
492  if (smartlist_len(pairs_tmp)) {
493  char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
494  size_t last_len = strlen(last);
495  if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
496  last[last_len-2] = '\0';
497  }
498  }
499  SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
500  if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
501  log_info(LD_DIR,
502  "Skipping digest pair %s with non-standard length.", escaped(cp));
503  } else if (cp[HEX_DIGEST_LEN] != '-') {
504  log_info(LD_DIR,
505  "Skipping digest pair %s with missing dash.", escaped(cp));
506  } else {
507  fp_pair_t pair;
508  if (base16_decode(pair.first, DIGEST_LEN,
509  cp, HEX_DIGEST_LEN) != DIGEST_LEN ||
510  base16_decode(pair.second,DIGEST_LEN,
512  log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
513  } else {
514  smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
515  }
516  }
517  tor_free(cp);
518  } SMARTLIST_FOREACH_END(cp);
519  smartlist_free(pairs_tmp);
520 
521  /* Uniq-and-sort */
522  smartlist_sort(pairs_result, compare_pairs_);
523  smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
524 
525  smartlist_add_all(pairs_out, pairs_result);
526  smartlist_free(pairs_result);
527  return 0;
528 }
529 
543 int
545  smartlist_t *fp_out, int *compressed_out,
546  int flags)
547 {
548  const int decode_hex = flags & DSR_HEX;
549  const int decode_base64 = flags & DSR_BASE64;
550  const int digests_are_256 = flags & DSR_DIGEST256;
551  const int sort_uniq = flags & DSR_SORT_UNIQ;
552 
553  const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
554  const int hex_digest_len = digests_are_256 ?
556  const int base64_digest_len = digests_are_256 ?
558  smartlist_t *fp_tmp = smartlist_new();
559 
560  tor_assert(!(decode_hex && decode_base64));
561  tor_assert(fp_out);
562 
563  smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
564  if (compressed_out)
565  *compressed_out = 0;
566  if (smartlist_len(fp_tmp)) {
567  char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
568  size_t last_len = strlen(last);
569  if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
570  last[last_len-2] = '\0';
571  if (compressed_out)
572  *compressed_out = 1;
573  }
574  }
575  if (decode_hex || decode_base64) {
576  const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
577  int i;
578  char *cp, *d = NULL;
579  for (i = 0; i < smartlist_len(fp_tmp); ++i) {
580  cp = smartlist_get(fp_tmp, i);
581  if (strlen(cp) != encoded_len) {
582  log_info(LD_DIR,
583  "Skipping digest %s with non-standard length.", escaped(cp));
584  smartlist_del_keeporder(fp_tmp, i--);
585  goto again;
586  }
587  d = tor_malloc_zero(digest_len);
588  if (decode_hex ?
589  (base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) :
590  (base64_decode(d, digest_len, cp, base64_digest_len)
591  != digest_len)) {
592  log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
593  smartlist_del_keeporder(fp_tmp, i--);
594  goto again;
595  }
596  smartlist_set(fp_tmp, i, d);
597  d = NULL;
598  again:
599  tor_free(cp);
600  tor_free(d);
601  }
602  }
603  if (sort_uniq) {
604  if (decode_hex || decode_base64) {
605  if (digests_are_256) {
608  } else {
609  smartlist_sort_digests(fp_tmp);
610  smartlist_uniq_digests(fp_tmp);
611  }
612  } else {
613  smartlist_sort_strings(fp_tmp);
614  smartlist_uniq_strings(fp_tmp);
615  }
616  }
617  smartlist_add_all(fp_out, fp_tmp);
618  smartlist_free(fp_tmp);
619  return 0;
620 }
621 
625 int
627  dir_spool_source_t source,
628  smartlist_t *spool_out,
629  int *compressed_out,
630  int flags)
631 {
632  smartlist_t *fingerprints = smartlist_new();
633 
634  tor_assert(flags & (DSR_HEX|DSR_BASE64));
635  const size_t digest_len =
636  (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
637 
638  int r = dir_split_resource_into_fingerprints(resource, fingerprints,
639  compressed_out, flags);
640  /* This is not a very efficient implementation XXXX */
641  SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
642  spooled_resource_t *spooled =
643  spooled_resource_new(source, digest, digest_len);
644  if (spooled)
645  smartlist_add(spool_out, spooled);
646  tor_free(digest);
647  } SMARTLIST_FOREACH_END(digest);
648 
649  smartlist_free(fingerprints);
650  return r;
651 }
Header file for dirserv.c.
#define DIR_PURPOSE_UPLOAD_HSDESC
Definition: directory.h:72
#define DIR_PURPOSE_SERVER
Definition: directory.h:62
int tor_sscanf(const char *buf, const char *pattern,...)
Definition: scanf.c:309
char * authdir_type_to_string(dirinfo_type_t auth)
Definition: directory.c:140
Header file for dirclient.c.
void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, dirreq_state_t new_state)
Definition: geoip_stats.c:550
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define TO_CONN(c)
Definition: or.h:735
Header file for geoip_stats.c.
Header file for dircache.c.
Header file for connection.c.
#define DOWNCAST(to, ptr)
Definition: or.h:110
int directory_handle_command(dir_connection_t *conn)
Definition: dircache.c:1751
uint8_t state
Definition: connection_st.h:44
#define DIR_PURPOSE_FETCH_STATUS_VOTE
Definition: directory.h:50
Headers for compress.c.
int dir_split_resource_into_fingerprint_pairs(const char *res, smartlist_t *pairs_out)
Definition: directory.c:485
unsigned int inbuf_reached_eof
Definition: connection_st.h:59
Header file for directory.c.
void smartlist_add(smartlist_t *sl, void *element)
int connection_dir_finished_connecting(dir_connection_t *conn)
Definition: directory.c:453
void smartlist_sort_digests256(smartlist_t *sl)
Definition: smartlist.c:846
void smartlist_uniq_digests256(smartlist_t *sl)
Definition: smartlist.c:863
smartlist_t * spool
#define MAX_DIRECTORY_OBJECT_SIZE
Definition: directory.c:339
Header file for config.c.
#define DIR_PURPOSE_UPLOAD_DIR
Definition: directory.h:43
#define HEX_DIGEST256_LEN
Definition: crypto_digest.h:37
const char * find_whitespace(const char *s)
Definition: util_string.c:347
#define DIR_CONN_STATE_CLIENT_READING
Definition: directory.h:23
void smartlist_uniq_strings(smartlist_t *sl)
Definition: smartlist.c:574
#define LD_HTTP
Definition: log.h:73
uint16_t port
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:209
#define tor_free(p)
Definition: malloc.h:52
#define tor_fragile_assert()
Definition: util_bug.h:240
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES
Definition: directory.h:53
#define DIR_PURPOSE_FETCH_CONSENSUS
Definition: directory.h:56
dirinfo_type_t
Definition: or.h:887
void smartlist_sort_strings(smartlist_t *sl)
Definition: smartlist.c:549
#define DIR_CONN_STATE_CLIENT_SENDING
Definition: directory.h:21
#define DIR_PURPOSE_UPLOAD_SIGNATURES
Definition: directory.h:47
void connection_dir_client_request_failed(dir_connection_t *conn)
Definition: dirclient.c:719
#define DIR_PURPOSE_FETCH_EXTRAINFO
Definition: directory.h:41
void smartlist_del_keeporder(smartlist_t *sl, int idx)
int connection_dir_finished_flushing(dir_connection_t *conn)
Definition: directory.c:407
void smartlist_uniq_digests(smartlist_t *sl)
Definition: smartlist.c:832
#define DIGEST256_LEN
Definition: digest_sizes.h:23
#define DIR_CONN_STATE_CLIENT_FINISHED
Definition: directory.h:25
void smartlist_uniq(smartlist_t *sl, int(*compare)(const void **a, const void **b), void(*free_fn)(void *a))
Definition: smartlist.c:390
#define DIR_PURPOSE_FETCH_SERVERDESC
Definition: directory.h:38
tor_assert(buffer)
#define DIR_PURPOSE_UPLOAD_VOTE
Definition: directory.h:45
dir_connection_t * TO_DIR_CONN(connection_t *c)
Definition: directory.c:77
#define DIGEST_LEN
Definition: digest_sizes.h:20
dir_spool_source_t
Definition: dirserv.h:20
Master header file for Tor-specific functionality.
int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose, const char *resource)
Definition: directory.c:90
#define LD_DIRSERV
Definition: log.h:87
#define DIR_PURPOSE_FETCH_HSDESC
Definition: directory.h:74
#define DIR_PURPOSE_FETCH_CERTIFICATE
Definition: directory.h:59
uint16_t marked_for_close
unsigned int type
Definition: connection_st.h:45
void tor_free_(void *mem)
Definition: malloc.c:227
int parse_http_response(const char *headers, int *code, time_t *date, compress_method_t *compression, char **reason)
Definition: directory.c:264
int connection_dir_process_inbuf(dir_connection_t *conn)
Definition: directory.c:347
#define DIR_CONN_STATE_SERVER_COMMAND_WAIT
Definition: directory.h:27
#define HEX_DIGEST_LEN
Definition: crypto_digest.h:35
#define LD_DIR
Definition: log.h:85
char * http_get_header(const char *headers, const char *which)
Definition: directory.c:229
Header file for fp_pair.c.
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition: smartlist.c:279
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:396
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int connection_dir_is_encrypted(const dir_connection_t *conn)
Definition: directory.c:160
const char * escaped(const char *s)
Definition: escape.c:126
#define DIR_PURPOSE_UPLOAD_RENDDESC_V2
Definition: directory.h:65
#define BASE64_DIGEST_LEN
Definition: crypto_digest.h:26
int dir_split_resource_into_fingerprints(const char *resource, smartlist_t *fp_out, int *compressed_out, int flags)
Definition: directory.c:544
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2
Definition: directory.h:35
void smartlist_sort_digests(smartlist_t *sl)
Definition: smartlist.c:824
#define DIR_PURPOSE_FETCH_MICRODESC
Definition: directory.h:70
Definition: or.h:890
int parse_rfc1123_time(const char *buf, time_t *t)
Definition: time_fmt.c:206
#define fast_memcmp(a, b, c)
Definition: di_ops.h:26
#define DIR_PURPOSE_HAS_FETCHED_HSDESC
Definition: directory.h:77
uint32_t magic
Definition: connection_st.h:41
#define BASE64_DIGEST256_LEN
Definition: crypto_digest.h:29
int dir_split_resource_into_spoolable(const char *resource, dir_spool_source_t source, smartlist_t *spool_out, int *compressed_out, int flags)
Definition: directory.c:626
static int compare_pairs_(const void **a, const void **b)
Definition: directory.c:470
compress_method_t compression_method_get_by_name(const char *name)
Definition: compress.c:403
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:506
#define CONN_TYPE_DIR
Definition: connection.h:35
compress_method_t
Definition: compress.h:21
void connection_dir_client_refetch_hsdesc_if_needed(dir_connection_t *dir_conn)
Definition: dirclient.c:3009
void connection_dir_about_to_close(dir_connection_t *dir_conn)
Definition: directory.c:389
#define DIR_CONN_STATE_CONNECTING
Definition: directory.h:19
int parse_http_command(const char *headers, char **command_out, char **url_out)
Definition: directory.c:175
void smartlist_sort(smartlist_t *sl, int(*compare)(const void **a, const void **b))
Definition: smartlist.c:334
int strcasecmpstart(const char *s1, const char *s2)
Definition: util_string.c:219
#define DIR_PURPOSE_FETCH_RENDDESC_V2
Definition: directory.h:68
#define DIR_CONN_STATE_SERVER_WRITING
Definition: directory.h:29
const char * eat_whitespace_no_nl(const char *s)
Definition: util_string.c:326
#define LD_BUG
Definition: log.h:83
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)