commit aaa3a085db05c4d98b7c51b5ef16da166e7c7f0a Merge: bae5dd6 54f41d6 Author: Andrea Shepard andrea@torproject.org Date: Fri May 10 19:39:48 2013 -0700
Merge bug5595-v2-squashed into maint-0.2.4
changes/bug5595 | 8 + src/or/Makefile.nmake | 1 + src/or/directory.c | 73 +++++-- src/or/dirvote.c | 2 +- src/or/fp_pair.c | 308 ++++++++++++++++++++++++++ src/or/fp_pair.h | 45 ++++ src/or/include.am | 2 + src/or/router.c | 3 +- src/or/routerlist.c | 516 ++++++++++++++++++++++++++++++++++++-------- src/or/routerlist.h | 18 ++- src/test/test_containers.c | 84 +++++++ 11 files changed, 949 insertions(+), 111 deletions(-)
diff --cc src/or/Makefile.nmake index d67123a,146866e..3b627b1 --- a/src/or/Makefile.nmake +++ b/src/or/Makefile.nmake @@@ -1,74 -1,28 +1,75 @@@ all: tor.exe
-CFLAGS = /I ..\win32 /I ......\build-alpha\include /I ..\common +CFLAGS = /I ..\win32 /I ......\build-alpha\include /I ..\common \ + /I ..\ext
-LIBS = ......\build-alpha\lib\libevent.a \ - ......\build-alpha\lib\libcrypto.a \ - ......\build-alpha\lib\libssl.a \ - ......\build-alpha\lib\libz.a \ - ws2_32.lib advapi32.lib shell32.lib +LIBS = ......\build-alpha\lib\libevent.lib \ + ......\build-alpha\lib\libcrypto.lib \ + ......\build-alpha\lib\libssl.lib \ + ......\build-alpha\lib\libz.lib \ + ws2_32.lib advapi32.lib shell32.lib \ + crypt32.lib gdi32.lib user32.lib
-LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \ - command.obj config.obj connection.obj connection_edge.obj \ - connection_or.obj control.obj cpuworker.obj directory.obj \ - dirserv.obj dirvote.obj dns.obj dnsserv.obj fp_pair.obj geoip.obj \ - hibernate.obj main.obj microdesc.obj networkstatus.obj \ - nodelist.obj onion.obj policies.obj reasons.obj relay.obj \ - rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \ - rephist.obj router.obj routerlist.obj routerparse.obj status.obj \ - config_codedigest.obj ntmain.obj +LIBTOR_OBJECTS = \ + addressmap.obj \ + buffers.obj \ + channel.obj \ + channeltls.obj \ + circuitbuild.obj \ + circuitlist.obj \ + circuitmux.obj \ + circuitmux_ewma.obj \ + circuitstats.obj \ + circuituse.obj \ + command.obj \ + config.obj \ + config_codedigest.obj \ + confparse.obj \ + connection.obj \ + connection_edge.obj \ + connection_or.obj \ + control.obj \ + cpuworker.obj \ + directory.obj \ + dirserv.obj \ + dirvote.obj \ + dns.obj \ + dnsserv.obj \ ++ fp_pair.obj \ + entrynodes.obj \ + geoip.obj \ + hibernate.obj \ + main.obj \ + microdesc.obj \ + networkstatus.obj \ + nodelist.obj \ + ntmain.obj \ + onion.obj \ + onion_fast.obj \ + onion_ntor.obj \ + onion_tap.obj \ + policies.obj \ + reasons.obj \ + relay.obj \ + rendclient.obj \ + rendcommon.obj \ + rendmid.obj \ + rendservice.obj \ + rephist.obj \ + replaycache.obj \ + router.obj \ + routerlist.obj \ + routerparse.obj \ + routerset.obj \ + statefile.obj \ + status.obj \ + transports.obj
libtor.lib: $(LIBTOR_OBJECTS) - lib $(LIBTOR_OBJECTS) /out:libtor.lib + lib $(LIBTOR_OBJECTS) /out:$@
tor.exe: libtor.lib tor_main.obj - $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common*.lib tor_main.obj + $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common*.lib tor_main.obj /Fe$@
clean: del $(LIBTOR_OBJECTS) *.lib tor.exe diff --cc src/or/directory.c index 38a423c,f65ac87..b4381ac --- a/src/or/directory.c +++ b/src/or/directory.c @@@ -856,8 -803,10 +856,10 @@@ connection_dir_bridge_routerdesc_failed static void connection_dir_download_cert_failed(dir_connection_t *conn, int status) { + const char *fp_pfx = "fp/"; + const char *fpsk_pfx = "fp-sk/"; smartlist_t *failed; - tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE); + tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
if (!conn->requested_resource) return; @@@ -1629,11 -1608,12 +1653,12 @@@ connection_dir_client_reached_eof(dir_c compress_method_t compression; int plausible; int skewed=0; - int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || - conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC); + int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || + conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC); int was_compressed=0; time_t now = time(NULL); + int src_code;
switch (connection_fetch_from_buf_http(TO_CONN(conn), &headers, MAX_HEADERS_SIZE, @@@ -1901,18 -1881,37 +1926,38 @@@ return -1; } log_info(LD_DIR,"Received authority certificates (size %d) from server " - "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); + "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port); - if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) { - log_warn(LD_DIR, "Unable to parse fetched certificates"); - /* if we fetched more than one and only some failed, the successful - * ones got flushed to disk so it's safe to call this on them */ - connection_dir_download_cert_failed(conn, status_code); ++ + /* + * Tell trusted_dirs_load_certs_from_string() whether it was by fp + * or fp-sk pair. + */ + src_code = -1; + if (!strcmpstart(conn->requested_resource, "fp/")) { + src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST; + } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) { + src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST; + } + + if (src_code != -1) { + if (trusted_dirs_load_certs_from_string(body, src_code, 1)<0) { + log_warn(LD_DIR, "Unable to parse fetched certificates"); + /* if we fetched more than one and only some failed, the successful + * ones got flushed to disk so it's safe to call this on them */ + connection_dir_download_cert_failed(conn, status_code); + } else { + directory_info_has_arrived(now, 0); + log_info(LD_DIR, "Successfully loaded certificates from fetch."); + } } else { - directory_info_has_arrived(now, 0); - log_info(LD_DIR, "Successfully loaded certificates from fetch."); + log_warn(LD_DIR, + "Couldn't figure out what to do with fetched certificates for " + "unknown resource %s", + conn->requested_resource); + connection_dir_download_cert_failed(conn, status_code); } } - if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { + if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { const char *msg; int st; log_info(LD_DIR,"Got votes (size %d) from server %s:%d", diff --cc src/or/include.am index d2be1fb,0000000..65dbeff mode 100644,000000..100644 --- a/src/or/include.am +++ b/src/or/include.am @@@ -1,193 -1,0 +1,195 @@@ +bin_PROGRAMS+= src/or/tor +noinst_LIBRARIES+= src/or/libtor.a + +if BUILD_NT_SERVICES +tor_platform_source=src/or/ntmain.c +else +tor_platform_source= +endif + +EXTRA_DIST+= src/or/ntmain.c src/or/or_sha1.i src/or/Makefile.nmake + +if USE_EXTERNAL_EVDNS +evdns_source= +else +evdns_source=src/ext/eventdns.c +endif + +if CURVE25519_ENABLED +onion_ntor_source=src/or/onion_ntor.c +else +onion_ntor_source= +endif + +src_or_libtor_a_SOURCES = \ + src/or/addressmap.c \ + src/or/buffers.c \ + src/or/channel.c \ + src/or/channeltls.c \ + src/or/circuitbuild.c \ + src/or/circuitlist.c \ + src/or/circuitmux.c \ + src/or/circuitmux_ewma.c \ + src/or/circuitstats.c \ + src/or/circuituse.c \ + src/or/command.c \ + src/or/config.c \ + src/or/confparse.c \ + src/or/connection.c \ + src/or/connection_edge.c \ + src/or/connection_or.c \ + src/or/control.c \ + src/or/cpuworker.c \ + src/or/directory.c \ + src/or/dirserv.c \ + src/or/dirvote.c \ + src/or/dns.c \ + src/or/dnsserv.c \ ++ src/or/fp_pair.c \ + src/or/geoip.c \ + src/or/entrynodes.c \ + src/or/hibernate.c \ + src/or/main.c \ + src/or/microdesc.c \ + src/or/networkstatus.c \ + src/or/nodelist.c \ + src/or/onion.c \ + src/or/onion_fast.c \ + src/or/onion_tap.c \ + src/or/transports.c \ + src/or/policies.c \ + src/or/reasons.c \ + src/or/relay.c \ + src/or/rendclient.c \ + src/or/rendcommon.c \ + src/or/rendmid.c \ + src/or/rendservice.c \ + src/or/rephist.c \ + src/or/replaycache.c \ + src/or/router.c \ + src/or/routerlist.c \ + src/or/routerparse.c \ + src/or/routerset.c \ + src/or/statefile.c \ + src/or/status.c \ + $(evdns_source) \ + $(tor_platform_source) \ + $(onion_ntor_source) \ + src/or/config_codedigest.c + +#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \ +# ../common/libor-event.a + + +src_or_tor_SOURCES = src/or/tor_main.c +AM_CPPFLAGS += -I$(srcdir)/src/or -Isrc/or + +src/or/tor_main.o: micro-revision.i + +AM_CPPFLAGS += -DSHARE_DATADIR=""$(datadir)"" \ + -DLOCALSTATEDIR=""$(localstatedir)"" \ + -DBINDIR=""$(bindir)"" + +# -L flags need to go in LDFLAGS. -l flags need to go in LDADD. +# This seems to matter nowhere but on windows, but I assure you that it +# matters a lot there, and is quite hard to debug if you forget to do it. + + +src_or_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ +src_or_tor_LDADD = src/or/libtor.a src/common/libor.a \ + src/common/libor-crypto.a $(LIBDONNA) \ + src/common/libor-event.a \ + @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + +ORHEADERS = \ + src/or/addressmap.h \ + src/or/buffers.h \ + src/or/channel.h \ + src/or/channeltls.h \ + src/or/circuitbuild.h \ + src/or/circuitlist.h \ + src/or/circuitmux.h \ + src/or/circuitmux_ewma.h \ + src/or/circuitstats.h \ + src/or/circuituse.h \ + src/or/command.h \ + src/or/config.h \ + src/or/confparse.h \ + src/or/connection.h \ + src/or/connection_edge.h \ + src/or/connection_or.h \ + src/or/control.h \ + src/or/cpuworker.h \ + src/or/directory.h \ + src/or/dirserv.h \ + src/or/dirvote.h \ + src/or/dns.h \ + src/or/dnsserv.h \ + src/or/eventdns_tor.h \ ++ src/or/fp_pair.h \ + src/or/geoip.h \ + src/or/entrynodes.h \ + src/or/hibernate.h \ + src/or/main.h \ + src/or/microdesc.h \ + src/or/networkstatus.h \ + src/or/nodelist.h \ + src/or/ntmain.h \ + src/or/onion.h \ + src/or/onion_fast.h \ + src/or/onion_ntor.h \ + src/or/onion_tap.h \ + src/or/or.h \ + src/or/transports.h \ + src/or/policies.h \ + src/or/reasons.h \ + src/or/relay.h \ + src/or/rendclient.h \ + src/or/rendcommon.h \ + src/or/rendmid.h \ + src/or/rendservice.h \ + src/or/rephist.h \ + src/or/replaycache.h \ + src/or/router.h \ + src/or/routerlist.h \ + src/or/routerset.h \ + src/or/routerparse.h \ + src/or/statefile.h \ + src/or/status.h + +noinst_HEADERS+= $(ORHEADERS) micro-revision.i + +src/or/config_codedigest.o: src/or/or_sha1.i + +micro-revision.i: FORCE + @rm -f micro-revision.tmp; \ + if test -d "$(top_srcdir)/.git" && \ + test -x "`which git 2>&1;true`"; then \ + HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \ + echo "$$HASH" > micro-revision.tmp; \ + fi; \ + if test ! -f micro-revision.tmp ; then \ + if test ! -f micro-revision.i ; then \ + echo '""' > micro-revision.i; \ + fi; \ + elif test ! -f micro-revision.i || \ + test x"`cat micro-revision.tmp`" != x"`cat micro-revision.i`"; then \ + mv micro-revision.tmp micro-revision.i; \ + fi; true + +src/or/or_sha1.i: $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS) + $(AM_V_GEN)if test "@SHA1SUM@" != none; then \ + (cd "$(srcdir)" && "@SHA1SUM@" $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS) ) | \ + "@SED@" -n 's/^(.*)$$/"\1\n"/p' > src/or/or_sha1.i; \ + elif test "@OPENSSL@" != none; then \ + (cd "$(srcdir)" && "@OPENSSL@" sha1 $(src_or_tor_SOURCES) $(src_or_libtor_a_SOURCES) $(ORHEADERS)) | \ + "@SED@" -n 's/SHA1((.*))= (.*)/"\2 \1\n"/p' > src/or/or_sha1.i; \ + else \ + rm src/or/or_sha1.i; \ + touch src/or/or_sha1.i; \ + fi + +CLEANFILES+= micro-revision.i src/or/micro-revision.i + +FORCE: diff --cc src/or/routerlist.c index 6ed168e,aa1660f..c2220f4 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@@ -20,7 -19,7 +20,8 @@@ #include "directory.h" #include "dirserv.h" #include "dirvote.h" +#include "entrynodes.h" + #include "fp_pair.h" #include "geoip.h" #include "hibernate.h" #include "main.h" @@@ -41,10 -39,25 +42,28 @@@
/****************************************************************************/
+ DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t) + DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t) + DECLARE_TYPED_DIGESTMAP_FNS(eimap_, digest_ei_map_t, extrainfo_t) + DECLARE_TYPED_DIGESTMAP_FNS(dsmap_, digest_ds_map_t, download_status_t) + #define SDMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(sdmap_to_digestmap(map), keyvar, signed_descriptor_t *, \ + valvar) + #define RIMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(rimap_to_digestmap(map), keyvar, routerinfo_t *, valvar) + #define EIMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(eimap_to_digestmap(map), keyvar, extrainfo_t *, valvar) + #define DSMAP_FOREACH(map, keyvar, valvar) \ + DIGESTMAP_FOREACH(dsmap_to_digestmap(map), keyvar, download_status_t *, \ + valvar) + + /* Forward declaration for cert_list_t */ + typedef struct cert_list_t cert_list_t; + /* static function prototypes */ +static int compute_weighted_bandwidths(const smartlist_t *sl, + bandwidth_weight_rule_t rule, + u64_dbl_t **bandwidths_out); static const routerstatus_t *router_pick_directory_server_impl( dirinfo_type_t auth, int flags); static const routerstatus_t *router_pick_trusteddirserver_impl( @@@ -190,17 -272,23 +280,23 @@@ already_have_cert(authority_cert_t *cer }
/** Load a bunch of new key certificates from the string <b>contents</b>. If - * <b>from_store</b> is true, the certificates are from the cache, and we - * don't need to flush them to disk. If <b>flush</b> is true, we need - * to flush any changed certificates to disk now. Return 0 on success, -1 - * if any certs fail to parse. */ + * <b>source</b> is TRUSTED_DIRS_CERTS_SRC_FROM_STORE, the certificates are + * from the cache, and we don't need to flush them to disk. If we are a + * dirauth loading our own cert, source is TRUSTED_DIRS_CERTS_SRC_SELF. + * Otherwise, source is download type: TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST + * or TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST. If <b>flush</b> is true, we + * need to flush any changed certificates to disk now. Return 0 on success, + * -1 if any certs fail to parse. + */ + int - trusted_dirs_load_certs_from_string(const char *contents, int from_store, + trusted_dirs_load_certs_from_string(const char *contents, int source, int flush) { - trusted_dir_server_t *ds; + dir_server_t *ds; const char *s, *eos; int failure_code = 0; + int from_store = (source == TRUSTED_DIRS_CERTS_SRC_FROM_STORE);
for (s = contents; *s; s = eos) { authority_cert_t *cert = authority_cert_parse_from_string(s, &eos); @@@ -504,10 -659,62 +666,63 @@@ authority_certs_fetch_missing(networkst if (should_delay_dir_fetches(get_options())) return;
- pending = digestmap_new(); - missing_digests = smartlist_new(); + pending_cert = fp_pair_map_new(); + pending_id = digestmap_new(); + missing_cert_digests = smartlist_new(); + missing_id_digests = smartlist_new(); + + /* + * First, we get the lists of already pending downloads so we don't + * duplicate effort. + */ + list_pending_downloads(pending_id, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); + list_pending_fpsk_downloads(pending_cert);
- list_pending_downloads(pending, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); + /* + * Now, we download any trusted authority certs we don't have by + * identity digest only. This gets the latest cert for that authority. + */ - SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) { ++ SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ds) { + int found = 0; + if (!(ds->type & V3_DIRINFO)) + continue; - if (smartlist_digest_isin(missing_id_digests, ds->v3_identity_digest)) ++ if (smartlist_contains_digest(missing_id_digests, ++ ds->v3_identity_digest)) + continue; + cl = get_cert_list(ds->v3_identity_digest); + SMARTLIST_FOREACH_BEGIN(cl->certs, authority_cert_t *, cert) { + if (now < cert->expires) { + /* It's not expired, and we weren't looking for something to + * verify a consensus with. Call it done. */ + download_status_reset(&(cl->dl_status_by_id)); + /* No sense trying to download it specifically by signing key hash */ + download_status_reset_by_sk_in_cl(cl, cert->signing_key_digest); + found = 1; + break; + } + } SMARTLIST_FOREACH_END(cert); + if (!found && + download_status_is_ready(&(cl->dl_status_by_id), now, + MAX_CERT_DL_FAILURES) && + !digestmap_get(pending_id, ds->v3_identity_digest)) { + log_info(LD_DIR, + "No current certificate known for authority %s " + "(ID digest %s); launching request.", + ds->nickname, hex_str(ds->v3_identity_digest, DIGEST_LEN)); + smartlist_add(missing_id_digests, ds->v3_identity_digest); + } + } SMARTLIST_FOREACH_END(ds); + + /* + * Next, if we have a consensus, scan through it and look for anything + * signed with a key from a cert we don't have. Those get downloaded + * by (fp,sk) pair, but if we don't know any certs at all for the fp + * (identity digest), and it's one of the trusted dir server certs + * we started off above or a pending download in pending_id, don't + * try to get it yet. Most likely, the one we'll get for that will + * have the right signing key too, and we'd just be downloading + * redundantly. + */ if (status) { SMARTLIST_FOREACH_BEGIN(status->voters, networkstatus_voter_info_t *, voter) { @@@ -517,7 -724,28 +732,29 @@@ if (!cache && !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest)) continue; /* We are not a cache, and we don't know this authority.*/ + + /* + * If we don't know *any* cert for this authority, and a download by ID + * is pending or we added it to missing_id_digests above, skip this + * one for now to avoid duplicate downloads. + */ cl = get_cert_list(voter->identity_digest); + if (smartlist_len(cl->certs) == 0) { + /* We have no certs at all for this one */ + + /* Do we have a download of one pending? */ + if (digestmap_get(pending_id, voter->identity_digest)) + continue; + + /* + * Are we about to launch a download of one due to the trusted + * dir server check above? + */ - if (smartlist_digest_isin(missing_id_digests, voter->identity_digest)) ++ if (smartlist_contains_digest(missing_id_digests, ++ voter->identity_digest)) + continue; + } + SMARTLIST_FOREACH_BEGIN(voter->sigs, document_signature_t *, sig) { cert = authority_cert_get_by_digests(voter->identity_digest, sig->signing_key_digest); diff --cc src/test/test_containers.c index ca90162,5fee5c9..005e102 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@@ -782,50 -783,88 +783,132 @@@ test_container_order_functions(void ; }
+static void +test_di_map(void *arg) +{ + di_digest256_map_t *map = NULL; + const uint8_t key1[] = "In view of the fact that it was "; + const uint8_t key2[] = "superficially convincing, being "; + const uint8_t key3[] = "properly enciphered in a one-tim"; + const uint8_t key4[] = "e cipher scheduled for use today"; + char *v1 = tor_strdup(", it came close to causing a disaster..."); + char *v2 = tor_strdup("I regret to have to advise you that the mission"); + char *v3 = tor_strdup("was actually initiated..."); + /* -- John Brunner, _The Shockwave Rider_ */ + + (void)arg; + + /* Try searching on an empty map. */ + tt_ptr_op(NULL, ==, dimap_search(map, key1, NULL)); + tt_ptr_op(NULL, ==, dimap_search(map, key2, NULL)); + tt_ptr_op(v3, ==, dimap_search(map, key2, v3)); + dimap_free(map, NULL); + map = NULL; + + /* Add a single entry. */ + dimap_add_entry(&map, key1, v1); + tt_ptr_op(NULL, ==, dimap_search(map, key2, NULL)); + tt_ptr_op(v3, ==, dimap_search(map, key2, v3)); + tt_ptr_op(v1, ==, dimap_search(map, key1, NULL)); + + /* Now try it with three entries in the map. */ + dimap_add_entry(&map, key2, v2); + dimap_add_entry(&map, key3, v3); + tt_ptr_op(v1, ==, dimap_search(map, key1, NULL)); + tt_ptr_op(v2, ==, dimap_search(map, key2, NULL)); + tt_ptr_op(v3, ==, dimap_search(map, key3, NULL)); + tt_ptr_op(NULL, ==, dimap_search(map, key4, NULL)); + tt_ptr_op(v1, ==, dimap_search(map, key4, v1)); + + done: + tor_free(v1); + tor_free(v2); + tor_free(v3); + dimap_free(map, NULL); +} + + /** Run unit tests for fp_pair-to-void* map functions */ + static void + test_container_fp_pair_map(void) + { + fp_pair_map_t *map; + fp_pair_t fp1, fp2, fp3, fp4, fp5, fp6; + void *v; + fp_pair_map_iter_t *iter; + fp_pair_t k; + + map = fp_pair_map_new(); + test_assert(map); + test_eq(fp_pair_map_size(map), 0); + test_assert(fp_pair_map_isempty(map)); + + memset(fp1.first, 0x11, DIGEST_LEN); + memset(fp1.second, 0x12, DIGEST_LEN); + memset(fp2.first, 0x21, DIGEST_LEN); + memset(fp2.second, 0x22, DIGEST_LEN); + memset(fp3.first, 0x31, DIGEST_LEN); + memset(fp3.second, 0x32, DIGEST_LEN); + memset(fp4.first, 0x41, DIGEST_LEN); + memset(fp4.second, 0x42, DIGEST_LEN); + memset(fp5.first, 0x51, DIGEST_LEN); + memset(fp5.second, 0x52, DIGEST_LEN); + memset(fp6.first, 0x61, DIGEST_LEN); + memset(fp6.second, 0x62, DIGEST_LEN); + + v = fp_pair_map_set(map, &fp1, (void*)99); + test_eq(v, NULL); + test_assert(!fp_pair_map_isempty(map)); + v = fp_pair_map_set(map, &fp2, (void*)101); + test_eq(v, NULL); + v = fp_pair_map_set(map, &fp1, (void*)100); + test_eq(v, (void*)99); + test_eq_ptr(fp_pair_map_get(map, &fp1), (void*)100); + test_eq_ptr(fp_pair_map_get(map, &fp2), (void*)101); + test_eq_ptr(fp_pair_map_get(map, &fp3), NULL); + fp_pair_map_assert_ok(map); + + v = fp_pair_map_remove(map, &fp2); + fp_pair_map_assert_ok(map); + test_eq_ptr(v, (void*)101); + test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); + test_eq_ptr(fp_pair_map_remove(map, &fp2), NULL); + + fp_pair_map_set(map, &fp2, (void*)101); + fp_pair_map_set(map, &fp3, (void*)102); + fp_pair_map_set(map, &fp4, (void*)103); + test_eq(fp_pair_map_size(map), 4); + fp_pair_map_assert_ok(map); + fp_pair_map_set(map, &fp5, (void*)104); + fp_pair_map_set(map, &fp6, (void*)105); + fp_pair_map_assert_ok(map); + + /* Test iterator. */ + iter = fp_pair_map_iter_init(map); + while (!fp_pair_map_iter_done(iter)) { + fp_pair_map_iter_get(iter, &k, &v); + test_eq_ptr(v, fp_pair_map_get(map, &k)); + + if (tor_memeq(&fp2, &k, sizeof(fp2))) { + iter = fp_pair_map_iter_next_rmv(map, iter); + } else { + iter = fp_pair_map_iter_next(map, iter); + } + } + + /* Make sure we removed fp2, but not the others. */ + test_eq_ptr(fp_pair_map_get(map, &fp2), NULL); + test_eq_ptr(fp_pair_map_get(map, &fp5), (void*)104); + + fp_pair_map_assert_ok(map); + /* Clean up after ourselves. */ + fp_pair_map_free(map, NULL); + map = NULL; + + done: + if (map) + fp_pair_map_free(map, NULL); + } + #define CONTAINER_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_container_ ## name }
@@@ -840,7 -879,7 +923,8 @@@ struct testcase_t container_tests[] = CONTAINER_LEGACY(strmap), CONTAINER_LEGACY(pqueue), CONTAINER_LEGACY(order_functions), + { "di_map", test_di_map, 0, NULL, NULL }, + CONTAINER_LEGACY(fp_pair_map), END_OF_TESTCASES };
tor-commits@lists.torproject.org