mirror of
https://github.com/cwinfo/yggdrasil-map
synced 2024-11-22 07:00:28 +00:00
replace tabs with spaces
This commit is contained in:
parent
26343b47fb
commit
e4b9b130db
106
web/database.py
106
web/database.py
@ -4,79 +4,79 @@ import time
|
|||||||
|
|
||||||
|
|
||||||
class NodeDB:
|
class NodeDB:
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.con = mdb.connect(
|
self.con = mdb.connect(
|
||||||
config['MYSQL_DATABASE_HOST'],
|
config['MYSQL_DATABASE_HOST'],
|
||||||
config['MYSQL_DATABASE_USER'],
|
config['MYSQL_DATABASE_USER'],
|
||||||
config['MYSQL_DATABASE_PASSWORD'],
|
config['MYSQL_DATABASE_PASSWORD'],
|
||||||
config['MYSQL_DATABASE_DB'])
|
config['MYSQL_DATABASE_DB'])
|
||||||
self.cur = self.con.cursor()
|
self.cur = self.con.cursor()
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, type, value, traceback):
|
||||||
self.con.commit()
|
self.con.commit()
|
||||||
self.con.close()
|
self.con.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def insert_node(self, node):
|
def insert_node(self, node):
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
self.cur.execute('''
|
self.cur.execute('''
|
||||||
INSERT INTO nodes (ip, name, version, first_seen, last_seen)
|
INSERT INTO nodes (ip, name, version, first_seen, last_seen)
|
||||||
VALUES (%s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s)
|
||||||
ON DUPLICATE KEY
|
ON DUPLICATE KEY
|
||||||
UPDATE name = %s, version = %s, last_seen = %s''', (
|
UPDATE name = %s, version = %s, last_seen = %s''', (
|
||||||
node.ip, node.label, node.version, now, now,
|
node.ip, node.label, node.version, now, now,
|
||||||
node.label, node.version, now))
|
node.label, node.version, now))
|
||||||
|
|
||||||
def insert_edge(self, edge, uploaded_by):
|
def insert_edge(self, edge, uploaded_by):
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
self.cur.execute('''
|
self.cur.execute('''
|
||||||
INSERT INTO edges (a, b, first_seen, last_seen, uploaded_by)
|
INSERT INTO edges (a, b, first_seen, last_seen, uploaded_by)
|
||||||
VALUES (%s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s)
|
||||||
ON DUPLICATE KEY
|
ON DUPLICATE KEY
|
||||||
UPDATE last_seen = %s''', (
|
UPDATE last_seen = %s''', (
|
||||||
edge.a.ip, edge.b.ip, now, now, uploaded_by,
|
edge.a.ip, edge.b.ip, now, now, uploaded_by,
|
||||||
now))
|
now))
|
||||||
|
|
||||||
def insert_graph(self, nodes, edges, uploaded_by):
|
def insert_graph(self, nodes, edges, uploaded_by):
|
||||||
for n in nodes.itervalues():
|
for n in nodes.itervalues():
|
||||||
self.insert_node(n)
|
self.insert_node(n)
|
||||||
|
|
||||||
for e in edges:
|
for e in edges:
|
||||||
self.insert_edge(e, uploaded_by)
|
self.insert_edge(e, uploaded_by)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_nodes(self, time_limit):
|
def get_nodes(self, time_limit):
|
||||||
since = int(time.time() - time_limit)
|
since = int(time.time() - time_limit)
|
||||||
cur = self.con.cursor(mdb.cursors.DictCursor)
|
cur = self.con.cursor(mdb.cursors.DictCursor)
|
||||||
cur.execute("SELECT ip, version, name FROM nodes WHERE last_seen > %s", (since,))
|
cur.execute("SELECT ip, version, name FROM nodes WHERE last_seen > %s", (since,))
|
||||||
db_nodes = cur.fetchall()
|
db_nodes = cur.fetchall()
|
||||||
|
|
||||||
nodes = dict()
|
nodes = dict()
|
||||||
for n in db_nodes:
|
for n in db_nodes:
|
||||||
nodes[n['ip']] = Node(n['ip'], n['version'], n['name'])
|
nodes[n['ip']] = Node(n['ip'], n['version'], n['name'])
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def get_edges(self, nodes, time_limit):
|
def get_edges(self, nodes, time_limit):
|
||||||
since = int(time.time() - time_limit)
|
since = int(time.time() - time_limit)
|
||||||
cur = self.con.cursor(mdb.cursors.DictCursor)
|
cur = self.con.cursor(mdb.cursors.DictCursor)
|
||||||
cur.execute("SELECT a, b FROM edges WHERE last_seen > %s", (since,))
|
cur.execute("SELECT a, b FROM edges WHERE last_seen > %s", (since,))
|
||||||
db_edges = cur.fetchall()
|
db_edges = cur.fetchall()
|
||||||
|
|
||||||
edges = []
|
edges = []
|
||||||
for e in db_edges:
|
for e in db_edges:
|
||||||
try:
|
try:
|
||||||
edges.append(Edge(nodes[e['a']], nodes[e['b']]))
|
edges.append(Edge(nodes[e['a']], nodes[e['b']]))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
return edges
|
return edges
|
||||||
|
|
||||||
def get_graph(self, time_limit):
|
def get_graph(self, time_limit):
|
||||||
nodes = self.get_nodes(time_limit)
|
nodes = self.get_nodes(time_limit)
|
||||||
edges = self.get_edges(nodes, time_limit)
|
edges = self.get_edges(nodes, time_limit)
|
||||||
return (nodes, edges)
|
return (nodes, edges)
|
||||||
|
58
web/graph.py
58
web/graph.py
@ -2,48 +2,48 @@ import re
|
|||||||
|
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
def __init__(self, ip, version=None, label=None):
|
def __init__(self, ip, version=None, label=None):
|
||||||
if not valid_cjdns_ip(ip):
|
if not valid_cjdns_ip(ip):
|
||||||
raise ValueError('Invalid IP address')
|
raise ValueError('Invalid IP address')
|
||||||
if not valid_version(version):
|
if not valid_version(version):
|
||||||
raise ValueError('Invalid version')
|
raise ValueError('Invalid version')
|
||||||
|
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.version = int(version)
|
self.version = int(version)
|
||||||
self.label = ip[-4:] if label == None else label
|
self.label = ip[-4:] if label == None else label
|
||||||
|
|
||||||
def __lt__(self, b):
|
def __lt__(self, b):
|
||||||
return self.ip < b.ip
|
return self.ip < b.ip
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Node(ip="%s", version=%s, label="%s")' % (
|
return 'Node(ip="%s", version=%s, label="%s")' % (
|
||||||
self.ip,
|
self.ip,
|
||||||
self.version,
|
self.version,
|
||||||
self.label)
|
self.label)
|
||||||
|
|
||||||
class Edge:
|
class Edge:
|
||||||
def __init__(self, a, b):
|
def __init__(self, a, b):
|
||||||
self.a, self.b = sorted([a, b])
|
self.a, self.b = sorted([a, b])
|
||||||
|
|
||||||
def __eq__(self, that):
|
def __eq__(self, that):
|
||||||
return self.a.ip == that.a.ip and self.b.ip == that.b.ip
|
return self.a.ip == that.a.ip and self.b.ip == that.b.ip
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Edge(a.ip="%s", b.ip="%s")' % (
|
return 'Edge(a.ip="%s", b.ip="%s")' % (
|
||||||
self.a.ip,
|
self.a.ip,
|
||||||
self.b.ip)
|
self.b.ip)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_re_cjdns_ip = re.compile(r'^fc[0-9a-f]{2}(:[0-9a-f]{4}){7}$', re.IGNORECASE)
|
_re_cjdns_ip = re.compile(r'^fc[0-9a-f]{2}(:[0-9a-f]{4}){7}$', re.IGNORECASE)
|
||||||
|
|
||||||
def valid_cjdns_ip(ip):
|
def valid_cjdns_ip(ip):
|
||||||
return _re_cjdns_ip.match(ip) != None
|
return _re_cjdns_ip.match(ip) != None
|
||||||
|
|
||||||
def valid_version(version):
|
def valid_version(version):
|
||||||
try:
|
try:
|
||||||
return int(version) < 20
|
return int(version) < 20
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -4,43 +4,43 @@ from graph import Node, Edge
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
def insert_graph_data(config, data, mail, ip):
|
def insert_graph_data(config, data, mail, ip):
|
||||||
try:
|
try:
|
||||||
graph_data = json.loads(data)
|
graph_data = json.loads(data)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return 'Invalid JSON'
|
return 'Invalid JSON'
|
||||||
|
|
||||||
nodes = dict()
|
nodes = dict()
|
||||||
edges = []
|
edges = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for n in graph_data['nodes']:
|
for n in graph_data['nodes']:
|
||||||
try:
|
try:
|
||||||
node = Node(n['ip'], version=n['version'])
|
node = Node(n['ip'], version=n['version'])
|
||||||
nodes[n['ip']] = node
|
nodes[n['ip']] = node
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for e in graph_data['edges']:
|
for e in graph_data['edges']:
|
||||||
try:
|
try:
|
||||||
edge = Edge(nodes[e['a']], nodes[e['b']])
|
edge = Edge(nodes[e['a']], nodes[e['b']])
|
||||||
edges.append(edge)
|
edges.append(edge)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
return 'Invalid JSON nodes'
|
return 'Invalid JSON nodes'
|
||||||
|
|
||||||
print "Accepted %d nodes and %d links." % (len(nodes), len(edges))
|
print "Accepted %d nodes and %d links." % (len(nodes), len(edges))
|
||||||
|
|
||||||
if len(nodes) == 0 or len(edges) == 0:
|
if len(nodes) == 0 or len(edges) == 0:
|
||||||
return 'No valid nodes or edges'
|
return 'No valid nodes or edges'
|
||||||
|
|
||||||
uploaded_by = ip
|
uploaded_by = ip
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with NodeDB(config) as db:
|
with NodeDB(config) as db:
|
||||||
db.insert_graph(nodes, edges, uploaded_by)
|
db.insert_graph(nodes, edges, uploaded_by)
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return 'Database failure'
|
return 'Database failure'
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -8,419 +8,419 @@ var mapOffset = {x: 0, y: 0};
|
|||||||
var zoom = 1.0;
|
var zoom = 1.0;
|
||||||
|
|
||||||
function changeHash(hash) {
|
function changeHash(hash) {
|
||||||
window.location.replace(('' + window.location).split('#')[0] + '#' + hash);
|
window.location.replace(('' + window.location).split('#')[0] + '#' + hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCanvasSize() {
|
function updateCanvasSize() {
|
||||||
$(canvas).attr({height: $(canvas).height(), width: $(canvas).width()});
|
$(canvas).attr({height: $(canvas).height(), width: $(canvas).width()});
|
||||||
ctx.translate(mapOffset.x, mapOffset.y);
|
ctx.translate(mapOffset.x, mapOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawCircle(ctx, x, y, radius, color) {
|
function drawCircle(ctx, x, y, radius, color) {
|
||||||
ctx.fillStyle = color;
|
ctx.fillStyle = color;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(x, y, radius, 0, Math.PI*2, true);
|
ctx.arc(x, y, radius, 0, Math.PI*2, true);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawLine(ctx, x1, y1, x2, y2, color) {
|
function drawLine(ctx, x1, y1, x2, y2, color) {
|
||||||
ctx.strokeStyle = color;
|
ctx.strokeStyle = color;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(x1, y1);
|
ctx.moveTo(x1, y1);
|
||||||
ctx.lineTo(x2, y2);
|
ctx.lineTo(x2, y2);
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawText(ctx, x, y, text, color, font) {
|
function drawText(ctx, x, y, text, color, font) {
|
||||||
// ctx.save();
|
// ctx.save();
|
||||||
// ctx.translate(x, y);
|
// ctx.translate(x, y);
|
||||||
// ctx.rotate(Math.PI/4);
|
// ctx.rotate(Math.PI/4);
|
||||||
ctx.fillStyle = color;
|
ctx.fillStyle = color;
|
||||||
ctx.font = font;
|
ctx.font = font;
|
||||||
ctx.textAlign = 'center';
|
ctx.textAlign = 'center';
|
||||||
ctx.fillText(text, x, y);
|
ctx.fillText(text, x, y);
|
||||||
// ctx.restore();
|
// ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawNetwork() {
|
function drawNetwork() {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
|
|
||||||
|
|
||||||
// Draw edges
|
// Draw edges
|
||||||
for (var i = 0; i < edges.length; ++i) {
|
for (var i = 0; i < edges.length; ++i) {
|
||||||
var edge = edges[i];
|
var edge = edges[i];
|
||||||
var highlight = edge.sourceNode.hover || edge.targetNode.hover;
|
var highlight = edge.sourceNode.hover || edge.targetNode.hover;
|
||||||
var color = highlight ? 'rgba(0, 0, 0, 0.5)' : 'rgba(0, 0, 0, 0.15)';
|
var color = highlight ? 'rgba(0, 0, 0, 0.5)' : 'rgba(0, 0, 0, 0.15)';
|
||||||
|
|
||||||
drawLine(ctx,
|
drawLine(ctx,
|
||||||
edge.sourceNode.x, edge.sourceNode.y,
|
edge.sourceNode.x, edge.sourceNode.y,
|
||||||
edge.targetNode.x, edge.targetNode.y,
|
edge.targetNode.x, edge.targetNode.y,
|
||||||
color);
|
color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw nodes
|
// Draw nodes
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
|
|
||||||
drawCircle(ctx, node.x, node.y, node.radius, node.color);
|
drawCircle(ctx, node.x, node.y, node.radius, node.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw labels
|
// Draw labels
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
|
|
||||||
if (node.radius > 4 || node.selected || node.hover) {
|
if (node.radius > 4 || node.selected || node.hover) {
|
||||||
var fontSize = 4 + node.radius * 0.4;
|
var fontSize = 4 + node.radius * 0.4;
|
||||||
|
|
||||||
drawText(ctx, node.x, node.y - node.radius - 1,
|
drawText(ctx, node.x, node.y - node.radius - 1,
|
||||||
node.label, node.textColor, fontSize + 'pt "ubuntu mono"');
|
node.label, node.textColor, fontSize + 'pt "ubuntu mono"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeAt(x, y) {
|
function getNodeAt(x, y) {
|
||||||
x -= mapOffset.x;
|
x -= mapOffset.x;
|
||||||
y -= mapOffset.y;
|
y -= mapOffset.y;
|
||||||
for (var i = nodes.length - 1; i >= 0; --i) {
|
for (var i = nodes.length - 1; i >= 0; --i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
var distPow2 = (node.x - x) * (node.x - x) + (node.y - y) * (node.y - y);
|
var distPow2 = (node.x - x) * (node.x - x) + (node.y - y) * (node.y - y);
|
||||||
|
|
||||||
if (distPow2 <= node.radius * node.radius) {
|
if (distPow2 <= node.radius * node.radius) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchNode(id) {
|
function searchNode(id) {
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
if (nodes[i].id == id)
|
if (nodes[i].id == id)
|
||||||
return nodes[i];
|
return nodes[i];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearNodes() {
|
function clearNodes() {
|
||||||
changeHash('');
|
changeHash('');
|
||||||
$('#node-info').html('');
|
$('#node-info').html('');
|
||||||
|
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
node.depth = 0xFFFF;
|
node.depth = 0xFFFF;
|
||||||
node.color = node.originalColor;
|
node.color = node.originalColor;
|
||||||
node.textColor = node.color;
|
node.textColor = node.color;
|
||||||
node.selected = false;
|
node.selected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNode(node, redraw) {
|
function selectNode(node, redraw) {
|
||||||
clearNodes();
|
clearNodes();
|
||||||
|
|
||||||
changeHash(node.id);
|
changeHash(node.id);
|
||||||
|
|
||||||
node.selected = true;
|
node.selected = true;
|
||||||
showNodeInfo(node);
|
showNodeInfo(node);
|
||||||
|
|
||||||
markPeers(node, 0);
|
markPeers(node, 0);
|
||||||
if (redraw)
|
if (redraw)
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
function markPeers(node, depth) {
|
function markPeers(node, depth) {
|
||||||
node.depth = depth;
|
node.depth = depth;
|
||||||
|
|
||||||
// var colors = ['#000000', '#333333', '#555555', '#777777', '#999999', '#BBBBBB', '#DDDDDD'];
|
// var colors = ['#000000', '#333333', '#555555', '#777777', '#999999', '#BBBBBB', '#DDDDDD'];
|
||||||
// var colors = ['#000000', '#29BBFF', '#09E844', '#FFBD0F', '#FF5E14', '#FF3C14', '#FF7357', '#FF9782', '#FFC8BD', '#FFE6E0'];
|
// var colors = ['#000000', '#29BBFF', '#09E844', '#FFBD0F', '#FF5E14', '#FF3C14', '#FF7357', '#FF9782', '#FFC8BD', '#FFE6E0'];
|
||||||
var colors = ['#000000', '#096EE8', '#09E8B8', '#36E809', '#ADE809', '#E8B809', '#E87509', '#E83A09', '#E86946', '#E8AC9B', '#E8C9C1'];
|
var colors = ['#000000', '#096EE8', '#09E8B8', '#36E809', '#ADE809', '#E8B809', '#E87509', '#E83A09', '#E86946', '#E8AC9B', '#E8C9C1'];
|
||||||
var txtCol = ['#000000', '#032247', '#034537', '#0E3D02', '#354703', '#403203', '#3D1F02', '#3B0E02', '#3B0E02', '#3B0E02', '#3B0E02'];
|
var txtCol = ['#000000', '#032247', '#034537', '#0E3D02', '#354703', '#403203', '#3D1F02', '#3B0E02', '#3B0E02', '#3B0E02', '#3B0E02'];
|
||||||
// var colors = ['#000000', '#064F8F', '#068F81', '#068F38', '#218F06', '#6F8F06', '#8F7806', '#8F5106'];
|
// var colors = ['#000000', '#064F8F', '#068F81', '#068F38', '#218F06', '#6F8F06', '#8F7806', '#8F5106'];
|
||||||
// var colors = ['#FFFFFF', '#29BBFF', '#17FF54', '#FFBD0F', '#FF3C14', '#590409'];
|
// var colors = ['#FFFFFF', '#29BBFF', '#17FF54', '#FFBD0F', '#FF3C14', '#590409'];
|
||||||
node.color = (depth >= colors.length) ? '#FFFFFF' : colors[depth];
|
node.color = (depth >= colors.length) ? '#FFFFFF' : colors[depth];
|
||||||
node.textColor = (depth >= txtCol.length) ? '#FFFFFF' : txtCol[depth];
|
node.textColor = (depth >= txtCol.length) ? '#FFFFFF' : txtCol[depth];
|
||||||
|
|
||||||
for (var i = 0; i < node.peers.length; ++i) {
|
for (var i = 0; i < node.peers.length; ++i) {
|
||||||
var n = node.peers[i];
|
var n = node.peers[i];
|
||||||
if (n.depth > depth + 1)
|
if (n.depth > depth + 1)
|
||||||
markPeers(n, depth + 1);
|
markPeers(n, depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showNodeInfo(node) {
|
function showNodeInfo(node) {
|
||||||
var ip_peers = [];
|
var ip_peers = [];
|
||||||
var dns_peers = [];
|
var dns_peers = [];
|
||||||
|
|
||||||
for (var i = 0; i < node.peers.length; ++i) {
|
for (var i = 0; i < node.peers.length; ++i) {
|
||||||
var n = node.peers[i];
|
var n = node.peers[i];
|
||||||
if (/^[0-9A-F]{4}$/i.test(n.label))
|
if (/^[0-9A-F]{4}$/i.test(n.label))
|
||||||
ip_peers.push(n);
|
ip_peers.push(n);
|
||||||
else
|
else
|
||||||
dns_peers.push(n);
|
dns_peers.push(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
var label_compare = function(a, b) {
|
var label_compare = function(a, b) {
|
||||||
return a.label.localeCompare(b.label);
|
return a.label.localeCompare(b.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_peers.sort(label_compare);
|
dns_peers.sort(label_compare);
|
||||||
ip_peers.sort(label_compare);
|
ip_peers.sort(label_compare);
|
||||||
|
|
||||||
var peers = dns_peers.concat(ip_peers);
|
var peers = dns_peers.concat(ip_peers);
|
||||||
|
|
||||||
var html =
|
var html =
|
||||||
'<h2>' + node.label + '</h2>' +
|
'<h2>' + node.label + '</h2>' +
|
||||||
'<span class="tt">' + node.id + '</span><br>' +
|
'<span class="tt">' + node.id + '</span><br>' +
|
||||||
'<br>' +
|
'<br>' +
|
||||||
'<strong>Version:</strong> ' + node.version + '<br>' +
|
'<strong>Version:</strong> ' + node.version + '<br>' +
|
||||||
'<strong>Peers:</strong> ' + node.peers.length + '<br>' +
|
'<strong>Peers:</strong> ' + node.peers.length + '<br>' +
|
||||||
'<strong>Centrality:</strong> ' + node.centrality + '<br>' +
|
'<strong>Centrality:</strong> ' + node.centrality + '<br>' +
|
||||||
'<table>' +
|
'<table>' +
|
||||||
// '<tr><td></td><td><strong>Their peers #</strong></td></tr>' +
|
// '<tr><td></td><td><strong>Their peers #</strong></td></tr>' +
|
||||||
peers.map(function (n) {
|
peers.map(function (n) {
|
||||||
return '<tr>' +
|
return '<tr>' +
|
||||||
'<td><a href="#' + n.id + '" class="tt">' + n.label + '</a></td>' +
|
'<td><a href="#' + n.id + '" class="tt">' + n.label + '</a></td>' +
|
||||||
'<td>' + n.peers.length + '</td></tr>';
|
'<td>' + n.peers.length + '</td></tr>';
|
||||||
}).join('') +
|
}).join('') +
|
||||||
'</table>';
|
'</table>';
|
||||||
|
|
||||||
$('#node-info').html(html);
|
$('#node-info').html(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mousePos(e) {
|
function mousePos(e) {
|
||||||
var rect = canvas.getBoundingClientRect();
|
var rect = canvas.getBoundingClientRect();
|
||||||
return {x: e.clientX - rect.left, y: e.clientY - rect.top};
|
return {x: e.clientX - rect.left, y: e.clientY - rect.top};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
canvas = document.getElementById('map');
|
canvas = document.getElementById('map');
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
updateCanvasSize();
|
updateCanvasSize();
|
||||||
|
|
||||||
|
|
||||||
jQuery.getJSON('/static/graph.json', function(data) {
|
jQuery.getJSON('/static/graph.json', function(data) {
|
||||||
nodes = data.nodes;
|
nodes = data.nodes;
|
||||||
edges = data.edges;
|
edges = data.edges;
|
||||||
|
|
||||||
// Calculate node radiuses
|
// Calculate node radiuses
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
node.x = node.x * 1.2;
|
node.x = node.x * 1.2;
|
||||||
node.y = node.y * 1.2;
|
node.y = node.y * 1.2;
|
||||||
node.radius = node.size;
|
node.radius = node.size;
|
||||||
node.hover = false;
|
node.hover = false;
|
||||||
node.selected = false;
|
node.selected = false;
|
||||||
node.edges = [];
|
node.edges = [];
|
||||||
node.peers = [];
|
node.peers = [];
|
||||||
node.depth = 0xFFFF;
|
node.depth = 0xFFFF;
|
||||||
// node.color = '#000';
|
// node.color = '#000';
|
||||||
node.originalColor = node.color;
|
node.originalColor = node.color;
|
||||||
node.textColor = node.color;
|
node.textColor = node.color;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newEdges = []
|
var newEdges = []
|
||||||
// Find node references for edges
|
// Find node references for edges
|
||||||
for (var i = 0; i < edges.length; ++i) {
|
for (var i = 0; i < edges.length; ++i) {
|
||||||
var edge = edges[i];
|
var edge = edges[i];
|
||||||
|
|
||||||
for (var n = 0; n < nodes.length; ++n) {
|
for (var n = 0; n < nodes.length; ++n) {
|
||||||
if (nodes[n].id == edge.sourceID) {
|
if (nodes[n].id == edge.sourceID) {
|
||||||
edge.sourceNode = nodes[n];
|
edge.sourceNode = nodes[n];
|
||||||
// edge.sourceNode.edges.append(edge);
|
// edge.sourceNode.edges.append(edge);
|
||||||
}
|
}
|
||||||
else if (nodes[n].id == edge.targetID)
|
else if (nodes[n].id == edge.targetID)
|
||||||
edge.targetNode = nodes[n];
|
edge.targetNode = nodes[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!edge.sourceNode || !edge.targetNode)
|
if (!edge.sourceNode || !edge.targetNode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
edge.sourceNode.edges.push(edge);
|
edge.sourceNode.edges.push(edge);
|
||||||
edge.targetNode.edges.push(edge);
|
edge.targetNode.edges.push(edge);
|
||||||
edge.sourceNode.peers.push(edge.targetNode);
|
edge.sourceNode.peers.push(edge.targetNode);
|
||||||
edge.targetNode.peers.push(edge.sourceNode);
|
edge.targetNode.peers.push(edge.sourceNode);
|
||||||
|
|
||||||
newEdges.push(edge);
|
newEdges.push(edge);
|
||||||
}
|
}
|
||||||
edges = newEdges;
|
edges = newEdges;
|
||||||
|
|
||||||
// Set update time
|
// Set update time
|
||||||
var delta = Math.round(new Date().getTime() / 1000) - data.created;
|
var delta = Math.round(new Date().getTime() / 1000) - data.created;
|
||||||
var min = Math.floor(delta / 60);
|
var min = Math.floor(delta / 60);
|
||||||
var sec = delta % 60;
|
var sec = delta % 60;
|
||||||
$('#update-time').text(min + ' min, ' + sec + ' s ago');
|
$('#update-time').text(min + ' min, ' + sec + ' s ago');
|
||||||
|
|
||||||
// Set stats
|
// Set stats
|
||||||
$('#number-of-nodes').text(nodes.length);
|
$('#number-of-nodes').text(nodes.length);
|
||||||
$('#number-of-connections').text(edges.length);
|
$('#number-of-connections').text(edges.length);
|
||||||
|
|
||||||
|
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
var id = window.location.hash.substring(1);
|
var id = window.location.hash.substring(1);
|
||||||
var node = searchNode(id);
|
var node = searchNode(id);
|
||||||
if (node) selectNode(node, false);
|
if (node) selectNode(node, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
|
|
||||||
$(window).resize(function() {
|
$(window).resize(function() {
|
||||||
updateCanvasSize();
|
updateCanvasSize();
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Initialize search
|
// Initialize search
|
||||||
var searchArray = [];
|
var searchArray = [];
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
|
|
||||||
searchArray.push({
|
searchArray.push({
|
||||||
value: node.label,
|
value: node.label,
|
||||||
data: node
|
data: node
|
||||||
});
|
});
|
||||||
|
|
||||||
searchArray.push({
|
searchArray.push({
|
||||||
value: node.id,
|
value: node.id,
|
||||||
data: node
|
data: node
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#search-box').autocomplete({
|
$('#search-box').autocomplete({
|
||||||
lookup: searchArray,
|
lookup: searchArray,
|
||||||
autoSelectFirst: true,
|
autoSelectFirst: true,
|
||||||
lookupLimit: 7,
|
lookupLimit: 7,
|
||||||
onSelect: function(suggestion) {
|
onSelect: function(suggestion) {
|
||||||
selectNode(suggestion.data, true);
|
selectNode(suggestion.data, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#search-box').keypress(function(e) {
|
$('#search-box').keypress(function(e) {
|
||||||
if (e.which == 13) {
|
if (e.which == 13) {
|
||||||
selectNode(searchNode($('#search-box').val()), true);
|
selectNode(searchNode($('#search-box').val()), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on('click', '#node-info a', function(e) {
|
$(document).on('click', '#node-info a', function(e) {
|
||||||
var id = e.target.hash.substring(1);
|
var id = e.target.hash.substring(1);
|
||||||
selectNode(searchNode(id), true);
|
selectNode(searchNode(id), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var mouseDownPos = null;
|
var mouseDownPos = null;
|
||||||
var mouseLastPos = null;
|
var mouseLastPos = null;
|
||||||
var mouseDownNode = null;
|
var mouseDownNode = null;
|
||||||
var mouseHoverNode = null;
|
var mouseHoverNode = null;
|
||||||
|
|
||||||
|
|
||||||
$(canvas).mousemove(function(e) {
|
$(canvas).mousemove(function(e) {
|
||||||
var mouse = mousePos(e);
|
var mouse = mousePos(e);
|
||||||
|
|
||||||
// Dragging
|
// Dragging
|
||||||
if (mouseDownPos != null) {
|
if (mouseDownPos != null) {
|
||||||
$('body').css('cursor', 'move');
|
$('body').css('cursor', 'move');
|
||||||
var dx = mouse.x - mouseLastPos.x;
|
var dx = mouse.x - mouseLastPos.x;
|
||||||
var dy = mouse.y - mouseLastPos.y;
|
var dy = mouse.y - mouseLastPos.y;
|
||||||
mapOffset.x += dx;
|
mapOffset.x += dx;
|
||||||
mapOffset.y += dy;
|
mapOffset.y += dy;
|
||||||
ctx.translate(dx, dy);
|
ctx.translate(dx, dy);
|
||||||
mouseLastPos = {x: mouse.x, y: mouse.y};
|
mouseLastPos = {x: mouse.x, y: mouse.y};
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
}
|
}
|
||||||
// Hovering
|
// Hovering
|
||||||
else {
|
else {
|
||||||
var node = getNodeAt(mouse.x, mouse.y);
|
var node = getNodeAt(mouse.x, mouse.y);
|
||||||
|
|
||||||
if (node == mouseHoverNode)
|
if (node == mouseHoverNode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
nodeMouseOut(mouseHoverNode);
|
nodeMouseOut(mouseHoverNode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (mouseHoverNode != null)
|
if (mouseHoverNode != null)
|
||||||
nodeMouseOut(mouseHoverNode);
|
nodeMouseOut(mouseHoverNode);
|
||||||
|
|
||||||
nodeMouseIn(node);
|
nodeMouseIn(node);
|
||||||
}
|
}
|
||||||
mouseHoverNode = node;
|
mouseHoverNode = node;
|
||||||
|
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$(canvas).mousedown(function(e) {
|
$(canvas).mousedown(function(e) {
|
||||||
var mouse = mousePos(e);
|
var mouse = mousePos(e);
|
||||||
mouseLastPos = mouseDownPos = {x: mouse.x, y: mouse.y};
|
mouseLastPos = mouseDownPos = {x: mouse.x, y: mouse.y};
|
||||||
mouseDownNode = getNodeAt(mouse.x, mouse.y);
|
mouseDownNode = getNodeAt(mouse.x, mouse.y);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
$(canvas).mouseup(function(e) {
|
$(canvas).mouseup(function(e) {
|
||||||
var mouse = mousePos(e);
|
var mouse = mousePos(e);
|
||||||
var mouseMoved =
|
var mouseMoved =
|
||||||
Math.abs(mouse.x - mouseDownPos.x) +
|
Math.abs(mouse.x - mouseDownPos.x) +
|
||||||
Math.abs(mouse.y - mouseDownPos.y) > 3
|
Math.abs(mouse.y - mouseDownPos.y) > 3
|
||||||
|
|
||||||
if (!mouseMoved) {
|
if (!mouseMoved) {
|
||||||
if (mouseDownNode)
|
if (mouseDownNode)
|
||||||
selectNode(mouseDownNode, true);
|
selectNode(mouseDownNode, true);
|
||||||
else {
|
else {
|
||||||
clearNodes();
|
clearNodes();
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$('body').css('cursor', 'auto');
|
$('body').css('cursor', 'auto');
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseDownPos = null;
|
mouseDownPos = null;
|
||||||
mouseDownNode = null;
|
mouseDownNode = null;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function handleScroll(e) {
|
function handleScroll(e) {
|
||||||
var mouse = mousePos(e);
|
var mouse = mousePos(e);
|
||||||
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
|
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
|
||||||
|
|
||||||
var ratio = (delta < 0) ? (3 / 4) : 1 + (1 / 3);
|
var ratio = (delta < 0) ? (3 / 4) : 1 + (1 / 3);
|
||||||
var mx = mouse.x - mapOffset.x;
|
var mx = mouse.x - mapOffset.x;
|
||||||
var my = mouse.y - mapOffset.y;
|
var my = mouse.y - mapOffset.y;
|
||||||
|
|
||||||
zoom *= ratio;
|
zoom *= ratio;
|
||||||
|
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
node.x = (node.x - mx) * ratio + mx;
|
node.x = (node.x - mx) * ratio + mx;
|
||||||
node.y = (node.y - my) * ratio + my;
|
node.y = (node.y - my) * ratio + my;
|
||||||
// node.x *= ratio;
|
// node.x *= ratio;
|
||||||
// node.y *= ratio;
|
// node.y *= ratio;
|
||||||
// node.radius *= ratio;
|
// node.radius *= ratio;
|
||||||
node.radius = (node.size) * zoom;
|
node.radius = (node.size) * zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawNetwork();
|
drawNetwork();
|
||||||
}
|
}
|
||||||
canvas.addEventListener("mousewheel", handleScroll, false);
|
canvas.addEventListener("mousewheel", handleScroll, false);
|
||||||
canvas.addEventListener("DOMMouseScroll", handleScroll, false);
|
canvas.addEventListener("DOMMouseScroll", handleScroll, false);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function nodeMouseIn(node) {
|
function nodeMouseIn(node) {
|
||||||
node.hover = true;
|
node.hover = true;
|
||||||
$('body').css('cursor', 'pointer');
|
$('body').css('cursor', 'pointer');
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeMouseOut(node) {
|
function nodeMouseOut(node) {
|
||||||
node.hover = false;
|
node.hover = false;
|
||||||
$('body').css('cursor', 'auto');
|
$('body').css('cursor', 'auto');
|
||||||
}
|
}
|
||||||
|
@ -5,25 +5,25 @@ import graphPlotter
|
|||||||
|
|
||||||
|
|
||||||
def generate_graph(time_limit=60*60*3):
|
def generate_graph(time_limit=60*60*3):
|
||||||
nodes, edges = load_graph_from_db(time_limit)
|
nodes, edges = load_graph_from_db(time_limit)
|
||||||
print '%d nodes, %d edges' % (len(nodes), len(edges))
|
print '%d nodes, %d edges' % (len(nodes), len(edges))
|
||||||
|
|
||||||
graph = graphPlotter.position_nodes(nodes, edges)
|
graph = graphPlotter.position_nodes(nodes, edges)
|
||||||
json = graphPlotter.get_graph_json(graph)
|
json = graphPlotter.get_graph_json(graph)
|
||||||
|
|
||||||
with open('static/graph.json', 'w') as f:
|
with open('static/graph.json', 'w') as f:
|
||||||
f.write(json)
|
f.write(json)
|
||||||
|
|
||||||
|
|
||||||
def load_graph_from_db(time_limit):
|
def load_graph_from_db(time_limit):
|
||||||
config = Config('./')
|
config = Config('./')
|
||||||
config.from_pyfile('web_config.cfg')
|
config.from_pyfile('web_config.cfg')
|
||||||
|
|
||||||
with NodeDB(config) as db:
|
with NodeDB(config) as db:
|
||||||
nodes = db.get_nodes(time_limit)
|
nodes = db.get_nodes(time_limit)
|
||||||
edges = db.get_edges(nodes, 60*60*24*7)
|
edges = db.get_edges(nodes, 60*60*24*7)
|
||||||
return (nodes, edges)
|
return (nodes, edges)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
generate_graph()
|
generate_graph()
|
||||||
|
18
web/web.py
18
web/web.py
@ -21,23 +21,23 @@ def add_ip():
|
|||||||
@app.route('/')
|
@app.route('/')
|
||||||
@app.route('/network')
|
@app.route('/network')
|
||||||
def page_network():
|
def page_network():
|
||||||
return render_template('network.html', page='network')
|
return render_template('network.html', page='network')
|
||||||
|
|
||||||
@app.route('/about')
|
@app.route('/about')
|
||||||
def page_about():
|
def page_about():
|
||||||
return render_template('about.html', page='about')
|
return render_template('about.html', page='about')
|
||||||
|
|
||||||
@app.route('/sendGraph', methods=['POST'])
|
@app.route('/sendGraph', methods=['POST'])
|
||||||
def page_sendGraph():
|
def page_sendGraph():
|
||||||
print "Receiving graph from %s" % (request.remote_addr)
|
print "Receiving graph from %s" % (request.remote_addr)
|
||||||
|
|
||||||
data = request.form['data']
|
data = request.form['data']
|
||||||
mail = request.form.get('mail', 'none')
|
mail = request.form.get('mail', 'none')
|
||||||
ret = insert_graph_data(ip=get_ip(), config=app.config, data=data, mail=mail)
|
ret = insert_graph_data(ip=get_ip(), config=app.config, data=data, mail=mail)
|
||||||
if ret == None:
|
if ret == None:
|
||||||
return 'OK'
|
return 'OK'
|
||||||
else:
|
else:
|
||||||
return 'Error: %s' % ret
|
return 'Error: %s' % ret
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='localhost', port=3000)
|
app.run(host='localhost', port=3000)
|
||||||
|
Loading…
Reference in New Issue
Block a user