mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 14:15:06 +03:00
Migrated to REST backend RIVM-31
This commit is contained in:
parent
609ba1a3cd
commit
d68d3db702
9 changed files with 237 additions and 313 deletions
|
@ -57,7 +57,7 @@ cat > /tmp/$PKGNAME/usr/share/applications/riv.desktop << EOF
|
|||
Name=RiV mesh
|
||||
GenericName=Mesh network
|
||||
Comment=RiV-mesh is an early-stage implementation of a fully end-to-end encrypted IPv6 network
|
||||
Exec=sh -c "/usr/bin/mesh-ui http://localhost:19019"
|
||||
Exec=sh -c "/usr/bin/mesh-ui"
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=riv
|
||||
|
|
|
@ -54,7 +54,7 @@ cp contrib/macos/mesh.plist pkgbuild/root/Library/LaunchDaemons
|
|||
cat > pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS/open-mesh-ui << EOF
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exec /Applications/RiV-mesh.app/Contents/MacOS/mesh-ui http://localhost:19019 1>/tmp/mesh-ui.stdout.log 2>/tmp/mesh-ui.stderr.log
|
||||
exec /Applications/RiV-mesh.app/Contents/MacOS/mesh-ui 1>/tmp/mesh-ui.stdout.log 2>/tmp/mesh-ui.stderr.log
|
||||
EOF
|
||||
|
||||
# Create the postinstall script
|
||||
|
|
|
@ -272,7 +272,6 @@ cat > wix.xml << EOF
|
|||
<CustomAction Id="LaunchApplication"
|
||||
FileKey="MeshUI"
|
||||
Impersonate="yes"
|
||||
ExeCommand='"http://localhost:19019"'
|
||||
Return="asyncNoWait" />
|
||||
|
||||
<!-- Step 3: Include the custom action -->
|
||||
|
@ -291,7 +290,6 @@ cat > wix.xml << EOF
|
|||
Description="RiV-mesh is IoT E2E encrypted network"
|
||||
Directory="DesktopFolder"
|
||||
Target="[MeshInstallFolder]mesh-ui.exe"
|
||||
Arguments="http://localhost:19019"
|
||||
WorkingDirectory="MeshInstallFolder"/>
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\RiV-chain\RiV-mesh"
|
||||
|
@ -303,7 +301,7 @@ cat > wix.xml << EOF
|
|||
Key="Software\Microsoft\Windows\CurrentVersion\Run"
|
||||
Name="RiV-mesh client"
|
||||
Type="string"
|
||||
Value='"[MeshInstallFolder]mesh-ui.exe" "http://localhost:19019"' />
|
||||
Value='"[MeshInstallFolder]mesh-ui.exe"' />
|
||||
<Condition>ASSISTANCE_START_VIA_REGISTRY</Condition>
|
||||
</Component>
|
||||
|
||||
|
|
|
@ -120,13 +120,13 @@ function showWindow(text) {
|
|||
button_info_close.onclick = function () {
|
||||
message.value = "";
|
||||
info.classList.add("is-hidden");
|
||||
//$("peer_list").remove();
|
||||
$("peer_list").remove();
|
||||
};
|
||||
var button_window_close = $("window_close");
|
||||
button_window_close.onclick = function () {
|
||||
message.value = "";
|
||||
info.classList.add("is-hidden");
|
||||
//$("peer_list").remove();
|
||||
$("peer_list").remove();
|
||||
};
|
||||
var button_window_save = $("window_save");
|
||||
button_window_save.onclick = function () {
|
||||
|
@ -142,8 +142,18 @@ function showWindow(text) {
|
|||
peer_list.push(peerURL);
|
||||
}
|
||||
}
|
||||
savePeers(JSON.stringify(peer_list));
|
||||
//$("peer_list").remove();
|
||||
fetch('api/peers', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Riv-Save-Config': 'true',
|
||||
},
|
||||
body: JSON.stringify({"peers": peer_list}),
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
$("peer_list").remove();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -249,32 +259,44 @@ ui.showAllPeers = () =>
|
|||
.then((peerList) => {
|
||||
var peers = add_table(peerList);
|
||||
//start peers test
|
||||
ping(JSON.stringify(peers));
|
||||
fetch('api/ping', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(peers)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
ui.getConnectedPeers = () =>
|
||||
fetch('api/getpeers')
|
||||
fetch('api/peers')
|
||||
.then((response) => response.json())
|
||||
|
||||
ui.updateConnectedPeersHandler = (cont) => {
|
||||
$("peers").innerText = "";
|
||||
const regexStrip = /%[^\]]*/gm;
|
||||
const regexMulticast = /:\/\/\[fe80::/;
|
||||
cont.peers.forEach(peer => {
|
||||
let row = $("peers").appendChild(document.createElement('div'));
|
||||
let flag = row.appendChild(document.createElement("span"));
|
||||
if(peer["remote"].match(regexMulticast))
|
||||
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.updateConnectedPeers = () =>
|
||||
ui.getConnectedPeers()
|
||||
.then((cont) => {
|
||||
$("peers").innerText = "";
|
||||
const regexStrip = /%[^\]]*/gm;
|
||||
const regexMulticast = /:\/\/\[fe80::/;
|
||||
cont.peers.forEach(peer => {
|
||||
let row = $("peers").appendChild(document.createElement('div'));
|
||||
let flag = row.appendChild(document.createElement("span"));
|
||||
if(peer["remote"].match(regexMulticast))
|
||||
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, ""));
|
||||
});
|
||||
}).catch((error) => {
|
||||
.then(ui.updateConnectedPeersHandler)
|
||||
.catch((error) => {
|
||||
$("peers").innerText = error.message;
|
||||
});
|
||||
|
||||
|
@ -286,7 +308,7 @@ ui.lookupCountryCodeByAddress = (address) => {
|
|||
}
|
||||
|
||||
ui.getSelfInfo = () =>
|
||||
fetch('api/getself')
|
||||
fetch('api/self')
|
||||
.then((response) => response.json())
|
||||
|
||||
ui.updateSelfInfo = () =>
|
||||
|
@ -301,6 +323,7 @@ ui.updateSelfInfo = () =>
|
|||
$("ipv6").innerText = error.message;
|
||||
});
|
||||
|
||||
ui.sse = new EventSource('/api/sse');
|
||||
|
||||
function main() {
|
||||
|
||||
|
@ -315,7 +338,17 @@ function main() {
|
|||
setInterval(ui.updateConnectedPeers, 5000);
|
||||
|
||||
ui.updateSelfInfo();
|
||||
setInterval(ui.updateSelfInfo, 5000);
|
||||
//setInterval(ui.updateSelfInfo, 5000);
|
||||
|
||||
ui.sse.addEventListener("ping", (e) => {
|
||||
let data = JSON.parse(e.data);
|
||||
setPingValue(data.peer, data.value);
|
||||
})
|
||||
|
||||
ui.sse.addEventListener("peers", (e) => {
|
||||
ui.updateConnectedPeersHandler(JSON.parse(e.data));
|
||||
})
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,25 +2,14 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/RiV-chain/RiV-mesh/src/defaults"
|
||||
"github.com/hjson/hjson-go"
|
||||
"github.com/webview/webview"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
|
||||
"github.com/RiV-chain/RiV-mesh/src/admin"
|
||||
"github.com/RiV-chain/RiV-mesh/src/defaults"
|
||||
"github.com/docopt/docopt-go"
|
||||
)
|
||||
|
||||
|
@ -32,7 +21,7 @@ Usage:
|
|||
mesh-ui -v | --version
|
||||
|
||||
Options:
|
||||
<index> Index file name [default: index.html].
|
||||
<index> Index file name [default: http://localhost:19019].
|
||||
-c --console Show debug console window.
|
||||
-h --help Show this screen.
|
||||
-v --version Show version.`
|
||||
|
@ -55,224 +44,20 @@ func main() {
|
|||
defer w.Destroy()
|
||||
w.SetTitle("RiV-mesh")
|
||||
w.SetSize(690, 920, webview.HintFixed)
|
||||
/*1. Create ~/.riv-mesh folder if not existing
|
||||
*2. Create ~/.riv-mesh/mesh.conf if not existing
|
||||
*3. If the file exists read Peers.
|
||||
*3.1 Invoke add peers for each record
|
||||
*/
|
||||
mesh_folder := ".riv-mesh"
|
||||
mesh_conf := "mesh.conf"
|
||||
user_home := get_user_home_path()
|
||||
mesh_settings_folder := filepath.Join(user_home, mesh_folder)
|
||||
err := os.MkdirAll(mesh_settings_folder, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to create folder: %v", err)
|
||||
}
|
||||
mesh_settings_path := filepath.Join(user_home, mesh_folder, mesh_conf)
|
||||
if _, err := os.Stat(mesh_settings_path); os.IsNotExist(err) {
|
||||
err := ioutil.WriteFile(mesh_settings_path, []byte(""), 0750)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to write file: %v", err)
|
||||
}
|
||||
} else {
|
||||
//read peers from mesh.conf
|
||||
conf, _ := ioutil.ReadFile(mesh_settings_path)
|
||||
var dat map[string]interface{}
|
||||
if err := hjson.Unmarshal(conf, &dat); err != nil {
|
||||
fmt.Printf("Unable to parse mesh.conf file: %v", err)
|
||||
} else {
|
||||
if dat["Peers"] != nil {
|
||||
peers := dat["Peers"].([]interface{})
|
||||
remove_peers()
|
||||
for _, u := range peers {
|
||||
log.Printf("Unmarshaled: %v", u.(string))
|
||||
add_peers(u.(string))
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Warning: Peers array not loaded from mesh.conf file")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if confui.IndexHtml == "" {
|
||||
confui.IndexHtml = "index.html"
|
||||
confui.IndexHtml = getEndpoint()
|
||||
}
|
||||
//Check is it URL already
|
||||
indexUrl, err := url.ParseRequestURI(confui.IndexHtml)
|
||||
if err != nil || len(indexUrl.Scheme) < 2 { // handling no scheme at all and windows c:\ as scheme detection
|
||||
confui.IndexHtml, err = filepath.Abs(confui.IndexHtml)
|
||||
if err != nil {
|
||||
panic(errors.New("Index file not found: " + err.Error()))
|
||||
}
|
||||
if stat, err := os.Stat(confui.IndexHtml); err != nil {
|
||||
panic(errors.New(fmt.Sprintf("Index file %v not found or permissians denied: %v", confui.IndexHtml, err.Error())))
|
||||
} else if stat.IsDir() {
|
||||
panic(errors.New(fmt.Sprintf("Index file %v not found", confui.IndexHtml)))
|
||||
}
|
||||
path_prefix := ""
|
||||
if indexUrl != nil && len(indexUrl.Scheme) == 1 {
|
||||
path_prefix = "/"
|
||||
}
|
||||
indexUrl, err = url.ParseRequestURI("file://" + path_prefix + strings.ReplaceAll(confui.IndexHtml, "\\", "/"))
|
||||
if err != nil {
|
||||
panic(errors.New("Index file URL parse error: " + err.Error()))
|
||||
}
|
||||
if confui.IndexHtml == "" {
|
||||
confui.IndexHtml = "http://localhost:19019"
|
||||
}
|
||||
|
||||
w.Bind("savePeers", func(peer_list string) {
|
||||
//log.Println("peers saved ", peer_list)
|
||||
var peers []string
|
||||
_ = json.Unmarshal([]byte(peer_list), &peers)
|
||||
log.Printf("Unmarshaled: %v", peers)
|
||||
remove_peers()
|
||||
for _, u := range peers {
|
||||
log.Printf("Unmarshaled: %v", u)
|
||||
add_peers(u)
|
||||
}
|
||||
//add peers to ~/mesh.conf
|
||||
dat := make(map[string]interface{})
|
||||
dat["Peers"] = peers
|
||||
bs, _ := hjson.Marshal(dat)
|
||||
e := ioutil.WriteFile(mesh_settings_path, bs, 0750)
|
||||
if e != nil {
|
||||
fmt.Printf("Unable to write file: %v", e)
|
||||
}
|
||||
})
|
||||
w.Bind("ping", func(peer_list string) {
|
||||
go ping(w, peer_list)
|
||||
})
|
||||
log.Printf("Opening: %v", indexUrl)
|
||||
w.Navigate(indexUrl.String())
|
||||
log.Printf("Opening: %v", confui.IndexHtml)
|
||||
w.Navigate(confui.IndexHtml)
|
||||
w.Run()
|
||||
}
|
||||
|
||||
func ping(w webview.WebView, peer_list string) {
|
||||
var peers []string
|
||||
_ = json.Unmarshal([]byte(peer_list), &peers)
|
||||
log.Printf("Unmarshaled: %v", peers)
|
||||
for _, u := range peers {
|
||||
log.Printf("Unmarshaled: %v", u)
|
||||
ping_time := check(u)
|
||||
log.Printf("ping: %d", ping_time)
|
||||
setPingValue(w, u, strconv.FormatInt(ping_time, 10))
|
||||
}
|
||||
}
|
||||
|
||||
func check(peer string) int64 {
|
||||
u, e := url.Parse(peer)
|
||||
if e != nil {
|
||||
return -1
|
||||
}
|
||||
t := time.Now()
|
||||
_, err := net.DialTimeout("tcp", u.Host, 5*time.Second)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
d := time.Since(t)
|
||||
return d.Milliseconds()
|
||||
}
|
||||
|
||||
func add_peers(uri string) {
|
||||
_, err := run_command_with_arg("addpeers", "uri="+uri)
|
||||
if err != nil {
|
||||
log.Println("Error in the add_peers() call:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func remove_peers() {
|
||||
run_command("removepeers")
|
||||
}
|
||||
|
||||
func setPingValue(p webview.WebView, peer string, value string) {
|
||||
p.Dispatch(func() {
|
||||
p.Eval("setPingValue('" + peer + "','" + value + "');")
|
||||
})
|
||||
}
|
||||
|
||||
func run_command(command string) []byte {
|
||||
data, err := run_command_with_arg(command, "")
|
||||
if err != nil {
|
||||
log.Println("Error in the "+command+" call:", err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func run_command_with_arg(command string, arg string) ([]byte, error) {
|
||||
logbuffer := &bytes.Buffer{}
|
||||
logger := log.New(logbuffer, "", log.Flags())
|
||||
|
||||
wrapErr := func(err error) error {
|
||||
logger.Println("Error:", err)
|
||||
return errors.New(fmt.Sprintln(logbuffer))
|
||||
}
|
||||
|
||||
endpoint := getEndpoint(logger)
|
||||
|
||||
var conn net.Conn
|
||||
u, err := url.Parse(endpoint)
|
||||
d := net.Dialer{Timeout: 5000 * time.Millisecond}
|
||||
if err == nil {
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "unix":
|
||||
logger.Println("Connecting to UNIX socket", endpoint[7:])
|
||||
conn, err = d.Dial("unix", endpoint[7:])
|
||||
case "tcp":
|
||||
logger.Println("Connecting to TCP socket", u.Host)
|
||||
conn, err = d.Dial("tcp", u.Host)
|
||||
default:
|
||||
logger.Println("Unknown protocol or malformed address - check your endpoint")
|
||||
err = errors.New("protocol not supported")
|
||||
}
|
||||
} else {
|
||||
logger.Println("Connecting to TCP socket", u.Host)
|
||||
conn, err = d.Dial("tcp", endpoint)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, wrapErr(err)
|
||||
}
|
||||
|
||||
logger.Println("Connected")
|
||||
defer conn.Close()
|
||||
|
||||
decoder := json.NewDecoder(conn)
|
||||
encoder := json.NewEncoder(conn)
|
||||
send := &admin.AdminSocketRequest{}
|
||||
recv := &admin.AdminSocketResponse{}
|
||||
send.Name = command
|
||||
args := map[string]string{}
|
||||
switch {
|
||||
case len(arg) > 0:
|
||||
tokens := strings.SplitN(arg, "=", 2)
|
||||
args[tokens[0]] = tokens[1]
|
||||
default:
|
||||
}
|
||||
|
||||
if send.Arguments, err = json.Marshal(args); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := encoder.Encode(&send); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logger.Printf("Request sent")
|
||||
//js, _ := json.Marshal(send)
|
||||
//fmt.Println("sent:", string(js))
|
||||
if err := decoder.Decode(&recv); err != nil {
|
||||
return nil, wrapErr(err)
|
||||
}
|
||||
if recv.Status == "error" {
|
||||
if err := recv.Error; err != "" {
|
||||
return nil, wrapErr(errors.New("Admin socket returned an error:" + err))
|
||||
} else {
|
||||
return nil, wrapErr(errors.New("Admin socket returned an error but didn't specify any error text"))
|
||||
}
|
||||
}
|
||||
if json, err := json.MarshalIndent(recv.Response, "", " "); err == nil {
|
||||
return json, nil
|
||||
}
|
||||
return nil, wrapErr(err)
|
||||
}
|
||||
|
||||
func getEndpoint(logger *log.Logger) string {
|
||||
func getEndpoint() string {
|
||||
if config, err := os.ReadFile(defaults.GetDefaults().DefaultConfigFile); err == nil {
|
||||
if bytes.Equal(config[0:2], []byte{0xFF, 0xFE}) ||
|
||||
bytes.Equal(config[0:2], []byte{0xFE, 0xFF}) {
|
||||
|
@ -280,25 +65,16 @@ func getEndpoint(logger *log.Logger) string {
|
|||
decoder := utf.NewDecoder()
|
||||
config, err = decoder.Bytes(config)
|
||||
if err != nil {
|
||||
return defaults.GetDefaults().DefaultAdminListen
|
||||
return ""
|
||||
}
|
||||
}
|
||||
var dat map[string]interface{}
|
||||
if err := hjson.Unmarshal(config, &dat); err != nil {
|
||||
return defaults.GetDefaults().DefaultAdminListen
|
||||
return ""
|
||||
}
|
||||
if ep, ok := dat["AdminListen"].(string); ok && (ep != "none" && ep != "") {
|
||||
logger.Println("Found platform default config file", defaults.GetDefaults().DefaultConfigFile)
|
||||
logger.Println("Using endpoint", ep, "from AdminListen")
|
||||
if ep, ok := dat["HttpAddress"].(string); ok && (ep != "none" && ep != "") {
|
||||
return ep
|
||||
} else {
|
||||
logger.Println("Configuration file doesn't contain appropriate AdminListen option")
|
||||
logger.Println("Falling back to platform default", defaults.GetDefaults().DefaultAdminListen)
|
||||
return defaults.GetDefaults().DefaultAdminListen
|
||||
}
|
||||
} else {
|
||||
logger.Println("Can't open config file from default location", defaults.GetDefaults().DefaultConfigFile)
|
||||
logger.Println("Falling back to platform default", defaults.GetDefaults().DefaultAdminListen)
|
||||
return defaults.GetDefaults().DefaultAdminListen
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -3,16 +3,5 @@
|
|||
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
func get_user_home_path() string {
|
||||
path, exists := os.LookupEnv("HOME")
|
||||
if exists {
|
||||
return path
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func Console(show bool) {
|
||||
}
|
||||
|
|
|
@ -4,19 +4,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func get_user_home_path() string {
|
||||
path, exists := os.LookupEnv("USERPROFILE")
|
||||
if exists {
|
||||
return path
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func Console(show bool) {
|
||||
var getWin = syscall.NewLazyDLL("kernel32.dll").NewProc("GetConsoleWindow")
|
||||
var showWin = syscall.NewLazyDLL("user32.dll").NewProc("ShowWindow")
|
||||
|
|
|
@ -13,7 +13,7 @@ var ed = {
|
|||
var d = new Date();
|
||||
d.setTime(d.getTime() + (10 * 60 * 1000));
|
||||
document.cookie = "access_key=" + btoa( "user=" + encodeURIComponent($('#nasInputUser').val()) + ";pwd=" + encodeURIComponent($('#nasInputPassword').val()))+ "; expires=" + d.toUTCString() + "; path=/";
|
||||
$.ajax({url: "api/getself"}).done(function () {
|
||||
$.ajax({url: "api/self"}).done(function () {
|
||||
window.location.reload();
|
||||
}).fail(function () {
|
||||
ed.nasLogoutCall();
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"archive/zip"
|
||||
"strings"
|
||||
|
@ -22,13 +23,20 @@ import (
|
|||
|
||||
// TODO: Add authentication
|
||||
|
||||
type ServerEvent struct {
|
||||
event string
|
||||
data string
|
||||
}
|
||||
|
||||
type AdminSocket struct {
|
||||
core *core.Core
|
||||
log core.Logger
|
||||
listener net.Listener
|
||||
handlers map[string]handler
|
||||
done chan struct{}
|
||||
config struct {
|
||||
core *core.Core
|
||||
log core.Logger
|
||||
listener net.Listener
|
||||
handlers map[string]handler
|
||||
done chan struct{}
|
||||
serverEvents chan ServerEvent
|
||||
serverEventNextId int
|
||||
config struct {
|
||||
listenaddr ListenAddress
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +111,7 @@ func New(c *core.Core, log core.Logger, opts ...SetupOption) (*AdminSocket, erro
|
|||
return res, nil
|
||||
})
|
||||
a.done = make(chan struct{})
|
||||
a.serverEvents = make(chan ServerEvent)
|
||||
go a.listen()
|
||||
return a, a.core.SetAdmin(a)
|
||||
}
|
||||
|
@ -247,33 +256,139 @@ func (a *AdminSocket) StartHttpServer(nc *config.NodeConfig) {
|
|||
http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Following methods are allowed: getself, getpeers. litening"+u.Host)
|
||||
})
|
||||
http.HandleFunc("/api/getself", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
req := &GetSelfRequest{}
|
||||
res := &GetSelfResponse{}
|
||||
if err := a.getSelfHandler(req, res); err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
http.HandleFunc("/api/self", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
req := &GetSelfRequest{}
|
||||
res := &GetSelfResponse{}
|
||||
if err := a.getSelfHandler(req, res); err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
fmt.Fprint(w, string(b[:]))
|
||||
default:
|
||||
http.Error(w, "Method Not Allowed", 405)
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
fmt.Fprint(w, string(b[:]))
|
||||
})
|
||||
http.HandleFunc("/api/getpeers", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
req := &GetPeersRequest{}
|
||||
res := &GetPeersResponse{}
|
||||
http.HandleFunc("/api/peers", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
req := &GetPeersRequest{}
|
||||
res := &GetPeersResponse{}
|
||||
|
||||
if err := a.getPeersHandler(req, res); err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
if err := a.getPeersHandler(req, res); err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
fmt.Fprint(w, string(b[:]))
|
||||
case "POST":
|
||||
req := &AddPeersRequest{}
|
||||
res := &AddPeersResponse{}
|
||||
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.addPeersHandler(req, res); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprint(w, string(b[:]))
|
||||
case "PUT":
|
||||
err := a.core.RemovePeers()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
req := &AddPeersRequest{}
|
||||
res := &AddPeersResponse{}
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.addPeersHandler(req, res); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprint(w, string(b[:]))
|
||||
//TODO save peers
|
||||
// saveHeaders := r.Header["Riv-Save-Config"]
|
||||
// if len(saveHeaders) > 0 && saveHeaders[0] == "true" {
|
||||
// nc.Peers =
|
||||
// }
|
||||
case "DELETE":
|
||||
err := a.core.RemovePeers()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
http.Error(w, "No content", http.StatusNoContent)
|
||||
default:
|
||||
http.Error(w, "Method Not Allowed", 405)
|
||||
}
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 503)
|
||||
}
|
||||
fmt.Fprint(w, string(b[:]))
|
||||
})
|
||||
http.HandleFunc("/api/ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
peer_list := []string{}
|
||||
|
||||
err := json.NewDecoder(r.Body).Decode(&peer_list)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
go a.ping(peer_list)
|
||||
http.Error(w, "Accepted", http.StatusAccepted)
|
||||
default:
|
||||
http.Error(w, "Method Not Allowed", 405)
|
||||
}
|
||||
})
|
||||
|
||||
http.HandleFunc("/api/sse", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
w.Header().Add("Content-Type", "text/event-stream")
|
||||
Loop:
|
||||
for {
|
||||
select {
|
||||
case v := <-a.serverEvents:
|
||||
fmt.Fprintln(w, "id:", a.serverEventNextId)
|
||||
fmt.Fprintln(w, "event:", v.event)
|
||||
fmt.Fprintln(w, "data:", v.data)
|
||||
fmt.Fprintln(w) //end of event
|
||||
a.serverEventNextId += 1
|
||||
default:
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
default:
|
||||
http.Error(w, "Method Not Allowed", 405)
|
||||
}
|
||||
})
|
||||
|
||||
var docFs = ""
|
||||
pakReader, err := zip.OpenReader(nc.WwwRoot)
|
||||
if err == nil {
|
||||
|
@ -300,6 +415,29 @@ func (a *AdminSocket) StartHttpServer(nc *config.NodeConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *AdminSocket) ping(peers []string) {
|
||||
for _, u := range peers {
|
||||
go func(u string) {
|
||||
data, _ := json.Marshal(map[string]string{"peer": u, "value": strconv.FormatInt(check(u), 10)})
|
||||
a.serverEvents <- ServerEvent{event: "ping", data: string(data)}
|
||||
}(u)
|
||||
}
|
||||
}
|
||||
|
||||
func check(peer string) int64 {
|
||||
u, e := url.Parse(peer)
|
||||
if e != nil {
|
||||
return -1
|
||||
}
|
||||
t := time.Now()
|
||||
_, err := net.DialTimeout("tcp", u.Host, 5*time.Second)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
d := time.Since(t)
|
||||
return d.Milliseconds()
|
||||
}
|
||||
|
||||
// IsStarted returns true if the module has been started.
|
||||
func (a *AdminSocket) IsStarted() bool {
|
||||
select {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue