diff options
author | Roger Dingledine <arma@torproject.org> | 2011-04-01 10:16:57 -0400 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2011-04-01 10:16:57 -0400 |
commit | c7473adec036031621dda7562efa019e6c95a968 (patch) | |
tree | 9e4ca2d4f309c83bc9c42b8385da2fda5d35b071 | |
parent | 704a27b029ac94e26e6e3695a292294c4d4905da (diff) | |
parent | 65eb0e41ac05fd65bf8bef87426886fec45f7ca4 (diff) | |
download | tor-c7473adec036031621dda7562efa019e6c95a968.tar.gz tor-c7473adec036031621dda7562efa019e6c95a968.zip |
Merge branch 'maint-0.2.2' into release-0.2.2
49 files changed, 722 insertions, 207 deletions
diff --git a/Doxyfile.in b/Doxyfile.in index 24355f5f04..344ee27149 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -1,4 +1,4 @@ -# Doxyfile 1.5.1 +# Doxyfile 1.5.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project @@ -14,6 +14,14 @@ # Project related configuration options #--------------------------------------------------------------------------- +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. @@ -46,23 +54,14 @@ CREATE_SUBDIRS = NO # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, -# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, -# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, -# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. OUTPUT_LANGUAGE = English -# This tag can be used to specify the encoding used in the generated output. -# The encoding is not always determined by the language that is chosen, -# but also whether or not the output is meant for Windows or non-Windows users. -# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES -# forces the Windows encoding (this is the default for the Windows binary), -# whereas setting the tag to NO uses a Unix-style encoding (the default for -# all platforms other than Windows). - -USE_WINDOWS_ENCODING = NO - # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). @@ -135,11 +134,19 @@ SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explicit @brief command for a brief description. +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. @@ -153,7 +160,7 @@ MULTILINE_CPP_IS_BRIEF = NO # If set to NO, the detailed description appears after the member # documentation. -DETAILS_AT_TOP = NO +# DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it @@ -189,14 +196,26 @@ ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to -# include (a tag file for) the STL sources as input, then you should +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration @@ -204,6 +223,26 @@ OPTIMIZE_OUTPUT_JAVA = NO BUILTIN_STL_SUPPORT = NO +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = NO + # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default @@ -219,6 +258,16 @@ DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -253,6 +302,14 @@ EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the @@ -328,6 +385,12 @@ SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, @@ -389,9 +452,21 @@ SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + # The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from the -# version control system). Doxygen will invoke the program by executing (via +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via # popen()) the command <command> <input-file>, where <command> is the value of # the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file # provided by doxygen. Whatever the program writes to standard output @@ -462,12 +537,20 @@ WARN_LOGFILE = INPUT = src/common \ src/or +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.c \ *.h @@ -498,6 +581,14 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). @@ -558,7 +649,7 @@ FILTER_SOURCE_FILES = NO # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. -SOURCE_BROWSER = NO +SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. @@ -571,13 +662,13 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES (the default) +# If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. @@ -677,11 +768,44 @@ HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs for Tor" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.torproject.Tor + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be @@ -702,6 +826,12 @@ HHC_LOCATION = GENERATE_CHI = NO +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. @@ -724,12 +854,20 @@ DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hiererachy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. GENERATE_TREEVIEW = NO @@ -739,6 +877,14 @@ GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- @@ -1087,6 +1233,15 @@ PERL_PATH = /usr/bin/perl CLASS_DIAGRAMS = YES +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. @@ -1100,6 +1255,24 @@ HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the @@ -1144,19 +1317,19 @@ INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. CALL_GRAPH = NO -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a caller dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO @@ -1189,39 +1362,31 @@ DOT_PATH = DOTFILE_DIRS = -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. -MAX_DOT_GRAPH_HEIGHT = 1024 +DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that a graph may be further truncated if the graph's -# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH -# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), -# the graph is not depth-constrained. +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, which results in a white background. -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). DOT_TRANSPARENT = NO diff --git a/changes/bug2683a b/changes/bug2683a new file mode 100644 index 0000000000..2fe308b030 --- /dev/null +++ b/changes/bug2683a @@ -0,0 +1,3 @@ + o Minor features + - Log the source of a rejected POSTed v3 networkstatus vote. + diff --git a/changes/bug2696 b/changes/bug2696 new file mode 100644 index 0000000000..6ea41d4a6a --- /dev/null +++ b/changes/bug2696 @@ -0,0 +1,5 @@ + o Minor features: + - Make compilation with clang possible when using + --enable-gcc-warnings by removing two warnings that clang hasn't + implemented yet and by fixing a few warnings. Implements ticket + 2696. diff --git a/changes/bug2698 b/changes/bug2698 new file mode 100644 index 0000000000..d995788bfc --- /dev/null +++ b/changes/bug2698 @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Fix an issue that prevented static linking of libevent on + some platforms (notably Linux). Fixes bug 2698, bugfix on + versions 0.2.1.23/0.2.2.8-alpha (the versions introducing + the --with-static-libevent configure option). + diff --git a/changes/bug2756 b/changes/bug2756 new file mode 100644 index 0000000000..0cad515a1b --- /dev/null +++ b/changes/bug2756 @@ -0,0 +1,11 @@ + o Minor bugfixes (spec conformance, performance): + - We now ask the other side of a stream (the client or the exit) + for more data on that stream when the amount of queued data on + that stream dips low enough. Previously, we wouldn't ask the + other side for more data until either it sent us more data + (which it wasn't supposed to do if it had exhausted its + window!) or until we had completely flushed all our queued + data. Fixing this should improve throughput. Fixes bug 2756; + bugfix on the earliest released versions of Tor (svn commit + r152). + diff --git a/changes/bug2757 b/changes/bug2757 new file mode 100644 index 0000000000..f947afaeb4 --- /dev/null +++ b/changes/bug2757 @@ -0,0 +1,6 @@ + - Minor bugfixes + o Avoid a double-mark-for-free warning when failing to attach a + transparent proxy connection. (We thought we had fixed this in + 0.2.2.23-alpha, but it turns out our fix was checking the wrong + connection.) Fixes bug 2757; bugfix on 0.1.2.1-alpha (the original + bug) and 0.2.2.23-alpha (the incorrect fix). diff --git a/changes/cbt_hi_res b/changes/cbt_hi_res new file mode 100644 index 0000000000..c0df1183cb --- /dev/null +++ b/changes/cbt_hi_res @@ -0,0 +1,7 @@ + o Minor features + - When expiring circuits, use microsecond timers rather than one-second + timers. This can avoid an unpleasant situation where a circuit is + launched near the end of one second and expired right near the + beginning of the next, and prevent fluctuations in circuit timeout + values. + diff --git a/changes/cbt_parallel_intro b/changes/cbt_parallel_intro new file mode 100644 index 0000000000..44e377fb3f --- /dev/null +++ b/changes/cbt_parallel_intro @@ -0,0 +1,4 @@ + o Minor features + - Use computed circuit-build timeouts to decide when to launch + parallel introdution circuits. (Previously, we would retry + after 15 seconds.) diff --git a/changes/doxygen b/changes/doxygen new file mode 100644 index 0000000000..5e5fcd12d6 --- /dev/null +++ b/changes/doxygen @@ -0,0 +1,6 @@ + o Documentation changes + - Modernize the doxygen configuration file slightly. Fixes bug 2707. + - Resolve all doxygen warnings except those for missing documentation. + Fixes bug 2705. + - Add doxygen documentation for more functions, fields, and types. + diff --git a/changes/log-typo-2011-03-15-01 b/changes/log-typo-2011-03-15-01 new file mode 100644 index 0000000000..3830df388f --- /dev/null +++ b/changes/log-typo-2011-03-15-01 @@ -0,0 +1,3 @@ + o Minor bugfixes + - Fix a minor typo in a log message. Bugfix on 0.2.2.6-alpha. + diff --git a/changes/zlib_aint_openssl b/changes/zlib_aint_openssl new file mode 100644 index 0000000000..dd8e10a328 --- /dev/null +++ b/changes/zlib_aint_openssl @@ -0,0 +1,3 @@ + o Minor bugfixes + - When warning about missing zlib development packages, give the + correct package names. Bugfix on 0.2.0.1-alpha. diff --git a/configure.in b/configure.in index 264473a397..276e111d7f 100644 --- a/configure.in +++ b/configure.in @@ -271,7 +271,19 @@ tor_libevent_pkg_debian="libevent-dev" tor_libevent_devpkg_redhat="libevent-devel" tor_libevent_devpkg_debian="libevent-dev" -TOR_SEARCH_LIBRARY(libevent, $trylibeventdir, [-levent $TOR_LIB_WS32], [ +dnl On Gnu/Linux or any place we require it, we'll add librt to the Libevent +dnl linking for static builds. +STATIC_LIBEVENT_FLAGS="" +if test "$enable_static_libevent" = "yes"; then + dnl Determine if we have clock_gettime in librt + AC_SEARCH_LIBS([clock_gettime], [rt], + [have_rt=yes]) + if test "$have_rt" = yes; then + STATIC_LIBEVENT_FLAGS=" -lrt " + fi +fi + +TOR_SEARCH_LIBRARY(libevent, $trylibeventdir, [-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32], [ #ifdef WIN32 #include <winsock2.h> #endif @@ -294,7 +306,7 @@ dnl Now check for particular libevent functions. save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" -LIBS="-levent $TOR_LIB_WS32 $LIBS" +LIBS="-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32 $LIBS" LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS" CPPFLAGS="$TOR_CPPFLAGS_libevent $CPPFLAGS" AC_CHECK_FUNCS(event_get_version event_get_version_number event_get_method event_set_log_callback evdns_set_outgoing_bind_address event_base_loopexit) @@ -315,7 +327,7 @@ if test "$enable_static_libevent" = "yes"; then if test "$tor_cv_library_libevent_dir" = "(system)"; then AC_MSG_ERROR("You must specify an explicit --with-libevent-dir=x option when using --enable-static-libevent") else - TOR_LIBEVENT_LIBS="$TOR_LIBDIR_libevent/libevent.a" + TOR_LIBEVENT_LIBS="$TOR_LIBDIR_libevent/libevent.a $STATIC_LIBEVENT_FLAGS" fi else TOR_LIBEVENT_LIBS="-levent" @@ -363,10 +375,10 @@ AC_SUBST(TOR_OPENSSL_LIBS) dnl ------------------------------------------------------ dnl Where do you live, zlib? And how do we call you? -tor_openssl_pkg_redhat="zlib" -tor_openssl_pkg_debian="zlib1g" -tor_openssl_devpkg_redhat="zlib-devel" -tor_openssl_devpkg_debian="zlib1g-dev" +tor_zlib_pkg_redhat="zlib" +tor_zlib_pkg_debian="zlib1g" +tor_zlib_devpkg_redhat="zlib-devel" +tor_zlib_devpkg_debian="zlib1g-dev" TOR_SEARCH_LIBRARY(zlib, $tryzlibdir, [-lz], [#include <zlib.h>], @@ -865,12 +877,13 @@ fi # Set CFLAGS _after_ all the above checks, since our warnings are stricter # than autoconf's macros like. if test "$GCC" = yes; then - CFLAGS="$CFLAGS -Wall -g -O2" # Disable GCC's strict aliasing checks. They are an hours-to-debug # accident waiting to happen. - CFLAGS="$CFLAGS -fno-strict-aliasing" + CFLAGS="$CFLAGS -Wall -fno-strict-aliasing" else - CFLAGS="$CFLAGS -g -O" + # Autoconf sets -g -O2 by default. Override optimization level + # for non-gcc compilers + CFLAGS="$CFLAGS -O" enable_gcc_warnings=no enable_gcc_warnings_advisory=no fi @@ -894,6 +907,11 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy #error #endif])], have_gcc43=yes, have_gcc43=no) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ +#if !defined(__clang__) || (__clang_major__ > 2) || (__clang_major__ == 2 && __clang_minor__ > 9) +#error +#endif])], have_clang29orlower=yes, have_clang29orlower=no) + save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wshorten-64-to-32" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], have_shorten64_flag=yes, @@ -924,11 +942,19 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy if test x$have_gcc42 = xyes ; then # These warnings break gcc 4.0.2 and work on gcc 4.2 # XXXX020 See if any of these work with earlier versions. - CFLAGS="$CFLAGS -Waddress -Wmissing-noreturn -Wnormalized=id -Woverride-init -Wstrict-overflow=1" + CFLAGS="$CFLAGS -Waddress -Wmissing-noreturn -Wstrict-overflow=1" + # We used to use -Wstrict-overflow=5, but that breaks us heavily under 4.3. fi - if test x$have_gcc43 = xyes ; then + if test x$have_gcc42 = xyes && test x$have_clang29orlower = xno; then + # These warnings break gcc 4.0.2 and clang, but work on gcc 4.2 + # We only disable these for clang 2.9 and lower, in case they are + # supported in later versions. + CFLAGS="$CFLAGS -Wnormalized=id -Woverride-init" + fi + + if test x$have_gcc43 = xyes ; then # These warnings break gcc 4.2 and work on gcc 4.3 # XXXX020 See if any of these work with earlier versions. CFLAGS="$CFLAGS -Wextra -Warray-bounds" diff --git a/src/common/address.c b/src/common/address.c index a2780fb051..0046d2da36 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -508,7 +508,8 @@ tor_addr_parse_mask_ports(const char *s, tor_addr_t *addr_out, tor_assert(s); tor_assert(addr_out); - /* IP, [], /mask, ports */ + /** Longest possible length for an address, mask, and port-range combination. + * Includes IP, [], /mask, :, ports */ #define MAX_ADDRESS_LENGTH (TOR_ADDR_BUF_LEN+2+(1+INET_NTOA_BUF_LEN)+12+1) if (strlen(s) > MAX_ADDRESS_LENGTH) { @@ -788,7 +789,7 @@ tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2, * Reduce over-specific masks (>128 for ipv6, >32 for ipv4) to 128 or 32. * * The mask is interpreted relative to <b>addr1</b>, so that if a is - * ::ffff:1.2.3.4, and b is 3.4.5.6, + * \::ffff:1.2.3.4, and b is 3.4.5.6, * tor_addr_compare_masked(a,b,100,CMP_SEMANTIC) is the same as * -tor_addr_compare_masked(b,a,4,CMP_SEMANTIC). * @@ -800,6 +801,8 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2, maskbits_t mbits, tor_addr_comparison_t how) { + /** Helper: Evaluates to -1 if a is less than b, 0 if a equals b, or 1 if a + * is greater than b. May evaluate a and b more than once. */ #define TRISTATE(a,b) (((a)<(b))?-1: (((a)==(b))?0:1)) sa_family_t family1, family2, v_family1, v_family2; diff --git a/src/common/address.h b/src/common/address.h index 371c6da190..d05a3de2e7 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -53,8 +53,20 @@ tor_addr_to_in6(const tor_addr_t *a) return a->family == AF_INET6 ? &a->addr.in6_addr : NULL; } +/** Given an IPv6 address <b>x</b>, yield it as an array of uint8_t. + * + * Requires that <b>x</b> is actually an IPv6 address. + */ #define tor_addr_to_in6_addr8(x) tor_addr_to_in6(x)->s6_addr +/** Given an IPv6 address <b>x</b>, yield it as an array of uint16_t. + * + * Requires that <b>x</b> is actually an IPv6 address. + */ #define tor_addr_to_in6_addr16(x) S6_ADDR16(*tor_addr_to_in6(x)) +/** Given an IPv6 address <b>x</b>, yield it as an array of uint32_t. + * + * Requires that <b>x</b> is actually an IPv6 address. + */ #define tor_addr_to_in6_addr32(x) S6_ADDR32(*tor_addr_to_in6(x)) /** Return an IPv4 address in network order for <b>a</b>, or 0 if @@ -71,7 +83,7 @@ tor_addr_to_ipv4h(const tor_addr_t *a) { return ntohl(tor_addr_to_ipv4n(a)); } -/* Given an IPv6 address, return its mapped IPv4 address in host order, or +/** Given an IPv6 address, return its mapped IPv4 address in host order, or * 0 if <b>a</b> is not an IPv6 address. * * (Does not check whether the address is really a mapped address */ @@ -102,8 +114,14 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u) return a->family == AF_INET ? (tor_addr_to_ipv4h(a) == u) : 0; } -#define TOR_ADDR_BUF_LEN 48 /* [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255] - */ +/** Length of a buffer that you need to allocate to be sure you can encode + * any tor_addr_t. + * + * This allows enough space for + * "[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]", + * plus a terminating NUL. + */ +#define TOR_ADDR_BUF_LEN 48 int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out); char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC; @@ -154,6 +172,7 @@ void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr); #define tor_addr_from_ipv4h(dest, v4addr) \ tor_addr_from_ipv4n((dest), htonl(v4addr)) void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes); +/** Set <b>dest</b> to the IPv4 address incoded in <b>in</b>. */ #define tor_addr_from_in(dest, in) \ tor_addr_from_ipv4n((dest), (in)->s_addr); void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6); diff --git a/src/common/aes.c b/src/common/aes.c index 39ab2946c9..c2fdeb594a 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -100,6 +100,9 @@ /* Figure out which AES optimizations to use. */ #ifdef USE_BUILTIN_AES +/** If this is defined, we take advantage of the fact that AES treats its + * input as a set of 4 32-bit words, so that there is no need to encode and + * decode the 128-bit counter before every block encryption */ # define USE_RIJNDAEL_COUNTER_OPTIMIZATION # if 0 && (defined(__powerpc__) || defined(__powerpc64__)) /* XXXX do more experimentation before concluding this is actually diff --git a/src/common/compat.c b/src/common/compat.c index d29cacf372..27489e568a 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -15,6 +15,8 @@ /* This is required on rh7 to make strptime not complain. * We also need it to make memmem get defined (where available) */ +/* XXXX023 We should just use AC_USE_SYSTEM_EXTENSIONS in our autoconf, + * and get this (and other important stuff!) automatically */ #define _GNU_SOURCE #include "compat.h" @@ -660,7 +662,9 @@ touch_file(const char *fname) /** Represents a lockfile on which we hold the lock. */ struct tor_lockfile_t { + /** Name of the file */ char *filename; + /** File descriptor used to hold the file open */ int fd; }; @@ -766,7 +770,8 @@ tor_lockfile_unlock(tor_lockfile_t *lockfile) tor_free(lockfile); } -/* Some old versions of Unix didn't define constants for these values, +/** @{ */ +/** Some old versions of Unix didn't define constants for these values, * and instead expect you to say 0, 1, or 2. */ #ifndef SEEK_CUR #define SEEK_CUR 1 @@ -774,6 +779,7 @@ tor_lockfile_unlock(tor_lockfile_t *lockfile) #ifndef SEEK_END #define SEEK_END 2 #endif +/** @} */ /** Return the position of <b>fd</b> with respect to the start of the file. */ off_t @@ -813,6 +819,7 @@ static int n_sockets_open = 0; /** Mutex to protect open_sockets, max_socket, and n_sockets_open. */ static tor_mutex_t *socket_accounting_mutex = NULL; +/** Helper: acquire the socket accounting lock. */ static INLINE void socket_accounting_lock(void) { @@ -821,6 +828,7 @@ socket_accounting_lock(void) tor_mutex_acquire(socket_accounting_mutex); } +/** Helper: release the socket accounting lock. */ static INLINE void socket_accounting_unlock(void) { @@ -879,6 +887,7 @@ tor_close_socket(int s) return r; } +/** @{ */ #ifdef DEBUG_SOCKET_COUNTING /** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is * now an open socket. */ @@ -903,6 +912,7 @@ mark_socket_open(int s) #else #define mark_socket_open(s) STMT_NIL #endif +/** @} */ /** As socket(), but counts the number of open sockets. */ int @@ -1090,6 +1100,8 @@ tor_socketpair(int family, int type, int protocol, int fd[2]) #endif } +/** Number of extra file descriptors to keep in reserve beyond those that we + * tell Tor it's allowed to use. */ #define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond _ConnLimit */ /** Learn the maximum allowed number of file descriptors. (Some systems @@ -1202,6 +1214,7 @@ set_max_file_descriptors(rlim_t limit, int *max_out) static int log_credential_status(void) { +/** Log level to use when describing non-error UID/GID status. */ #define CREDENTIAL_LOG_LEVEL LOG_INFO /* Real, effective and saved UIDs */ uid_t ruid, euid, suid; @@ -1983,6 +1996,12 @@ tor_gettimeofday(struct timeval *timeval) #define TIME_FNS_NEED_LOCKS #endif +/** @{ */ +/** As localtime_r, but defined for platforms that don't have it: + * + * Convert *<b>timep</b> to a struct tm in local time, and store the value in + * *<b>result</b>. Return the result on success, or NULL on failure. + */ #ifndef HAVE_LOCALTIME_R #ifdef TIME_FNS_NEED_LOCKS struct tm * @@ -2010,7 +2029,14 @@ tor_localtime_r(const time_t *timep, struct tm *result) } #endif #endif +/** @} */ +/** @{ */ +/** As gmtimee_r, but defined for platforms that don't have it: + * + * Convert *<b>timep</b> to a struct tm in UTC, and store the value in + * *<b>result</b>. Return the result on success, or NULL on failure. + */ #ifndef HAVE_GMTIME_R #ifdef TIME_FNS_NEED_LOCKS struct tm * @@ -2038,6 +2064,7 @@ tor_gmtime_r(const time_t *timep, struct tm *result) } #endif #endif +/** @} */ #if defined(USE_WIN32_THREADS) void diff --git a/src/common/compat.h b/src/common/compat.h index ee20e716c0..550c08b533 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -312,6 +312,7 @@ const char *tor_fix_source_file(const char *fname); /* ===== Time compatibility */ #if !defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) +/** Implementation of timeval for platforms that don't have it. */ struct timeval { time_t tv_sec; unsigned int tv_usec; @@ -332,6 +333,48 @@ struct tm *tor_localtime_r(const time_t *timep, struct tm *result); struct tm *tor_gmtime_r(const time_t *timep, struct tm *result); #endif +#ifndef timeradd +/** Replacement for timeradd on platforms that do not have it: sets tvout to + * the sum of tv1 and tv2. */ +#define timeradd(tv1,tv2,tvout) \ + do { \ + (tvout)->tv_sec = (tv1)->tv_sec + (tv2)->tv_sec; \ + (tvout)->tv_usec = (tv2)->tv_usec + (tv2)->tv_usec; \ + if ((tvout)->tv_usec >= 1000000) { \ + (tvout)->tv_usec -= 1000000; \ + (tvout)->tv_sec++; \ + } \ + } while (0) +#endif + +#ifndef timersub +/** Replacement for timersub on platforms that do not have it: sets tvout to + * tv1 minus tv2. */ +#define timersub(tv1,tv2,tvout) \ + do { \ + (tvout)->tv_sec = (tv1)->tv_sec - (tv2)->tv_sec; \ + (tvout)->tv_usec = (tv2)->tv_usec - (tv2)->tv_usec; \ + if ((tvout)->tv_usec < 0) { \ + (tvout)->tv_usec += 1000000; \ + (tvout)->tv_sec--; \ + } \ + } while (0) +#endif + +#ifndef timercmp +/** Replacement for timersub on platforms that do not have it: returns true + * iff the relational operator "op" makes the expression tv1 op tv2 true. + * + * Note that while this definition should work for all boolean opeators, some + * platforms' native timercmp definitions do not support >=, <=, or ==. So + * don't use those. + */ +#define timercmp(tv1,tv2,op) \ + (((tv1)->tv_sec == (tv2)->tv_sec) ? \ + ((tv1)->tv_usec op (tv2)->tv_usec) : \ + ((tv1)->tv_sec op (tv2)->tv_sec)) +#endif + /* ===== File compatibility */ int replace_file(const char *from, const char *to); int touch_file(const char *fname); @@ -364,9 +407,9 @@ int get_n_open_sockets(void); #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags) #define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags) -/* Define struct in6_addr on platforms that do not have it. Generally, - * these platforms are ones without IPv6 support, but we want to have - * a working in6_addr there anyway, so we can use it to parse IPv6 +/** Implementatino of struct in6_addr for platforms that do not have it. + * Generally, these platforms are ones without IPv6 support, but we want to + * have a working in6_addr there anyway, so we can use it to parse IPv6 * addresses. */ #if !defined(HAVE_STRUCT_IN6_ADDR) struct in6_addr @@ -382,9 +425,10 @@ struct in6_addr }; #endif +/** @{ */ +/** Many BSD variants seem not to define these. */ #if defined(__APPLE__) || defined(__darwin__) || defined(__FreeBSD__) \ || defined(__NetBSD__) || defined(__OpenBSD__) -/* Many BSD variants seem not to define these. */ #ifndef s6_addr16 #define s6_addr16 __u6_addr.__u6_addr16 #endif @@ -392,12 +436,15 @@ struct in6_addr #define s6_addr32 __u6_addr.__u6_addr32 #endif #endif +/** @} */ #ifndef HAVE_SA_FAMILY_T typedef uint16_t sa_family_t; #endif -/* Apparently, MS and Solaris don't define s6_addr16 or s6_addr32. */ +/** @{ */ +/** Apparently, MS and Solaris don't define s6_addr16 or s6_addr32; these + * macros get you a pointer to s6_addr32 or local equivalent. */ #ifdef HAVE_STRUCT_IN6_ADDR_S6_ADDR32 #define S6_ADDR32(x) ((uint32_t*)(x).s6_addr32) #else @@ -408,9 +455,10 @@ typedef uint16_t sa_family_t; #else #define S6_ADDR16(x) ((uint16_t*)((char*)&(x).s6_addr)) #endif +/** @} */ -/* Define struct sockaddr_in6 on platforms that do not have it. See notes - * on struct in6_addr. */ +/** Implementation of struct sockaddr_in6 on platforms that do not have + * it. See notes on struct in6_addr. */ #if !defined(HAVE_STRUCT_SOCKADDR_IN6) struct sockaddr_in6 { sa_family_t sin6_family; @@ -534,10 +582,14 @@ void spawn_exit(void) ATTR_NORETURN; /** A generic lock structure for multithreaded builds. */ typedef struct tor_mutex_t { #if defined(USE_WIN32_THREADS) + /** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */ CRITICAL_SECTION mutex; #elif defined(USE_PTHREADS) + /** Pthreads-only: with pthreads, we implement locks with + * pthread_mutex_t. */ pthread_mutex_t mutex; #else + /** No-threads only: Dummy variable so that tor_mutex_t takes up space. */ int _unused; #endif } tor_mutex_t; diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index b9af61be88..3efc56d8d8 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -36,13 +36,19 @@ */ typedef uint32_t le_version_t; -/* Macros: returns the number of a libevent version. */ +/** @{ */ +/** Macros: returns the number of a libevent version as a le_version_t */ #define V(major, minor, patch) \ (((major) << 24) | ((minor) << 16) | ((patch) << 8)) #define V_OLD(major, minor, patch) \ V((major), (minor), (patch)-'a'+1) +/** @} */ +/** Represetns a version of libevent so old we can't figure out what version + * it is. */ #define LE_OLD V(0,0,0) +/** Represents a version of libevent so weird we can't figure out what version + * it it. */ #define LE_OTHER V(0,0,99) static le_version_t tor_get_libevent_version(const char **v_out); @@ -199,8 +205,8 @@ tor_libevent_get_base(void) } #ifndef HAVE_EVENT_BASE_LOOPEXIT -/* Replacement for event_base_loopexit on some very old versions of Libevent - that we are not yet brave enough to deprecate. */ +/** Replacement for event_base_loopexit on some very old versions of Libevent + * that we are not yet brave enough to deprecate. */ int tor_event_base_loopexit(struct event_base *base, struct timeval *tv) { @@ -222,9 +228,9 @@ tor_libevent_get_method(void) #endif } -/** Return the le_version_t for the current version of libevent. If the - * version is very new, return LE_OTHER. If the version is so old that it - * doesn't support event_get_version(), return LE_OLD. DOCDOC */ +/** Return the le_version_t for the version of libevent specified in the + * string <b>v</b>. If the version is very new or uses an unrecognized + * version, format, return LE_OTHER. */ static le_version_t tor_decode_libevent_version(const char *v) { @@ -274,7 +280,7 @@ le_versions_compatibility(le_version_t v) } /** Return the version number of the currently running version of Libevent. - See le_version_t for info on the format. + * See le_version_t for info on the format. */ static le_version_t tor_get_libevent_version(const char **v_out) diff --git a/src/common/container.c b/src/common/container.c index 979e097d99..7208d36803 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -639,15 +639,27 @@ smartlist_uniq_strings(smartlist_t *sl) * } */ -/* For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x] - * = 2*x + 1. But this is C, so we have to adjust a little. */ +/** @{ */ +/** Functions to manipulate heap indices to find a node's parent and children. + * + * For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x] + * = 2*x + 1. But this is C, so we have to adjust a little. */ //#define LEFT_CHILD(i) ( ((i)+1)*2 - 1) //#define RIGHT_CHILD(i) ( ((i)+1)*2 ) //#define PARENT(i) ( ((i)+1)/2 - 1) #define LEFT_CHILD(i) ( 2*(i) + 1 ) #define RIGHT_CHILD(i) ( 2*(i) + 2 ) #define PARENT(i) ( ((i)-1) / 2 ) - +/** }@ */ + +/** @{ */ +/** Helper macros for heaps: Given a local variable <b>idx_field_offset</b> + * set to the offset of an integer index within the heap element structure, + * IDX_OF_ITEM(p) gives you the index of p, and IDXP(p) gives you a pointer to + * where p's index is stored. Given additionally a local smartlist <b>sl</b>, + * UPDATE_IDX(i) sets the index of the element at <b>i</b> to the correct + * value (that is, to <b>i</b>). + */ #define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset)) #define UPDATE_IDX(i) do { \ @@ -656,6 +668,7 @@ smartlist_uniq_strings(smartlist_t *sl) } while (0) #define IDX_OF_ITEM(p) (*IDXP(p)) +/** @} */ /** Helper. <b>sl</b> may have at most one violation of the heap property: * the item at <b>idx</b> may be greater than one or both of its children. diff --git a/src/common/container.h b/src/common/container.h index 768ba89b84..8a3a405273 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -15,6 +15,7 @@ * and macros defined here. **/ typedef struct smartlist_t { + /** @{ */ /** <b>list</b> has enough capacity to store exactly <b>capacity</b> elements * before it needs to be resized. Only the first <b>num_used</b> (\<= * capacity) elements point to valid data. @@ -22,6 +23,7 @@ typedef struct smartlist_t { void **list; int num_used; int capacity; + /** @} */ } smartlist_t; smartlist_t *smartlist_create(void); @@ -595,9 +597,9 @@ bitarray_is_set(bitarray_t *b, int bit) /** A set of digests, implemented as a Bloom filter. */ typedef struct { - int mask; /* One less than the number of bits in <b>ba</b>; always one less + int mask; /**< One less than the number of bits in <b>ba</b>; always one less * than a power of two. */ - bitarray_t *ba; /* A bit array to implement the Bloom filter. */ + bitarray_t *ba; /**< A bit array to implement the Bloom filter. */ } digestset_t; #define BIT(n) ((n) & set->mask) diff --git a/src/common/crypto.c b/src/common/crypto.c index cfbc002dca..2ef40c29c7 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -68,13 +68,15 @@ #endif #if OPENSSL_VERSION_NUMBER < 0x00908000l -/* On OpenSSL versions before 0.9.8, there is no working SHA256 +/** @{ */ +/** On OpenSSL versions before 0.9.8, there is no working SHA256 * implementation, so we use Tom St Denis's nice speedy one, slightly adapted - * to our needs */ + * to our needs. These macros make it usable by us. */ #define SHA256_CTX sha256_state #define SHA256_Init sha256_init #define SHA256_Update sha256_process #define LTC_ARGCHK(x) tor_assert(x) +/** @} */ #include "sha256.c" #define SHA256_Final(a,b) sha256_done(b,a) @@ -104,21 +106,22 @@ static int _n_openssl_mutexes = 0; /** A public key, or a public/private key-pair. */ struct crypto_pk_env_t { - int refs; /* reference counting so we don't have to copy keys */ - RSA *key; + int refs; /**< reference count, so we don't have to copy keys */ + RSA *key; /**< The key itself */ }; /** Key and stream information for a stream cipher. */ struct crypto_cipher_env_t { - char key[CIPHER_KEY_LEN]; - aes_cnt_cipher_t *cipher; + char key[CIPHER_KEY_LEN]; /**< The raw key. */ + aes_cnt_cipher_t *cipher; /**< The key in format usable for counter-mode AES + * encryption */ }; /** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake * while we're waiting for the second.*/ struct crypto_dh_env_t { - DH *dh; + DH *dh; /**< The openssl DH object */ }; static int setup_openssl_threading(void); @@ -1470,7 +1473,7 @@ crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *cipher, /* SHA-1 */ -/** Compute the SHA1 digest of <b>len</b> bytes in data stored in +/** Compute the SHA1 digest of the <b>len</b> bytes on data stored in * <b>m</b>. Write the DIGEST_LEN byte result into <b>digest</b>. * Return 0 on success, -1 on failure. */ @@ -1482,6 +1485,9 @@ crypto_digest(char *digest, const char *m, size_t len) return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL); } +/** Compute a 256-bit digest of <b>len</b> bytes in data stored in <b>m</b>, + * using the algorithm <b>algorithm</b>. Write the DIGEST_LEN256-byte result + * into <b>digest</b>. Return 0 on success, -1 on failure. */ int crypto_digest256(char *digest, const char *m, size_t len, digest_algorithm_t algorithm) @@ -1541,13 +1547,14 @@ crypto_digest_algorithm_parse_name(const char *name) /** Intermediate information about the digest of a stream of data. */ struct crypto_digest_env_t { union { - SHA_CTX sha1; - SHA256_CTX sha2; - } d; - digest_algorithm_t algorithm : 8; + SHA_CTX sha1; /**< state for SHA1 */ + SHA256_CTX sha2; /**< state for SHA256 */ + } d; /**< State for the digest we're using. Only one member of the + * union is usable, depending on the value of <b>algorithm</b>. */ + digest_algorithm_t algorithm : 8; /**< Which algorithm is in use? */ }; -/** Allocate and return a new digest object. +/** Allocate and return a new digest object to compute SHA1 digests. */ crypto_digest_env_t * crypto_new_digest_env(void) @@ -1559,6 +1566,8 @@ crypto_new_digest_env(void) return r; } +/** Allocate and return a new digest object to compute 256-bit digests + * using <b>algorithm</b>. */ crypto_digest_env_t * crypto_new_digest256_env(digest_algorithm_t algorithm) { @@ -1732,6 +1741,10 @@ init_dh_param(void) dh_param_g = g; } +/** Number of bits to use when choosing the x or y value in a Diffie-Hellman + * handshake. Since we exponentiate by this value, choosing a smaller one + * lets our handhake go faster. + */ #define DH_PRIVATE_KEY_BITS 320 /** Allocate and return a new DH object for a key exchange. @@ -1983,15 +1996,22 @@ crypto_dh_free(crypto_dh_env_t *dh) /* random numbers */ -/* This is how much entropy OpenSSL likes to add right now, so maybe it will +/** How many bytes of entropy we add at once. + * + * This is how much entropy OpenSSL likes to add right now, so maybe it will * work for us too. */ #define ADD_ENTROPY 32 -/* Use RAND_poll if OpenSSL is 0.9.6 release or later. (The "f" means - "release".) */ +/** True iff we should use OpenSSL's RAND_poll function to add entropy to its + * pool. + * + * Use RAND_poll if OpenSSL is 0.9.6 release or later. (The "f" means + *"release".) */ #define HAVE_RAND_POLL (OPENSSL_VERSION_NUMBER >= 0x0090600fl) -/* Versions of OpenSSL prior to 0.9.7k and 0.9.8c had a bug where RAND_poll +/** True iff it's safe to use RAND_poll after setup. + * + * Versions of OpenSSL prior to 0.9.7k and 0.9.8c had a bug where RAND_poll * would allocate an fd_set on the stack, open a new file, and try to FD_SET * that fd without checking whether it fit in the fd_set. Thus, if the * system has not just been started up, it is unsafe to call */ @@ -2000,6 +2020,7 @@ crypto_dh_free(crypto_dh_env_t *dh) OPENSSL_VERSION_NUMBER <= 0x00907fffl) || \ (OPENSSL_VERSION_NUMBER >= 0x0090803fl)) +/** Set the seed of the weak RNG to a random value. */ static void seed_weak_rng(void) { @@ -2253,9 +2274,12 @@ base64_encode(char *dest, size_t destlen, const char *src, size_t srclen) return ret; } +/** @{ */ +/** Special values used for the base64_decode_table */ #define X 255 #define SP 64 #define PAD 65 +/** @} */ /** Internal table mapping byte values to what they represent in base64. * Numbers 0..63 are 6-bit integers. SPs are spaces, and should be * skipped. Xs are invalid and must not appear in base64. PAD indicates @@ -2659,6 +2683,7 @@ _openssl_dynlock_destroy_cb(struct CRYPTO_dynlock_value *v, tor_free(v); } +/** @{ */ /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being * multithreaded. */ static int @@ -2684,4 +2709,5 @@ setup_openssl_threading(void) return 0; } #endif +/** @} */ diff --git a/src/common/log.c b/src/common/log.c index cfa0721c27..28d002967b 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -36,8 +36,12 @@ #include "torlog.h" #include "container.h" +/** @{ */ +/** The string we stick at the end of a log message when it is too long, + * and its length. */ #define TRUNCATED_STR "[...truncated]" #define TRUNCATED_STR_LEN 14 +/** @} */ /** Information for a single logfile; only used in log.c */ typedef struct logfile_t { @@ -109,17 +113,19 @@ static int syslog_count = 0; /** Represents a log message that we are going to send to callback-driven * loggers once we can do so in a non-reentrant way. */ typedef struct pending_cb_message_t { - int severity; - log_domain_mask_t domain; - char *msg; + int severity; /**< The severity of the message */ + log_domain_mask_t domain; /**< The domain of the message */ + char *msg; /**< The content of the message */ } pending_cb_message_t; /** Log messages waiting to be replayed onto callback-based logs */ static smartlist_t *pending_cb_messages = NULL; +/** Lock the log_mutex to prevent others from changing the logfile_t list */ #define LOCK_LOGS() STMT_BEGIN \ tor_mutex_acquire(&log_mutex); \ STMT_END +/** Unlock the log_mutex */ #define UNLOCK_LOGS() STMT_BEGIN tor_mutex_release(&log_mutex); STMT_END /** What's the lowest log level anybody cares about? Checking this lets us @@ -382,7 +388,10 @@ logv(int severity, log_domain_mask_t domain, const char *funcname, UNLOCK_LOGS(); } -/** Output a message to the log. */ +/** Output a message to the log. It gets logged to all logfiles that + * care about messages with <b>severity</b> in <b>domain</b>. The content + * is formatted printf style basedc on <b>format</b> and extra arguments. + * */ void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) { @@ -396,6 +405,9 @@ tor_log(int severity, log_domain_mask_t domain, const char *format, ...) /** Output a message to the log, prefixed with a function name <b>fn</b>. */ #ifdef __GNUC__ +/** GCC-based implementation of the log_fn backend, used when we have + * variadic macros. All arguments are as for log_fn, except for + * <b>fn</b>, which is the name of the calling functions. */ void _log_fn(int severity, log_domain_mask_t domain, const char *fn, const char *format, ...) @@ -408,6 +420,11 @@ _log_fn(int severity, log_domain_mask_t domain, const char *fn, va_end(ap); } #else +/** @{ */ +/** Variant implementation of log_fn, log_debug, log_info,... for C compilers + * without variadic macros. In this case, the calling function sets + * _log_fn_function_name to the name of the function, then invokes the + * appropriate _log_fn, _log_debug, etc. */ const char *_log_fn_function_name=NULL; void _log_fn(int severity, log_domain_mask_t domain, const char *format, ...) @@ -476,6 +493,7 @@ _log_err(log_domain_mask_t domain, const char *format, ...) va_end(ap); _log_fn_function_name = NULL; } +/** @} */ #endif /** Free all storage held by <b>victim</b>. */ diff --git a/src/common/memarea.c b/src/common/memarea.c index 194deb8d2c..6893639a6e 100644 --- a/src/common/memarea.c +++ b/src/common/memarea.c @@ -30,12 +30,18 @@ #endif #ifdef USE_SENTINELS +/** Magic value that we stick at the end of a memarea so we can make sure + * there are no run-off-the-end bugs. */ #define SENTINEL_VAL 0x90806622u +/** How many bytes per area do we devote to the sentinel? */ #define SENTINEL_LEN sizeof(uint32_t) +/** Given a mem_area_chunk_t with SENTINEL_LEN extra bytes allocated at the + * end, set those bytes. */ #define SET_SENTINEL(chunk) \ STMT_BEGIN \ set_uint32( &(chunk)->u.mem[chunk->mem_size], SENTINEL_VAL ); \ STMT_END +/** Assert that the sentinel on a memarea is set correctly. */ #define CHECK_SENTINEL(chunk) \ STMT_BEGIN \ uint32_t sent_val = get_uint32(&(chunk)->u.mem[chunk->mem_size]); \ @@ -73,8 +79,11 @@ typedef struct memarea_chunk_t { } u; } memarea_chunk_t; +/** How many bytes are needed for overhead before we get to the memory part + * of a chunk? */ #define CHUNK_HEADER_SIZE STRUCT_OFFSET(memarea_chunk_t, u) +/** What's the smallest that we'll allocate a chunk? */ #define CHUNK_SIZE 4096 /** A memarea_t is an allocation region for a set of small memory requests diff --git a/src/common/torgzip.c b/src/common/torgzip.c index b2a205f7d9..e9079e0ba5 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -79,6 +79,7 @@ method_bits(compress_method_t method) return method == GZIP_METHOD ? 15+16 : 15; } +/** @{ */ /* These macros define the maximum allowable compression factor. Anything of * size greater than CHECK_FOR_COMPRESSION_BOMB_AFTER is not allowed to * have an uncompression factor (uncompressed size:compressed size ratio) of @@ -94,6 +95,7 @@ method_bits(compress_method_t method) */ #define MAX_UNCOMPRESSION_FACTOR 25 #define CHECK_FOR_COMPRESSION_BOMB_AFTER (1024*64) +/** @} */ /** Return true if uncompressing an input of size <b>in_size</b> to an input * of size at least <b>size_out</b> looks like a compression bomb. */ @@ -389,12 +391,12 @@ detect_compression_method(const char *in, size_t in_len) /** Internal state for an incremental zlib compression/decompression. The * body of this struct is not exposed. */ struct tor_zlib_state_t { - struct z_stream_s stream; - int compress; + struct z_stream_s stream; /**< The zlib stream */ + int compress; /**< True if we are compressing; false if we are inflating */ - /* Number of bytes read so far. Used to detect zlib bombs. */ + /** Number of bytes read so far. Used to detect zlib bombs. */ size_t input_so_far; - /* Number of bytes written so far. Used to detect zlib bombs. */ + /** Number of bytes written so far. Used to detect zlib bombs. */ size_t output_so_far; }; diff --git a/src/common/torint.h b/src/common/torint.h index 1faf65abab..f5bebf8b9d 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -329,7 +329,7 @@ typedef uint32_t uintptr_t; #endif #endif -/* Any size_t larger than this amount is likely to be an underflow. */ +/** Any size_t larger than this amount is likely to be an underflow. */ #define SIZE_T_CEILING (SSIZE_T_MAX-16) #endif /* __TORINT_H */ diff --git a/src/common/torlog.h b/src/common/torlog.h index 791e363946..000e32ddab 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file log.h + * \file torlog.h * * \brief Headers for log.c **/ @@ -99,6 +99,7 @@ * immediately. Used as a flag, not a log domain. */ #define LD_NOCB (1u<<31) +/** Mask of zero or more log domains, OR'd together. */ typedef uint32_t log_domain_mask_t; /** Configures which severities are logged for each logging domain for a given diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index a54f232f51..37b761f99b 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -457,7 +457,7 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n) * Add a new build time value <b>time</b> to the set of build times. Time * units are milliseconds. * - * circuit_build_times <b>cbt</a> is a circular array, so loop around when + * circuit_build_times <b>cbt</b> is a circular array, so loop around when * array is full. */ int @@ -655,7 +655,7 @@ circuit_build_times_update_state(circuit_build_times_t *cbt, /** * Shuffle the build times array. * - * Stolen from http://en.wikipedia.org/wiki/Fisher\u2013Yates_shuffle + * Adapted from http://en.wikipedia.org/wiki/Fisher-Yates_shuffle */ static void circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, @@ -2041,7 +2041,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) struct timeval end; long timediff; tor_gettimeofday(&end); - timediff = tv_mdiff(&circ->_base.highres_created, &end); + timediff = tv_mdiff(&circ->_base.timestamp_created, &end); /* * If the circuit build time is much greater than we would have cut diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index b4f5f45615..d1fea37c25 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -398,8 +398,7 @@ circuit_initial_package_window(void) static void init_circuit_base(circuit_t *circ) { - circ->timestamp_created = time(NULL); - tor_gettimeofday(&circ->highres_created); + tor_gettimeofday(&circ->timestamp_created); circ->package_window = circuit_initial_package_window(); circ->deliver_window = CIRCWINDOW_START; @@ -609,9 +608,10 @@ circuit_dump_details(int severity, circuit_t *circ, int conn_array_index, const char *type, int this_circid, int other_circid) { log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), " - "state %d (%s), born %d:", + "state %d (%s), born %ld:", conn_array_index, type, this_circid, other_circid, circ->state, - circuit_state_to_string(circ->state), (int)circ->timestamp_created); + circuit_state_to_string(circ->state), + (long)circ->timestamp_created.tv_sec); if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */ circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ)); } diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 8d9d115863..447ec8412d 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -31,7 +31,7 @@ extern circuit_t *global_circuitlist; /* from circuitlist.c */ /********* END VARIABLES ************/ -static void circuit_expire_old_circuits_clientside(time_t now); +static void circuit_expire_old_circuits_clientside(void); static void circuit_increment_failure_count(void); /** Return 1 if <b>circ</b> could be returned by circuit_get_best(). @@ -162,7 +162,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) return 1; } else { if (a->timestamp_dirty || - a->timestamp_created > b->timestamp_created) + timercmp(&a->timestamp_created, &b->timestamp_created, >)) return 1; if (CIRCUIT_IS_ORIGIN(b) && TO_ORIGIN_CIRCUIT(b)->build_state->is_internal) @@ -204,7 +204,7 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, int need_uptime, int need_internal) { circuit_t *circ, *best=NULL; - time_t now = time(NULL); + struct timeval now; int intro_going_on_but_too_old = 0; tor_assert(conn); @@ -213,17 +213,16 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT || purpose == CIRCUIT_PURPOSE_C_REND_JOINED); + tor_gettimeofday(&now); + for (circ=global_circuitlist;circ;circ = circ->next) { if (!circuit_is_acceptable(circ,conn,must_be_open,purpose, - need_uptime,need_internal,now)) + need_uptime,need_internal,now.tv_sec)) continue; -/* XXX022 make this 15 be a function of circuit finishing times we've - * seen lately, a la Fallon Chen's GSoC work -RD */ -#define REND_PARALLEL_INTRO_DELAY 15 if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT && - !must_be_open && circ->state != CIRCUIT_STATE_OPEN && - circ->timestamp_created + REND_PARALLEL_INTRO_DELAY < now) { + !must_be_open && circ->state != CIRCUIT_STATE_OPEN && + tv_mdiff(&now, &circ->timestamp_created) > circ_times.timeout_ms) { intro_going_on_but_too_old = 1; continue; } @@ -275,22 +274,38 @@ circuit_conforms_to_options(const origin_circuit_t *circ, * at least CircuitBuildTimeout seconds ago. */ void -circuit_expire_building(time_t now) +circuit_expire_building(void) { circuit_t *victim, *next_circ = global_circuitlist; /* circ_times.timeout_ms and circ_times.close_ms are from * circuit_build_times_get_initial_timeout() if we haven't computed * custom timeouts yet */ - time_t general_cutoff = now - tor_lround(circ_times.timeout_ms/1000); - time_t begindir_cutoff = now - tor_lround(circ_times.timeout_ms/2000); - time_t fourhop_cutoff = now - tor_lround(4*circ_times.timeout_ms/3000); - time_t cannibalize_cutoff = now - tor_lround(circ_times.timeout_ms/2000); - time_t close_cutoff = now - tor_lround(circ_times.close_ms/1000); - time_t introcirc_cutoff = begindir_cutoff; + struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff, + cannibalize_cutoff, close_cutoff, extremely_old_cutoff; + struct timeval now; + struct timeval introcirc_cutoff; cpath_build_state_t *build_state; + tor_gettimeofday(&now); +#define SET_CUTOFF(target, msec) do { \ + long ms = tor_lround(msec); \ + struct timeval diff; \ + diff.tv_sec = ms / 1000; \ + diff.tv_usec = (ms % 1000) * 1000; \ + timersub(&now, &diff, &target); \ + } while (0) + + SET_CUTOFF(general_cutoff, circ_times.timeout_ms); + SET_CUTOFF(begindir_cutoff, circ_times.timeout_ms / 2.0); + SET_CUTOFF(fourhop_cutoff, circ_times.timeout_ms * (4/3.0)); + SET_CUTOFF(cannibalize_cutoff, circ_times.timeout_ms / 2.0); + SET_CUTOFF(close_cutoff, circ_times.close_ms); + SET_CUTOFF(extremely_old_cutoff, circ_times.close_ms*2 + 1000); + + introcirc_cutoff = begindir_cutoff; + while (next_circ) { - time_t cutoff; + struct timeval cutoff; victim = next_circ; next_circ = next_circ->next; if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */ @@ -312,7 +327,7 @@ circuit_expire_building(time_t now) else cutoff = general_cutoff; - if (victim->timestamp_created > cutoff) + if (timercmp(&victim->timestamp_created, &cutoff, >)) continue; /* it's still young, leave it alone */ #if 0 @@ -358,7 +373,7 @@ circuit_expire_building(time_t now) * because that's set when they switch purposes */ if (TO_ORIGIN_CIRCUIT(victim)->rend_data || - victim->timestamp_dirty > cutoff) + victim->timestamp_dirty > cutoff.tv_sec) continue; break; case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: @@ -367,7 +382,7 @@ circuit_expire_building(time_t now) * make an introduction attempt. so timestamp_dirty * will reflect the time since the last attempt. */ - if (victim->timestamp_dirty > cutoff) + if (victim->timestamp_dirty > cutoff.tv_sec) continue; break; } @@ -407,15 +422,15 @@ circuit_expire_building(time_t now) * it off at, we probably had a suspend event along this codepath, * and we should discard the value. */ - if (now - victim->timestamp_created > 2*circ_times.close_ms/1000+1) { + if (timercmp(&victim->timestamp_created, &extremely_old_cutoff, <)) { log_notice(LD_CIRC, "Extremely large value for circuit build timeout: %lds. " "Assuming clock jump. Purpose %d", - (long)(now - victim->timestamp_created), + (long)(now.tv_sec - victim->timestamp_created.tv_sec), victim->purpose); } else if (circuit_build_times_count_close(&circ_times, first_hop_succeeded, - victim->timestamp_created)) { + victim->timestamp_created.tv_sec)) { circuit_build_times_set_timeout(&circ_times); } } @@ -636,7 +651,7 @@ circuit_build_needed_circs(time_t now) time_to_new_circuit = now + options->NewCircuitPeriod; if (proxy_mode(get_options())) addressmap_clean(now); - circuit_expire_old_circuits_clientside(now); + circuit_expire_old_circuits_clientside(); #if 0 /* disable for now, until predict-and-launch-new can cull leftovers */ circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL); @@ -725,17 +740,20 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) * for too long and has no streams on it: mark it for close. */ static void -circuit_expire_old_circuits_clientside(time_t now) +circuit_expire_old_circuits_clientside(void) { circuit_t *circ; - time_t cutoff; + struct timeval cutoff, now; + + tor_gettimeofday(&now); + cutoff = now; if (circuit_build_times_needs_circuits(&circ_times)) { /* Circuits should be shorter lived if we need more of them * for learning a good build timeout */ - cutoff = now - IDLE_TIMEOUT_WHILE_LEARNING; + cutoff.tv_sec -= IDLE_TIMEOUT_WHILE_LEARNING; } else { - cutoff = now - get_options()->CircuitIdleTimeout; + cutoff.tv_sec -= get_options()->CircuitIdleTimeout; } for (circ = global_circuitlist; circ; circ = circ->next) { @@ -745,15 +763,15 @@ circuit_expire_old_circuits_clientside(time_t now) * on it, mark it for close. */ if (circ->timestamp_dirty && - circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now && + circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now.tv_sec && !TO_ORIGIN_CIRCUIT(circ)->p_streams /* nothing attached */ ) { - log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, " + log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %ld sec ago, " "purpose %d)", - circ->n_circ_id, (int)(now - circ->timestamp_dirty), + circ->n_circ_id, (long)(now.tv_sec - circ->timestamp_dirty), circ->purpose); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } else if (!circ->timestamp_dirty && circ->state == CIRCUIT_STATE_OPEN) { - if (circ->timestamp_created < cutoff) { + if (timercmp(&circ->timestamp_created, &cutoff, <)) { if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL || circ->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT || circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || @@ -762,8 +780,8 @@ circuit_expire_old_circuits_clientside(time_t now) circ->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) || circ->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) { log_debug(LD_CIRC, - "Closing circuit that has been unused for %ld seconds.", - (long)(now - circ->timestamp_created)); + "Closing circuit that has been unused for %ld msec.", + tv_mdiff(&circ->timestamp_created, &now)); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); } else if (!TO_ORIGIN_CIRCUIT(circ)->is_ancient) { /* Server-side rend joined circuits can end up really old, because @@ -775,9 +793,9 @@ circuit_expire_old_circuits_clientside(time_t now) circ->purpose != CIRCUIT_PURPOSE_S_INTRO) { log_notice(LD_CIRC, "Ancient non-dirty circuit %d is still around after " - "%ld seconds. Purpose: %d", + "%ld milliseconds. Purpose: %d", TO_ORIGIN_CIRCUIT(circ)->global_identifier, - (long)(now - circ->timestamp_created), + tv_mdiff(&circ->timestamp_created, &now), circ->purpose); /* FFFF implement a new circuit_purpose_to_string() so we don't * just print out a number for circ->purpose */ @@ -1123,7 +1141,7 @@ circuit_launch_by_extend_info(uint8_t purpose, /* reset the birth date of this circ, else expire_building * will see it and think it's been trying to build since it * began. */ - circ->_base.timestamp_created = time(NULL); + tor_gettimeofday(&circ->_base.timestamp_created); switch (purpose) { case CIRCUIT_PURPOSE_C_ESTABLISH_REND: case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: diff --git a/src/or/circuituse.h b/src/or/circuituse.h index 1a604b415f..a121099aca 100644 --- a/src/or/circuituse.h +++ b/src/or/circuituse.h @@ -12,7 +12,7 @@ #ifndef _TOR_CIRCUITUSE_H #define _TOR_CIRCUITUSE_H -void circuit_expire_building(time_t now); +void circuit_expire_building(void); void circuit_remove_handled_ports(smartlist_t *needed_ports); int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, int min); diff --git a/src/or/config.c b/src/or/config.c index d4be2072d8..5719a64088 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4770,10 +4770,10 @@ options_save_current(void) } /** Mapping from a unit name to a multiplier for converting that unit into a - * base unit. */ + * base unit. Used by config_parse_unit. */ struct unit_table_t { - const char *unit; - uint64_t multiplier; + const char *unit; /**< The name of the unit */ + uint64_t multiplier; /**< How many of the base unit appear in this unit */ }; /** Table to map the names of memory units to the number of bytes they diff --git a/src/or/connection.c b/src/or/connection.c index fd30ac8cb6..c65c91b73b 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1178,7 +1178,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) } if (connection_init_accepted_conn(newconn, conn->type) < 0) { - if (! conn->marked_for_close) + if (! newconn->marked_for_close) connection_mark_for_close(newconn); return 0; } @@ -3245,6 +3245,8 @@ connection_flushed_some(connection_t *conn) r = connection_dirserv_flushed_some(TO_DIR_CONN(conn)); } else if (conn->type == CONN_TYPE_OR) { r = connection_or_flushed_some(TO_OR_CONN(conn)); + } else if (CONN_IS_EDGE(conn)) { + r = connection_edge_flushed_some(TO_EDGE_CONN(conn)); } conn->in_flushed_some = 0; return r; diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index f02479fd59..85a52257a8 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -301,6 +301,23 @@ connection_edge_end_errno(edge_connection_t *conn) return connection_edge_end(conn, reason); } +/** We just wrote some data to <b>conn</b>; act appropriately. + * + * (That is, if it's open, consider sending a stream-level sendme cell if we + * have just flushed enough.) + */ +int +connection_edge_flushed_some(edge_connection_t *conn) +{ + switch (conn->_base.state) { + case AP_CONN_STATE_OPEN: + case EXIT_CONN_STATE_OPEN: + connection_edge_consider_sending_sendme(conn); + break; + } + return 0; +} + /** Connection <b>conn</b> has finished writing and has no bytes left on * its outbuf. * diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index fa5f91cf8d..0b08dd07ca 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -23,6 +23,7 @@ int connection_edge_process_inbuf(edge_connection_t *conn, int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn); int connection_edge_end(edge_connection_t *conn, uint8_t reason); int connection_edge_end_errno(edge_connection_t *conn); +int connection_edge_flushed_some(edge_connection_t *conn); int connection_edge_finished_flushing(edge_connection_t *conn); int connection_edge_finished_connecting(edge_connection_t *conn); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 2d2444462d..ff863fd550 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -467,7 +467,7 @@ connection_or_init_conn_from_address(or_connection_t *conn, * Requires that both input connections are open; not is_bad_for_new_circs, * and not impossibly non-canonical. * - * If </b>forgive_new_connections</b> is true, then we do not call + * If <b>forgive_new_connections</b> is true, then we do not call * <b>a</b>better than <b>b</b> simply because b has no circuits, * unless b is also relatively old. */ diff --git a/src/or/directory.c b/src/or/directory.c index f8d587f35c..00de1f2f80 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -3259,6 +3259,8 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, write_http_status_line(conn, status, "Vote stored"); } else { tor_assert(msg); + log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").", + conn->_base.address, msg); write_http_status_line(conn, status, msg); } goto done; diff --git a/src/or/geoip.c b/src/or/geoip.c index e5694b9618..654241c1c0 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -284,11 +284,18 @@ geoip_is_loaded(void) typedef struct clientmap_entry_t { HT_ENTRY(clientmap_entry_t) node; uint32_t ipaddr; + /** Time when we last saw this IP address, in MINUTES since the epoch. + * + * (This will run out of space around 4011 CE. If Tor is still in use around + * 4000 CE, please remember to add more bits to last_seen_in_minutes.) */ unsigned int last_seen_in_minutes:30; unsigned int action:2; } clientmap_entry_t; -#define ACTION_MASK 3 +/** Largest allowable value for last_seen_in_minutes. (It's a 30-bit field, + * so it can hold up to (1u<<30)-1, or 0x3fffffffu. + */ +#define MAX_LAST_SEEN_IN_MINUTES 0X3FFFFFFFu /** Map from client IP address to last time seen. */ static HT_HEAD(clientmap, clientmap_entry_t) client_history = @@ -413,15 +420,16 @@ geoip_note_client_seen(geoip_client_action_t action, lookup.ipaddr = addr; lookup.action = (int)action; ent = HT_FIND(clientmap, &client_history, &lookup); - if (ent) { - ent->last_seen_in_minutes = now / 60; - } else { + if (! ent) { ent = tor_malloc_zero(sizeof(clientmap_entry_t)); ent->ipaddr = addr; - ent->last_seen_in_minutes = now / 60; ent->action = (int)action; HT_INSERT(clientmap, &client_history, ent); } + if (now / 60 <= (int)MAX_LAST_SEEN_IN_MINUTES && now >= 0) + ent->last_seen_in_minutes = (unsigned)(now/60); + else + ent->last_seen_in_minutes = 0; if (action == GEOIP_CLIENT_NETWORKSTATUS || action == GEOIP_CLIENT_NETWORKSTATUS_V2) { diff --git a/src/or/main.c b/src/or/main.c index 214a4fad5d..83d1e1e517 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1150,7 +1150,9 @@ run_scheduled_events(time_t now) * We do this before step 4, so it can try building more if * it's not comfortable with the number of available circuits. */ - circuit_expire_building(now); + /* XXXX022 If our circuit build timeout is much lower than a second, maybe + we should do this more often? */ + circuit_expire_building(); /** 3b. Also look at pending streams and prune the ones that 'began' * a long time ago but haven't gotten a 'connected' yet. diff --git a/src/or/main.h b/src/or/main.h index d399aaaaf3..ed0fb97703 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -23,9 +23,11 @@ int connection_is_on_closeable_list(connection_t *conn); smartlist_t *get_connection_array(void); +/** Bitmask for events that we can turn on and off with + * connection_watch_events. */ typedef enum watchable_events { - READ_EVENT=0x02, - WRITE_EVENT=0x04 + READ_EVENT=0x02, /**< We want to know when a connection is readable */ + WRITE_EVENT=0x04 /**< We want to know when a connection is writable */ } watchable_events_t; void connection_watch_events(connection_t *conn, watchable_events_t events); int connection_is_reading(connection_t *conn); diff --git a/src/or/ntmain.c b/src/or/ntmain.c index 06ca2df91e..b2fee648cc 100644 --- a/src/or/ntmain.c +++ b/src/or/ntmain.c @@ -54,6 +54,11 @@ static int nt_service_cmd_stop(void); struct service_fns { int loaded; + /** @{ */ + /** Function pointers for Windows API functions related to service + * management. These are NULL, or they point to the . They're set by + * calling the LOAD macro below. */ + BOOL (WINAPI *ChangeServiceConfig2A_fn)( SC_HANDLE hService, DWORD dwInfoLevel, @@ -122,6 +127,7 @@ struct service_fns { LPTSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse); + /** @} */ } service_fns = { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -144,6 +150,10 @@ nt_service_loadlibrary(void) goto err; } +/* Helper macro: try to load a function named <b>f</b> from "library" into + * service_functions.<b>f</b>_fn. On failure, log an error message, and goto + * err. + */ #define LOAD(f) STMT_BEGIN \ if (!(fn = GetProcAddress(library, #f))) { \ log_err(LD_BUG, \ diff --git a/src/or/or.h b/src/or/or.h index 910bf8d8af..3cadd3173e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -848,9 +848,13 @@ typedef struct cell_t { /** Parsed variable-length onion routing cell. */ typedef struct var_cell_t { + /** Type of the cell: CELL_VERSIONS, etc. */ uint8_t command; + /** Circuit thich received the cell */ circid_t circ_id; + /** Number of bytes actually stored in <b>payload</b> */ uint16_t payload_len; + /** Payload of this cell */ uint8_t payload[1]; } var_cell_t; @@ -1679,8 +1683,13 @@ typedef struct networkstatus_v2_t { * sorted by identity_digest. */ } networkstatus_v2_t; +/** Linked list of microdesc hash lines for a single router in a directory + * vote. + */ typedef struct vote_microdesc_hash_t { + /** Next element in the list, or NULL. */ struct vote_microdesc_hash_t *next; + /** The raw contents of the microdesc hash line, excluding the "m". */ char *microdesc_hash_line; } vote_microdesc_hash_t; @@ -1692,6 +1701,7 @@ typedef struct vote_routerstatus_t { * networkstatus_t.known_flags. */ char *version; /**< The version that the authority says this router is * running. */ + /** The hash or hashes that the authority claims this microdesc has. */ vote_microdesc_hash_t *microdesc; } vote_routerstatus_t; @@ -2116,10 +2126,9 @@ typedef struct circuit_t { * length ONIONSKIN_CHALLENGE_LEN. */ char *n_conn_onionskin; - time_t timestamp_created; /**< When was this circuit created? */ + struct timeval timestamp_created; /**< When was the circuit created? */ time_t timestamp_dirty; /**< When the circuit was first used, or 0 if the * circuit is clean. */ - struct timeval highres_created; /**< When exactly was the circuit created? */ uint16_t marked_for_close; /**< Should we close this circuit at the end of * the main loop? (If true, holds the line number @@ -3218,8 +3227,19 @@ typedef struct { } fp_pair_t; /********************************* dirserv.c ***************************/ + +/** An enum to describe what format we're generating a routerstatus line in. + */ typedef enum { - NS_V2, NS_V3_CONSENSUS, NS_V3_VOTE, NS_CONTROL_PORT, + /** For use in a v2 opinion */ + NS_V2, + /** For use in a consensus networkstatus document (ns flavor) */ + NS_V3_CONSENSUS, + /** For use in a vote networkstatus document */ + NS_V3_VOTE, + /** For passing to the controlport in response to a GETINFO request */ + NS_CONTROL_PORT, + /** For use in a consensus networkstatus document (microdesc flavor) */ NS_V3_CONSENSUS_MICRODESC } routerstatus_format_type_t; @@ -3236,9 +3256,14 @@ typedef struct measured_bw_line_t { /** Describes the schedule by which votes should be generated. */ typedef struct vote_timing_t { + /** Length in seconds between one consensus becoming valid and the next + * becoming valid. */ int vote_interval; + /** For how many intervals is a consensus valid? */ int n_intervals_valid; + /** Time in seconds allowed to propagate votes */ int vote_delay; + /** Time in seconds allowed to propagate signatures */ int dist_delay; } vote_timing_t; diff --git a/src/or/relay.c b/src/or/relay.c index a6c25062a3..076b46b934 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -52,9 +52,9 @@ static int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); static int circuit_queue_streams_are_blocked(circuit_t *circ); +/* XXXX023 move this all to compat_libevent */ /** Cache the current hi-res time; the cache gets reset when libevent * calls us. */ - static struct timeval cached_time_hires = {0, 0}; /** Stop reading on edge connections when we have this many cells @@ -76,7 +76,7 @@ tor_gettimeofday_cached(struct timeval *tv) void tor_gettimeofday_cache_clear(void) { - cached_time_hires.tv_sec = 0; + cached_time_hires.tv_sec = 0; } /** Stats: how many relay cells have originated at this hop, or have @@ -1409,8 +1409,9 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, goto repeat_connection_edge_package_raw_inbuf; } -/** Called when we've just received a relay data cell, or when - * we've just finished flushing all bytes to stream <b>conn</b>. +/** Called when we've just received a relay data cell, when + * we've just finished flushing all bytes to stream <b>conn</b>, + * or when we've flushed *some* bytes to the stream <b>conn</b>. * * If conn->outbuf is not too full, and our deliver window is * low, send back a suitable number of stream-level sendme cells. diff --git a/src/or/relay.h b/src/or/relay.h index dbba09239a..f64752da5d 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -64,5 +64,7 @@ void cell_ewma_set_scale_factor(or_options_t *options, networkstatus_t *consensus); void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn); +void tor_gettimeofday_cache_clear(void); + #endif diff --git a/src/or/rendclient.c b/src/or/rendclient.c index ba5987c698..01b2b62d3a 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -403,7 +403,7 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) tor_assert(rend_query); /* Determine responsible dirs. Even if we can't get all we want, * work with the ones we have. If it's empty, we'll notice below. */ - (int) hid_serv_get_responsible_directories(responsible_dirs, desc_id); + hid_serv_get_responsible_directories(responsible_dirs, desc_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id, DIGEST_LEN); diff --git a/src/or/rephist.c b/src/or/rephist.c index e4afe62b67..06704cf817 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -2337,7 +2337,6 @@ typedef struct circ_buffer_stats_t { uint32_t local_circ_id; } circ_buffer_stats_t; -/** Holds stats. */ smartlist_t *circuits_for_buffer_stats = NULL; /** Remember cell statistics for circuit <b>circ</b> at time @@ -2357,9 +2356,9 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) return; if (!circuits_for_buffer_stats) circuits_for_buffer_stats = smartlist_create(); - start_of_interval = circ->timestamp_created > + start_of_interval = circ->timestamp_created.tv_sec > start_of_buffer_stats_interval ? - circ->timestamp_created : + circ->timestamp_created.tv_sec : start_of_buffer_stats_interval; interval_length = (int) (end_of_interval - start_of_interval); stat = tor_malloc_zero(sizeof(circ_buffer_stats_t)); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 28ce97ebde..e0605dcd4d 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -2822,7 +2822,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, ns->flavor = flav = flavor; } if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) { - log_warn(LD_DIR, "Flavor found on non-consenus networkstatus."); + log_warn(LD_DIR, "Flavor found on non-consensus networkstatus."); goto err; } diff --git a/src/or/routerparse.h b/src/or/routerparse.h index bde7800b7d..8b8cde25f6 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file routerpase.h + * \file routerparse.h * \brief Header file for routerparse.c. **/ @@ -82,7 +82,5 @@ int rend_parse_introduction_points(rend_service_descriptor_t *parsed, size_t intro_points_encoded_size); int rend_parse_client_keys(strmap_t *parsed_clients, const char *str); -void tor_gettimeofday_cache_clear(void); - #endif diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 6ea7f295ed..781081a4ad 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -384,12 +384,14 @@ test_crypto_pk(void) /* Now try signing. */ strlcpy(data1, "Ossifrage", 1024); test_eq(128, crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10)); - test_eq(10, crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); + test_eq(10, + crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); test_streq(data3, "Ossifrage"); /* Try signing digests. */ test_eq(128, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2), data1, 10)); - test_eq(20, crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); + test_eq(20, + crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128)); test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128)); diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 1f3beb4baa..8fd94289a9 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -748,11 +748,11 @@ test_dir_v3_networkstatus(void) sign_skey_leg1 = pk_generate(4); test_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, - AUTHORITY_SIGNKEY_1, -1)); + AUTHORITY_SIGNKEY_1, -1)); test_assert(!crypto_pk_read_private_key_from_string(sign_skey_2, - AUTHORITY_SIGNKEY_2, -1)); + AUTHORITY_SIGNKEY_2, -1)); test_assert(!crypto_pk_read_private_key_from_string(sign_skey_3, - AUTHORITY_SIGNKEY_3, -1)); + AUTHORITY_SIGNKEY_3, -1)); test_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key)); test_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key)); |