5
0
mirror of https://github.com/cwinfo/yggdrasil-map synced 2024-11-09 16:00:27 +00:00
yggdrasil-map/scripts/sendGraph.py

221 lines
4.8 KiB
Python
Raw Normal View History

2014-05-28 16:48:46 +00:00
#!/usr/bin/env python2
###############################################################################
# CONFIG
# URL where data is sent
2015-07-26 17:08:35 +00:00
# fc00.atomshare.net for clearnet access
# h.fc00.atomshare.net for hyperboria
# [fc53:dcc5:e89d:9082:4097:6622:5e82:c654] for DNS-less access
url = 'http://fc00.atomshare.net/sendGraph'
2014-05-28 16:48:46 +00:00
# Cjdns path without trailing slash
2015-07-26 17:08:35 +00:00
cjdns_path = '/opt/cjdns'
2014-05-28 16:48:46 +00:00
# ----------------------
# RPC connection details
# ----------------------
# If this is set to True connection details will be loaded from ~/.cjdnsadmin
cjdns_use_default = True
2014-06-02 20:22:37 +00:00
# otherwise these are used.
cjdns_ip = '127.0.0.1'
cjdns_first_port = 11234
cjdns_password = 'hunter2'
cjdns_processes = 1 # This can be used if you are running multiple instances
# of cjdns with consecutive port numbers
2014-05-28 16:48:46 +00:00
###############################################################################
import sys
import urllib
import urllib2
from collections import deque
2014-06-02 20:22:37 +00:00
import traceback
2014-05-28 16:48:46 +00:00
import json
sys.path.append(cjdns_path + '/contrib/python/cjdnsadmin/')
import cjdnsadmin
2014-06-02 20:22:37 +00:00
import adminTools
2015-07-26 17:08:35 +00:00
from publicToIp6 import PublicToIp6_convert
2014-05-28 16:48:46 +00:00
def main():
2014-06-02 20:22:37 +00:00
all_nodes = dict()
all_edges = []
2014-06-02 20:22:37 +00:00
for process in range(0, 1 if cjdns_use_default else cjdns_processes):
2014-06-04 18:41:33 +00:00
print 'Connecting port %d...' % (cjdns_first_port + process),; sys.stdout.flush()
2014-06-02 20:22:37 +00:00
try:
cjdns = cjdns_connect(process)
print adminTools.whoami(cjdns)['IP']
nodes, edges = generate_graph(cjdns)
# Merge results
all_nodes.update(nodes)
for e in edges:
if not e in all_edges:
all_edges.append(e)
except Exception, err:
2014-06-04 18:41:33 +00:00
print 'Failed!'
2014-06-02 20:22:37 +00:00
print traceback.format_exc()
success = send_graph(all_nodes, all_edges)
2014-05-28 16:48:46 +00:00
sys.exit(0 if success else 1)
2014-06-02 20:22:37 +00:00
def generate_graph(cjdns):
2014-05-28 16:48:46 +00:00
source_nodes = cjdns_get_node_store(cjdns)
2014-06-04 18:41:33 +00:00
print ' Found %d source nodes.' % len(source_nodes)
2014-05-28 16:48:46 +00:00
nodes, edges = cjdns_graph_from_nodes(cjdns, source_nodes)
2015-07-26 17:08:35 +00:00
print ' Found %d nodes and %d links.' % (len(nodes), len(edges))
2014-05-28 16:48:46 +00:00
2014-06-02 20:22:37 +00:00
return (nodes, edges)
def send_graph(nodes, edges):
2014-05-28 16:48:46 +00:00
graph_data = {
'nodes': [],
'edges': []
}
for n in nodes.values():
graph_data['nodes'].append({
'ip': n.ip,
'version': n.version
})
2015-07-26 17:08:35 +00:00
2014-05-28 16:48:46 +00:00
for e in edges:
graph_data['edges'].append({
'a': e.a.ip,
'b': e.b.ip
})
json_str = json.dumps(graph_data)
2014-06-04 18:41:33 +00:00
print 'Sending data...',; sys.stdout.flush()
answer = send_data(json_str)
success = answer == 'OK'
print ('Done!' if success else answer)
return success
2014-05-28 16:48:46 +00:00
class Node:
def __init__(self, ip, version=None):
2014-05-28 16:48:46 +00:00
self.ip = ip
self.version = version
2014-06-02 20:22:37 +00:00
def __lt__(self, b):
return self.ip < b.ip
2014-05-28 16:48:46 +00:00
class Edge:
def __init__(self, a, b):
self.a, self.b = sorted([a, b])
2014-06-02 20:22:37 +00:00
def __eq__(self, that):
return self.a.ip == that.a.ip and self.b.ip == that.b.ip
2014-05-28 16:48:46 +00:00
2014-06-02 20:22:37 +00:00
def cjdns_connect(process=0):
2014-05-28 16:48:46 +00:00
if cjdns_use_default:
return cjdnsadmin.connectWithAdminInfo()
else:
2014-06-02 20:22:37 +00:00
return cjdnsadmin.connect(cjdns_ip, cjdns_first_port + process, cjdns_password)
2014-05-28 16:48:46 +00:00
def cjdns_get_node_store(cjdns):
nodes = dict()
i = 0
while True:
res = cjdns.NodeStore_dumpTable(i)
if not 'routingTable' in res:
break
for n in res['routingTable']:
if not 'ip' in n:
continue
ip = n['ip']
version = None
if 'version' in n:
version = n['version']
nodes[ip] = Node(ip, version)
if not 'more' in res or res['more'] != 1:
break
i += 1
return nodes
def cjdns_graph_from_nodes(cjdns, source_nodes):
nodes_to_check = deque(source_nodes.values())
nodes = source_nodes.copy()
edges = []
while len(nodes_to_check) > 0:
node = nodes_to_check.pop()
nodes[node.ip] = node
resp = cjdns.NodeStore_nodeForAddr(node.ip)
if not 'result' in resp:
continue
res = resp['result']
if 'protocolVersion' in res:
node.version = res['protocolVersion']
if 'linkCount' in res:
for i in range(0, int(res['linkCount'])):
2015-07-26 17:08:35 +00:00
resp = cjdns.NodeStore_getLink(parent=node.ip, linkNum=i)
2014-05-28 16:48:46 +00:00
if not 'result' in resp:
continue
res = resp['result']
if not 'child' in res or not 'isOneHop' in res or res['isOneHop'] != 1:
continue
# Add node
2015-07-26 17:08:35 +00:00
child_id = res['child']
child_key = '.'.join(child_id.rsplit('.', 2)[1:])
child_ip = PublicToIp6_convert(child_key)
2014-05-28 16:48:46 +00:00
if not child_ip in nodes:
n = Node(child_ip)
nodes[child_ip] = n
nodes_to_check.append(n)
# Add edge
e = Edge(nodes[node.ip], nodes[child_ip])
2015-07-26 17:08:35 +00:00
print node.ip, child_ip
2014-06-02 20:22:37 +00:00
if not e in edges:
2014-05-28 16:48:46 +00:00
edges.append(e)
return (nodes, edges)
def send_data(graph_data):
post_data = urllib.urlencode({'data': graph_data})
req = urllib2.Request(url, post_data)
response = urllib2.urlopen(req)
2014-06-04 18:41:33 +00:00
return response.read()
2014-05-28 16:48:46 +00:00
2014-06-04 18:41:33 +00:00
if __name__ == '__main__':
2014-05-28 16:48:46 +00:00
main()