[BUGFIX] improve websocket and stats of nodes

This commit is contained in:
Martin Geno 2017-05-09 01:03:44 +02:00
parent 9579f62815
commit 24248d3673
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
9 changed files with 108 additions and 82 deletions

View File

@ -64,7 +64,7 @@ func main() {
go func() {
if err := srv.ListenAndServe(); err != nil {
panic(err)
log.Log.Panic(err)
}
}()

View File

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

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>FreifunkManager</title>
<link rel="stylesheet" href="/node_modules/semantic-ui-css/semantic.min.css">
<link rel="stylesheet" href="/css/main.css">
<script src="//localhost:35729/livereload.js"></script>
<script src="/js/config.js"></script>
@ -21,6 +22,7 @@
<br />
Karten &amp; Knoten...
</p>
<p class="error"></p>
<noscript>
<strong>JavaScript required</strong>
</noscript>

View File

@ -10,9 +10,8 @@ var gui = {};
console.log(store.will())
}
gui.disable = function disable(err){
document.querySelector('.loader').innerHTML += err
+ '<br /><br /><button onclick="location.reload(true)" class="btn text">Try to reload</button>';
console.warn(err);
document.querySelector('.loader p.error').innerHTML = err
+ '<br /><br /><button onclick="location.reload(true)" class="ui labeled icon button"><i class="bomb icon"></i>Try to reload</button>';
};
gui.connecting = function connecting(){

View File

@ -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!<br/> <small>(Automatische Neuverbindung)</small>");
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();
})();

View File

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

View File

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

View File

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

View File

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