aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile.in20
-rw-r--r--changes/bug255685
-rw-r--r--changes/ticket321962
-rwxr-xr-xscripts/git/git-setup-dirs.sh4
-rwxr-xr-xscripts/git/pre-push.git-hook60
-rw-r--r--src/app/app.dox8
-rw-r--r--src/app/config/app_config.dox4
-rw-r--r--src/app/main/app_main.dox4
-rw-r--r--src/core/core.dox8
-rw-r--r--src/core/crypto/core_crypto.dox4
-rw-r--r--src/core/mainloop/core_mainloop.dox4
-rw-r--r--src/core/or/circuitmux.c56
-rw-r--r--src/core/or/circuitmux.h56
-rw-r--r--src/core/or/circuitmux_ewma.c109
-rw-r--r--src/core/or/circuitmux_ewma.h107
-rw-r--r--src/core/or/core_or.dox4
-rw-r--r--src/core/or/destroy_cell_queue_st.h2
-rw-r--r--src/core/proto/core_proto.dox4
-rw-r--r--src/feature/api/feature_api.dox4
-rw-r--r--src/feature/client/feature_client.dox4
-rw-r--r--src/feature/control/feature_control.dox4
-rw-r--r--src/feature/dirauth/feature_dirauth.dox4
-rw-r--r--src/feature/dircache/feature_dircache.dox4
-rw-r--r--src/feature/dirclient/feature_dirclient.dox4
-rw-r--r--src/feature/dircommon/feature_dircommon.dox4
-rw-r--r--src/feature/dirparse/feature_dirparse.dox4
-rw-r--r--src/feature/feature.dox9
-rw-r--r--src/feature/hibernate/feature_hibernate.dox4
-rw-r--r--src/feature/hs/feature_hs.dox4
-rw-r--r--src/feature/hs_common/feature_hs_common.dox4
-rw-r--r--src/feature/keymgt/feature_keymgt.dox4
-rw-r--r--src/feature/nodelist/feature_nodelist.dox4
-rw-r--r--src/feature/relay/feature_relay.dox4
-rw-r--r--src/feature/rend/feature_rend.dox4
-rw-r--r--src/feature/rend/rendcache.c11
-rw-r--r--src/feature/rend/rendcache.h2
-rw-r--r--src/feature/rend/rendclient.c19
-rw-r--r--src/feature/stats/feature_stats.dox4
-rw-r--r--src/lib/arch/lib_arch.dox4
-rw-r--r--src/lib/buf/lib_buf.dox4
-rw-r--r--src/lib/cc/lib_cc.dox4
-rw-r--r--src/lib/compress/lib_compress.dox4
-rw-r--r--src/lib/conf/lib_conf.dox4
-rw-r--r--src/lib/confmgt/lib_confmgt.dox4
-rw-r--r--src/lib/container/lib_container.dox4
-rw-r--r--src/lib/crypt_ops/lib_crypt_ops.dox4
-rw-r--r--src/lib/ctime/lib_ctime.dox4
-rw-r--r--src/lib/defs/lib_defs.dox4
-rw-r--r--src/lib/dispatch/lib_dispatch.dox4
-rw-r--r--src/lib/encoding/lib_encoding.dox4
-rw-r--r--src/lib/err/lib_err.dox4
-rw-r--r--src/lib/evloop/lib_evloop.dox4
-rw-r--r--src/lib/fdio/lib_fdio.dox4
-rw-r--r--src/lib/fs/lib_fs.dox4
-rw-r--r--src/lib/geoip/lib_geoip.dox4
-rw-r--r--src/lib/intmath/lib_intmath.dox4
-rw-r--r--src/lib/lib.dox8
-rw-r--r--src/lib/lock/lib_lock.dox4
-rw-r--r--src/lib/log/lib_log.dox4
-rw-r--r--src/lib/malloc/lib_malloc.dox4
-rw-r--r--src/lib/math/lib_math.dox4
-rw-r--r--src/lib/memarea/lib_memarea.dox4
-rw-r--r--src/lib/meminfo/lib_meminfo.dox4
-rw-r--r--src/lib/net/lib_net.dox4
-rw-r--r--src/lib/osinfo/lib_osinfo.dox4
-rw-r--r--src/lib/process/lib_process.dox4
-rw-r--r--src/lib/pubsub/lib_pubsub.dox4
-rw-r--r--src/lib/sandbox/lib_sandbox.dox4
-rw-r--r--src/lib/smartlist_core/lib_smartlist_core.dox4
-rw-r--r--src/lib/stats/lib_stats.dox4
-rw-r--r--src/lib/string/lib_string.dox4
-rw-r--r--src/lib/subsys/lib_subsys.dox4
-rw-r--r--src/lib/term/lib_term.dox4
-rw-r--r--src/lib/testsupport/lib_testsupport.dox4
-rw-r--r--src/lib/thread/lib_thread.dox4
-rw-r--r--src/lib/time/lib_time.dox4
-rw-r--r--src/lib/tls/lib_tls.dox4
-rw-r--r--src/lib/trace/lib_trace.dox4
-rw-r--r--src/lib/version/lib_version.dox4
-rw-r--r--src/lib/wallclock/lib_wallclock.dox4
-rw-r--r--src/mainpage.dox11
-rw-r--r--src/test/fakecircs.c88
-rw-r--r--src/test/fakecircs.h17
-rw-r--r--src/test/include.am3
-rw-r--r--src/test/test.c1
-rw-r--r--src/test/test.h1
-rw-r--r--src/test/test_circuitmux.c390
-rw-r--r--src/test/test_circuitmux_ewma.c228
-rw-r--r--src/test/test_circuitpadding.c81
-rw-r--r--src/test/test_relay.c38
-rw-r--r--src/tools/tools.dox8
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.
+
+**/