5
0
mirror of https://github.com/cwinfo/yggdrasil-map synced 2024-11-22 14:00:27 +00:00

use sendGraph script from Kubuxu

This commit is contained in:
Michał Zieliński 2015-11-21 12:52:48 +01:00
parent e4b9b130db
commit 22052a3840

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
############################################################################### ###############################################################################
# CONFIG # CONFIG
@ -6,12 +6,10 @@
# www.fc00.org for clearnet access # www.fc00.org for clearnet access
# h.fc00.org for hyperboria # h.fc00.org for hyperboria
# [fc53:dcc5:e89d:9082:4097:6622:5e82:c654] for DNS-less access # [fc53:dcc5:e89d:9082:4097:6622:5e82:c654] for DNS-less access
url = 'http://www.fc00.org/sendGraph' url = 'http://h.fc00.org/sendGraph'
# update your email address, so I can contact you in case something goes wrong
your_mail = 'bad_mail@example.com'
# Cjdns path without trailing slash # update your email address, so I can contact you in case something goes wrong
cjdns_path = '/opt/cjdns' your_email = 'your@email.here'
# ---------------------- # ----------------------
# RPC connection details # RPC connection details
@ -22,137 +20,81 @@ cjdns_use_default = True
# otherwise these are used. # otherwise these are used.
cjdns_ip = '127.0.0.1' cjdns_ip = '127.0.0.1'
cjdns_first_port = 11234 cjdns_port = 11234
cjdns_password = 'hunter2' cjdns_password = 'NONE'
cjdns_processes = 1 # This can be used if you are running multiple instances
# of cjdns with consecutive port numbers
############################################################################### ###############################################################################
import sys import sys
if your_mail == 'bad_mail@example.com':
sys.exit('Please edit sendGraph.py to include your email address.')
import urllib
import urllib2
from collections import deque
import traceback import traceback
import json import json
sys.path.append(cjdns_path + '/contrib/python/cjdnsadmin/')
import cjdnsadmin import requests
import adminTools
from publicToIp6 import PublicToIp6_convert import cjdns
from cjdns import key_utils
from cjdns import admin_tools
def main(): def main():
all_nodes = dict() con = connect()
all_edges = []
for process in range(0, 1 if cjdns_use_default else cjdns_processes): nodes = dump_node_store(con)
print 'Connecting port %d...' % (cjdns_first_port + process),; sys.stdout.flush() edges = {}
for k in nodes:
node = nodes[k]
node_ip = node['ip']
print(node)
peers = get_peers(con, node['path'])
get_edges_for_peers(edges, peers, node_ip)
send_graph(nodes, edges)
sys.exit(0)
def connect():
try: 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:
print 'Failed!'
print traceback.format_exc()
success = send_graph(all_nodes, all_edges)
sys.exit(0 if success else 1)
def generate_graph(cjdns):
source_nodes = cjdns_get_node_store(cjdns)
print ' Found %d source nodes.' % len(source_nodes)
nodes, edges = cjdns_graph_from_nodes(cjdns, source_nodes)
print ' Found %d nodes and %d links.' % (len(nodes), len(edges))
return (nodes, edges)
def send_graph(nodes, edges):
graph_data = {
'nodes': [],
'edges': []
}
for n in nodes.values():
graph_data['nodes'].append({
'ip': n.ip,
'version': n.version
})
for e in edges:
graph_data['edges'].append({
'a': e.a.ip,
'b': e.b.ip
})
json_str = json.dumps(graph_data)
print 'Sending data...',; sys.stdout.flush()
answer = send_data(json_str)
success = answer == 'OK'
print ('Done!' if success else answer)
return success
class Node:
def __init__(self, ip, version=None):
self.ip = ip
self.version = version
def __lt__(self, b):
return self.ip < b.ip
class Edge:
def __init__(self, a, b):
self.a, self.b = sorted([a, b])
def __eq__(self, that):
return self.a.ip == that.a.ip and self.b.ip == that.b.ip
def cjdns_connect(process=0):
if cjdns_use_default: if cjdns_use_default:
return cjdnsadmin.connectWithAdminInfo() print('Connecting using default or ~/.cjdnsadmin credentials...')
con = cjdns.connectWithAdminInfo()
else: else:
return cjdnsadmin.connect(cjdns_ip, cjdns_first_port + process, cjdns_password) print('Connecting to port %d...' % (cjdns_port))
con = cjdns.connect(cjdns_ip, cjdns_port, cjdns_password)
def cjdns_get_node_store(cjdns): print(admin_tools.whoami(con)['IP'])
return con
except:
print('Failed!')
print(traceback.format_exc())
sys.exit(1)
def dump_node_store(con):
nodes = dict() nodes = dict()
i = 0 i = 0
while True: while True:
res = cjdns.NodeStore_dumpTable(i) res = con.NodeStore_dumpTable(i)
if not 'routingTable' in res: if not 'routingTable' in res:
break break
for n in res['routingTable']: for n in res['routingTable']:
if not 'ip' in n: if not all(key in n for key in ('addr', 'path', 'ip')):
continue continue
ip = n['ip'] ip = n['ip']
path = n['path']
addr = n['addr']
version = None version = None
if 'version' in n: if 'version' in n:
version = n['version'] version = n['version']
nodes[ip] = Node(ip, version) nodes[ip] = {'ip': ip, 'path': path, 'addr': addr, 'version': version}
if not 'more' in res or res['more'] != 1: if not 'more' in res or res['more'] != 1:
break break
@ -161,59 +103,89 @@ def cjdns_get_node_store(cjdns):
return nodes return nodes
def cjdns_graph_from_nodes(cjdns, source_nodes):
nodes_to_check = deque(source_nodes.values())
nodes = source_nodes.copy() def get_peers(con, path):
edges = [] peers = set()
while len(nodes_to_check) > 0: i = 1
node = nodes_to_check.pop() while i < 5:
nodes[node.ip] = node res = con.RouterModule_getPeers(path)
resp = cjdns.NodeStore_nodeForAddr(node.ip) if ('result' in res and res['result'] == 'timeout') or \
('error' in res and res['error'] != 'none'):
failure = ''
if 'error' in res:
failure = res['error']
if 'result' in res:
if len(failure) != 0:
failure += '/'
failure += res['result']
if not 'result' in resp: print('get_peers: getPeers failed with {:s} on {:s}, trying again. {:d} tries remaining.'
.format(failure, path, 4 - i))
i += 1
continue continue
res = resp['result'] else:
break
if 'protocolVersion' in res: if 'result' not in res or res['result'] != 'peers':
node.version = res['protocolVersion'] print('get_peers: failed too many times, skipping.')
print(res)
return peers
if 'linkCount' in res: for peer in res['peers']:
for i in range(0, int(res['linkCount'])): key = peer.split('.', 5)[-1]
resp = cjdns.NodeStore_getLink(parent=node.ip, linkNum=i) peers |= {key}
if not 'result' in resp:
continue
res = resp['result'] return peers
if not 'child' in res or not 'isOneHop' in res or res['isOneHop'] != 1:
continue
# Add node
child_id = res['child']
child_key = '.'.join(child_id.rsplit('.', 2)[1:])
child_ip = PublicToIp6_convert(child_key)
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])
if not e in edges:
edges.append(e)
return (nodes, edges)
def get_edges_for_peers(edges, peers, node_ip):
for peer_key in peers:
peer_ip = key_utils.to_ipv6(peer_key)
def send_data(graph_data): if node_ip > peer_ip:
post_data = urllib.urlencode({'data': graph_data, 'mail': your_mail}) A = node_ip
req = urllib2.Request(url, post_data) B = peer_ip
response = urllib2.urlopen(req) else:
return response.read() A = peer_ip
B = node_ip
edge = { 'A': A,
'B': B }
if A not in edges:
edges[A] = []
if not([True for edge in edges[A] if edge['B'] == B]):
edges[A] += [edge]
def send_graph(nodes, edges):
graph = {
'nodes': [],
'edges': [edge for sublist in edges.values()
for edge in sublist],
}
for node in nodes.values():
graph['nodes'].append({
'ip': node['ip'],
'version': node['version'],
})
print('Nodes: {:d}\nEdges: {:d}\n'.format(len(nodes), len(edges)))
json_graph = json.dumps(graph)
print('Sending data to {:s}...'.format(url))
payload = {'data': json_graph, 'mail': your_email}
r = requests.post(url, data=payload)
if r.status_code == requests.codes.ok:
print('Done!')
else:
print('Submission failed with error code {:d}'.format(r.status_code))