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
import (
"encoding/hex"
"net"
"time"
......@@ -57,19 +58,19 @@ func Run(plugin *node.Plugin) {
func getEventDispatchers(conn *network.ManagedConnection) *EventDispatchers {
return &EventDispatchers{
AddNode: func(nodeId []byte) {
log.Debugw("AddNode", "nodeId", nodeId)
log.Debugw("AddNode", "nodeId", hex.EncodeToString(nodeId))
_, _ = conn.Write((&addnode.Packet{NodeId: nodeId}).Marshal())
},
RemoveNode: func(nodeId []byte) {
log.Debugw("RemoveNode", "nodeId", nodeId)
log.Debugw("RemoveNode", "nodeId", hex.EncodeToString(nodeId))
_, _ = conn.Write((&removenode.Packet{NodeId: nodeId}).Marshal())
},
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())
},
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())
},
}
......@@ -80,7 +81,9 @@ func reportCurrentStatus(eventDispatchers *EventDispatchers) {
eventDispatchers.AddNode(local.GetInstance().ID().Bytes())
}
reportKnownPeers(eventDispatchers)
reportChosenNeighbors(eventDispatchers)
reportAcceptedNeighbors(eventDispatchers)
}
func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispatchers *EventDispatchers) {
......@@ -123,6 +126,7 @@ func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispa
var onClose *events.Closure
onClose = events.NewClosure(func() {
discover.Events.PeerDiscovered.Detach(onDiscoverPeer)
discover.Events.PeerDeleted.Detach(onDeletePeer)
selection.Events.IncomingPeering.Detach(onAddAcceptedNeighbor)
selection.Events.OutgoingPeering.Detach(onAddChosenNeighbor)
selection.Events.Dropped.Detach(onRemoveNeighbor)
......@@ -132,15 +136,32 @@ func setupHooks(plugin *node.Plugin, conn *network.ManagedConnection, eventDispa
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) {
if autopeering.Selection != nil {
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())
}
}
}
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 {
go conn.Read(make([]byte, 1))
......
......@@ -7,15 +7,84 @@ import (
func index(w http.ResponseWriter, r *http.Request) {
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="../../dist/3d-force-graph.js"></script>-->
</head>
<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>
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) {
};
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]) {
case "_":
// do nothing - its just a ping
......@@ -43,13 +113,13 @@ func index(w http.ResponseWriter, r *http.Request) {
break;
case "C":
connectNodes(e.data.substr(1, 64), e.data.substr(65, 128));
console.log("Connect nodes:",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, 64));
break;
case "c":
disconnectNodes(e.data.substr(1, 64), e.data.substr(65, 128));
console.log("Disconnect nodes:",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, 64));
break;
case "O":
......@@ -73,14 +143,45 @@ func index(w http.ResponseWriter, r *http.Request) {
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)
.graphData(data)
.enableNodeDrag(false)
.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null)
.onNodeClick(removeNodeX)
.nodeColor(node => node.online ? 'rgba(0,255,0,1)' : 'rgba(255,255,255,1)')
.graphData(data);
.onNodeClick(showNodeStat)
.nodeColor(node => highlightNodes.indexOf(node) === -1 ? 'rgba(0,255,255,0.6)' : 'rgb(255,0,0,1)')
.linkWidth(link => highlightLinks.indexOf(link) === -1 ? 1 : 4)
.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;
......@@ -92,6 +193,14 @@ func index(w http.ResponseWriter, r *http.Request) {
}
}, 500)
function updateHighlight() {
// trigger update of highlighted objects in scene
Graph
.nodeColor(Graph.nodeColor())
.linkWidth(Graph.linkWidth())
.linkDirectionalParticles(Graph.linkDirectionalParticles());
}
updateGraph = function() {
updateRequired = true;
};
......@@ -144,6 +253,7 @@ func index(w http.ResponseWriter, r *http.Request) {
}
nodesById[sourceNodeId].online = true;
nodesById[targetNodeId].online = true;
existingLinks[sourceNodeId + targetNodeId] = true
data.links = [...data.links, { source: sourceNodeId, target: targetNodeId }];
updateGraph();
......@@ -158,10 +268,28 @@ func index(w http.ResponseWriter, r *http.Request) {
updateGraph();
}
function removeNodeX(node) {
if (node.id in nodesById) {
removeNode(node.id);
}
function clearNodeStat() {
document.getElementById("nodeId").innerHTML = ""
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>
</body>`)
......
......@@ -16,6 +16,7 @@ var lock sync.Mutex
func Configure(plugin *node.Plugin) {
server.Events.AddNode.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("AddNode", "nodeID", nodeId)
lock.Lock()
defer lock.Unlock()
......@@ -25,6 +26,7 @@ func Configure(plugin *node.Plugin) {
}))
server.Events.RemoveNode.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("RemoveNode", "nodeID", nodeId)
lock.Lock()
defer lock.Unlock()
......@@ -32,6 +34,7 @@ func Configure(plugin *node.Plugin) {
}))
server.Events.NodeOnline.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("NodeOnline", "nodeID", nodeId)
lock.Lock()
defer lock.Unlock()
......@@ -39,6 +42,7 @@ func Configure(plugin *node.Plugin) {
}))
server.Events.NodeOffline.Attach(events.NewClosure(func(nodeId string) {
plugin.Node.Logger.Debugw("NodeOffline", "nodeID", nodeId)
lock.Lock()
defer lock.Unlock()
......@@ -46,6 +50,7 @@ func Configure(plugin *node.Plugin) {
}))
server.Events.ConnectNodes.Attach(events.NewClosure(func(sourceId string, targetId string) {
plugin.Node.Logger.Debugw("ConnectNodes", "sourceID", sourceId, "targetId", targetId)
lock.Lock()
defer lock.Unlock()
......@@ -59,6 +64,7 @@ func Configure(plugin *node.Plugin) {
}))
server.Events.DisconnectNodes.Attach(events.NewClosure(func(sourceId string, targetId string) {
plugin.Node.Logger.Debugw("DisconnectNodes", "sourceID", sourceId, "targetId", targetId)
lock.Lock()
defer lock.Unlock()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment