From 399ad486f5854c0a624396cd09ae9902cdde64f6 Mon Sep 17 00:00:00 2001 From: Mihail Slobodyanuk Date: Thu, 22 Dec 2022 13:35:49 +0200 Subject: [PATCH] get peers update moved to sse --- contrib/ui/mesh-ui/ui/assets/mesh-ui-es5.js | 29 ++++---- contrib/ui/mesh-ui/ui/assets/mesh-ui.js | 35 +++++----- go.mod | 5 +- go.sum | 2 + src/core/core.go | 20 +++--- src/core/link.go | 4 ++ src/restapi/rest_server.go | 75 +++++++++++++-------- 7 files changed, 99 insertions(+), 71 deletions(-) diff --git a/contrib/ui/mesh-ui/ui/assets/mesh-ui-es5.js b/contrib/ui/mesh-ui/ui/assets/mesh-ui-es5.js index d8bdf6b8..915f3d38 100644 --- a/contrib/ui/mesh-ui/ui/assets/mesh-ui-es5.js +++ b/contrib/ui/mesh-ui/ui/assets/mesh-ui-es5.js @@ -298,15 +298,20 @@ ui.getConnectedPeers = function () { }; ui.updateConnectedPeersHandler = function (peers) { + ui.updateStatus(peers); + ui.updateSpeed(peers); $("peers").innerText = ""; - var regexStrip = /%[^\]]*/gm; - peers.forEach(function (peer) { - var row = $("peers").appendChild(document.createElement('div')); - row.className = "overflow-ellipsis"; - var flag = row.appendChild(document.createElement("span")); - if (peer.isMulticast) flag.className = "fa fa-thin fa-share-nodes peer-connected-fl";else flag.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer.url) + " peer-connected-fl"; - row.append(peer.url.replace(regexStrip, "")); - }); + if (peers) { + var regexStrip = /%[^\]]*/gm; + peers.forEach(function (peer) { + var row = $("peers").appendChild(document.createElement('div')); + row.className = "overflow-ellipsis"; + var flag = row.appendChild(document.createElement("span")); + if (peer.multicast) flag.className = "fa fa-thin fa-share-nodes peer-connected-fl"; + else flag.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer.remote) + " peer-connected-fl"; + row.append(peer.remote.replace(regexStrip, "")); + }); + } }; ui.updateStatus = function (peers) { @@ -350,13 +355,10 @@ ui.updateSpeed = function (peers) { ui.updateConnectedPeers = function () { return ui.getConnectedPeers().then(function (peers) { - ui.updateConnectedPeersHandler(peers); - ui.updateStatus(peers); - ui.updateSpeed(peers); + return ui.updateConnectedPeersHandler(peers); }).catch(function (error) { + ui.updateConnectedPeersHandler(); $("peers").innerText = error.message; - ui.updateStatus(); - ui.updateSpeed(); }); }; @@ -397,7 +399,6 @@ function main() { ui.getAllPeers().then(function () { return ui.updateConnectedPeers(); }); - setInterval(ui.updateConnectedPeers, 5000); ui.updateSelfInfo(); //setInterval(ui.updateSelfInfo, 5000); diff --git a/contrib/ui/mesh-ui/ui/assets/mesh-ui.js b/contrib/ui/mesh-ui/ui/assets/mesh-ui.js index 37c94af0..f7652047 100644 --- a/contrib/ui/mesh-ui/ui/assets/mesh-ui.js +++ b/contrib/ui/mesh-ui/ui/assets/mesh-ui.js @@ -285,18 +285,22 @@ ui.getConnectedPeers = () => .then((response) => response.json()) ui.updateConnectedPeersHandler = (peers) => { + ui.updateStatus(peers); + ui.updateSpeed(peers); $("peers").innerText = ""; - const regexStrip = /%[^\]]*/gm; - peers.forEach(peer => { - let row = $("peers").appendChild(document.createElement('div')); - row.className = "overflow-ellipsis" - let flag = row.appendChild(document.createElement("span")); - if(peer.isMulticast) - flag.className = "fa fa-thin fa-share-nodes peer-connected-fl"; - else - flag.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer.url) + " peer-connected-fl"; - row.append(peer.url.replace(regexStrip, "")); - }); + if(peers) { + const regexStrip = /%[^\]]*/gm; + peers.forEach(peer => { + let row = $("peers").appendChild(document.createElement('div')); + row.className = "overflow-ellipsis" + let flag = row.appendChild(document.createElement("span")); + if(peer.multicast) + flag.className = "fa fa-thin fa-share-nodes peer-connected-fl"; + else + flag.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer.remote) + " peer-connected-fl"; + row.append(peer.remote.replace(regexStrip, "")); + }); + } } ui.updateStatus = peers => { @@ -332,14 +336,10 @@ ui.updateSpeed = peers => { ui.updateConnectedPeers = () => ui.getConnectedPeers() - .then(peers => {ui.updateConnectedPeersHandler(peers); - ui.updateStatus(peers); - ui.updateSpeed(peers); - }) + .then(peers => ui.updateConnectedPeersHandler(peers)) .catch((error) => { + ui.updateConnectedPeersHandler(); $("peers").innerText = error.message; - ui.updateStatus(); - ui.updateSpeed(); }); ui.lookupCountryCodeByAddress = (address) => { @@ -374,7 +374,6 @@ function main() { $("showAllPeersBtn").addEventListener("click", ui.showAllPeers); ui.getAllPeers().then(() => ui.updateConnectedPeers()); - setInterval(ui.updateConnectedPeers, 5000); ui.updateSelfInfo(); //setInterval(ui.updateSelfInfo, 5000); diff --git a/go.mod b/go.mod index b32cd9a5..e9cf5569 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,10 @@ require ( require github.com/webview/webview v0.0.0-20221220082822-77e021440a0f -require github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect +require ( + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect + github.com/vorot93/golang-signals v0.0.0-20170221070717-d9e83421ce45 // indirect +) require ( github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 diff --git a/go.sum b/go.sum index 69abf0e4..53d3cd3f 100644 --- a/go.sum +++ b/go.sum @@ -98,6 +98,8 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vorot93/golang-signals v0.0.0-20170221070717-d9e83421ce45 h1:hB/hkjwf3BQnZE6Wk3SBwMJz0NqnGdwXoNzHVSYb0N0= +github.com/vorot93/golang-signals v0.0.0-20170221070717-d9e83421ce45/go.mod h1:dfjQkJsG5auteUbnfLIcU72Y/z8tj7DuW9fik8f2Zn0= github.com/webview/webview v0.0.0-20221218140943-9db4b8c3e9af h1:QO77Qt3ucuL5l8tFIAMXrLaDx4rYI9Nz89x+nrJwYJo= github.com/webview/webview v0.0.0-20221218140943-9db4b8c3e9af/go.mod h1:rpXAuuHgyEJb6kXcXldlkOjU6y4x+YcASKKXJNUhh0Y= github.com/webview/webview v0.0.0-20221220082822-77e021440a0f h1:whomWpMJmyN9uHtIjBIE2jmjN8ZccngNh3kCg4G16FA= diff --git a/src/core/core.go b/src/core/core.go index 67a4fb55..24dc3782 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -13,6 +13,7 @@ import ( iwt "github.com/Arceliar/ironwood/types" "github.com/Arceliar/phony" "github.com/gologme/log" + signals "github.com/vorot93/golang-signals" "github.com/RiV-chain/RiV-mesh/src/version" ) @@ -25,15 +26,16 @@ type Core struct { // guarantee that it will be covered by the mutex phony.Inbox *iwe.PacketConn - ctx context.Context - cancel context.CancelFunc - secret ed25519.PrivateKey - public ed25519.PublicKey - links links - proto protoHandler - log Logger - addPeerTimer *time.Timer - config struct { + ctx context.Context + cancel context.CancelFunc + secret ed25519.PrivateKey + public ed25519.PublicKey + links links + proto protoHandler + log Logger + addPeerTimer *time.Timer + PeersChangedSignal signals.Signal + config struct { _peers map[Peer]*linkInfo // configurable after startup _listeners map[ListenAddress]struct{} // configurable after startup nodeinfo NodeInfo // immutable after startup diff --git a/src/core/link.go b/src/core/link.go index a9a24218..f01997dc 100644 --- a/src/core/link.go +++ b/src/core/link.go @@ -199,6 +199,9 @@ func (intf *link) handler(dial *linkDial) error { intf.links.core.log.Infof("Connected %s %s: %s, source %s", dir, strings.ToUpper(intf.info.linkType), remoteStr, localStr) + time.AfterFunc(time.Millisecond*500, func() { + intf.links.core.PeersChangedSignal.Emit(nil) + }) err = intf.links.core.HandleConn(meta.key, intf.conn, intf.options.priority) switch err { case io.EOF, net.ErrClosed, nil: @@ -208,6 +211,7 @@ func (intf *link) handler(dial *linkDial) error { intf.links.core.log.Infof("Disconnected %s %s: %s, source %s; error: %s", dir, strings.ToUpper(intf.info.linkType), remoteStr, localStr, err) } + intf.links.core.PeersChangedSignal.Emit(nil) if !intf.incoming && dial != nil { // The connection was one that we dialled, so wait a second and try to diff --git a/src/restapi/rest_server.go b/src/restapi/rest_server.go index 243b8329..4b4ecb6c 100644 --- a/src/restapi/rest_server.go +++ b/src/restapi/rest_server.go @@ -46,7 +46,7 @@ type RestServer struct { func NewRestServer(cfg RestServerCfg) (*RestServer, error) { a := &RestServer{ RestServerCfg: cfg, - serverEvents: make(chan ServerEvent), + serverEvents: make(chan ServerEvent, 10), serverEventNextId: 0, } if cfg.ListenAddress == "none" || cfg.ListenAddress == "" { @@ -85,6 +85,18 @@ func NewRestServer(cfg RestServerCfg) (*RestServer, error) { http.HandleFunc("/api/ping", a.apiPingHandler) http.HandleFunc("/api/sse", a.apiSseHandler) + var _ = a.Core.PeersChangedSignal.Connect(func(data interface{}) { + b, err := a.prepareGetPeers() + if err != nil { + a.Log.Errorf("get peers failed: %w", err) + return + } + + select { + case a.serverEvents <- ServerEvent{Event: "peers", Data: string(b)}: + default: + } + }) return a, nil } @@ -134,6 +146,7 @@ func (a *RestServer) apiSelfHandler(w http.ResponseWriter, r *http.Request) { b, err := json.Marshal(result) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) + return } fmt.Fprint(w, string(b[:])) default: @@ -141,6 +154,36 @@ func (a *RestServer) apiSelfHandler(w http.ResponseWriter, r *http.Request) { } } +func (a *RestServer) prepareGetPeers() ([]byte, error) { + peers := a.Core.GetPeers() + response := make([]map[string]interface{}, 0, len(peers)) + for _, p := range peers { + addr := a.Core.AddrForKey(p.Key) + response = append(response, map[string]interface{}{ + "address": net.IP(addr[:]).String(), + "key": hex.EncodeToString(p.Key), + "port": p.Port, + "priority": uint64(p.Priority), // can't be uint8 thanks to gobind + "coords": p.Coords, + "remote": p.Remote, + "bytes_recvd": p.RXBytes, + "bytes_sent": p.TXBytes, + "uptime": p.Uptime.Seconds(), + "multicast": strings.Contains(p.Remote, "[fe80::"), + }) + } + sort.Slice(response, func(i, j int) bool { + if !response[i]["multicast"].(bool) && response[j]["multicast"].(bool) { + return true + } + if response[i]["priority"].(uint64) < response[j]["priority"].(uint64) { + return true + } + return response[i]["port"].(uint64) < response[j]["port"].(uint64) + }) + return json.Marshal(response) +} + func (a *RestServer) apiPeersHandler(w http.ResponseWriter, r *http.Request) { var handleDelete = func() error { err := a.Core.RemovePeers() @@ -186,36 +229,10 @@ func (a *RestServer) apiPeersHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": w.Header().Add("Content-Type", "application/json") - - peers := a.Core.GetPeers() - response := make([]map[string]interface{}, 0, len(peers)) - for _, p := range peers { - addr := a.Core.AddrForKey(p.Key) - response = append(response, map[string]interface{}{ - "address": net.IP(addr[:]).String(), - "key": hex.EncodeToString(p.Key), - "port": p.Port, - "priority": uint64(p.Priority), // can't be uint8 thanks to gobind - "coords": p.Coords, - "remote": p.Remote, - "bytes_recvd": p.RXBytes, - "bytes_sent": p.TXBytes, - "uptime": p.Uptime.Seconds(), - "mulicast": strings.Contains(p.Remote, "[fe80::"), - }) - } - sort.Slice(response, func(i, j int) bool { - if !response[i]["mulicast"].(bool) && response[j]["mulicast"].(bool) { - return true - } - if response[i]["priority"].(uint64) < response[j]["priority"].(uint64) { - return true - } - return response[i]["port"].(uint64) < response[j]["port"].(uint64) - }) - b, err := json.Marshal(response) + b, err := a.prepareGetPeers() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) + return } fmt.Fprint(w, string(b[:])) case "POST":