From 24248d36735f9fc4473e70098ab1ec457b269852 Mon Sep 17 00:00:00 2001
From: Martin Geno
Date: Tue, 9 May 2017 01:03:44 +0200
Subject: [PATCH] [BUGFIX] improve websocket and stats of nodes
---
cmd/freifunkmanager/main.go | 2 +-
runtime/nodes.go | 7 +++-
webroot/index.html | 2 +
webroot/js/gui.js | 5 +--
webroot/js/socket.js | 48 ++++++++++++++--------
websocket/client.go | 80 ++++++++++++++++++++-----------------
websocket/msg.go | 8 ++--
websocket/server.go | 30 ++++++--------
yanic/dial.go | 8 ++--
9 files changed, 108 insertions(+), 82 deletions(-)
diff --git a/cmd/freifunkmanager/main.go b/cmd/freifunkmanager/main.go
index 9d5327f..0f6b472 100644
--- a/cmd/freifunkmanager/main.go
+++ b/cmd/freifunkmanager/main.go
@@ -64,7 +64,7 @@ func main() {
go func() {
if err := srv.ListenAndServe(); err != nil {
- panic(err)
+ log.Log.Panic(err)
}
}()
diff --git a/runtime/nodes.go b/runtime/nodes.go
index 99266ad..8ff20e1 100644
--- a/runtime/nodes.go
+++ b/runtime/nodes.go
@@ -41,11 +41,16 @@ func (nodes *Nodes) AddNode(n *yanic.Node) {
if cNode := nodes.List[node.NodeID]; cNode != nil {
cNode.Lastseen = time.Now()
- if _, ok := nodes.ToUpdate[node.NodeID]; ok {
+ cNode.Stats = node.Stats
+ if uNode, ok := nodes.ToUpdate[node.NodeID]; ok {
+ uNode.Lastseen = time.Now()
+ uNode.Stats = node.Stats
if nodes.List[node.NodeID].IsEqual(node) {
delete(nodes.ToUpdate, node.NodeID)
nodes.List[node.NodeID] = node
nodes.notify(node, true)
+ } else {
+ nodes.notify(uNode, false)
}
} else {
nodes.List[node.NodeID] = node
diff --git a/webroot/index.html b/webroot/index.html
index d79351d..98f9e9c 100644
--- a/webroot/index.html
+++ b/webroot/index.html
@@ -4,6 +4,7 @@
FreifunkManager
+
@@ -21,6 +22,7 @@
Karten & Knoten...
+
diff --git a/webroot/js/gui.js b/webroot/js/gui.js
index 2e647b7..afe150c 100644
--- a/webroot/js/gui.js
+++ b/webroot/js/gui.js
@@ -10,9 +10,8 @@ var gui = {};
console.log(store.will())
}
gui.disable = function disable(err){
- document.querySelector('.loader').innerHTML += err
- + '
';
- console.warn(err);
+ document.querySelector('.loader p.error').innerHTML = err
+ + '
';
};
gui.connecting = function connecting(){
diff --git a/webroot/js/socket.js b/webroot/js/socket.js
index 8cd3a94..33358f3 100644
--- a/webroot/js/socket.js
+++ b/webroot/js/socket.js
@@ -1,35 +1,51 @@
-var socket = new WebSocket(config.backend);
+var socket = {};
(function(){
- // When the connection is open, send some data to the server
- socket.onopen = function () {
+
+ function onerror(err) {
+ gui.disable("Es besteht ein Verbindungsproblem!");
+ console.warn(err);
+ }
+
+ function onopen() {
gui.enable();
- };
+ }
- // Log errors
- socket.onerror = function (err) {
- gui.disable(err);
- };
-
- // Log messages from the server
- socket.onmessage = function (e) {
+ function onmessage(e) {
var msg = JSON.parse(e.data);
- if(msg.state === "current") {
+ if(msg.type === "current") {
store.updateReal(msg.node);
gui.render();
- } else if (msg.state === "to-update") {
+ } else if (msg.type === "to-update") {
store.update(msg.node);
gui.render();
} else {
gui.disable(e);
}
- };
+ }
- socket.sendnode = function(node) {
+ function onclose(){
+ gui.disable("Es besteht ein Verbindungsproblem!
(Automatische Neuverbindung)");
+ console.log("socket closed by server");
+ setTimeout(connect, 5000);
+ }
+
+ function sendnode(node) {
var msg = {node:node};
var string = JSON.stringify(msg);
socket.send(string);
- };
+ }
+
+ function connect() {
+ socket = new WebSocket(config.backend);
+ socket.onopen = onopen;
+ socket.onerror = onerror;
+ socket.onmessage = onmessage;
+ socket.onclose = onclose;
+ socket.sendnode = sendnode;
+ }
+
+ connect();
})();
diff --git a/websocket/client.go b/websocket/client.go
index b2c4fb1..24a8f73 100644
--- a/websocket/client.go
+++ b/websocket/client.go
@@ -11,27 +11,25 @@ import (
const channelBufSize = 100
type Client struct {
- ip string
- ws *websocket.Conn
- ch chan *Message
- doneCh chan bool
-}
-
-func disconnect(c *Client) {
- delete(clients, c.ip)
+ ip string
+ ws *websocket.Conn
+ ch chan *Message
+ writeQuit chan bool
+ readQuit chan bool
}
func NewClient(ip string, ws *websocket.Conn) *Client {
if ws == nil {
- panic("ws cannot be nil")
+ log.Log.Panic("ws cannot be nil")
}
return &Client{
- ws: ws,
- ch: make(chan *Message, channelBufSize),
- doneCh: make(chan bool),
- ip: ip,
+ ws: ws,
+ ch: make(chan *Message, channelBufSize),
+ writeQuit: make(chan bool),
+ readQuit: make(chan bool),
+ ip: ip,
}
}
@@ -39,22 +37,15 @@ func (c *Client) Write(msg *Message) {
select {
case c.ch <- msg:
default:
- disconnect(c)
- log.HTTP(c.ws.Request()).Error("client is disconnected.")
+ delete(clients, c.ip)
+ log.HTTP(c.ws.Request()).Error("client disconnected")
}
}
-func (c *Client) Done() {
- c.doneCh <- true
-}
-
-func (c *Client) allNodes() {
- for _, node := range nodes.List {
- c.Write(&Message{State: StateCurrentNode, Node: node})
- }
- for _, node := range nodes.ToUpdate {
- c.Write(&Message{State: StateUpdateNode, Node: node})
- }
+func (c *Client) Close() {
+ c.writeQuit <- true
+ c.readQuit <- true
+ log.HTTP(c.ws.Request()).Info("client disconnecting...")
}
// Listen Write and Read request via chanel
@@ -64,6 +55,22 @@ func (c *Client) Listen() {
c.listenRead()
}
+func (c *Client) allNodes() {
+ for _, node := range nodes.List {
+ c.Write(&Message{Type: MessageTypeCurrentNode, Node: node})
+ }
+ for _, node := range nodes.ToUpdate {
+ c.Write(&Message{Type: MessageTypeUpdateNode, Node: node})
+ }
+}
+
+func (c *Client) handleMassage(msg *Message) {
+ switch msg.Type {
+ case MessageTypeUpdateNode:
+ nodes.UpdateNode(msg.Node)
+ }
+}
+
// Listen write request via chanel
func (c *Client) listenWrite() {
for {
@@ -71,9 +78,10 @@ func (c *Client) listenWrite() {
case msg := <-c.ch:
websocket.JSON.Send(c.ws, msg)
- case <-c.doneCh:
- disconnect(c)
- c.doneCh <- true
+ case <-c.writeQuit:
+ close(c.ch)
+ close(c.writeQuit)
+ delete(clients, c.ip)
return
}
}
@@ -84,22 +92,22 @@ func (c *Client) listenRead() {
for {
select {
- case <-c.doneCh:
- disconnect(c)
- c.doneCh <- true
+ case <-c.readQuit:
+ close(c.readQuit)
+ delete(clients, c.ip)
return
default:
var msg Message
err := websocket.JSON.Receive(c.ws, &msg)
if err == io.EOF {
- log.HTTP(c.ws.Request()).Info("disconnect")
- c.doneCh <- true
+ close(c.readQuit)
+ c.writeQuit <- true
+ return
} else if err != nil {
log.HTTP(c.ws.Request()).Error(err)
} else {
- log.HTTP(c.ws.Request()).Info("recieve nodeupdate")
- nodes.UpdateNode(msg.Node)
+ c.handleMassage(&msg)
}
}
}
diff --git a/websocket/msg.go b/websocket/msg.go
index e3f716a..daeec1f 100644
--- a/websocket/msg.go
+++ b/websocket/msg.go
@@ -3,11 +3,11 @@ package websocket
import "github.com/FreifunkBremen/freifunkmanager/runtime"
type Message struct {
- State string `json:"state"`
- Node *runtime.Node `json:"node"`
+ Type string `json:"type"`
+ Node *runtime.Node `json:"node"`
}
const (
- StateUpdateNode = "to-update"
- StateCurrentNode = "current"
+ MessageTypeUpdateNode = "to-update"
+ MessageTypeCurrentNode = "current"
)
diff --git a/websocket/server.go b/websocket/server.go
index 7a520a7..a7c3ec5 100644
--- a/websocket/server.go
+++ b/websocket/server.go
@@ -12,48 +12,42 @@ import (
var nodes *runtime.Nodes
var clients map[string]*Client
-var quit chan struct{}
func Start(nodeBind *runtime.Nodes) {
nodes = nodeBind
clients = make(map[string]*Client)
- quit = make(chan struct{})
http.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) {
+ r := ws.Request()
+ ip := httpLib.GetRemoteIP(r)
+
defer func() {
ws.Close()
+ delete(clients, ip)
+ log.HTTP(r).Info("client disconnected")
}()
- r := ws.Request()
+
log.HTTP(r).Infof("new client")
- ip := httpLib.GetRemoteIP(r)
+
client := NewClient(ip, ws)
clients[ip] = client
client.Listen()
+
}))
nodes.AddNotify(Notify)
- /*
- for {
- select {
- case <-quit:
- return
- }
- }*/
}
func Notify(node *runtime.Node, real bool) {
- state := StateUpdateNode
+ msgType := MessageTypeUpdateNode
if real {
- state = StateCurrentNode
+ msgType = MessageTypeCurrentNode
}
for _, c := range clients {
- c.Write(&Message{State: state, Node: node})
+ c.Write(&Message{Type: msgType, Node: node})
}
}
func Close() {
- for _, c := range clients {
- c.Done()
- }
- close(quit)
+ log.Log.Infof("websocket stopped with %d clients", len(clients))
}
diff --git a/yanic/dial.go b/yanic/dial.go
index 9bece08..87b16eb 100644
--- a/yanic/dial.go
+++ b/yanic/dial.go
@@ -38,9 +38,11 @@ func (d *Dialer) Start() {
go d.parser()
}
func (d *Dialer) Close() {
- close(d.quit)
- d.conn.Close()
- close(d.queue)
+ if d != nil {
+ d.conn.Close()
+ close(d.queue)
+ close(d.quit)
+ }
}
func (d *Dialer) reciever() {