Skip to content
Snippets Groups Projects
Unverified Commit 9a848b52 authored by Angelo Capossele's avatar Angelo Capossele Committed by GitHub
Browse files

Merge pull request #174 from iotaledger/fix/analysis-server

Fix/analysis server
parents 913dc537 a436b66e
No related branches found
No related tags found
No related merge requests found
package client package client
import ( import (
"encoding/hex"
"net" "net"
"time" "time"
...@@ -57,19 +58,19 @@ func Run(plugin *node.Plugin) { ...@@ -57,19 +58,19 @@ func Run(plugin *node.Plugin) {
func getEventDispatchers(conn *network.ManagedConnection) *EventDispatchers { func getEventDispatchers(conn *network.ManagedConnection) *EventDispatchers {
return &EventDispatchers{ return &EventDispatchers{
AddNode: func(nodeId []byte) { AddNode: func(nodeId []byte) {
log.Debugw("AddNode", "nodeId", nodeId) log.Debugw("AddNode", "nodeId", hex.EncodeToString(nodeId))
_, _ = conn.Write((&addnode.Packet{NodeId: nodeId}).Marshal()) _, _ = conn.Write((&addnode.Packet{NodeId: nodeId}).Marshal())
}, },
RemoveNode: func(nodeId []byte) { RemoveNode: func(nodeId []byte) {
log.Debugw("RemoveNode", "nodeId", nodeId) log.Debugw("RemoveNode", "nodeId", hex.EncodeToString(nodeId))
_, _ = conn.Write((&removenode.Packet{NodeId: nodeId}).Marshal()) _, _ = conn.Write((&removenode.Packet{NodeId: nodeId}).Marshal())
}, },
ConnectNodes: func(sourceId []byte, targetId []byte) { ConnectNodes: func(sourceId []byte, targetId []byte) {
log.Debugw("ConnectNodes", "sourceId", sourceId, "targetId", targetId) log.Debugw("ConnectNodes", "sourceId", hex.EncodeToString(sourceId), "targetId", hex.EncodeToString(targetId))
_, _ = conn.Write((&connectnodes.Packet{SourceId: sourceId, TargetId: targetId}).Marshal()) _, _ = conn.Write((&connectnodes.Packet{SourceId: sourceId, TargetId: targetId}).Marshal())
}, },
DisconnectNodes: func(sourceId []byte, targetId []byte) { DisconnectNodes: func(sourceId []byte, targetId []byte) {
log.Debugw("DisconnectNodes", "sourceId", sourceId, "targetId", targetId) log.Debugw("DisconnectNodes", "sourceId", hex.EncodeToString(sourceId), "targetId", hex.EncodeToString(targetId))
_, _ = conn.Write((&disconnectnodes.Packet{SourceId: sourceId, TargetId: targetId}).Marshal()) _, _ = conn.Write((&disconnectnodes.Packet{SourceId: sourceId, TargetId: targetId}).Marshal())
}, },
} }
...@@ -80,7 +81,9 @@ func reportCurrentStatus(eventDispatchers *EventDispatchers) { ...@@ -80,7 +81,9 @@ func reportCurrentStatus(eventDispatchers *EventDispatchers) {
eventDispatchers.AddNode(local.GetInstance().ID().Bytes()) eventDispatchers.AddNode(local.GetInstance().ID().Bytes())
} }
reportKnownPeers(eventDispatchers)
reportChosenNeighbors(eventDispatchers) reportChosenNeighbors(eventDispatchers)
reportAcceptedNeighbors(eventDispatchers)
} }
func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispatchers *EventDispatchers) { func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispatchers *EventDispatchers) {
...@@ -123,6 +126,7 @@ func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispa ...@@ -123,6 +126,7 @@ func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispa
var onClose *events.Closure var onClose *events.Closure
onClose = events.NewClosure(func() { onClose = events.NewClosure(func() {
discover.Events.PeerDiscovered.Detach(onDiscoverPeer) discover.Events.PeerDiscovered.Detach(onDiscoverPeer)
discover.Events.PeerDeleted.Detach(onDeletePeer)
selection.Events.IncomingPeering.Detach(onAddAcceptedNeighbor) selection.Events.IncomingPeering.Detach(onAddAcceptedNeighbor)
selection.Events.OutgoingPeering.Detach(onAddChosenNeighbor) selection.Events.OutgoingPeering.Detach(onAddChosenNeighbor)
selection.Events.Dropped.Detach(onRemoveNeighbor) selection.Events.Dropped.Detach(onRemoveNeighbor)
...@@ -132,15 +136,32 @@ func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispa ...@@ -132,15 +136,32 @@ func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispa
conn.Events.Close.Attach(onClose) conn.Events.Close.Attach(onClose)
} }
func reportKnownPeers(dispatchers *EventDispatchers) {
if autopeering.Discovery != nil {
for _, peer := range autopeering.Discovery.GetVerifiedPeers() {
dispatchers.AddNode(peer.ID().Bytes())
}
}
}
func reportChosenNeighbors(dispatchers *EventDispatchers) { func reportChosenNeighbors(dispatchers *EventDispatchers) {
if autopeering.Selection != nil { if autopeering.Selection != nil {
for _, chosenNeighbor := range autopeering.Selection.GetOutgoingNeighbors() { for _, chosenNeighbor := range autopeering.Selection.GetOutgoingNeighbors() {
dispatchers.AddNode(chosenNeighbor.ID().Bytes()) //dispatchers.AddNode(chosenNeighbor.ID().Bytes())
dispatchers.ConnectNodes(local.GetInstance().ID().Bytes(), chosenNeighbor.ID().Bytes()) dispatchers.ConnectNodes(local.GetInstance().ID().Bytes(), chosenNeighbor.ID().Bytes())
} }
} }
} }
func reportAcceptedNeighbors(dispatchers *EventDispatchers) {
if autopeering.Selection != nil {
for _, acceptedNeighbor := range autopeering.Selection.GetIncomingNeighbors() {
//dispatchers.AddNode(acceptedNeighbor.ID().Bytes())
dispatchers.ConnectNodes(local.GetInstance().ID().Bytes(), acceptedNeighbor.ID().Bytes())
}
}
}
func keepConnectionAlive(conn *network.ManagedConnection, shutdownSignal <-chan struct{}) bool { func keepConnectionAlive(conn *network.ManagedConnection, shutdownSignal <-chan struct{}) bool {
go conn.Read(make([]byte, 1)) go conn.Read(make([]byte, 1))
......
...@@ -7,14 +7,83 @@ import ( ...@@ -7,14 +7,83 @@ import (
func index(w http.ResponseWriter, r *http.Request) { func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `<head> fmt.Fprintf(w, `<head>
<style> body { margin: 0; } </style> <style>
body {
text-align: center;
margin: 0;
overflow: hidden;
}
#nfo{
position:absolute;
right: 0;
padding:10px;
}
#knownPeers{
position:relative;
margin:0;
font-size:14px;
font-weight: bold;
text-align:right;
color:#aaa;
}
#avgNeighbors{
position:relative;
margin:0;
font-size:13px;
text-align:right;
color:grey;
}
#graphc {
position: absolute;
top: 0px;
right: 0px;
margin:0;
right: 0px;
}
#nodeId{
position:relative;
margin:0;
padding:5px 0;
font-size:13px;
font-weight: bold;
text-align:right;
color:#aaa;
}
#nodestat{
position:relative;
margin:0;
font-size:12px;
text-align:right;
color:grey;
}
#in, #out{
margin:0;
padding: 3px 0;
}
</style>
<script src="https://unpkg.com/3d-force-graph"></script> <script src="https://unpkg.com/3d-force-graph"></script>
<!--<script src="../../dist/3d-force-graph.js"></script>--> <!--<script src="../../dist/3d-force-graph.js"></script>-->
</head> </head>
<body> <body>
<div id="3d-graph"></div> <div id="graphc"></div>
<div id="nfo">
<p id="knownPeers"></p>
<p id="avgNeighbors"></p>
<div id="nodeId"></div>
<div id="nodestat">
<p id="in"></p>
<p id="out"></p>
</div>
<script> <script>
var socket = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/datastream"); var socket = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/datastream");
...@@ -26,7 +95,8 @@ func index(w http.ResponseWriter, r *http.Request) { ...@@ -26,7 +95,8 @@ func index(w http.ResponseWriter, r *http.Request) {
}; };
socket.onmessage = function (e) { socket.onmessage = function (e) {
console.log("Len: ", data.nodes.length); document.getElementById("knownPeers").innerHTML = "Known peers: " + data.nodes.length;
document.getElementById("avgNeighbors").innerHTML = "Average neighbors: " + parseFloat(((data.links.length * 2) / data.nodes.length).toFixed(2));
switch (e.data[0]) { switch (e.data[0]) {
case "_": case "_":
// do nothing - its just a ping // do nothing - its just a ping
...@@ -43,13 +113,13 @@ func index(w http.ResponseWriter, r *http.Request) { ...@@ -43,13 +113,13 @@ func index(w http.ResponseWriter, r *http.Request) {
break; break;
case "C": case "C":
connectNodes(e.data.substr(1, 64), e.data.substr(65, 128)); connectNodes(e.data.substr(1, 64), e.data.substr(65, 64));
console.log("Connect nodes:",e.data.substr(1, 64), " - ", e.data.substr(65, 128)); console.log("Connect nodes:",e.data.substr(1, 64), " - ", e.data.substr(65, 64));
break; break;
case "c": case "c":
disconnectNodes(e.data.substr(1, 64), e.data.substr(65, 128)); disconnectNodes(e.data.substr(1, 64), e.data.substr(65, 64));
console.log("Disconnect nodes:",e.data.substr(1, 64), " - ", e.data.substr(65, 128)); console.log("Disconnect nodes:",e.data.substr(1, 64), " - ", e.data.substr(65, 64));
break; break;
case "O": case "O":
...@@ -73,14 +143,45 @@ func index(w http.ResponseWriter, r *http.Request) { ...@@ -73,14 +143,45 @@ func index(w http.ResponseWriter, r *http.Request) {
var existingLinks = {}; var existingLinks = {};
const elem = document.getElementById("3d-graph"); let highlightNodes = [];
let highlightLinks = [];
let highlightLink = null;
const elem = document.getElementById("graphc");
//.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null)
const Graph = ForceGraph3D()(elem) const Graph = ForceGraph3D()(elem)
.graphData(data)
.enableNodeDrag(false) .enableNodeDrag(false)
.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null) .onNodeClick(showNodeStat)
.onNodeClick(removeNodeX) .nodeColor(node => highlightNodes.indexOf(node) === -1 ? 'rgba(0,255,255,0.6)' : 'rgb(255,0,0,1)')
.nodeColor(node => node.online ? 'rgba(0,255,0,1)' : 'rgba(255,255,255,1)') .linkWidth(link => highlightLinks.indexOf(link) === -1 ? 1 : 4)
.graphData(data); .linkDirectionalParticles(link => highlightLinks.indexOf(link) === -1 ? 0 : 4)
.linkDirectionalParticleWidth(4)
.onNodeHover(node => {
// no state change
if ((!node && !highlightNodes.length) || (highlightNodes.length === 1 && highlightNodes[0] === node)) return;
highlightNodes = node ? [node] : [];
highlightLinks = [];
clearNodeStat();
if (node != null) {
highlightLinks = data.links.filter(l => (l.target.id == node.id) || (l.source.id == node.id));
showNodeStat(node);
}
updateHighlight();
})
.onLinkHover(link => {
// no state change
if ((!link && !highlightLinks.length) || (highlightLinks.length === 1 && highlightLinks[0] === link)) return;
highlightLinks = [link];
highlightNodes = link ? [link.source, link.target] : [];
updateHighlight();
});
var updateRequired = true; var updateRequired = true;
...@@ -92,6 +193,14 @@ func index(w http.ResponseWriter, r *http.Request) { ...@@ -92,6 +193,14 @@ func index(w http.ResponseWriter, r *http.Request) {
} }
}, 500) }, 500)
function updateHighlight() {
// trigger update of highlighted objects in scene
Graph
.nodeColor(Graph.nodeColor())
.linkWidth(Graph.linkWidth())
.linkDirectionalParticles(Graph.linkDirectionalParticles());
}
updateGraph = function() { updateGraph = function() {
updateRequired = true; updateRequired = true;
}; };
...@@ -144,6 +253,7 @@ func index(w http.ResponseWriter, r *http.Request) { ...@@ -144,6 +253,7 @@ func index(w http.ResponseWriter, r *http.Request) {
} }
nodesById[sourceNodeId].online = true; nodesById[sourceNodeId].online = true;
nodesById[targetNodeId].online = true; nodesById[targetNodeId].online = true;
existingLinks[sourceNodeId + targetNodeId] = true
data.links = [...data.links, { source: sourceNodeId, target: targetNodeId }]; data.links = [...data.links, { source: sourceNodeId, target: targetNodeId }];
updateGraph(); updateGraph();
...@@ -158,10 +268,28 @@ func index(w http.ResponseWriter, r *http.Request) { ...@@ -158,10 +268,28 @@ func index(w http.ResponseWriter, r *http.Request) {
updateGraph(); updateGraph();
} }
function removeNodeX(node) { function clearNodeStat() {
if (node.id in nodesById) { document.getElementById("nodeId").innerHTML = ""
removeNode(node.id); document.getElementById("in").innerHTML = ""
document.getElementById("out").innerHTML = ""
} }
function showNodeStat(node) {
document.getElementById("nodeId").innerHTML = "ID: " + node.id.substr(0, 16);
var incoming = data.links.filter(l => (l.target.id == node.id));
document.getElementById("in").innerHTML = "IN: " + incoming.length + "<br>";
incoming.forEach(function(link){
document.getElementById("in").innerHTML += link.source.id.substr(0, 16) + " &rarr; NODE <br>";
});
var outgoing = data.links.filter(l => (l.source.id == node.id));
document.getElementById("out").innerHTML = "OUT: " + outgoing.length + "<br>";
outgoing.forEach(function(link){
document.getElementById("out").innerHTML += "NODE &rarr; " + link.target.id.substr(0, 16) + "<br>";
});
nodesById[node.id].color = 'rgba(0,255,255,1)'
} }
</script> </script>
</body>`) </body>`)
......
...@@ -16,6 +16,7 @@ var lock sync.Mutex ...@@ -16,6 +16,7 @@ var lock sync.Mutex
func Configure(plugin *node.Plugin) { func Configure(plugin *node.Plugin) {
server.Events.AddNode.Attach(events.NewClosure(func(nodeId string) { server.Events.AddNode.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("AddNode", "nodeID", nodeId)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
...@@ -25,6 +26,7 @@ func Configure(plugin *node.Plugin) { ...@@ -25,6 +26,7 @@ func Configure(plugin *node.Plugin) {
})) }))
server.Events.RemoveNode.Attach(events.NewClosure(func(nodeId string) { server.Events.RemoveNode.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("RemoveNode", "nodeID", nodeId)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
...@@ -32,6 +34,7 @@ func Configure(plugin *node.Plugin) { ...@@ -32,6 +34,7 @@ func Configure(plugin *node.Plugin) {
})) }))
server.Events.NodeOnline.Attach(events.NewClosure(func(nodeId string) { server.Events.NodeOnline.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("NodeOnline", "nodeID", nodeId)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
...@@ -39,6 +42,7 @@ func Configure(plugin *node.Plugin) { ...@@ -39,6 +42,7 @@ func Configure(plugin *node.Plugin) {
})) }))
server.Events.NodeOffline.Attach(events.NewClosure(func(nodeId string) { server.Events.NodeOffline.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("NodeOffline", "nodeID", nodeId)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
...@@ -46,6 +50,7 @@ func Configure(plugin *node.Plugin) { ...@@ -46,6 +50,7 @@ func Configure(plugin *node.Plugin) {
})) }))
server.Events.ConnectNodes.Attach(events.NewClosure(func(sourceId string, targetId string) { server.Events.ConnectNodes.Attach(events.NewClosure(func(sourceId string, targetId string) {
plugin.Node.Logger.Debugw("ConnectNodes", "sourceID", sourceId, "targetId", targetId)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
...@@ -59,6 +64,7 @@ func Configure(plugin *node.Plugin) { ...@@ -59,6 +64,7 @@ func Configure(plugin *node.Plugin) {
})) }))
server.Events.DisconnectNodes.Attach(events.NewClosure(func(sourceId string, targetId string) { server.Events.DisconnectNodes.Attach(events.NewClosure(func(sourceId string, targetId string) {
plugin.Node.Logger.Debugw("DisconnectNodes", "sourceID", sourceId, "targetId", targetId)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment