diff --git a/README.md b/README.md index fe09a27..1067e46 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Forked from the code for http://www.fc00.org (http://h.fc00.org on Hyperboria). ## Sending your view of the network -This code reads a map of known nodes from `y.yakamo.org:3000/current` (reachable over yggdrasil). In order to display an accurate map of the network, we need your help. If you run a yggdrasil node, plase send your network view using the [send-view.py](https://github.com/yakamok/Niflheim-api/blob/master/send-view.py) script. +This code reads a map of known nodes from `y.yakamo.org:3000/current` (reachable over yggdrasil). You may alternatively generate your own view of the network by running [a crawler script](scripts/crawl-dht.py), but this may take some time (figuring out how to run it and use the results is left as an exercise to the user). ## Web server ```bash diff --git a/scripts/crawl-dht.py b/scripts/crawl-dht.py new file mode 100644 index 0000000..b5e9306 --- /dev/null +++ b/scripts/crawl-dht.py @@ -0,0 +1,75 @@ +import json +import socket +import sys +import time + +#gives the option to get data from an external server instead and send that +#if no options given it will default to localhost instead +if len(sys.argv) == 3: + host_port = (sys.argv[1], int(sys.argv[2])) +else: + host_port = ('localhost', 9001) + +def getDHTPingRequest(key, coords, target=None): + if target: + return '{{"keepalive":true, "request":"dhtPing", "box_pub_key":"{}", "coords":"{}", "target":"{}"}}'.format(key, coords, target) + else: + return '{{"keepalive":true, "request":"dhtPing", "box_pub_key":"{}", "coords":"{}"}}'.format(key, coords) + +def doRequest(req): + try: + ygg = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ygg.connect(host_port) + ygg.send(req) + data = json.loads(ygg.recv(1024*15)) + return data + except: + return None + +visited = dict() # Add nodes after a successful lookup response +rumored = dict() # Add rumors about nodes to ping +timedout = dict() +def handleResponse(address, info, data): + global visited + global rumored + global timedout + timedout[str(address)] = {'box_pub_key':str(info['box_pub_key']), 'coords':str(info['coords'])} + if not data: return + if 'response' not in data: return + if 'nodes' not in data['response']: return + for addr,rumor in data['response']['nodes'].iteritems(): + if addr in visited: continue + rumored[addr] = rumor + if address not in visited: + # TODO? remove this, it's debug output that happens to be in the same format as yakamo's "current" json file + now = time.time() + visited[str(address)] = {'box_pub_key':str(info['box_pub_key']), 'coords':str(info['coords']), 'time':now} + if address in timedout: del timedout[address] + if len(visited) > 1: sys.stdout.write(",\n") + sys.stdout.write('"{}": ["{}", {}]'.format(address, info['coords'], int(now))) + sys.stdout.flush() +# End handleResponse + +# Get self info +selfInfo = doRequest('{"keepalive":true, "request":"getSelf"}') + +# Initialize dicts of visited/rumored nodes +for k,v in selfInfo['response']['self'].iteritems(): rumored[k] = v + +# Loop over rumored nodes and ping them, adding to visited if they respond +print '{"yggnodes": {' +while len(rumored) > 0: + for k,v in rumored.iteritems(): + handleResponse(k, v, doRequest(getDHTPingRequest(v['box_pub_key'], v['coords']))) + # These next two are imperfect workarounds to deal with old kad nodes + handleResponse(k, v, doRequest(getDHTPingRequest(v['box_pub_key'], v['coords'], '0'*128))) + handleResponse(k, v, doRequest(getDHTPingRequest(v['box_pub_key'], v['coords'], 'f'*128))) + break + del rumored[k] +print '\n}}' +#End + +# TODO do something with the results + +#print visited +#print timedout diff --git a/web/graphPlotter.py b/web/graphPlotter.py index 53c882d..078c99b 100644 --- a/web/graphPlotter.py +++ b/web/graphPlotter.py @@ -8,10 +8,10 @@ def position_nodes(nodes, edges): G = pgv.AGraph(strict=True, directed=False, size='10!') for n in nodes.values(): - G.add_node(n.coords, label=n.ip, version=n.version) + G.add_node(n.ip, label=n.label, coords=n.coords) for e in edges: - G.add_edge(e.a.coords, e.b.coords, len=1.0) + G.add_edge(e.a.ip, e.b.ip, len=1.0) G.layout(prog='neato', args='-Gepsilon=0.0001 -Gmaxiter=100000') @@ -66,7 +66,7 @@ def get_graph_json(G): 'id': n.name, 'label': name if name else n.attr['label'], 'name': name, - 'version': n.attr['version'], + 'coords': n.attr['coords'], 'x': float(pos[0]), 'y': float(pos[1]), 'color': _gradient_color(neighbor_ratio, [(100, 100, 100), (0, 0, 0)]), diff --git a/web/static/network.js b/web/static/network.js index 235f430..21568a9 100644 --- a/web/static/network.js +++ b/web/static/network.js @@ -174,7 +174,7 @@ function showNodeInfo(node) { '