Commit 43b5e5e6 authored by Julien Muchembled's avatar Julien Muchembled

Allow the registry to know the topology, for debugging purpose

parent a85c8c02
...@@ -170,7 +170,7 @@ def node_by_ll(addr): ...@@ -170,7 +170,7 @@ def node_by_ll(addr):
_ll[a] = n, t _ll[a] = n, t
return _ll[addr] return _ll[addr]
def babel_svg(z=4): def route_svg(z=4):
graph = {} graph = {}
for n in nodes: for n in nodes:
g = graph[n] = defaultdict(list) g = graph[n] = defaultdict(list)
...@@ -214,18 +214,42 @@ if len(sys.argv) > 1: ...@@ -214,18 +214,42 @@ if len(sys.argv) > 1:
class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self): def do_GET(self):
if self.path == '/': svg = None
if self.path == '/route.html':
svg = route_svg()
elif self.path == '/tunnel.html':
gv = registry.Popen(('python', '-c', r"""if 1:
import math, xmlrpclib
g = xmlrpclib.ServerProxy('http://localhost/').topology()
print 'digraph {'
a = 2 * math.pi / len(g)
z = 4
for i, n in enumerate(sorted(g)):
p = g[n]
print '"%s"[pos="%s,%s!"%s];' % (n,
z * math.cos(a * i), z * math.sin(a * i),
', style=dashed' if p is None else '')
for p in p or ():
print '"%s" -> "%s";' % (n, p)
print '}'
"""), stdout=subprocess.PIPE).communicate()[0]
if gv:
svg = subprocess.Popen(('neato', '-Tsvg'),
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
).communicate(gv)[0]
if not svg:
self.send_error(500)
return
else:
self.send_error(404)
return
mt = 'text/html' mt = 'text/html'
x = babel_svg()
body = """<html> body = """<html>
<head><meta http-equiv="refresh" content="10"/></head> <head><meta http-equiv="refresh" content="10"/></head>
<body> <body>
%s %s
</body> </body>
</html>""" % x[x.find('<svg'):] </html>""" % svg[svg.find('<svg'):]
else:
self.send_error(404)
return
self.send_response(200) self.send_response(200)
self.send_header('Content-Length', len(body)) self.send_header('Content-Length', len(body))
self.send_header('Content-type', mt + '; charset=utf-8') self.send_header('Content-type', mt + '; charset=utf-8')
......
#!/usr/bin/env python #!/usr/bin/env python
import random, select, smtplib, sqlite3, string, socket import random, select, smtplib, sqlite3, string, socket
import subprocess, time, threading, traceback, errno, logging, os, xmlrpclib import subprocess, time, threading, traceback, errno, logging, os, xmlrpclib
from collections import deque
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
from email.mime.text import MIMEText from email.mime.text import MIMEText
from OpenSSL import crypto from OpenSSL import crypto
...@@ -223,5 +224,41 @@ class main(object): ...@@ -223,5 +224,41 @@ class main(object):
os.close(r) os.close(r)
os.close(w) os.close(w)
def topology(self, handler):
if handler.client_address[0] in ('127.0.0.1', '::'):
is_registry = utils.binFromIp(self.config.private
)[len(self.network):].startswith
peers = deque('%u/%u' % (int(x, 2), len(x))
for x, in self.db.execute("SELECT prefix FROM cert")
if is_registry(x))
assert len(peers) == 1
cookie = hex(random.randint(0, 1<<32))[2:]
graph = dict.fromkeys(peers)
asked = 0
while True:
r, w, _ = select.select([self.sock],
[self.sock] if peers else [], [], 1)
if r:
answer = self.sock.recv(1<<16)
if answer[0] == '\xfe':
answer = answer[1:].split('\n')[:-1]
if len(answer) >= 3 and answer[0] == cookie:
x = answer[3:]
assert answer[1] not in x, (answer, graph)
graph[answer[1]] = x[:int(answer[2])]
x = set(x).difference(graph)
peers += x
graph.update(dict.fromkeys(x))
if w:
x = utils.binFromSubnet(peers.popleft())
x = utils.ipFromBin(self.network + x)
try:
self.sock.sendto('\xff%s\n' % cookie, (x, tunnel.PORT))
except socket.error:
pass
elif not r:
break
return graph
if __name__ == "__main__": if __name__ == "__main__":
main() main()
...@@ -294,3 +294,16 @@ class TunnelManager(object): ...@@ -294,3 +294,16 @@ class TunnelManager(object):
self.sock.sendto('\1' + ''.join(msg), address) self.sock.sendto('\1' + ''.join(msg), address)
except socket.error, e: except socket.error, e:
logging.info('Failed to reply to %s (%s)', address, e) logging.info('Failed to reply to %s (%s)', address, e)
elif code == 255:
# the registry wants to know the topology for debugging purpose
if utils.binFromIp(address[0]) == self._peer_db.registry_ip:
msg = ['\xfe%s%u/%u\n%u\n' % (msg[1:],
int(self._prefix, 2), len(self._prefix),
len(self._connection_dict))]
msg.extend('%s/%s\n' % (int(x, 2), len(x))
for x in (self._connection_dict, self._served)
for x in x)
try:
self.sock.sendto(''.join(msg), address)
except socket.error, e:
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment