/** Note that we've seen a client connect from the IP <b>addr</b> (host order) * at time <b>now</b>. Ignored by all but bridges. */ void geoip_note_client_seen(geoip_client_action_t action, uint32_t addr, time_t now) { or_options_t *options = get_options(); clientmap_entry_t lookup, *ent; if (action == GEOIP_CLIENT_CONNECT) { if (!(options->BridgeRelay && options->BridgeRecordUsageByCountry)) return; /* Did we recently switch from bridge to relay or back? */ if (client_history_starts > now) return; } else { #ifndef ENABLE_GEOIP_STATS return; #else if (options->BridgeRelay || options->BridgeAuthoritativeDir || !options->DirRecordUsageByCountry) return; #endif } /* Rotate the current request period. */ while (current_request_period_starts + REQUEST_HIST_PERIOD < now) { if (!geoip_countries) geoip_countries = smartlist_create(); if (!current_request_period_starts) { current_request_period_starts = now; break; } SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1], sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; }); current_request_period_starts += REQUEST_HIST_PERIOD; if (n_old_request_periods < REQUEST_HIST_LEN-1) ++n_old_request_periods; }
/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing * it from lists as appropriate. */ void circuit_set_state(circuit_t *circ, uint8_t state) { tor_assert(circ); if (state == circ->state) return; if (!circuits_pending_or_conns) circuits_pending_or_conns = smartlist_create(); if (circ->state == CIRCUIT_STATE_OR_WAIT) { /* remove from waiting-circuit list. */ smartlist_remove(circuits_pending_or_conns, circ); } if (state == CIRCUIT_STATE_OR_WAIT) { /* add to waiting-circuit list. */ smartlist_add(circuits_pending_or_conns, circ); } if (state == CIRCUIT_STATE_OPEN) tor_assert(!circ->n_conn_onionskin); circ->state = state; }
/** Launch all client listeners that tor wants us to launch. */ static int launch_client_listeners(const managed_proxy_t *proxy) { int ret=-1; config_t *cfg = NULL; /* list of transports */ smartlist_t *transports = smartlist_create(); smartlist_split_string(transports, proxy->vars.transports, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); SMARTLIST_FOREACH_BEGIN(transports, char *, transport) { /* clients should find their own listen port */ cfg = config_create_managed(proxy->is_server, transport, "127.0.0.1:0", proxy->vars.or_port); if (cfg) /* if config was created; put it in the config smartlist */ smartlist_add(proxy->configs, cfg); else print_method_error_line(transport, proxy, ST_LAUNCH_FAIL_SETUP); } SMARTLIST_FOREACH_END(transport);
/** Run unit tests for digest set code (implemented as a hashtable or as a * bloom filter) */ static void test_container_digestset(void *unused) { smartlist_t *included = smartlist_create(); char d[SHA256_LENGTH]; int i; int ok = 1; int false_positives = 0; digestset_t *set = NULL; for (i = 0; i < 1000; ++i) { random_bytes((uchar *)d, SHA256_LENGTH); smartlist_add(included, xmemdup(d, SHA256_LENGTH)); } set = digestset_new(1000); SMARTLIST_FOREACH(included, const char *, cp, if (digestset_isin(set, cp)) ok = 0); tt_assert(ok); SMARTLIST_FOREACH(included, const char *, cp, digestset_add(set, cp)); SMARTLIST_FOREACH(included, const char *, cp, if (!digestset_isin(set, cp)) ok = 0); tt_assert(ok); for (i = 0; i < 1000; ++i) { random_bytes((uchar *)d, SHA256_LENGTH); if (digestset_isin(set, d)) ++false_positives; } tt_assert(false_positives < 50); /* Should be far lower. */ end: if (set) digestset_free(set); SMARTLIST_FOREACH(included, char *, cp, free(cp)); smartlist_free(included); }
/** Run unit tests for basic dynamic-sized array functionality. */ static void test_container_smartlist_basic(void *unused) { smartlist_t *sl; /* XXXX test sort_digests, uniq_strings, uniq_digests */ /* Test smartlist add, del_keeporder, insert, get. */ sl = smartlist_create(); smartlist_add(sl, (void*)1); smartlist_add(sl, (void*)2); smartlist_add(sl, (void*)3); smartlist_add(sl, (void*)4); smartlist_del_keeporder(sl, 1); smartlist_insert(sl, 1, (void*)22); smartlist_insert(sl, 0, (void*)0); smartlist_insert(sl, 5, (void*)555); tt_ptr_op(smartlist_get(sl,0), ==, (void*)0); tt_ptr_op(smartlist_get(sl,1), ==, (void*)1); tt_ptr_op(smartlist_get(sl,2), ==, (void*)22); tt_ptr_op(smartlist_get(sl,3), ==, (void*)3); tt_ptr_op(smartlist_get(sl,4), ==, (void*)4); tt_ptr_op(smartlist_get(sl,5), ==, (void*)555); /* Try deleting in the middle. */ smartlist_del(sl, 1); tt_ptr_op(smartlist_get(sl, 1), ==, (void*)555); /* Try deleting at the end. */ smartlist_del(sl, 4); tt_int_op(smartlist_len(sl), ==, 4); /* test isin. */ tt_assert(smartlist_isin(sl, (void*)3)); tt_assert(!smartlist_isin(sl, (void*)99)); end: smartlist_free(sl); }
/** Replace all "private" entries in *<b>policy</b> with their expanded * equivalents. */ void policy_expand_private(smartlist_t **policy) { static const char *private_nets[] = { "0.0.0.0/8", "169.254.0.0/16", "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", NULL }; uint16_t port_min, port_max; int i; smartlist_t *tmp; if (!*policy) return; tmp = smartlist_create(); SMARTLIST_FOREACH(*policy, addr_policy_t *, p, { if (! p->is_private) { smartlist_add(tmp, p); continue; } for (i = 0; private_nets[i]; ++i) { addr_policy_t policy; memcpy(&policy, p, sizeof(addr_policy_t)); policy.is_private = 0; policy.is_canonical = 0; if (parse_addr_and_port_range(private_nets[i], &policy.addr, &policy.maskbits, &port_min, &port_max)) { tor_assert(0); } smartlist_add(tmp, addr_policy_get_canonical_entry(&policy)); } addr_policy_free(p); });
/** Configure accounting start/end time settings based on * options->AccountingStart. Return 0 on success, -1 on failure. If * <b>validate_only</b> is true, do not change the current settings. */ int accounting_parse_options(or_options_t *options, int validate_only) { time_unit_t unit; int ok, idx; long d,h,m; smartlist_t *items; const char *v = options->AccountingStart; const char *s; char *cp; if (!v) { if (!validate_only) { cfg_unit = UNIT_MONTH; cfg_start_day = 1; cfg_start_hour = 0; cfg_start_min = 0; } return 0; } items = smartlist_create(); smartlist_split_string(items, v, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0); if (smartlist_len(items)<2) { log_warn(LD_CONFIG, "Too few arguments to AccountingStart"); goto err; } s = smartlist_get(items,0); if (0==strcasecmp(s, "month")) { unit = UNIT_MONTH; } else if (0==strcasecmp(s, "week")) { unit = UNIT_WEEK; } else if (0==strcasecmp(s, "day")) { unit = UNIT_DAY; } else { log_warn(LD_CONFIG, "Unrecognized accounting unit '%s': only 'month', 'week'," " and 'day' are supported.", s); goto err; } switch (unit) { case UNIT_WEEK: d = tor_parse_long(smartlist_get(items,1), 10, 1, 7, &ok, NULL); if (!ok) { log_warn(LD_CONFIG, "Weekly accounting must begin on a day between " "1 (Monday) and 7 (Sunday)"); goto err; } break; case UNIT_MONTH: d = tor_parse_long(smartlist_get(items,1), 10, 1, 28, &ok, NULL); if (!ok) { log_warn(LD_CONFIG, "Monthly accounting must begin on a day between " "1 and 28"); goto err; } break; case UNIT_DAY: d = 0; break; /* Coverity dislikes unreachable default cases; some compilers warn on * switch statements missing a case. Tell Coverity not to worry. */ /* coverity[dead_error_begin] */ default: tor_assert(0); } idx = unit==UNIT_DAY?1:2; if (smartlist_len(items) != (idx+1)) { log_warn(LD_CONFIG,"Accounting unit '%s' requires %d argument%s.", s, idx, (idx>1)?"s":""); goto err; } s = smartlist_get(items, idx); h = tor_parse_long(s, 10, 0, 23, &ok, &cp); if (!ok) { log_warn(LD_CONFIG,"Accounting start time not parseable: bad hour."); goto err; } if (!cp || *cp!=':') { log_warn(LD_CONFIG, "Accounting start time not parseable: not in HH:MM format"); goto err; } m = tor_parse_long(cp+1, 10, 0, 59, &ok, &cp); if (!ok) { log_warn(LD_CONFIG, "Accounting start time not parseable: bad minute"); goto err; } if (!cp || *cp!='\0') { log_warn(LD_CONFIG, "Accounting start time not parseable: not in HH:MM format"); goto err; } if (!validate_only) { cfg_unit = unit; cfg_start_day = (int)d; cfg_start_hour = (int)h; cfg_start_min = (int)m; } SMARTLIST_FOREACH(items, char *, item, tor_free(item)); smartlist_free(items); return 0; err: SMARTLIST_FOREACH(items, char *, item, tor_free(item)); smartlist_free(items); return -1; }
SendDlgItemMessage(hDlg,15500,TBM_SETPOS,1,tmpOptions->CircuitPathLength); show_bans(); show_favorites(); SendDlgItemMessage(hDlg,15503,TBM_SETRANGE,1,MAKELONG(0,100)); SendDlgItemMessage(hDlg,15503,TBM_SETPOS,1,tmpOptions->FavoriteExitNodesPriority); } else if(uMsg==WM_COMMAND) { if((LOWORD(wParam)>=15400)&&(LOWORD(wParam)<=15404)) { tmpOptions->_AllowInvalid=0; char *tmp1=tor_malloc(32768),*tmp2; if(tmpOptions->AllowInvalidNodes) { SMARTLIST_FOREACH(tmpOptions->AllowInvalidNodes, char *, cp, tor_free(cp)); smartlist_clear(tmpOptions->AllowInvalidNodes); } else tmpOptions->AllowInvalidNodes=smartlist_create(); tmp2=tmp1; if(IsDlgButtonChecked(hDlg,15400)==BST_CHECKED){ *tmp2++='e';*tmp2++='n';*tmp2++='t';*tmp2++='r';*tmp2++='y';} if(IsDlgButtonChecked(hDlg,15401)==BST_CHECKED){ if(tmp1!=tmp2) *tmp2++=',';*tmp2++='e';*tmp2++='x';*tmp2++='i';*tmp2++='t';} if(IsDlgButtonChecked(hDlg,15402)==BST_CHECKED){ if(tmp1!=tmp2) *tmp2++=',';*tmp2++='m';*tmp2++='i';*tmp2++='d';*tmp2++='d';*tmp2++='l';*tmp2++='e';} if(IsDlgButtonChecked(hDlg,15404)==BST_CHECKED){ if(tmp1!=tmp2) *tmp2++=',';*tmp2++='i';*tmp2++='n';*tmp2++='t';*tmp2++='r';*tmp2++='o';*tmp2++='d';*tmp2++='u';*tmp2++='c';*tmp2++='t';*tmp2++='i';*tmp2++='o';*tmp2++='n';} if(IsDlgButtonChecked(hDlg,15403)==BST_CHECKED){ if(tmp1!=tmp2) *tmp2++=',';*tmp2++='r';*tmp2++='e';*tmp2++='n';*tmp2++='d';*tmp2++='e';*tmp2++='z';*tmp2++='v';*tmp2++='o';*tmp2++='u';*tmp2++='s';} smartlist_split_string(tmpOptions->AllowInvalidNodes, tmp1, ",",SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tor_free(tmp1); } else if(LOWORD(wParam)==15405) { if(IsDlgButtonChecked(hDlg,15405)==BST_CHECKED) { if(IsDlgButtonChecked(hDlg,15501)==BST_CHECKED) tmpOptions->EnforceDistinctSubnets=1; else if(IsDlgButtonChecked(hDlg,15502)==BST_CHECKED) tmpOptions->EnforceDistinctSubnets=2; else { tmpOptions->EnforceDistinctSubnets=1;
/** Run unit tests for smartlist-of-strings functionality. */ static void test_container_smartlist_strings(void *unused) { smartlist_t *sl = smartlist_create(); char *cp=NULL, *cp_alloc=NULL; size_t sz; /* Test split and join */ tt_int_op(smartlist_len(sl), ==, 0); smartlist_split_string(sl, "abc", ":", 0, 0); tt_int_op(smartlist_len(sl), ==, 1); tt_str_op(smartlist_get(sl, 0), ==, "abc"); smartlist_split_string(sl, "a::bc::", "::", 0, 0); tt_int_op(smartlist_len(sl), ==, 4); tt_str_op(smartlist_get(sl, 1), ==, "a"); tt_str_op(smartlist_get(sl, 2), ==, "bc"); tt_str_op(smartlist_get(sl, 3), ==, ""); cp_alloc = smartlist_join_strings(sl, "", 0, NULL); tt_str_op(cp_alloc, ==, "abcabc"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); tt_str_op(cp_alloc, ==, "abc!a!bc!"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); tt_str_op(cp_alloc, ==, "abcXYaXYbcXY"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); tt_str_op(cp_alloc, ==, "abcXYaXYbcXYXY"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "", 1, NULL); tt_str_op(cp_alloc, ==, "abcabc"); free(cp_alloc); smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); tt_int_op(smartlist_len(sl), ==, 8); tt_str_op(smartlist_get(sl, 4), ==, ""); tt_str_op(smartlist_get(sl, 5), ==, "def"); tt_str_op(smartlist_get(sl, 6), ==, " "); tt_str_op(smartlist_get(sl, 7), ==, "ghijk"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); tt_int_op(smartlist_len(sl), ==, 3); tt_str_op(smartlist_get(sl,0), ==, "a"); tt_str_op(smartlist_get(sl,1), ==, "bbd"); tt_str_op(smartlist_get(sl,2), ==, "cdef"); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE, 0); tt_int_op(smartlist_len(sl), ==, 8); tt_str_op(smartlist_get(sl,3), ==, "z"); tt_str_op(smartlist_get(sl,4), ==, "zhasd"); tt_str_op(smartlist_get(sl,5), ==, ""); tt_str_op(smartlist_get(sl,6), ==, "bnud"); tt_str_op(smartlist_get(sl,7), ==, ""); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, " ab\tc \td ef ", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 4); tt_str_op(smartlist_get(sl,0), ==, "ab"); tt_str_op(smartlist_get(sl,1), ==, "c"); tt_str_op(smartlist_get(sl,2), ==, "d"); tt_str_op(smartlist_get(sl,3), ==, "ef"); smartlist_split_string(sl, "ghi\tj", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 6); tt_str_op(smartlist_get(sl,4), ==, "ghi"); tt_str_op(smartlist_get(sl,5), ==, "j"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); tt_str_op(cp_alloc, ==, ""); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); tt_str_op(cp_alloc, ==, "XY"); free(cp_alloc); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 3); tt_str_op(smartlist_get(sl, 0), ==, "z"); tt_str_op(smartlist_get(sl, 1), ==, "zhasd"); tt_str_op(smartlist_get(sl, 2), ==, "bnud"); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); tt_int_op(smartlist_len(sl), ==, 5); tt_str_op(smartlist_get(sl, 3), ==, "z"); tt_str_op(smartlist_get(sl, 4), ==, "zhasd <> <> bnud<>"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "abcd\n", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 1); tt_str_op(smartlist_get(sl, 0), ==, "abcd"); smartlist_split_string(sl, "efgh", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 2); tt_str_op(smartlist_get(sl, 1), ==, "efgh"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); /* Test swapping, shuffling, and sorting. */ smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); tt_int_op(smartlist_len(sl), ==, 7); smartlist_sort(sl, _compare_strs); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "and,arma,by,nickm,onion,router,the"); free(cp_alloc); smartlist_swap(sl, 1, 5); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "and,router,by,nickm,onion,arma,the"); free(cp_alloc); smartlist_shuffle(sl); tt_int_op(smartlist_len(sl), ==, 7); tt_assert(smartlist_string_isin(sl, "and")); tt_assert(smartlist_string_isin(sl, "router")); tt_assert(smartlist_string_isin(sl, "by")); tt_assert(smartlist_string_isin(sl, "nickm")); tt_assert(smartlist_string_isin(sl, "onion")); tt_assert(smartlist_string_isin(sl, "arma")); tt_assert(smartlist_string_isin(sl, "the")); /* Test bsearch. */ smartlist_sort(sl, _compare_strs); tt_str_op(smartlist_bsearch(sl, "zNicKM", _compare_without_first_ch), ==, "nickm"); tt_str_op(smartlist_bsearch(sl, " AND", _compare_without_first_ch), ==, "and"); tt_ptr_op(smartlist_bsearch(sl, " ANz", _compare_without_first_ch), ==, NULL); /* Test bsearch_idx */ { int f; tt_int_op(smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f), ==, 0); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f), ==, 0); tt_int_op(f, ==, 1); tt_int_op(smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f), ==, 1); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f), ==, 1); tt_int_op(f, ==, 1); tt_int_op(smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f), ==, 2); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f), ==, 7); tt_int_op(f, ==, 0); } /* Test reverse() and pop_last() */ smartlist_reverse(sl); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "the,router,onion,nickm,by,arma,and"); free(cp_alloc); cp_alloc = smartlist_pop_last(sl); tt_str_op(cp_alloc, ==, "and"); free(cp_alloc); tt_int_op(smartlist_len(sl), ==, 6); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); cp_alloc = smartlist_pop_last(sl); tt_ptr_op(cp_alloc, ==, NULL); /* Test uniq() */ smartlist_split_string(sl, "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", ",", 0, 0); smartlist_sort(sl, _compare_strs); smartlist_uniq(sl, _compare_strs, free); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "50,a,canal,man,noon,panama,plan,radar"); free(cp_alloc); /* Test string_isin and isin_case and num_isin */ tt_assert(smartlist_string_isin(sl, "noon")); tt_assert(!smartlist_string_isin(sl, "noonoon")); tt_assert(smartlist_string_isin_case(sl, "nOOn")); tt_assert(!smartlist_string_isin_case(sl, "nooNooN")); tt_assert(smartlist_string_num_isin(sl, 50)); tt_assert(!smartlist_string_num_isin(sl, 60)); /* Test smartlist_choose */ { int i; int allsame = 1; int allin = 1; void *first = smartlist_choose(sl); tt_assert(smartlist_isin(sl, first)); for (i = 0; i < 100; ++i) { void *second = smartlist_choose(sl); if (second != first) allsame = 0; if (!smartlist_isin(sl, second)) allin = 0; } tt_assert(!allsame); tt_assert(allin); } SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); /* Test string_remove and remove and join_strings2 */ smartlist_split_string(sl, "Some say the Earth will end in ice and some in fire", " ", 0, 0); cp = smartlist_get(sl, 4); tt_str_op(cp, ==, "will"); smartlist_add(sl, cp); smartlist_remove(sl, cp); free(cp); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); free(cp_alloc); smartlist_string_remove(sl, "in"); cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); tt_str_op(cp_alloc, ==, "Some+say+the+Earth+fire+end+some+ice+and"); tt_int_op((int)sz, ==, 40); end: SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_free(sl); free(cp_alloc); }
/** Run unit tests for string-to-void* map functions */ static void test_container_strmap(void *unused) { strmap_t *map; strmap_iter_t *iter; const char *k; void *v; char *visited = NULL; smartlist_t *found_keys = NULL; map = strmap_new(); tt_assert(map); tt_int_op(strmap_size(map), ==, 0); tt_assert(strmap_isempty(map)); v = strmap_set(map, "K1", (void*)99); tt_ptr_op(v, ==, NULL); tt_assert(!strmap_isempty(map)); v = strmap_set(map, "K2", (void*)101); tt_ptr_op(v, ==, NULL); v = strmap_set(map, "K1", (void*)100); tt_int_op((void*)99, ==, v); tt_ptr_op(strmap_get(map, "K1"), ==, (void*)100); tt_ptr_op(strmap_get(map, "K2"), ==, (void*)101); tt_ptr_op(strmap_get(map, "K-not-there"), ==, NULL); strmap_assert_ok(map); v = strmap_remove(map,"K2"); strmap_assert_ok(map); tt_ptr_op(v, ==, (void*)101); tt_ptr_op(strmap_get(map, "K2"), ==, NULL); tt_ptr_op(strmap_remove(map, "K2"), ==, NULL); strmap_set(map, "K2", (void*)101); strmap_set(map, "K3", (void*)102); strmap_set(map, "K4", (void*)103); tt_int_op(strmap_size(map), ==, 4); strmap_assert_ok(map); strmap_set(map, "K5", (void*)104); strmap_set(map, "K6", (void*)105); strmap_assert_ok(map); /* Test iterator. */ iter = strmap_iter_init(map); found_keys = smartlist_create(); while (!strmap_iter_done(iter)) { strmap_iter_get(iter,&k,&v); smartlist_add(found_keys, xstrdup(k)); tt_ptr_op(v, ==, strmap_get(map, k)); if (!strcmp(k, "K2")) { iter = strmap_iter_next_rmv(map,iter); } else { iter = strmap_iter_next(map,iter); } } /* Make sure we removed K2, but not the others. */ tt_ptr_op(strmap_get(map, "K2"), ==, NULL); tt_ptr_op(strmap_get(map, "K5"), ==, (void*)104); /* Make sure we visited everyone once */ smartlist_sort_strings(found_keys); visited = smartlist_join_strings(found_keys, ":", 0, NULL); tt_str_op(visited, ==, "K1:K2:K3:K4:K5:K6"); strmap_assert_ok(map); /* Clean up after ourselves. */ strmap_free(map, NULL); map = NULL; /* Now try some lc functions. */ map = strmap_new(); strmap_set_lc(map,"Ab.C", (void*)1); tt_ptr_op(strmap_get(map, "ab.c"), ==, (void*)1); strmap_assert_ok(map); tt_ptr_op(strmap_get_lc(map, "AB.C"), ==, (void*)1); tt_ptr_op(strmap_get(map, "AB.C"), ==, NULL); tt_ptr_op(strmap_remove_lc(map, "aB.C"), ==, (void*)1); strmap_assert_ok(map); tt_ptr_op(strmap_get_lc(map, "AB.C"), ==, NULL); end: if (map) strmap_free(map,NULL); if (found_keys) { SMARTLIST_FOREACH(found_keys, char *, cp, free(cp)); smartlist_free(found_keys); } free(visited); }
/** Run unit tests for heap-based priority queue functions. */ static void test_container_pqueue(void *unused) { smartlist_t *sl = smartlist_create(); int (*cmp)(const void *, const void*); const int offset = offsetof(pq_entry_t, idx); #define ENTRY(s) pq_entry_t s = { #s, -1 } ENTRY(cows); ENTRY(zebras); ENTRY(fish); ENTRY(frogs); ENTRY(apples); ENTRY(squid); ENTRY(daschunds); ENTRY(eggplants); ENTRY(weissbier); ENTRY(lobsters); ENTRY(roquefort); ENTRY(chinchillas); ENTRY(fireflies); #define OK() smartlist_pqueue_assert_ok(sl, cmp, offset) cmp = _compare_strings_for_pqueue; smartlist_pqueue_add(sl, cmp, offset, &cows); smartlist_pqueue_add(sl, cmp, offset, &zebras); smartlist_pqueue_add(sl, cmp, offset, &fish); smartlist_pqueue_add(sl, cmp, offset, &frogs); smartlist_pqueue_add(sl, cmp, offset, &apples); smartlist_pqueue_add(sl, cmp, offset, &squid); smartlist_pqueue_add(sl, cmp, offset, &daschunds); smartlist_pqueue_add(sl, cmp, offset, &eggplants); smartlist_pqueue_add(sl, cmp, offset, &weissbier); smartlist_pqueue_add(sl, cmp, offset, &lobsters); smartlist_pqueue_add(sl, cmp, offset, &roquefort); OK(); tt_int_op(smartlist_len(sl), ==, 11); tt_ptr_op(smartlist_get(sl, 0), ==, &apples); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &apples); tt_int_op(smartlist_len(sl), ==, 10); OK(); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &cows); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &daschunds); smartlist_pqueue_add(sl, cmp, offset, &chinchillas); OK(); smartlist_pqueue_add(sl, cmp, offset, &fireflies); OK(); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &chinchillas); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &eggplants); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &fireflies); OK(); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &fish); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &frogs); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &lobsters); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &roquefort); OK(); tt_int_op(smartlist_len(sl), ==, 3); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &squid); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &weissbier); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &zebras); tt_int_op(smartlist_len(sl), ==, 0); OK(); /* Now test remove. */ smartlist_pqueue_add(sl, cmp, offset, &cows); smartlist_pqueue_add(sl, cmp, offset, &fish); smartlist_pqueue_add(sl, cmp, offset, &frogs); smartlist_pqueue_add(sl, cmp, offset, &apples); smartlist_pqueue_add(sl, cmp, offset, &squid); smartlist_pqueue_add(sl, cmp, offset, &zebras); tt_int_op(smartlist_len(sl), ==, 6); OK(); smartlist_pqueue_remove(sl, cmp, offset, &zebras); tt_int_op(smartlist_len(sl), ==, 5); OK(); smartlist_pqueue_remove(sl, cmp, offset, &cows); tt_int_op(smartlist_len(sl), ==, 4); OK(); smartlist_pqueue_remove(sl, cmp, offset, &apples); tt_int_op(smartlist_len(sl), ==, 3); OK(); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &fish); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &frogs); tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset), ==, &squid); tt_int_op(smartlist_len(sl), ==, 0); OK(); #undef OK end: smartlist_free(sl); }
/** Given: * comma-separated list of "<transport>-<bindaddr>" strings in 'all_bindaddrs'. * comma-separated list of "<transport>" strings in 'all_transports'. Return: * 0, if - all <transport> strings in 'all_bindaddrs' match with <transport> strings in 'all_transports' (order matters). AND - if all <bindaddr> strings in 'all_bindaddrs' are valid addrports. * -1, otherwise. */ int validate_bindaddrs(const char *all_bindaddrs, const char *all_transports) { int ret,i,n_bindaddrs,n_transports; struct evutil_addrinfo *bindaddr_test; char *bindaddr = NULL; char *transport = NULL; /* a list of "<proto>-<bindaddr>" strings */ smartlist_t *bindaddrs = smartlist_create(); /* a list holding (<proto>, <bindaddr>) for each 'bindaddrs' entry */ smartlist_t *split_bindaddr = NULL; /* a list of "<proto>" strings */ smartlist_t *transports = smartlist_create(); smartlist_split_string(bindaddrs, all_bindaddrs, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); smartlist_split_string(transports, all_transports, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); n_bindaddrs = smartlist_len(bindaddrs); n_transports = smartlist_len(transports); if (n_bindaddrs != n_transports) goto err; for (i=0;i<n_bindaddrs;i++) { bindaddr = smartlist_get(bindaddrs, i); transport = smartlist_get(transports, i); split_bindaddr = smartlist_create(); smartlist_split_string(split_bindaddr, bindaddr, "-", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); /* (<proto>, <bindaddr>) */ if (smartlist_len(split_bindaddr) != 2) goto err; /* "all <transport> strings in 'all_bindaddrs' match with <transport> strings in 'all_transports' (order matters)." */ if (strcmp(smartlist_get(split_bindaddr,0), transport)) goto err; /* "if all <bindaddr> strings in 'all_bindaddrs' are valid addrports." */ bindaddr_test = resolve_address_port(smartlist_get(split_bindaddr, 1), 1, 1, NULL); if (!bindaddr_test) goto err; evutil_freeaddrinfo(bindaddr_test); SMARTLIST_FOREACH(split_bindaddr, char *, cp, free(cp)); smartlist_free(split_bindaddr); split_bindaddr = NULL; } ret = 0; goto done; err: ret = -1; done: SMARTLIST_FOREACH(bindaddrs, char *, cp, free(cp)); smartlist_free(bindaddrs); SMARTLIST_FOREACH(transports, char *, cp, free(cp)); smartlist_free(transports); if (split_bindaddr) { SMARTLIST_FOREACH(split_bindaddr, char *, cp, free(cp)); smartlist_free(split_bindaddr); } return ret; }
/** Run digestmap_t performance benchmarks. */ static void bench_dmap(void) { smartlist_t *sl = smartlist_create(); smartlist_t *sl2 = smartlist_create(); uint64_t start, end, pt2, pt3, pt4; int iters = 8192; const int elts = 4000; const int fpostests = 100000; char d[20]; int i,n=0, fp = 0; digestmap_t *dm = digestmap_new(); digestset_t *ds = digestset_new(elts); for (i = 0; i < elts; ++i) { crypto_rand(d, 20); smartlist_add(sl, tor_memdup(d, 20)); } for (i = 0; i < elts; ++i) { crypto_rand(d, 20); smartlist_add(sl2, tor_memdup(d, 20)); } printf("nbits=%d\n", ds->mask+1); reset_perftime(); start = perftime(); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); } pt2 = perftime(); printf("digestmap_set: %.2f ns per element\n", NANOCOUNT(start, pt2, iters*elts)); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); } pt3 = perftime(); printf("digestmap_get: %.2f ns per element\n", NANOCOUNT(pt2, pt3, iters*elts*2)); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); } pt4 = perftime(); printf("digestset_add: %.2f ns per element\n", NANOCOUNT(pt3, pt4, iters*elts)); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); } end = perftime(); printf("digestset_isin: %.2f ns per element.\n", NANOCOUNT(pt4, end, iters*elts*2)); /* We need to use this, or else the whole loop gets optimized out. */ printf("Hits == %d\n", n); for (i = 0; i < fpostests; ++i) { crypto_rand(d, 20); if (digestset_isin(ds, d)) ++fp; } printf("False positive rate on digestset: %.2f%%\n", (fp/(double)fpostests)*100); digestmap_free(dm, NULL); digestset_free(ds); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); smartlist_free(sl); smartlist_free(sl2); }