|
@@ -17,8 +17,10 @@
|
|
|
#include "rendmid.h"
|
|
|
#include "rendservice.h"
|
|
|
#include "rephist.h"
|
|
|
+#include "router.h"
|
|
|
#include "routerlist.h"
|
|
|
#include "routerparse.h"
|
|
|
+#include "networkstatus.h"
|
|
|
|
|
|
/** Return 0 if one and two are the same service ids, else -1 or 1 */
|
|
|
int
|
|
@@ -935,3 +937,75 @@ rend_data_client_create(const char *onion_address, const char *desc_id,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+/** Determine the routers that are responsible for <b>id</b> (binary) and
|
|
|
+ * add pointers to those routers' routerstatus_t to <b>responsible_dirs</b>.
|
|
|
+ * Return -1 if we're returning an empty smartlist, else return 0.
|
|
|
+ */
|
|
|
+int
|
|
|
+hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
|
|
|
+ const char *id)
|
|
|
+{
|
|
|
+ int start, found, n_added = 0, i;
|
|
|
+ networkstatus_t *c = networkstatus_get_latest_consensus();
|
|
|
+ if (!c || !smartlist_len(c->routerstatus_list)) {
|
|
|
+ log_warn(LD_REND, "We don't have a consensus, so we can't perform v2 "
|
|
|
+ "rendezvous operations.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ tor_assert(id);
|
|
|
+ start = networkstatus_vote_find_entry_idx(c, id, &found);
|
|
|
+ if (start == smartlist_len(c->routerstatus_list)) start = 0;
|
|
|
+ i = start;
|
|
|
+ do {
|
|
|
+ routerstatus_t *r = smartlist_get(c->routerstatus_list, i);
|
|
|
+ if (r->is_hs_dir) {
|
|
|
+ smartlist_add(responsible_dirs, r);
|
|
|
+ if (++n_added == REND_NUMBER_OF_CONSECUTIVE_REPLICAS)
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (++i == smartlist_len(c->routerstatus_list))
|
|
|
+ i = 0;
|
|
|
+ } while (i != start);
|
|
|
+
|
|
|
+ /* Even though we don't have the desired number of hidden service
|
|
|
+ * directories, be happy if we got any. */
|
|
|
+ return smartlist_len(responsible_dirs) ? 0 : -1;
|
|
|
+}
|
|
|
+
|
|
|
+/** Return true if this node is currently acting as hidden service
|
|
|
+ * directory, false otherwise. */
|
|
|
+int
|
|
|
+hid_serv_acting_as_directory(void)
|
|
|
+{
|
|
|
+ const routerinfo_t *me = router_get_my_routerinfo();
|
|
|
+ if (!me)
|
|
|
+ return 0;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+/** Return true if this node is responsible for storing the descriptor ID
|
|
|
+ * in <b>query</b> and false otherwise. */
|
|
|
+MOCK_IMPL(int, hid_serv_responsible_for_desc_id,
|
|
|
+ (const char *query))
|
|
|
+{
|
|
|
+ const routerinfo_t *me;
|
|
|
+ routerstatus_t *last_rs;
|
|
|
+ const char *my_id, *last_id;
|
|
|
+ int result;
|
|
|
+ smartlist_t *responsible;
|
|
|
+ if (!hid_serv_acting_as_directory())
|
|
|
+ return 0;
|
|
|
+ if (!(me = router_get_my_routerinfo()))
|
|
|
+ return 0; /* This is redundant, but let's be paranoid. */
|
|
|
+ my_id = me->cache_info.identity_digest;
|
|
|
+ responsible = smartlist_new();
|
|
|
+ if (hid_serv_get_responsible_directories(responsible, query) < 0) {
|
|
|
+ smartlist_free(responsible);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ last_rs = smartlist_get(responsible, smartlist_len(responsible)-1);
|
|
|
+ last_id = last_rs->identity_digest;
|
|
|
+ result = rend_id_is_in_interval(my_id, query, last_id);
|
|
|
+ smartlist_free(responsible);
|
|
|
+ return result;
|
|
|
+}
|