Преглед изворни кода

Added nextHop inter-router API to allow traceroute

Caleb James DeLisle пре 9 година
родитељ
комит
72393903d3

+ 3 - 0
dht/CJDHTConstants.h

@@ -21,6 +21,9 @@
 // Signifying that this message is a query and defining the query type.
 static String* const CJDHTConstants_QUERY = String_CONST_SO("q");
 
+// Get the next hop in a (hypothetical) packet forward operation
+static String* const CJDHTConstants_QUERY_NH = String_CONST_SO("nh");
+
 // Find nodes query. "fn"
 static String* const CJDHTConstants_QUERY_FN = String_CONST_SO("fn");
 

+ 29 - 0
dht/dhtcore/RouterModule.c

@@ -341,6 +341,19 @@ static inline int handleQuery(struct DHTMessage* message,
         nodeList =
             NodeStore_getPeers(targetPath, RouterModule_K, message->allocator, module->nodeStore);
 
+    } else if (String_equals(queryType, CJDHTConstants_QUERY_NH)) {
+        // get the target
+        String* target = Dict_getString(query->asDict, CJDHTConstants_TARGET);
+        if (target == NULL || target->len != Address_SEARCH_TARGET_SIZE) {
+            return 0;
+        }
+        struct Node_Two* nn = NodeStore_getBest(module->nodeStore, target->bytes);
+        nodeList = Allocator_calloc(message->allocator, sizeof(struct NodeList), 1);
+        if (nn) {
+            nodeList->size = 1;
+            nodeList->nodes = Allocator_calloc(message->allocator, sizeof(char*), 1);
+            nodeList->nodes[0] = nn;
+        }
     }
 
     return (nodeList) ? sendNodes(nodeList, message, module, version) : 0;
@@ -603,6 +616,22 @@ struct RouterModule_Promise* RouterModule_pingNode(struct Address* addr,
     return promise;
 }
 
+struct RouterModule_Promise* RouterModule_nextHop(struct Address* whoToAsk,
+                                                  uint8_t target[16],
+                                                  uint32_t timeoutMilliseconds,
+                                                  struct RouterModule* module,
+                                                  struct Allocator* alloc)
+{
+    struct RouterModule_Promise* promise =
+        RouterModule_newMessage(whoToAsk, timeoutMilliseconds, module, alloc);
+    Dict* d = Dict_new(promise->alloc);
+    Dict_putString(d, CJDHTConstants_QUERY, CJDHTConstants_QUERY_NH, promise->alloc);
+    String* targetStr = String_newBinary(target, 16, promise->alloc);
+    Dict_putString(d, CJDHTConstants_TARGET, targetStr, promise->alloc);
+    RouterModule_sendMessage(promise, d);
+    return promise;
+}
+
 struct RouterModule_Promise* RouterModule_findNode(struct Address* whoToAsk,
                                                    uint8_t target[16],
                                                    uint32_t timeoutMilliseconds,

+ 6 - 0
dht/dhtcore/RouterModule.h

@@ -111,6 +111,12 @@ struct Node_Two* RouterModule_nodeForPath(uint64_t path, struct RouterModule* mo
 
 uint32_t RouterModule_globalMeanResponseTime(struct RouterModule* module);
 
+struct RouterModule_Promise* RouterModule_nextHop(struct Address* whoToAsk,
+                                                  uint8_t target[16],
+                                                  uint32_t timeoutMilliseconds,
+                                                  struct RouterModule* module,
+                                                  struct Allocator* alloc);
+
 struct RouterModule_Promise* RouterModule_getPeers(struct Address* addr,
                                                    uint64_t nearbyLabel,
                                                    uint32_t timeoutMilliseconds,

+ 39 - 0
dht/dhtcore/RouterModule_admin.c

@@ -286,6 +286,38 @@ static void findNode(Dict* args, void* vctx, String* txid, struct Allocator* req
     rp->callback = findNodeResponse;
 }
 
+static void nextHop(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
+{
+    struct Context* ctx = Identity_check((struct Context*) vctx);
+    String* nodeToQueryStr = Dict_getString(args, String_CONST("nodeToQuery"));
+    String* targetStr = Dict_getString(args, String_CONST("target"));
+    int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout"));
+    uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0;
+
+    char* err = NULL;
+    struct Address* nodeToQuery = getNode(nodeToQueryStr, ctx, &err, requestAlloc);
+    uint8_t target[16];
+
+    if (!err && AddrTools_parseIp(target, targetStr->bytes)) { err = "parse_target"; }
+
+    if (err) {
+        Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL);
+        Admin_sendMessage(&errDict, txid, ctx->admin);
+        return;
+    }
+
+    struct RouterModule_Promise* rp =
+        RouterModule_nextHop(nodeToQuery, target, timeout, ctx->module, ctx->allocator);
+
+    struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1);
+    Identity_set(ping);
+    ping->txid = String_clone(txid, rp->alloc);
+    ping->rp = rp;
+    ping->ctx = ctx;
+    rp->userData = ping;
+    rp->callback = findNodeResponse;
+}
+
 void RouterModule_admin_register(struct RouterModule* module,
                                  struct Router* router,
                                  struct Admin* admin,
@@ -301,6 +333,13 @@ void RouterModule_admin_register(struct RouterModule* module,
     }));
     Identity_set(ctx);
 
+    Admin_registerFunction("RouterModule_nextHop", nextHop, ctx, true,
+        ((struct Admin_FunctionArg[]) {
+            { .name = "nodeToQuery", .required = 1, .type = "String" },
+            { .name = "target", .required = 1, .type = "String" },
+            { .name = "timeout", .required = 0, .type = "Int" }
+        }), admin);
+
     Admin_registerFunction("RouterModule_lookup", lookup, ctx, true,
         ((struct Admin_FunctionArg[]) {
             { .name = "address", .required = 1, .type = "String" }

+ 11 - 1
util/version/Version.h

@@ -253,15 +253,25 @@ Version_COMPAT(10, ([7,8,9]))
  */
 Version_COMPAT(11, ([7,8,9,10]))
 
+/*
+ * Version 12:
+ * November 21, 2014
+ *
+ * New inter-router API "nh" which has same semantics as "fn" but gets the next hop in
+ * a hypothetical packet forwarding operation.
+ */
+Version_COMPAT(12, ([7,8,9,10,11]))
+
 /**
  * The current protocol version.
  */
-#define Version_CURRENT_PROTOCOL 11
+#define Version_CURRENT_PROTOCOL 12
 #define Version_7_COMPAT
 #define Version_8_COMPAT
 #define Version_9_COMPAT
 #define Version_10_COMPAT
 #define Version_11_COMPAT
+#define Version_12_COMPAT
 
 #define Version_MINIMUM_COMPATIBLE 7
 #define Version_DEFAULT_ASSUMPTION 7