aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dircache/dirserv.h
blob: 73a64b1b7e62142ab06cff32c0b79262bdab834b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file dirserv.h
 * \brief Header file for dirserv.c.
 **/

#ifndef TOR_DIRSERV_H
#define TOR_DIRSERV_H

struct ed25519_public_key_t;

#include "lib/testsupport/testsupport.h"

/** 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,
    DIR_SPOOL_EXTRA_BY_DIGEST, DIR_SPOOL_EXTRA_BY_FP,
    DIR_SPOOL_MICRODESC,
    DIR_SPOOL_NETWORKSTATUS,
    DIR_SPOOL_CONSENSUS_CACHE_ENTRY,
} dir_spool_source_t;
#define dir_spool_source_bitfield_t ENUM_BF(dir_spool_source_t)

/** Object to remember the identity of an object that we are spooling,
 * or about to spool, in response to a directory request.
 *
 * (Why do we spool?  Because some directory responses are very large,
 * and we don't want to just shove the complete answer into the output
 * buffer: that would take a ridiculous amount of RAM.)
 *
 * If the spooled resource is relatively small (like microdescriptors,
 * descriptors, etc), we look them up by ID as needed, and add the whole
 * thing onto the output buffer at once.  If the spooled reseource is
 * big (like networkstatus documents), we reference-count it, and add it
 * a few K at a time.
 */
typedef struct spooled_resource_t {
  /**
   * If true, we add the entire object to the outbuf.  If false,
   * we spool the object a few K at a time.
   */
  unsigned spool_eagerly : 1;
  /**
   * Tells us what kind of object to get, and how to look it up.
   */
  dir_spool_source_bitfield_t spool_source : 7;
  /**
   * Tells us the specific object to spool.
   */
  uint8_t digest[DIGEST256_LEN];
  /**
   * A large object that we're spooling. Holds a reference count.  Only
   * used when spool_eagerly is false.
   */
  struct cached_dir_t *cached_dir_ref;
  /**
   * A different kind of large object that we might be spooling. Also
   * reference-counted.  Also only used when spool_eagerly is false.
   */
  struct consensus_cache_entry_t *consensus_cache_entry;
  const uint8_t *cce_body;
  size_t cce_len;
  /**
   * The current offset into cached_dir or cce_body. Only used when
   * spool_eagerly is false */
  off_t cached_dir_offset;
} spooled_resource_t;

int connection_dirserv_flushed_some(dir_connection_t *conn);

enum dir_spool_source_t;
int dir_split_resource_into_spoolable(const char *resource,
                                      enum dir_spool_source_t source,
                                      smartlist_t *spool_out,
                                      int *compressed_out,
                                      int flags);

#ifdef HAVE_MODULE_DIRCACHE
/** Is the dircache module enabled? */
#define have_module_dircache() (1)
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
MOCK_DECL(cached_dir_t *, dirserv_get_consensus, (const char *flavor_name));
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
                                              size_t consensus_len,
                                              const char *flavor_name,
                                              const common_digests_t *digests,
                                              const uint8_t *sha3_as_signed,
                                              time_t published);
#else /* !defined(HAVE_MODULE_DIRCACHE) */
#define have_module_dircache() (0)
#define directory_caches_unknown_auth_certs(opt) \
  ((void)(opt), 0)
#define directory_caches_dir_info(opt) \
  ((void)(opt), 0)
#define directory_permits_begindir_requests(opt) \
  ((void)(opt), 0)
#define dirserv_get_consensus(flav) \
  ((void)(flav), NULL)
#define dirserv_set_cached_consensus_networkstatus(a,b,c,d,e,f) \
  STMT_BEGIN {                                                  \
    (void)(a);                                                  \
    (void)(b);                                                  \
    (void)(c);                                                  \
    (void)(d);                                                  \
    (void)(e);                                                  \
    (void)(f);                                                  \
  } STMT_END
#endif /* defined(HAVE_MODULE_DIRCACHE) */

void dirserv_clear_old_networkstatuses(time_t cutoff);
int dirserv_get_routerdesc_spool(smartlist_t *spools_out, const char *key,
                                 dir_spool_source_t source,
                                 int conn_is_encrypted,
                                 const char **msg_out);

void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
cached_dir_t *new_cached_dir(char *s, time_t published);

spooled_resource_t *spooled_resource_new(dir_spool_source_t source,
                                         const uint8_t *digest,
                                         size_t digestlen);
spooled_resource_t *spooled_resource_new_from_cache_entry(
                                      struct consensus_cache_entry_t *entry);
void spooled_resource_free_(spooled_resource_t *spooled);
#define spooled_resource_free(sp) \
  FREE_AND_NULL(spooled_resource_t, spooled_resource_free_, (sp))
void dirserv_spool_remove_missing_and_guess_size(dir_connection_t *conn,
                                                 time_t cutoff,
                                                 int compression,
                                                 size_t *size_out,
                                                 int *n_expired_out);
void dirserv_spool_sort(dir_connection_t *conn);
void dir_conn_clear_spool(dir_connection_t *conn);

#endif /* !defined(TOR_DIRSERV_H) */