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

replace tabs with spaces

This commit is contained in:
Michał Zieliński 2015-11-21 12:47:21 +01:00
parent 26343b47fb
commit e4b9b130db
6 changed files with 422 additions and 422 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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');
} }

View File

@ -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()

View File

@ -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)