diff options
91 files changed, 1271 insertions, 333 deletions
diff --git a/Doxyfile.in b/Doxyfile.in index eedb6a4334..0128f12812 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -161,7 +161,7 @@ INLINE_INHERITED_MEMB = NO # shortest path that makes the file name unique will be used # The default value is: YES. -FULL_PATH_NAMES = NO +FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand @@ -173,7 +173,7 @@ FULL_PATH_NAMES = NO # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = @top_srcdir@/src # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -316,7 +316,7 @@ OPTIMIZE_OUTPUT_SLICE = NO # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. -EXTENSION_MAPPING = +EXTENSION_MAPPING = dox=C h=C c=C # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable @@ -816,10 +816,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @top_srcdir@/src/lib \ - @top_srcdir@/src/core \ - @top_srcdir@/src/feature \ - @top_srcdir@/src/app +INPUT = @top_srcdir@/src/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -845,7 +842,8 @@ INPUT_ENCODING = UTF-8 # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ - *.h + *.h \ + *.dox # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -860,7 +858,9 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = @top_srcdir@/src/ext \ + @top_srcdir@/src/trunnel \ + @top_srcdir@/src/test # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -1181,7 +1181,7 @@ HTML_EXTRA_FILES = # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_HUE = 150 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A diff --git a/changes/bug25568 b/changes/bug25568 new file mode 100644 index 0000000000..eeb7235cae --- /dev/null +++ b/changes/bug25568 @@ -0,0 +1,5 @@ + o Minor bugfixes (onion service v2): + - When sending the INTRO cell for a v2 Onion Service, look at the failure + cache alongside timeout values to check if the intro point is marked + as failed. Previously, we only looked at if the relay timeout values. + Fixes bug 25568; bugfix on 0.2.7.3-rc. Patch by Neel Chauhan. diff --git a/changes/ticket32196 b/changes/ticket32196 new file mode 100644 index 0000000000..d642478fe4 --- /dev/null +++ b/changes/ticket32196 @@ -0,0 +1,2 @@ + o Testing (circuit, EWMA): + - Add unit tests for circuitmux and EWMA subsystems. Closes ticket 32196. diff --git a/scripts/git/git-setup-dirs.sh b/scripts/git/git-setup-dirs.sh index 87779c7304..495b22b261 100755 --- a/scripts/git/git-setup-dirs.sh +++ b/scripts/git/git-setup-dirs.sh @@ -71,7 +71,7 @@ if [ "$DEFAULT_UPSTREAM_REMOTE" != "origin" ]; then fi # GitHub repositories GITHUB_PULL=${TOR_GITHUB_PULL:-"https://github.com/torproject/tor.git"} -GITHUB_PUSH=${TOR_GITHUB_PUSH:-"No pushes to GitHub"} +GITHUB_PUSH=${TOR_GITHUB_PUSH:-"No_Pushing_To_GitHub"} ########################## # Git branches to manage # @@ -506,5 +506,5 @@ for ((i=0; i<COUNT; i++)); do done echo -echo "Remember to copy the git hooks from tor/git/hooks/*.git-hook to" +echo "Remember to copy the git hooks from tor/scripts/git/*.git-hook to" echo "$ORIGIN_PATH/.git/hooks/*" diff --git a/scripts/git/pre-push.git-hook b/scripts/git/pre-push.git-hook index 7be184ec6e..6a85e951a8 100755 --- a/scripts/git/pre-push.git-hook +++ b/scripts/git/pre-push.git-hook @@ -58,35 +58,39 @@ do fi # Call the pre-commit hook for the common checks, if it is executable - # Only check the files newly modified in this branch - CHECK_FILTER="git diff --name-only --diff-filter=ACMR $range" - # Use the appropriate owned tor source list to filter the changed files - if [ -d src/lib ]; then - # This is the layout in 0.3.5 - CHECK_FILES="$($CHECK_FILTER \ - src/lib/*/*.[ch] \ - src/core/*/*.[ch] \ - src/feature/*/*.[ch] \ - src/app/*/*.[ch] \ - src/test/*.[ch] \ - src/test/*/*.[ch] \ - src/tools/*.[ch] \ - )" - elif [ -d src/common ]; then - # This was the layout before 0.3.5 - CHECK_FILES="$($CHECK_FILTER \ - src/common/*/*.[ch] \ - src/or/*/*.[ch] \ - src/test/*.[ch] \ - src/test/*/*.[ch] \ - src/tools/*.[ch] - )" - fi + if [ -x scripts/git/pre-commit.git-hook ]; then + # Only check the files newly modified in this branch + CHECK_FILTER="git diff --name-only --diff-filter=ACMR $range" + # Use the appropriate owned tor source list to filter the changed + # files + if [ -d src/lib ]; then + # This is the layout in 0.3.5 + CHECK_FILES="$($CHECK_FILTER \ + src/lib/*/*.[ch] \ + src/core/*/*.[ch] \ + src/feature/*/*.[ch] \ + src/app/*/*.[ch] \ + src/test/*.[ch] \ + src/test/*/*.[ch] \ + src/tools/*.[ch] \ + )" + elif [ -d src/common ]; then + # This was the layout before 0.3.5 + CHECK_FILES="$($CHECK_FILTER \ + src/common/*/*.[ch] \ + src/or/*/*.[ch] \ + src/test/*.[ch] \ + src/test/*/*.[ch] \ + src/tools/*.[ch] + )" + fi - # We want word splitting here, because file names are space separated - # shellcheck disable=SC2086 - if ! scripts/git/pre-commit.git-hook $CHECK_FILES ; then - exit 1 + # We want word splitting here, because file names are space + # separated + # shellcheck disable=SC2086 + if ! scripts/git/pre-commit.git-hook $CHECK_FILES ; then + exit 1 + fi fi if [[ "$remote_name" != "$upstream_name" ]]; then diff --git a/src/app/app.dox b/src/app/app.dox new file mode 100644 index 0000000000..29e8651d51 --- /dev/null +++ b/src/app/app.dox @@ -0,0 +1,8 @@ +/** +@dir app +@brief app: top-level entry point for Tor + +The "app" directory has Tor's main entry point and configuration logic, +and is responsible for initializing and managing the other modules in +Tor. +**/ diff --git a/src/app/config/app_config.dox b/src/app/config/app_config.dox new file mode 100644 index 0000000000..03762fd27d --- /dev/null +++ b/src/app/config/app_config.dox @@ -0,0 +1,4 @@ +/** +@dir app/config +@brief app/config +**/ diff --git a/src/app/main/app_main.dox b/src/app/main/app_main.dox new file mode 100644 index 0000000000..1d94f89814 --- /dev/null +++ b/src/app/main/app_main.dox @@ -0,0 +1,4 @@ +/** +@dir app/main +@brief app/main +**/ diff --git a/src/core/core.dox b/src/core/core.dox new file mode 100644 index 0000000000..1352daebd3 --- /dev/null +++ b/src/core/core.dox @@ -0,0 +1,8 @@ +/** +@dir core +@brief core: main loop and onion routing functionality + +The "core" directory has the central protocols for Tor, which every +client and relay must implement in order to perform onion routing. + +**/ diff --git a/src/core/crypto/core_crypto.dox b/src/core/crypto/core_crypto.dox new file mode 100644 index 0000000000..e5acdd6528 --- /dev/null +++ b/src/core/crypto/core_crypto.dox @@ -0,0 +1,4 @@ +/** +@dir core/crypto +@brief core/crypto +**/ diff --git a/src/core/mainloop/core_mainloop.dox b/src/core/mainloop/core_mainloop.dox new file mode 100644 index 0000000000..9b32cb7f60 --- /dev/null +++ b/src/core/mainloop/core_mainloop.dox @@ -0,0 +1,4 @@ +/** +@dir core/mainloop +@brief core/mainloop +**/ diff --git a/src/core/or/circuitmux.c b/src/core/or/circuitmux.c index b2628bec3f..f92a53eb27 100644 --- a/src/core/or/circuitmux.c +++ b/src/core/or/circuitmux.c @@ -69,14 +69,14 @@ * made to attach all existing circuits to the new policy. **/ +#define CIRCUITMUX_PRIVATE + #include "core/or/or.h" #include "core/or/channel.h" #include "core/or/circuitlist.h" #include "core/or/circuitmux.h" #include "core/or/relay.h" -#include "core/or/cell_queue_st.h" -#include "core/or/destroy_cell_queue_st.h" #include "core/or/or_circuit_st.h" /* @@ -84,12 +84,6 @@ */ /* - * Map of muxinfos for circuitmux_t to use; struct is defined below (name - * of struct must match HT_HEAD line). - */ -typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t; - -/* * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to * break the hash table code). */ @@ -103,49 +97,6 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t; typedef struct circuit_muxinfo_s circuit_muxinfo_t; /* - * Structures for circuitmux.c - */ - -struct circuitmux_s { - /* Keep count of attached, active circuits */ - unsigned int n_circuits, n_active_circuits; - - /* Total number of queued cells on all circuits */ - unsigned int n_cells; - - /* - * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t - */ - chanid_circid_muxinfo_map_t *chanid_circid_map; - - /** List of queued destroy cells */ - destroy_cell_queue_t destroy_cell_queue; - /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit - * returned the destroy queue. Used to force alternation between - * destroy/non-destroy cells. - * - * XXXX There is no reason to think that alternating is a particularly good - * approach -- it's just designed to prevent destroys from starving other - * cells completely. - */ - unsigned int last_cell_was_destroy : 1; - /** Destroy counter: increment this when a destroy gets queued, decrement - * when we unqueue it, so we can test to make sure they don't starve. - */ - int64_t destroy_ctr; - - /* - * Circuitmux policy; if this is non-NULL, it can override the built- - * in round-robin active circuits behavior. This is how EWMA works in - * the new circuitmux_t world. - */ - const circuitmux_policy_t *policy; - - /* Policy-specific data */ - circuitmux_policy_data_t *policy_data; -}; - -/* * This struct holds whatever we want to store per attached circuit on a * circuitmux_t; right now, just the count of queued cells and the direction. */ @@ -221,9 +172,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a) ((unsigned int)(a->chan_id & 0xffffffff))); } -/* Declare the struct chanid_circid_muxinfo_map type */ -HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t); - /* Emit a bunch of hash table stuff */ HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, chanid_circid_entry_hash, chanid_circid_entries_eq) diff --git a/src/core/or/circuitmux.h b/src/core/or/circuitmux.h index 67cd9bcdd8..c68c31b29a 100644 --- a/src/core/or/circuitmux.h +++ b/src/core/or/circuitmux.h @@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, MOCK_DECL(int, circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2)); +#ifdef CIRCUITMUX_PRIVATE + +#include "core/or/destroy_cell_queue_st.h" + +/* + * Map of muxinfos for circuitmux_t to use; struct is defined below (name + * of struct must match HT_HEAD line). + */ +typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t) + chanid_circid_muxinfo_map_t; + +/* + * Structures for circuitmux.c + */ + +struct circuitmux_s { + /* Keep count of attached, active circuits */ + unsigned int n_circuits, n_active_circuits; + + /* Total number of queued cells on all circuits */ + unsigned int n_cells; + + /* + * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t + */ + chanid_circid_muxinfo_map_t *chanid_circid_map; + + /** List of queued destroy cells */ + destroy_cell_queue_t destroy_cell_queue; + /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit + * returned the destroy queue. Used to force alternation between + * destroy/non-destroy cells. + * + * XXXX There is no reason to think that alternating is a particularly good + * approach -- it's just designed to prevent destroys from starving other + * cells completely. + */ + unsigned int last_cell_was_destroy : 1; + /** Destroy counter: increment this when a destroy gets queued, decrement + * when we unqueue it, so we can test to make sure they don't starve. + */ + int64_t destroy_ctr; + + /* + * Circuitmux policy; if this is non-NULL, it can override the built- + * in round-robin active circuits behavior. This is how EWMA works in + * the new circuitmux_t world. + */ + const circuitmux_policy_t *policy; + + /* Policy-specific data */ + circuitmux_policy_data_t *policy_data; +}; + +#endif /* CIRCUITMUX_PRIVATE */ + #endif /* !defined(TOR_CIRCUITMUX_H) */ diff --git a/src/core/or/circuitmux_ewma.c b/src/core/or/circuitmux_ewma.c index 3f83c3fd5a..5c9eac1c3f 100644 --- a/src/core/or/circuitmux_ewma.c +++ b/src/core/or/circuitmux_ewma.c @@ -58,115 +58,6 @@ /** The natural logarithm of 0.5. */ #define LOG_ONEHALF -0.69314718055994529 -/*** EWMA structures ***/ - -typedef struct cell_ewma_s cell_ewma_t; -typedef struct ewma_policy_data_s ewma_policy_data_t; -typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; - -/** - * The cell_ewma_t structure keeps track of how many cells a circuit has - * transferred recently. It keeps an EWMA (exponentially weighted moving - * average) of the number of cells flushed from the circuit queue onto a - * connection in channel_flush_from_first_active_circuit(). - */ - -struct cell_ewma_s { - /** The last 'tick' at which we recalibrated cell_count. - * - * A cell sent at exactly the start of this tick has weight 1.0. Cells sent - * since the start of this tick have weight greater than 1.0; ones sent - * earlier have less weight. */ - unsigned int last_adjusted_tick; - /** The EWMA of the cell count. */ - double cell_count; - /** True iff this is the cell count for a circuit's previous - * channel. */ - unsigned int is_for_p_chan : 1; - /** The position of the circuit within the OR connection's priority - * queue. */ - int heap_index; -}; - -struct ewma_policy_data_s { - circuitmux_policy_data_t base_; - - /** - * Priority queue of cell_ewma_t for circuits with queued cells waiting - * for room to free up on the channel that owns this circuitmux. Kept - * in heap order according to EWMA. This was formerly in channel_t, and - * in or_connection_t before that. - */ - smartlist_t *active_circuit_pqueue; - - /** - * The tick on which the cell_ewma_ts in active_circuit_pqueue last had - * their ewma values rescaled. This was formerly in channel_t, and in - * or_connection_t before that. - */ - unsigned int active_circuit_pqueue_last_recalibrated; -}; - -struct ewma_policy_circ_data_s { - circuitmux_policy_circ_data_t base_; - - /** - * The EWMA count for the number of cells flushed from this circuit - * onto this circuitmux. Used to determine which circuit to flush - * from next. This was formerly in circuit_t and or_circuit_t. - */ - cell_ewma_t cell_ewma; - - /** - * Pointer back to the circuit_t this is for; since we're separating - * out circuit selection policy like this, we can't attach cell_ewma_t - * to the circuit_t any more, so we can't use SUBTYPE_P directly to a - * circuit_t like before; instead get it here. - */ - circuit_t *circ; -}; - -#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU -#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U - -/*** Downcasts for the above types ***/ - -static ewma_policy_data_t * -TO_EWMA_POL_DATA(circuitmux_policy_data_t *); - -static ewma_policy_circ_data_t * -TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *); - -/** - * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert - * if the cast is impossible. - */ - -static inline ewma_policy_data_t * -TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) -{ - if (!pol) return NULL; - else { - tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); - return DOWNCAST(ewma_policy_data_t, pol); - } -} - -/** - * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t - * and assert if the cast is impossible. - */ - -static inline ewma_policy_circ_data_t * -TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) -{ - if (!pol) return NULL; - else { - tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); - return DOWNCAST(ewma_policy_circ_data_t, pol); - } -} - /*** Static declarations for circuitmux_ewma.c ***/ static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma); diff --git a/src/core/or/circuitmux_ewma.h b/src/core/or/circuitmux_ewma.h index b45ce1f916..dcfbc17a82 100644 --- a/src/core/or/circuitmux_ewma.h +++ b/src/core/or/circuitmux_ewma.h @@ -22,9 +22,114 @@ void cmux_ewma_set_options(const or_options_t *options, void circuitmux_ewma_free_all(void); #ifdef CIRCUITMUX_EWMA_PRIVATE + +/*** EWMA structures ***/ + +typedef struct cell_ewma_s cell_ewma_t; +typedef struct ewma_policy_data_s ewma_policy_data_t; +typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; + +/** + * The cell_ewma_t structure keeps track of how many cells a circuit has + * transferred recently. It keeps an EWMA (exponentially weighted moving + * average) of the number of cells flushed from the circuit queue onto a + * connection in channel_flush_from_first_active_circuit(). + */ + +struct cell_ewma_s { + /** The last 'tick' at which we recalibrated cell_count. + * + * A cell sent at exactly the start of this tick has weight 1.0. Cells sent + * since the start of this tick have weight greater than 1.0; ones sent + * earlier have less weight. */ + unsigned int last_adjusted_tick; + /** The EWMA of the cell count. */ + double cell_count; + /** True iff this is the cell count for a circuit's previous + * channel. */ + unsigned int is_for_p_chan : 1; + /** The position of the circuit within the OR connection's priority + * queue. */ + int heap_index; +}; + +struct ewma_policy_data_s { + circuitmux_policy_data_t base_; + + /** + * Priority queue of cell_ewma_t for circuits with queued cells waiting + * for room to free up on the channel that owns this circuitmux. Kept + * in heap order according to EWMA. This was formerly in channel_t, and + * in or_connection_t before that. + */ + smartlist_t *active_circuit_pqueue; + + /** + * The tick on which the cell_ewma_ts in active_circuit_pqueue last had + * their ewma values rescaled. This was formerly in channel_t, and in + * or_connection_t before that. + */ + unsigned int active_circuit_pqueue_last_recalibrated; +}; + +struct ewma_policy_circ_data_s { + circuitmux_policy_circ_data_t base_; + + /** + * The EWMA count for the number of cells flushed from this circuit + * onto this circuitmux. Used to determine which circuit to flush + * from next. This was formerly in circuit_t and or_circuit_t. + */ + cell_ewma_t cell_ewma; + + /** + * Pointer back to the circuit_t this is for; since we're separating + * out circuit selection policy like this, we can't attach cell_ewma_t + * to the circuit_t any more, so we can't use SUBTYPE_P directly to a + * circuit_t like before; instead get it here. + */ + circuit_t *circ; +}; + +#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU +#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U + +/*** Downcasts for the above types ***/ + +/** + * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert + * if the cast is impossible. + */ + +static inline ewma_policy_data_t * +TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) +{ + if (!pol) return NULL; + else { + tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); + return DOWNCAST(ewma_policy_data_t, pol); + } +} + +/** + * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t + * and assert if the cast is impossible. + */ + +static inline ewma_policy_circ_data_t * +TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) +{ + if (!pol) return NULL; + else { + tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); + return DOWNCAST(ewma_policy_circ_data_t, pol); + } +} + STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out); STATIC void cell_ewma_initialize_ticks(void); -#endif + +#endif /* CIRCUITMUX_EWMA_PRIVATE */ #endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */ diff --git a/src/core/or/core_or.dox b/src/core/or/core_or.dox new file mode 100644 index 0000000000..1289a85c80 --- /dev/null +++ b/src/core/or/core_or.dox @@ -0,0 +1,4 @@ +/** +@dir core/or +@brief core/or +**/ diff --git a/src/core/or/destroy_cell_queue_st.h b/src/core/or/destroy_cell_queue_st.h index fc817c1b42..3c4df050c2 100644 --- a/src/core/or/destroy_cell_queue_st.h +++ b/src/core/or/destroy_cell_queue_st.h @@ -12,6 +12,8 @@ #ifndef DESTROY_CELL_QUEUE_ST_H #define DESTROY_CELL_QUEUE_ST_H +#include "core/or/cell_queue_st.h" + /** A single queued destroy cell. */ struct destroy_cell_t { TOR_SIMPLEQ_ENTRY(destroy_cell_t) next; diff --git a/src/core/proto/core_proto.dox b/src/core/proto/core_proto.dox new file mode 100644 index 0000000000..3e1e4ddb6d --- /dev/null +++ b/src/core/proto/core_proto.dox @@ -0,0 +1,4 @@ +/** +@dir core/proto +@brief core/proto +**/ diff --git a/src/feature/api/feature_api.dox b/src/feature/api/feature_api.dox new file mode 100644 index 0000000000..cb723b0601 --- /dev/null +++ b/src/feature/api/feature_api.dox @@ -0,0 +1,4 @@ +/** +@dir feature/api +@brief feature/api +**/ diff --git a/src/feature/client/feature_client.dox b/src/feature/client/feature_client.dox new file mode 100644 index 0000000000..1a4881c50a --- /dev/null +++ b/src/feature/client/feature_client.dox @@ -0,0 +1,4 @@ +/** +@dir feature/client +@brief feature/client +**/ diff --git a/src/feature/control/feature_control.dox b/src/feature/control/feature_control.dox new file mode 100644 index 0000000000..1f6e83c1dd --- /dev/null +++ b/src/feature/control/feature_control.dox @@ -0,0 +1,4 @@ +/** +@dir feature/control +@brief feature/control +**/ diff --git a/src/feature/dirauth/feature_dirauth.dox b/src/feature/dirauth/feature_dirauth.dox new file mode 100644 index 0000000000..fa4bee5b31 --- /dev/null +++ b/src/feature/dirauth/feature_dirauth.dox @@ -0,0 +1,4 @@ +/** +@dir feature/dirauth +@brief feature/dirauth +**/ diff --git a/src/feature/dircache/feature_dircache.dox b/src/feature/dircache/feature_dircache.dox new file mode 100644 index 0000000000..5f1c5cc70f --- /dev/null +++ b/src/feature/dircache/feature_dircache.dox @@ -0,0 +1,4 @@ +/** +@dir feature/dircache +@brief feature/dircache +**/ diff --git a/src/feature/dirclient/feature_dirclient.dox b/src/feature/dirclient/feature_dirclient.dox new file mode 100644 index 0000000000..984a17cf51 --- /dev/null +++ b/src/feature/dirclient/feature_dirclient.dox @@ -0,0 +1,4 @@ +/** +@dir feature/dirclient +@brief feature/dirclient +**/ diff --git a/src/feature/dircommon/feature_dircommon.dox b/src/feature/dircommon/feature_dircommon.dox new file mode 100644 index 0000000000..2eff21065c --- /dev/null +++ b/src/feature/dircommon/feature_dircommon.dox @@ -0,0 +1,4 @@ +/** +@dir feature/dircommon +@brief feature/dircommon +**/ diff --git a/src/feature/dirparse/feature_dirparse.dox b/src/feature/dirparse/feature_dirparse.dox new file mode 100644 index 0000000000..a6b34c1f5f --- /dev/null +++ b/src/feature/dirparse/feature_dirparse.dox @@ -0,0 +1,4 @@ +/** +@dir feature/dirparse +@brief feature/dirparse +**/ diff --git a/src/feature/feature.dox b/src/feature/feature.dox new file mode 100644 index 0000000000..1d9c3a9df4 --- /dev/null +++ b/src/feature/feature.dox @@ -0,0 +1,9 @@ +/** +@dir feature +@brief feature: domain-specific modules + +The "feature" directory has modules that Tor uses only for a particular +role or service, such as maintaining/using an onion service, operating as a +relay or a client, or being a directory authority. + +**/ diff --git a/src/feature/hibernate/feature_hibernate.dox b/src/feature/hibernate/feature_hibernate.dox new file mode 100644 index 0000000000..e24620a43c --- /dev/null +++ b/src/feature/hibernate/feature_hibernate.dox @@ -0,0 +1,4 @@ +/** +@dir feature/hibernate +@brief feature/hibernate +**/ diff --git a/src/feature/hs/feature_hs.dox b/src/feature/hs/feature_hs.dox new file mode 100644 index 0000000000..08801d002d --- /dev/null +++ b/src/feature/hs/feature_hs.dox @@ -0,0 +1,4 @@ +/** +@dir feature/hs +@brief feature/hs +**/ diff --git a/src/feature/hs_common/feature_hs_common.dox b/src/feature/hs_common/feature_hs_common.dox new file mode 100644 index 0000000000..8fd4f1b07c --- /dev/null +++ b/src/feature/hs_common/feature_hs_common.dox @@ -0,0 +1,4 @@ +/** +@dir feature/hs_common +@brief feature/hs_common +**/ diff --git a/src/feature/keymgt/feature_keymgt.dox b/src/feature/keymgt/feature_keymgt.dox new file mode 100644 index 0000000000..8f72c70bbd --- /dev/null +++ b/src/feature/keymgt/feature_keymgt.dox @@ -0,0 +1,4 @@ +/** +@dir feature/keymgt +@brief feature/keymgt +**/ diff --git a/src/feature/nodelist/feature_nodelist.dox b/src/feature/nodelist/feature_nodelist.dox new file mode 100644 index 0000000000..faeb9970b3 --- /dev/null +++ b/src/feature/nodelist/feature_nodelist.dox @@ -0,0 +1,4 @@ +/** +@dir feature/nodelist +@brief feature/nodelist +**/ diff --git a/src/feature/relay/feature_relay.dox b/src/feature/relay/feature_relay.dox new file mode 100644 index 0000000000..9aa7af48e6 --- /dev/null +++ b/src/feature/relay/feature_relay.dox @@ -0,0 +1,4 @@ +/** +@dir feature/relay +@brief feature/relay +**/ diff --git a/src/feature/rend/feature_rend.dox b/src/feature/rend/feature_rend.dox new file mode 100644 index 0000000000..fcba0d460f --- /dev/null +++ b/src/feature/rend/feature_rend.dox @@ -0,0 +1,4 @@ +/** +@dir feature/rend +@brief feature/rend +**/ diff --git a/src/feature/rend/rendcache.c b/src/feature/rend/rendcache.c index c3f86d8c82..2d8de2a80d 100644 --- a/src/feature/rend/rendcache.c +++ b/src/feature/rend/rendcache.c @@ -228,6 +228,17 @@ rend_cache_entry_free_void(void *p) rend_cache_entry_free_(p); } +/** Check if a failure cache entry exists for the given intro point. */ +bool +rend_cache_intro_failure_exists(const char *service_id, + const uint8_t *intro_identity) +{ + tor_assert(service_id); + tor_assert(intro_identity); + + return cache_failure_intro_lookup(intro_identity, service_id, NULL); +} + /** Free all storage held by the service descriptor cache. */ void rend_cache_free_all(void) diff --git a/src/feature/rend/rendcache.h b/src/feature/rend/rendcache.h index aec97eabb8..c83f36d189 100644 --- a/src/feature/rend/rendcache.h +++ b/src/feature/rend/rendcache.h @@ -80,6 +80,8 @@ int rend_cache_store_v2_desc_as_client(const char *desc, rend_cache_entry_t **entry); size_t rend_cache_get_total_allocation(void); +bool rend_cache_intro_failure_exists(const char *service_id, + const uint8_t *intro_identity); void rend_cache_intro_failure_note(rend_intro_point_failure_t failure, const uint8_t *identity, const char *service_id); diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c index 2540066dfc..bc94c88efb 100644 --- a/src/feature/rend/rendclient.c +++ b/src/feature/rend/rendclient.c @@ -1048,18 +1048,29 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry, const or_options_t *options = get_options(); smartlist_t *usable_nodes; int n_excluded = 0; + char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; /* We'll keep a separate list of the usable nodes. If this becomes empty, * no nodes are usable. */ usable_nodes = smartlist_new(); smartlist_add_all(usable_nodes, entry->parsed->intro_nodes); + /* Get service ID so we can use it to query the failure cache. If we fail to + * parse it, this cache entry is no good. */ + if (BUG(rend_get_service_id(entry->parsed->pk, service_id) < 0)) { + return NULL; + } + /* Remove the intro points that have timed out during this HS * connection attempt from our list of usable nodes. */ - SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip, - if (ip->timed_out) { - SMARTLIST_DEL_CURRENT(usable_nodes, ip); - }); + SMARTLIST_FOREACH_BEGIN(usable_nodes, const rend_intro_point_t *, ip) { + bool failed_intro = + rend_cache_intro_failure_exists(service_id, + (const uint8_t *) ip->extend_info->identity_digest); + if (ip->timed_out || failed_intro) { + SMARTLIST_DEL_CURRENT(usable_nodes, ip); + }; + } SMARTLIST_FOREACH_END(ip); again: if (smartlist_len(usable_nodes) == 0) { diff --git a/src/feature/stats/feature_stats.dox b/src/feature/stats/feature_stats.dox new file mode 100644 index 0000000000..fc4ffd19df --- /dev/null +++ b/src/feature/stats/feature_stats.dox @@ -0,0 +1,4 @@ +/** +@dir feature/stats +@brief feature/stats +**/ diff --git a/src/lib/arch/lib_arch.dox b/src/lib/arch/lib_arch.dox new file mode 100644 index 0000000000..60b5fafeb4 --- /dev/null +++ b/src/lib/arch/lib_arch.dox @@ -0,0 +1,4 @@ +/** +@dir lib/arch +@brief lib/arch +**/ diff --git a/src/lib/buf/lib_buf.dox b/src/lib/buf/lib_buf.dox new file mode 100644 index 0000000000..f21c4b1b72 --- /dev/null +++ b/src/lib/buf/lib_buf.dox @@ -0,0 +1,4 @@ +/** +@dir lib/buf +@brief lib/buf +**/ diff --git a/src/lib/cc/lib_cc.dox b/src/lib/cc/lib_cc.dox new file mode 100644 index 0000000000..804260cb29 --- /dev/null +++ b/src/lib/cc/lib_cc.dox @@ -0,0 +1,4 @@ +/** +@dir lib/cc +@brief lib/cc +**/ diff --git a/src/lib/compress/lib_compress.dox b/src/lib/compress/lib_compress.dox new file mode 100644 index 0000000000..ac60794565 --- /dev/null +++ b/src/lib/compress/lib_compress.dox @@ -0,0 +1,4 @@ +/** +@dir lib/compress +@brief lib/compress +**/ diff --git a/src/lib/conf/lib_conf.dox b/src/lib/conf/lib_conf.dox new file mode 100644 index 0000000000..40a1d9f90f --- /dev/null +++ b/src/lib/conf/lib_conf.dox @@ -0,0 +1,4 @@ +/** +@dir lib/conf +@brief lib/conf +**/ diff --git a/src/lib/confmgt/lib_confmgt.dox b/src/lib/confmgt/lib_confmgt.dox new file mode 100644 index 0000000000..964fe1d074 --- /dev/null +++ b/src/lib/confmgt/lib_confmgt.dox @@ -0,0 +1,4 @@ +/** +@dir lib/confmgt +@brief lib/confmgt +**/ diff --git a/src/lib/container/lib_container.dox b/src/lib/container/lib_container.dox new file mode 100644 index 0000000000..6ee719f47e --- /dev/null +++ b/src/lib/container/lib_container.dox @@ -0,0 +1,4 @@ +/** +@dir lib/container +@brief lib/container +**/ diff --git a/src/lib/crypt_ops/lib_crypt_ops.dox b/src/lib/crypt_ops/lib_crypt_ops.dox new file mode 100644 index 0000000000..1ea0b67d59 --- /dev/null +++ b/src/lib/crypt_ops/lib_crypt_ops.dox @@ -0,0 +1,4 @@ +/** +@dir lib/crypt_ops +@brief lib/crypt_ops +**/ diff --git a/src/lib/ctime/lib_ctime.dox b/src/lib/ctime/lib_ctime.dox new file mode 100644 index 0000000000..476c95991c --- /dev/null +++ b/src/lib/ctime/lib_ctime.dox @@ -0,0 +1,4 @@ +/** +@dir lib/ctime +@brief lib/ctime +**/ diff --git a/src/lib/defs/lib_defs.dox b/src/lib/defs/lib_defs.dox new file mode 100644 index 0000000000..5adb527fc7 --- /dev/null +++ b/src/lib/defs/lib_defs.dox @@ -0,0 +1,4 @@ +/** +@dir lib/defs +@brief lib/defs +**/ diff --git a/src/lib/dispatch/lib_dispatch.dox b/src/lib/dispatch/lib_dispatch.dox new file mode 100644 index 0000000000..f194eff481 --- /dev/null +++ b/src/lib/dispatch/lib_dispatch.dox @@ -0,0 +1,4 @@ +/** +@dir lib/dispatch +@brief lib/dispatch +**/ diff --git a/src/lib/encoding/lib_encoding.dox b/src/lib/encoding/lib_encoding.dox new file mode 100644 index 0000000000..4a5fad9271 --- /dev/null +++ b/src/lib/encoding/lib_encoding.dox @@ -0,0 +1,4 @@ +/** +@dir lib/encoding +@brief lib/encoding +**/ diff --git a/src/lib/err/lib_err.dox b/src/lib/err/lib_err.dox new file mode 100644 index 0000000000..8994fa5fd8 --- /dev/null +++ b/src/lib/err/lib_err.dox @@ -0,0 +1,4 @@ +/** +@dir lib/err +@brief lib/err +**/ diff --git a/src/lib/evloop/lib_evloop.dox b/src/lib/evloop/lib_evloop.dox new file mode 100644 index 0000000000..86b60e3cd5 --- /dev/null +++ b/src/lib/evloop/lib_evloop.dox @@ -0,0 +1,4 @@ +/** +@dir lib/evloop +@brief lib/evloop +**/ diff --git a/src/lib/fdio/lib_fdio.dox b/src/lib/fdio/lib_fdio.dox new file mode 100644 index 0000000000..b868d28aab --- /dev/null +++ b/src/lib/fdio/lib_fdio.dox @@ -0,0 +1,4 @@ +/** +@dir lib/fdio +@brief lib/fdio +**/ diff --git a/src/lib/fs/lib_fs.dox b/src/lib/fs/lib_fs.dox new file mode 100644 index 0000000000..ad775ba553 --- /dev/null +++ b/src/lib/fs/lib_fs.dox @@ -0,0 +1,4 @@ +/** +@dir lib/fs +@brief lib/fs +**/ diff --git a/src/lib/geoip/lib_geoip.dox b/src/lib/geoip/lib_geoip.dox new file mode 100644 index 0000000000..7ad99e8f55 --- /dev/null +++ b/src/lib/geoip/lib_geoip.dox @@ -0,0 +1,4 @@ +/** +@dir lib/geoip +@brief lib/geoip +**/ diff --git a/src/lib/intmath/lib_intmath.dox b/src/lib/intmath/lib_intmath.dox new file mode 100644 index 0000000000..ce71e455d1 --- /dev/null +++ b/src/lib/intmath/lib_intmath.dox @@ -0,0 +1,4 @@ +/** +@dir lib/intmath +@brief lib/intmath +**/ diff --git a/src/lib/lib.dox b/src/lib/lib.dox new file mode 100644 index 0000000000..f1b2291c76 --- /dev/null +++ b/src/lib/lib.dox @@ -0,0 +1,8 @@ +/** +@dir lib +@brief lib: low-level functionality. + +The "lib" directory contains low-level functionality, most of it not +necessarily Tor-specific. + +**/ diff --git a/src/lib/lock/lib_lock.dox b/src/lib/lock/lib_lock.dox new file mode 100644 index 0000000000..44693e7a69 --- /dev/null +++ b/src/lib/lock/lib_lock.dox @@ -0,0 +1,4 @@ +/** +@dir lib/lock +@brief lib/lock +**/ diff --git a/src/lib/log/lib_log.dox b/src/lib/log/lib_log.dox new file mode 100644 index 0000000000..915d652407 --- /dev/null +++ b/src/lib/log/lib_log.dox @@ -0,0 +1,4 @@ +/** +@dir lib/log +@brief lib/log +**/ diff --git a/src/lib/malloc/lib_malloc.dox b/src/lib/malloc/lib_malloc.dox new file mode 100644 index 0000000000..4923f14463 --- /dev/null +++ b/src/lib/malloc/lib_malloc.dox @@ -0,0 +1,4 @@ +/** +@dir lib/malloc +@brief lib/malloc +**/ diff --git a/src/lib/math/lib_math.dox b/src/lib/math/lib_math.dox new file mode 100644 index 0000000000..c2e121dc8c --- /dev/null +++ b/src/lib/math/lib_math.dox @@ -0,0 +1,4 @@ +/** +@dir lib/math +@brief lib/math +**/ diff --git a/src/lib/memarea/lib_memarea.dox b/src/lib/memarea/lib_memarea.dox new file mode 100644 index 0000000000..dbd98de5ec --- /dev/null +++ b/src/lib/memarea/lib_memarea.dox @@ -0,0 +1,4 @@ +/** +@dir lib/memarea +@brief lib/memarea +**/ diff --git a/src/lib/meminfo/lib_meminfo.dox b/src/lib/meminfo/lib_meminfo.dox new file mode 100644 index 0000000000..c8def7e2f9 --- /dev/null +++ b/src/lib/meminfo/lib_meminfo.dox @@ -0,0 +1,4 @@ +/** +@dir lib/meminfo +@brief lib/meminfo +**/ diff --git a/src/lib/net/lib_net.dox b/src/lib/net/lib_net.dox new file mode 100644 index 0000000000..03783c12aa --- /dev/null +++ b/src/lib/net/lib_net.dox @@ -0,0 +1,4 @@ +/** +@dir lib/net +@brief lib/net +**/ diff --git a/src/lib/osinfo/lib_osinfo.dox b/src/lib/osinfo/lib_osinfo.dox new file mode 100644 index 0000000000..7733755f20 --- /dev/null +++ b/src/lib/osinfo/lib_osinfo.dox @@ -0,0 +1,4 @@ +/** +@dir lib/osinfo +@brief lib/osinfo +**/ diff --git a/src/lib/process/lib_process.dox b/src/lib/process/lib_process.dox new file mode 100644 index 0000000000..efb1adc091 --- /dev/null +++ b/src/lib/process/lib_process.dox @@ -0,0 +1,4 @@ +/** +@dir lib/process +@brief lib/process +**/ diff --git a/src/lib/pubsub/lib_pubsub.dox b/src/lib/pubsub/lib_pubsub.dox new file mode 100644 index 0000000000..9a3fc6dfac --- /dev/null +++ b/src/lib/pubsub/lib_pubsub.dox @@ -0,0 +1,4 @@ +/** +@dir lib/pubsub +@brief lib/pubsub +**/ diff --git a/src/lib/sandbox/lib_sandbox.dox b/src/lib/sandbox/lib_sandbox.dox new file mode 100644 index 0000000000..eb42d97589 --- /dev/null +++ b/src/lib/sandbox/lib_sandbox.dox @@ -0,0 +1,4 @@ +/** +@dir lib/sandbox +@brief lib/sandbox +**/ diff --git a/src/lib/smartlist_core/lib_smartlist_core.dox b/src/lib/smartlist_core/lib_smartlist_core.dox new file mode 100644 index 0000000000..507d0fe92f --- /dev/null +++ b/src/lib/smartlist_core/lib_smartlist_core.dox @@ -0,0 +1,4 @@ +/** +@dir lib/smartlist_core +@brief lib/smartlist_core +**/ diff --git a/src/lib/stats/lib_stats.dox b/src/lib/stats/lib_stats.dox new file mode 100644 index 0000000000..897c41418f --- /dev/null +++ b/src/lib/stats/lib_stats.dox @@ -0,0 +1,4 @@ +/** +@dir lib/stats +@brief lib/stats +**/ diff --git a/src/lib/string/lib_string.dox b/src/lib/string/lib_string.dox new file mode 100644 index 0000000000..3e038ea072 --- /dev/null +++ b/src/lib/string/lib_string.dox @@ -0,0 +1,4 @@ +/** +@dir lib/string +@brief lib/string +**/ diff --git a/src/lib/subsys/lib_subsys.dox b/src/lib/subsys/lib_subsys.dox new file mode 100644 index 0000000000..f9cd5eeb81 --- /dev/null +++ b/src/lib/subsys/lib_subsys.dox @@ -0,0 +1,4 @@ +/** +@dir lib/subsys +@brief lib/subsys +**/ diff --git a/src/lib/term/lib_term.dox b/src/lib/term/lib_term.dox new file mode 100644 index 0000000000..2bc5125839 --- /dev/null +++ b/src/lib/term/lib_term.dox @@ -0,0 +1,4 @@ +/** +@dir lib/term +@brief lib/term +**/ diff --git a/src/lib/testsupport/lib_testsupport.dox b/src/lib/testsupport/lib_testsupport.dox new file mode 100644 index 0000000000..63ccc47d34 --- /dev/null +++ b/src/lib/testsupport/lib_testsupport.dox @@ -0,0 +1,4 @@ +/** +@dir lib/testsupport +@brief lib/testsupport +**/ diff --git a/src/lib/thread/lib_thread.dox b/src/lib/thread/lib_thread.dox new file mode 100644 index 0000000000..68937ef793 --- /dev/null +++ b/src/lib/thread/lib_thread.dox @@ -0,0 +1,4 @@ +/** +@dir lib/thread +@brief lib/thread +**/ diff --git a/src/lib/time/lib_time.dox b/src/lib/time/lib_time.dox new file mode 100644 index 0000000000..50abf072f7 --- /dev/null +++ b/src/lib/time/lib_time.dox @@ -0,0 +1,4 @@ +/** +@dir lib/time +@brief lib/time +**/ diff --git a/src/lib/tls/lib_tls.dox b/src/lib/tls/lib_tls.dox new file mode 100644 index 0000000000..40b7b2c27e --- /dev/null +++ b/src/lib/tls/lib_tls.dox @@ -0,0 +1,4 @@ +/** +@dir lib/tls +@brief lib/tls +**/ diff --git a/src/lib/trace/lib_trace.dox b/src/lib/trace/lib_trace.dox new file mode 100644 index 0000000000..a1ae256506 --- /dev/null +++ b/src/lib/trace/lib_trace.dox @@ -0,0 +1,4 @@ +/** +@dir lib/trace +@brief lib/trace +**/ diff --git a/src/lib/version/lib_version.dox b/src/lib/version/lib_version.dox new file mode 100644 index 0000000000..213e1a1ae8 --- /dev/null +++ b/src/lib/version/lib_version.dox @@ -0,0 +1,4 @@ +/** +@dir lib/version +@brief lib/version +**/ diff --git a/src/lib/wallclock/lib_wallclock.dox b/src/lib/wallclock/lib_wallclock.dox new file mode 100644 index 0000000000..7bb2b075d1 --- /dev/null +++ b/src/lib/wallclock/lib_wallclock.dox @@ -0,0 +1,4 @@ +/** +@dir lib/wallclock +@brief lib/wallclock +**/ diff --git a/src/mainpage.dox b/src/mainpage.dox new file mode 100644 index 0000000000..84eea3c526 --- /dev/null +++ b/src/mainpage.dox @@ -0,0 +1,11 @@ +/** +@mainpage Tor source reference + +@section intro Getting to know Tor + +Welcome to the Tor source code documentation! Here we have documentation for +nearly every function, type, and module in the Tor source code. The high-level +documentation is a work in progress. For now, have a look at the source code +overview in doc/HACKING/design. + +**/ diff --git a/src/test/fakecircs.c b/src/test/fakecircs.c new file mode 100644 index 0000000000..62027e0339 --- /dev/null +++ b/src/test/fakecircs.c @@ -0,0 +1,88 @@ +/* Copyright (c) 2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file fakecircs.c + * \brief Fake circuits API for unit test. + **/ + +#define CHANNEL_PRIVATE +#define CIRCUITBUILD_PRIVATE +#define CIRCUITLIST_PRIVATE +#define CRYPT_PATH_PRIVATE + +#include "core/or/or.h" + +#include "core/crypto/relay_crypto.h" +#include "core/or/channel.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitpadding.h" +#include "core/or/crypt_path.h" +#include "core/or/relay.h" +#include "core/or/relay_crypto_st.h" + +#include "fakecircs.h" + +/** Return newly allocated OR circuit using the given nchan and pchan. It must + * be freed with the free_fake_orcirc(). */ +or_circuit_t * +new_fake_orcirc(channel_t *nchan, channel_t *pchan) +{ + or_circuit_t *orcirc = NULL; + circuit_t *circ = NULL; + crypt_path_t tmp_cpath; + char whatevs_key[CPATH_KEY_MATERIAL_LEN]; + + orcirc = tor_malloc_zero(sizeof(*orcirc)); + circ = &(orcirc->base_); + circ->magic = OR_CIRCUIT_MAGIC; + + circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan); + cell_queue_init(&(circ->n_chan_cells)); + + circ->n_hop = NULL; + circ->streams_blocked_on_n_chan = 0; + circ->streams_blocked_on_p_chan = 0; + circ->n_delete_pending = 0; + circ->p_delete_pending = 0; + circ->received_destroy = 0; + circ->state = CIRCUIT_STATE_OPEN; + circ->purpose = CIRCUIT_PURPOSE_OR; + circ->package_window = CIRCWINDOW_START_MAX; + circ->deliver_window = CIRCWINDOW_START_MAX; + circ->n_chan_create_cell = NULL; + + circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan); + cell_queue_init(&(orcirc->p_chan_cells)); + + memset(&tmp_cpath, 0, sizeof(tmp_cpath)); + if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key, + sizeof(whatevs_key), 0, 0)<0) { + log_warn(LD_BUG,"Circuit initialization failed"); + return NULL; + } + orcirc->crypto = tmp_cpath.pvt_crypto; + + return orcirc; +} + +/** Free fake OR circuit which MUST be created by new_fake_orcirc(). */ +void +free_fake_orcirc(or_circuit_t *orcirc) +{ + circuit_t *circ = TO_CIRCUIT(orcirc); + + relay_crypto_clear(&orcirc->crypto); + + circpad_circuit_free_all_machineinfos(circ); + + if (orcirc->p_chan && orcirc->p_chan->cmux) { + circuitmux_detach_circuit(orcirc->p_chan->cmux, circ); + } + if (circ->n_chan && circ->n_chan->cmux) { + circuitmux_detach_circuit(circ->n_chan->cmux, circ); + } + + tor_free_(circ); +} diff --git a/src/test/fakecircs.h b/src/test/fakecircs.h new file mode 100644 index 0000000000..5fd02027f0 --- /dev/null +++ b/src/test/fakecircs.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file fakecircs.h + * \brief Declarations for fake circuits for test suite use. + **/ + +#ifndef TOR_FAKECIRCS_H +#define TOR_FAKECIRCS_H + +#include "core/or/or_circuit_st.h" + +or_circuit_t *new_fake_orcirc(channel_t *nchan, channel_t *pchan); +void free_fake_orcirc(or_circuit_t *orcirc); + +#endif /* TOR_FAKECIRCS_H */ diff --git a/src/test/include.am b/src/test/include.am index 11604938ee..bd7ab71a20 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -99,6 +99,7 @@ if UNITTESTS_ENABLED # ADD_C_FILE: INSERT SOURCES HERE. src_test_test_SOURCES += \ + src/test/fakecircs.c \ src/test/log_test_helpers.c \ src/test/hs_test_helpers.c \ src/test/rend_test_helpers.c \ @@ -122,6 +123,7 @@ src_test_test_SOURCES += \ src/test/test_checkdir.c \ src/test/test_circuitlist.c \ src/test/test_circuitmux.c \ + src/test/test_circuitmux_ewma.c \ src/test/test_circuitbuild.c \ src/test/test_circuituse.c \ src/test/test_circuitstats.c \ @@ -340,6 +342,7 @@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS+= \ src/test/fakechans.h \ + src/test/fakecircs.h \ src/test/hs_test_helpers.h \ src/test/log_test_helpers.h \ src/test/rend_test_helpers.h \ diff --git a/src/test/test.c b/src/test/test.c index e8cfe62733..90c0058be8 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -674,6 +674,7 @@ struct testgroup_t testgroups[] = { { "circuitpadding/", circuitpadding_tests }, { "circuitlist/", circuitlist_tests }, { "circuitmux/", circuitmux_tests }, + { "circuitmux_ewma/", circuitmux_ewma_tests }, { "circuitstats/", circuitstats_tests }, { "circuituse/", circuituse_tests }, { "compat/libevent/", compat_libevent_tests }, diff --git a/src/test/test.h b/src/test/test.h index 21d2efe7df..967562890f 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -199,6 +199,7 @@ extern struct testcase_t checkdir_tests[]; extern struct testcase_t circuitbuild_tests[]; extern struct testcase_t circuitlist_tests[]; extern struct testcase_t circuitmux_tests[]; +extern struct testcase_t circuitmux_ewma_tests[]; extern struct testcase_t circuitstats_tests[]; extern struct testcase_t circuituse_tests[]; extern struct testcase_t compat_libevent_tests[]; diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index a2b3e62fe8..6d9e5c472d 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -5,29 +5,23 @@ #define CIRCUITMUX_PRIVATE #define CIRCUITMUX_EWMA_PRIVATE #define RELAY_PRIVATE + #include "core/or/or.h" #include "core/or/channel.h" #include "core/or/circuitmux.h" #include "core/or/circuitmux_ewma.h" +#include "core/or/destroy_cell_queue_st.h" #include "core/or/relay.h" #include "core/or/scheduler.h" -#include "test/test.h" -#include "core/or/destroy_cell_queue_st.h" +#include "test/fakechans.h" +#include "test/fakecircs.h" +#include "test/test.h" #include <math.h> -/* XXXX duplicated function from test_circuitlist.c */ -static channel_t * -new_fake_channel(void) -{ - channel_t *chan = tor_malloc_zero(sizeof(channel_t)); - channel_init(chan); - return chan; -} - static int -has_queued_writes(channel_t *c) +mock_has_queued_writes_true(channel_t *c) { (void) c; return 1; @@ -44,16 +38,14 @@ test_cmux_destroy_cell_queue(void *arg) packed_cell_t *pc = NULL; destroy_cell_t *dc = NULL; - scheduler_init(); + MOCK(scheduler_release_channel, scheduler_release_channel_mock); (void) arg; - cmux = circuitmux_alloc(); - tt_assert(cmux); ch = new_fake_channel(); - circuitmux_set_policy(cmux, &ewma_policy); - ch->has_queued_writes = has_queued_writes; + ch->has_queued_writes = mock_has_queued_writes_true; ch->wide_circ_ids = 1; + cmux = ch->cmux; circ = circuitmux_get_first_active_circuit(cmux, &cq); tt_ptr_op(circ, OP_EQ, NULL); @@ -78,10 +70,11 @@ test_cmux_destroy_cell_queue(void *arg) tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 2); done: - circuitmux_free(cmux); - channel_free(ch); + free_fake_channel(ch); packed_cell_free(pc); tor_free(dc); + + UNMOCK(scheduler_release_channel); } static void @@ -125,9 +118,364 @@ test_cmux_compute_ticks(void *arg) ; } +static void +test_cmux_allocate(void *arg) +{ + circuitmux_t *cmux = NULL; + + (void) arg; + + cmux = circuitmux_alloc(); + tt_assert(cmux); + tt_assert(cmux->chanid_circid_map); + tt_int_op(HT_SIZE(cmux->chanid_circid_map), OP_EQ, 0); + tt_uint_op(cmux->n_circuits, OP_EQ, 0); + tt_uint_op(cmux->n_active_circuits, OP_EQ, 0); + tt_uint_op(cmux->n_cells, OP_EQ, 0); + tt_uint_op(cmux->last_cell_was_destroy, OP_EQ, 0); + tt_int_op(cmux->destroy_ctr, OP_EQ, 0); + tt_ptr_op(cmux->policy, OP_EQ, NULL); + tt_ptr_op(cmux->policy_data, OP_EQ, NULL); + + tt_assert(TOR_SIMPLEQ_EMPTY(&cmux->destroy_cell_queue.head)); + + done: + circuitmux_free(cmux); +} + +static void +test_cmux_attach_circuit(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + cell_direction_t cdir; + unsigned int n_cells; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is + * called for a new channel on the circuit. This means, we should now have + * the created circuit attached on both the pchan and nchan cmux. */ + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1); + + /* There should be _no_ active circuit due to no queued cells. */ + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0); + tt_uint_op(circuitmux_num_active_circuits(nchan->cmux), OP_EQ, 0); + + /* Circuit should not be active on the cmux. */ + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0); + + /* Not active so no cells. */ + n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ); + tt_uint_op(n_cells, OP_EQ, 0); + n_cells = circuitmux_num_cells(pchan->cmux); + tt_uint_op(n_cells, OP_EQ, 0); + n_cells = circuitmux_num_cells_for_circuit(nchan->cmux, circ); + tt_uint_op(n_cells, OP_EQ, 0); + n_cells = circuitmux_num_cells(nchan->cmux); + tt_uint_op(n_cells, OP_EQ, 0); + + /* So it should be attached :) */ + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1); + + /* Query the chanid<->circid map in the cmux subsytem with what we just + * created and validate the cell direction. */ + cdir = circuitmux_attached_circuit_direction(pchan->cmux, circ); + tt_int_op(cdir, OP_EQ, CELL_DIRECTION_IN); + cdir = circuitmux_attached_circuit_direction(nchan->cmux, circ); + tt_int_op(cdir, OP_EQ, CELL_DIRECTION_OUT); + + /* + * We'll activate->deactivate->activate to test all code paths of + * circuitmux_set_num_cells(). + */ + + /* Activate circuit. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + + /* Deactivate. */ + circuitmux_clear_num_cells(pchan->cmux, circ); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0); + + /* Re-activate. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + + /* Once re-attached, it should become inactive because the circuit has no + * cells while the chanid<->circid object has some. The attach code will + * reset the count on the cmux for that circuit: + * + * if (chanid_circid_muxinfo_t->muxinfo.cell_count > 0 && cell_count == 0) { + */ + circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN); + n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ); + tt_uint_op(n_cells, OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0); + + /* Lets queue a cell on the circuit now so it becomes active when + * re-attaching: + * + * else if (chanid_circid_muxinfo_t->muxinfo.cell_count == 0 && + * cell_count > 0) { + */ + orcirc->p_chan_cells.n = 1; + circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_detach_circuit(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is + * called for a new channel on the circuit. This means, we should now have + * the created circuit attached on both the pchan and nchan cmux. */ + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1); + + /* Now, detach the circuit from pchan and then nchan. */ + circuitmux_detach_circuit(pchan->cmux, circ); + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0); + circuitmux_detach_circuit(nchan->cmux, circ); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_detach_all_circuits(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + smartlist_t *detached_out = smartlist_new(); + + (void) arg; + + /* Channels need to be registered in order for the detach all circuit + * function to find them. */ + pchan = new_fake_channel(); + tt_assert(pchan); + channel_register(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + channel_register(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* Just make sure it is attached. */ + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1); + + /* Queue some cells so we can test if the circuit becomes inactive on the + * cmux after the mass detach. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + circuitmux_set_num_cells(nchan->cmux, circ, 4); + + /* Detach all on pchan and then nchan. */ + circuitmux_detach_all_circuits(pchan->cmux, detached_out); + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(smartlist_len(detached_out), OP_EQ, 1); + circuitmux_detach_all_circuits(nchan->cmux, NULL); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0); + + done: + smartlist_free(detached_out); + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_policy(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + channel_register(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + channel_register(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* Confirm we have the EWMA policy by default for new channels. */ + tt_ptr_op(circuitmux_get_policy(pchan->cmux), OP_EQ, &ewma_policy); + tt_ptr_op(circuitmux_get_policy(nchan->cmux), OP_EQ, &ewma_policy); + + /* Putting cell on the cmux means will make the notify policy code path to + * trigger. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + + /* Clear it out. */ + circuitmux_clear_policy(pchan->cmux); + + /* Set back the EWMA policy. */ + circuitmux_set_policy(pchan->cmux, &ewma_policy); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_xmit_cell(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* Queue 4 cells on the circuit. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 4); + tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 4); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1); + + /* Emit the first cell. Circuit should still be active. */ + circuitmux_notify_xmit_cells(pchan->cmux, circ, 1); + tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 3); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 3); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1); + + /* Emit the last 3 cells. Circuit should become inactive. */ + circuitmux_notify_xmit_cells(pchan->cmux, circ, 3); + tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 0); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0); + + /* Queue a DESTROY cell. */ + pchan->has_queued_writes = mock_has_queued_writes_true; + circuitmux_append_destroy_cell(pchan, pchan->cmux, orcirc->p_circ_id, 0); + tt_int_op(pchan->cmux->destroy_ctr, OP_EQ, 1); + tt_int_op(pchan->cmux->destroy_cell_queue.n, OP_EQ, 1); + tt_int_op(circuitmux_count_queued_destroy_cells(pchan, pchan->cmux), + OP_EQ, 1); + + /* Emit the DESTROY cell. */ + circuitmux_notify_xmit_destroy(pchan->cmux); + tt_int_op(pchan->cmux->destroy_ctr, OP_EQ, 0); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void * +cmux_setup_test(const struct testcase_t *tc) +{ + static int whatever; + + (void) tc; + + cell_ewma_initialize_ticks(); + return &whatever; +} + +static int +cmux_cleanup_test(const struct testcase_t *tc, void *ptr) +{ + (void) tc; + (void) ptr; + + circuitmux_ewma_free_all(); + + return 1; +} + +static struct testcase_setup_t cmux_test_setup = { + .setup_fn = cmux_setup_test, + .cleanup_fn = cmux_cleanup_test, +}; + +#define TEST_CMUX(name) \ + { #name, test_cmux_##name, TT_FORK, &cmux_test_setup, NULL } + struct testcase_t circuitmux_tests[] = { - { "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL }, - { "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL }, + /* Test circuitmux_t object */ + TEST_CMUX(allocate), + TEST_CMUX(attach_circuit), + TEST_CMUX(detach_circuit), + TEST_CMUX(detach_all_circuits), + TEST_CMUX(policy), + TEST_CMUX(xmit_cell), + + /* Misc. */ + TEST_CMUX(compute_ticks), + TEST_CMUX(destroy_cell_queue), + END_OF_TESTCASES }; diff --git a/src/test/test_circuitmux_ewma.c b/src/test/test_circuitmux_ewma.c new file mode 100644 index 0000000000..8b3edf2b06 --- /dev/null +++ b/src/test/test_circuitmux_ewma.c @@ -0,0 +1,228 @@ +/* Copyright (c) 2013-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define CIRCUITMUX_PRIVATE +#define CIRCUITMUX_EWMA_PRIVATE + +#include "core/or/or.h" +#include "core/or/circuitmux.h" +#include "core/or/circuitmux_ewma.h" + +#include "test/fakechans.h" +#include "test/fakecircs.h" +#include "test/test.h" + +static void +test_cmux_ewma_active_circuit(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t *pol_data = NULL; + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + + /* Get EWMA specific objects. */ + + /* Make circuit active. */ + ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); + + circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data); + tt_mem_op(entry, OP_EQ, &circ, sizeof(circ)); + + done: + ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void +test_cmux_ewma_xmit_cell(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t *pol_data = NULL; + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + ewma_policy_data_t *ewma_pol_data; + ewma_policy_circ_data_t *ewma_data; + double old_cell_count; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); + + /* Make circuit active. */ + ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); + + /* Move back in time the last time we calibrated so we scale the active + * circuit when emitting a cell. */ + ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100; + ewma_data->cell_ewma.last_adjusted_tick = + ewma_pol_data->active_circuit_pqueue_last_recalibrated; + + /* Grab old cell count. */ + old_cell_count = ewma_data->cell_ewma.cell_count; + + ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1); + + /* Our old cell count should be lower to what we have since we just emitted + * a cell and thus we scale. */ + tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count); + + done: + ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void +test_cmux_ewma_notify_circ(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t *pol_data = NULL; + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + const ewma_policy_data_t *ewma_pol_data; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + + /* Currently, notify_circ_active() ignores cmux and circ. They can not be + * NULL so it is fine to pass garbage. */ + ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); + + /* We should have an active circuit in the queue so its EWMA value can be + * tracked. */ + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1); + tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); + + ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data); + /* Should be removed from the active queue. */ + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0); + tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); + + done: + ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void +test_cmux_ewma_policy_circ_data(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t pol_data; /* garbage */ + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + const ewma_policy_circ_data_t *ewma_data; + + (void) arg; + + /* Currently, alloc_circ_data() ignores every parameter _except_ the cell + * direction so it is OK to pass garbage. They can not be NULL. */ + circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC); + + ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); + tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t)); + tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0); + tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1); + tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0); + ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data); + + circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ, + CELL_DIRECTION_IN, 42); + tt_assert(circ_data); + tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC); + + ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); + tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t)); + tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0); + tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1); + tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1); + + done: + ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data); +} + +static void +test_cmux_ewma_policy_data(void *arg) +{ + circuitmux_t cmux; /* garbage. */ + circuitmux_policy_data_t *pol_data = NULL; + const ewma_policy_data_t *ewma_pol_data; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC); + + /* Test EWMA object. */ + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + tt_assert(ewma_pol_data->active_circuit_pqueue); + tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); + + done: + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void * +cmux_ewma_setup_test(const struct testcase_t *tc) +{ + static int whatever; + + (void) tc; + + cell_ewma_initialize_ticks(); + cmux_ewma_set_options(NULL, NULL); + + return &whatever; +} + +static int +cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr) +{ + (void) tc; + (void) ptr; + + circuitmux_ewma_free_all(); + + return 1; +} + +static struct testcase_setup_t cmux_ewma_test_setup = { + .setup_fn = cmux_ewma_setup_test, + .cleanup_fn = cmux_ewma_cleanup_test, +}; + +#define TEST_CMUX_EWMA(name) \ + { #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL } + +struct testcase_t circuitmux_ewma_tests[] = { + TEST_CMUX_EWMA(active_circuit), + TEST_CMUX_EWMA(policy_data), + TEST_CMUX_EWMA(policy_circ_data), + TEST_CMUX_EWMA(notify_circ), + TEST_CMUX_EWMA(xmit_cell), + + END_OF_TESTCASES +}; diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c index 934ddb0208..70e2081c55 100644 --- a/src/test/test_circuitpadding.c +++ b/src/test/test_circuitpadding.c @@ -38,6 +38,7 @@ #include "core/or/or_circuit_st.h" #include "core/or/origin_circuit_st.h" +#include "test/fakecircs.h" #include "test/rng_test_helpers.h" /* Start our monotime mocking at 1 second past whatever monotime_init() @@ -53,7 +54,6 @@ circid_t get_unique_circ_id_by_chan(channel_t *chan); void helper_create_basic_machine(void); static void helper_create_conditional_machines(void); -static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan); channel_t *new_fake_channel(void); void test_circuitpadding_negotiation(void *arg); void test_circuitpadding_wronghop(void *arg); @@ -67,7 +67,6 @@ void test_circuitpadding_state_length(void *arg); static void simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, int padding); -void free_fake_orcirc(circuit_t *circ); void free_fake_origin_circuit(origin_circuit_t *circ); static int deliver_negotiated = 1; @@ -127,62 +126,6 @@ circuit_get_nth_node_mock(origin_circuit_t *circ, int hop) return &padding_node; } -static or_circuit_t * -new_fake_orcirc(channel_t *nchan, channel_t *pchan) -{ - or_circuit_t *orcirc = NULL; - circuit_t *circ = NULL; - crypt_path_t tmp_cpath; - char whatevs_key[CPATH_KEY_MATERIAL_LEN]; - - orcirc = tor_malloc_zero(sizeof(*orcirc)); - circ = &(orcirc->base_); - circ->magic = OR_CIRCUIT_MAGIC; - - //circ->n_chan = nchan; - circ->n_circ_id = get_unique_circ_id_by_chan(nchan); - cell_queue_init(&(circ->n_chan_cells)); - circ->n_hop = NULL; - circ->streams_blocked_on_n_chan = 0; - circ->streams_blocked_on_p_chan = 0; - circ->n_delete_pending = 0; - circ->p_delete_pending = 0; - circ->received_destroy = 0; - circ->state = CIRCUIT_STATE_OPEN; - circ->purpose = CIRCUIT_PURPOSE_OR; - circ->package_window = CIRCWINDOW_START_MAX; - circ->deliver_window = CIRCWINDOW_START_MAX; - circ->n_chan_create_cell = NULL; - - //orcirc->p_chan = pchan; - orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan); - cell_queue_init(&(orcirc->p_chan_cells)); - - circuit_set_p_circid_chan(orcirc, orcirc->p_circ_id, pchan); - circuit_set_n_circid_chan(circ, circ->n_circ_id, nchan); - - memset(&tmp_cpath, 0, sizeof(tmp_cpath)); - if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key, - sizeof(whatevs_key), 0, 0)<0) { - log_warn(LD_BUG,"Circuit initialization failed"); - return NULL; - } - orcirc->crypto = tmp_cpath.pvt_crypto; - - return orcirc; -} - -void -free_fake_orcirc(circuit_t *circ) -{ - or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); - - relay_crypto_clear(&orcirc->crypto); - - circpad_circuit_free_all_machineinfos(circ); - tor_free(circ); -} - void free_fake_origin_circuit(origin_circuit_t *circ) { @@ -413,7 +356,7 @@ test_circuitpadding_rtt(void *arg) circpad_machine_current_state( client_side->padding_info[0])->histogram_edges[0]); done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); timers_shutdown(); @@ -1439,7 +1382,7 @@ test_circuitpadding_wronghop(void *arg) /* Test 2: Test no padding */ free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); client_side = TO_CIRCUIT(origin_circuit_new()); relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, @@ -1484,7 +1427,7 @@ test_circuitpadding_wronghop(void *arg) done: free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); monotime_disable_test_mocking(); @@ -1553,7 +1496,7 @@ test_circuitpadding_negotiation(void *arg) /* Test 2: Test no padding */ free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); client_side = TO_CIRCUIT(origin_circuit_new()); relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel)); @@ -1591,7 +1534,7 @@ test_circuitpadding_negotiation(void *arg) /* 3. Test failure to negotiate a machine due to desync */ free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); client_side = TO_CIRCUIT(origin_circuit_new()); relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel)); @@ -1619,7 +1562,7 @@ test_circuitpadding_negotiation(void *arg) done: free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); monotime_disable_test_mocking(); @@ -1939,7 +1882,7 @@ test_circuitpadding_state_length(void *arg) tor_free(client_machine); free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); @@ -2312,7 +2255,7 @@ test_circuitpadding_circuitsetup_machine(void *arg) tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec, OP_NE, 0); circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); timers_advance_and_run(5000); /* No cells sent */ @@ -2616,7 +2559,7 @@ test_circuitpadding_global_rate_limiting(void *arg) tt_int_op(retval, OP_EQ, 0); done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp)); @@ -2769,7 +2712,7 @@ test_circuitpadding_reduce_disable(void *arg) tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL); done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); testing_disable_reproducible_rng(); @@ -3075,7 +3018,7 @@ helper_test_hs_machines(bool test_intro_circs) } done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); diff --git a/src/test/test_relay.c b/src/test/test_relay.c index 0b7a7be332..f7809b47ef 100644 --- a/src/test/test_relay.c +++ b/src/test/test_relay.c @@ -21,42 +21,10 @@ /* Test suite stuff */ #include "test/test.h" #include "test/fakechans.h" - -static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan); +#include "test/fakecircs.h" static void test_relay_append_cell_to_circuit_queue(void *arg); -static or_circuit_t * -new_fake_orcirc(channel_t *nchan, channel_t *pchan) -{ - or_circuit_t *orcirc = NULL; - circuit_t *circ = NULL; - - orcirc = tor_malloc_zero(sizeof(*orcirc)); - circ = &(orcirc->base_); - circ->magic = OR_CIRCUIT_MAGIC; - - circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan); - cell_queue_init(&(circ->n_chan_cells)); - - circ->n_hop = NULL; - circ->streams_blocked_on_n_chan = 0; - circ->streams_blocked_on_p_chan = 0; - circ->n_delete_pending = 0; - circ->p_delete_pending = 0; - circ->received_destroy = 0; - circ->state = CIRCUIT_STATE_OPEN; - circ->purpose = CIRCUIT_PURPOSE_OR; - circ->package_window = CIRCWINDOW_START_MAX; - circ->deliver_window = CIRCWINDOW_START_MAX; - circ->n_chan_create_cell = NULL; - - circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan); - cell_queue_init(&(orcirc->p_chan_cells)); - - return orcirc; -} - static void assert_circuit_ok_mock(const circuit_t *c) { @@ -145,7 +113,7 @@ test_relay_close_circuit(void *arg) cell_queue_clear(&orcirc->base_.n_chan_cells); cell_queue_clear(&orcirc->p_chan_cells); } - tor_free(orcirc); + free_fake_orcirc(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); UNMOCK(assert_circuit_ok); @@ -218,7 +186,7 @@ test_relay_append_cell_to_circuit_queue(void *arg) cell_queue_clear(&orcirc->base_.n_chan_cells); cell_queue_clear(&orcirc->p_chan_cells); } - tor_free(orcirc); + free_fake_orcirc(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); diff --git a/src/tools/tools.dox b/src/tools/tools.dox new file mode 100644 index 0000000000..54aa4df48e --- /dev/null +++ b/src/tools/tools.dox @@ -0,0 +1,8 @@ +/** +@dir tools +@brief tools: other command-line tools for use with Tor. + +The "tools" directory has a few other programs that use Tor, but are not part +of the main Tor binary. + +**/ |