mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 22:25:07 +03:00
Admin socket and yggdrasilctl
refactoring (#939)
This commit is contained in:
parent
4f2abece81
commit
c6fe81b5d2
11 changed files with 401 additions and 470 deletions
|
@ -7,6 +7,7 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -28,13 +29,17 @@ type AdminSocket struct {
|
|||
done chan struct{}
|
||||
}
|
||||
|
||||
type AdminSocketRequest struct {
|
||||
Name string `json:"request"`
|
||||
Arguments map[string]string `json:"arguments,omitempty"`
|
||||
KeepAlive bool `json:"keepalive,omitempty"`
|
||||
}
|
||||
|
||||
type AdminSocketResponse struct {
|
||||
Status string `json:"status"`
|
||||
Request struct {
|
||||
Name string `json:"request"`
|
||||
KeepAlive bool `json:"keepalive"`
|
||||
} `json:"request"`
|
||||
Response interface{} `json:"response"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Request AdminSocketRequest `json:"request"`
|
||||
Response json.RawMessage `json:"response"`
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
|
@ -43,11 +48,12 @@ type handler struct {
|
|||
}
|
||||
|
||||
type ListResponse struct {
|
||||
List map[string]ListEntry `json:"list"`
|
||||
List []ListEntry `json:"list"`
|
||||
}
|
||||
|
||||
type ListEntry struct {
|
||||
Fields []string `json:"fields"`
|
||||
Command string `json:"command"`
|
||||
Fields []string `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// AddHandler is called for each admin function to add the handler and help documentation to the API.
|
||||
|
@ -73,14 +79,16 @@ func (a *AdminSocket) Init(c *core.Core, nc *config.NodeConfig, log *log.Logger,
|
|||
a.done = make(chan struct{})
|
||||
close(a.done) // Start in a done / not-started state
|
||||
_ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) {
|
||||
res := &ListResponse{
|
||||
List: map[string]ListEntry{},
|
||||
}
|
||||
res := &ListResponse{}
|
||||
for name, handler := range a.handlers {
|
||||
res.List[name] = ListEntry{
|
||||
Fields: handler.args,
|
||||
}
|
||||
res.List = append(res.List, ListEntry{
|
||||
Command: name,
|
||||
Fields: handler.args,
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.List, func(i, j int) bool {
|
||||
return strings.Compare(res.List[i].Command, res.List[j].Command) < 0
|
||||
})
|
||||
return res, nil
|
||||
})
|
||||
return a.core.SetAdmin(a)
|
||||
|
@ -277,22 +285,28 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
|||
if err = json.Unmarshal(buf, &resp.Request); err == nil {
|
||||
if resp.Request.Name == "" {
|
||||
resp.Status = "error"
|
||||
resp.Response = &ErrorResponse{
|
||||
resp.Response, _ = json.Marshal(ErrorResponse{
|
||||
Error: "No request specified",
|
||||
}
|
||||
})
|
||||
} else if h, ok := a.handlers[strings.ToLower(resp.Request.Name)]; ok {
|
||||
resp.Response, err = h.handler(buf)
|
||||
res, err := h.handler(buf)
|
||||
if err != nil {
|
||||
resp.Status = "error"
|
||||
resp.Response = &ErrorResponse{
|
||||
resp.Response, _ = json.Marshal(ErrorResponse{
|
||||
Error: err.Error(),
|
||||
}
|
||||
})
|
||||
}
|
||||
if resp.Response, err = json.Marshal(res); err != nil {
|
||||
resp.Status = "error"
|
||||
resp.Response, _ = json.Marshal(ErrorResponse{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
resp.Status = "error"
|
||||
resp.Response = &ErrorResponse{
|
||||
resp.Response, _ = json.Marshal(ErrorResponse{
|
||||
Error: fmt.Sprintf("Unknown action '%s', try 'list' for help", resp.Request.Name),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if err = encoder.Encode(resp); err != nil {
|
||||
|
@ -305,3 +319,16 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
type DataUnit uint64
|
||||
|
||||
func (d DataUnit) String() string {
|
||||
switch {
|
||||
case d > 1024*1024*1024:
|
||||
return fmt.Sprintf("%2.fgb", float64(d)/1024/1024/1024)
|
||||
case d > 1024*1024:
|
||||
return fmt.Sprintf("%2.fmb", float64(d)/1024/1024)
|
||||
default:
|
||||
return fmt.Sprintf("%2.fkb", float64(d)/1024)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
)
|
||||
|
@ -10,25 +12,30 @@ import (
|
|||
type GetDHTRequest struct{}
|
||||
|
||||
type GetDHTResponse struct {
|
||||
DHT map[string]DHTEntry `json:"dht"`
|
||||
DHT []DHTEntry `json:"dht"`
|
||||
}
|
||||
|
||||
type DHTEntry struct {
|
||||
IPAddress string `json:"address"`
|
||||
PublicKey string `json:"key"`
|
||||
Port uint64 `json:"port"`
|
||||
Rest uint64 `json:"rest"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getDHTHandler(req *GetDHTRequest, res *GetDHTResponse) error {
|
||||
res.DHT = map[string]DHTEntry{}
|
||||
for _, d := range a.core.GetDHT() {
|
||||
dht := a.core.GetDHT()
|
||||
res.DHT = make([]DHTEntry, 0, len(dht))
|
||||
for _, d := range dht {
|
||||
addr := address.AddrForKey(d.Key)
|
||||
so := net.IP(addr[:]).String()
|
||||
res.DHT[so] = DHTEntry{
|
||||
res.DHT = append(res.DHT, DHTEntry{
|
||||
IPAddress: net.IP(addr[:]).String(),
|
||||
PublicKey: hex.EncodeToString(d.Key[:]),
|
||||
Port: d.Port,
|
||||
Rest: d.Rest,
|
||||
}
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.DHT, func(i, j int) bool {
|
||||
return strings.Compare(res.DHT[i].PublicKey, res.DHT[j].PublicKey) < 0
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
)
|
||||
|
@ -11,23 +13,28 @@ type GetPathsRequest struct {
|
|||
}
|
||||
|
||||
type GetPathsResponse struct {
|
||||
Paths map[string]PathEntry `json:"paths"`
|
||||
Paths []PathEntry `json:"paths"`
|
||||
}
|
||||
|
||||
type PathEntry struct {
|
||||
IPAddress string `json:"address"`
|
||||
PublicKey string `json:"key"`
|
||||
Path []uint64 `json:"path"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getPathsHandler(req *GetPathsRequest, res *GetPathsResponse) error {
|
||||
res.Paths = map[string]PathEntry{}
|
||||
for _, p := range a.core.GetPaths() {
|
||||
paths := a.core.GetPaths()
|
||||
res.Paths = make([]PathEntry, 0, len(paths))
|
||||
for _, p := range paths {
|
||||
addr := address.AddrForKey(p.Key)
|
||||
so := net.IP(addr[:]).String()
|
||||
res.Paths[so] = PathEntry{
|
||||
res.Paths = append(res.Paths, PathEntry{
|
||||
IPAddress: net.IP(addr[:]).String(),
|
||||
PublicKey: hex.EncodeToString(p.Key),
|
||||
Path: p.Path,
|
||||
}
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Paths, func(i, j int) bool {
|
||||
return strings.Compare(res.Paths[i].PublicKey, res.Paths[j].PublicKey) < 0
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
)
|
||||
|
@ -11,33 +12,38 @@ type GetPeersRequest struct {
|
|||
}
|
||||
|
||||
type GetPeersResponse struct {
|
||||
Peers map[string]PeerEntry `json:"peers"`
|
||||
Peers []PeerEntry `json:"peers"`
|
||||
}
|
||||
|
||||
type PeerEntry struct {
|
||||
IPAddress string `json:"address"`
|
||||
PublicKey string `json:"key"`
|
||||
Port uint64 `json:"port"`
|
||||
Coords []uint64 `json:"coords"`
|
||||
Remote string `json:"remote"`
|
||||
RXBytes uint64 `json:"bytes_recvd"`
|
||||
TXBytes uint64 `json:"bytes_sent"`
|
||||
RXBytes DataUnit `json:"bytes_recvd"`
|
||||
TXBytes DataUnit `json:"bytes_sent"`
|
||||
Uptime float64 `json:"uptime"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersResponse) error {
|
||||
res.Peers = map[string]PeerEntry{}
|
||||
for _, p := range a.core.GetPeers() {
|
||||
peers := a.core.GetPeers()
|
||||
res.Peers = make([]PeerEntry, 0, len(peers))
|
||||
for _, p := range peers {
|
||||
addr := address.AddrForKey(p.Key)
|
||||
so := net.IP(addr[:]).String()
|
||||
res.Peers[so] = PeerEntry{
|
||||
res.Peers = append(res.Peers, PeerEntry{
|
||||
IPAddress: net.IP(addr[:]).String(),
|
||||
PublicKey: hex.EncodeToString(p.Key),
|
||||
Port: p.Port,
|
||||
Coords: p.Coords,
|
||||
Remote: p.Remote,
|
||||
RXBytes: p.RXBytes,
|
||||
TXBytes: p.TXBytes,
|
||||
RXBytes: DataUnit(p.RXBytes),
|
||||
TXBytes: DataUnit(p.TXBytes),
|
||||
Uptime: p.Uptime.Seconds(),
|
||||
}
|
||||
})
|
||||
}
|
||||
sort.Slice(res.Peers, func(i, j int) bool {
|
||||
return res.Peers[i].Port < res.Peers[j].Port
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -9,28 +9,22 @@ import (
|
|||
type GetSelfRequest struct{}
|
||||
|
||||
type GetSelfResponse struct {
|
||||
Self map[string]SelfEntry `json:"self"`
|
||||
}
|
||||
|
||||
type SelfEntry struct {
|
||||
BuildName string `json:"build_name"`
|
||||
BuildVersion string `json:"build_version"`
|
||||
PublicKey string `json:"key"`
|
||||
IPAddress string `json:"address"`
|
||||
Coords []uint64 `json:"coords"`
|
||||
Subnet string `json:"subnet"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getSelfHandler(req *GetSelfRequest, res *GetSelfResponse) error {
|
||||
res.Self = make(map[string]SelfEntry)
|
||||
self := a.core.GetSelf()
|
||||
addr := a.core.Address().String()
|
||||
snet := a.core.Subnet()
|
||||
res.Self[addr] = SelfEntry{
|
||||
BuildName: version.BuildName(),
|
||||
BuildVersion: version.BuildVersion(),
|
||||
PublicKey: hex.EncodeToString(self.Key[:]),
|
||||
Subnet: snet.String(),
|
||||
Coords: self.Coords,
|
||||
}
|
||||
res.BuildName = version.BuildName()
|
||||
res.BuildVersion = version.BuildVersion()
|
||||
res.PublicKey = hex.EncodeToString(self.Key[:])
|
||||
res.IPAddress = a.core.Address().String()
|
||||
res.Subnet = snet.String()
|
||||
res.Coords = self.Coords
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
)
|
||||
|
@ -10,21 +12,26 @@ import (
|
|||
type GetSessionsRequest struct{}
|
||||
|
||||
type GetSessionsResponse struct {
|
||||
Sessions map[string]SessionEntry `json:"sessions"`
|
||||
Sessions []SessionEntry `json:"sessions"`
|
||||
}
|
||||
|
||||
type SessionEntry struct {
|
||||
IPAddress string `json:"address"`
|
||||
PublicKey string `json:"key"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getSessionsHandler(req *GetSessionsRequest, res *GetSessionsResponse) error {
|
||||
res.Sessions = map[string]SessionEntry{}
|
||||
for _, s := range a.core.GetSessions() {
|
||||
sessions := a.core.GetSessions()
|
||||
res.Sessions = make([]SessionEntry, 0, len(sessions))
|
||||
for _, s := range sessions {
|
||||
addr := address.AddrForKey(s.Key)
|
||||
so := net.IP(addr[:]).String()
|
||||
res.Sessions[so] = SessionEntry{
|
||||
res.Sessions = append(res.Sessions, SessionEntry{
|
||||
IPAddress: net.IP(addr[:]).String(),
|
||||
PublicKey: hex.EncodeToString(s.Key[:]),
|
||||
}
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Sessions, func(i, j int) bool {
|
||||
return strings.Compare(res.Sessions[i].PublicKey, res.Sessions[j].PublicKey) < 0
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -13,7 +12,7 @@ import (
|
|||
"github.com/Arceliar/phony"
|
||||
|
||||
//"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||
)
|
||||
|
||||
|
@ -154,7 +153,7 @@ func (m *nodeinfo) _sendRes(key keyArray) {
|
|||
type GetNodeInfoRequest struct {
|
||||
Key string `json:"key"`
|
||||
}
|
||||
type GetNodeInfoResponse map[string]interface{}
|
||||
type GetNodeInfoResponse map[string]json.RawMessage
|
||||
|
||||
func (m *nodeinfo) nodeInfoAdminHandler(in json.RawMessage) (interface{}, error) {
|
||||
var req GetNodeInfoRequest
|
||||
|
@ -182,8 +181,8 @@ func (m *nodeinfo) nodeInfoAdminHandler(in json.RawMessage) (interface{}, error)
|
|||
if err := msg.UnmarshalJSON(info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip := net.IP(address.AddrForKey(kbs)[:])
|
||||
res := GetNodeInfoResponse{ip.String(): msg}
|
||||
key := hex.EncodeToString(kbs[:])
|
||||
res := GetNodeInfoResponse{key: msg}
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue