mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-30 07:05:06 +03:00
Fixed #884
This commit is contained in:
parent
74910f96da
commit
82dd30ee5c
61 changed files with 2197 additions and 2030 deletions
12
src/admin/addpeer.go
Normal file
12
src/admin/addpeer.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package admin
|
||||
|
||||
type AddPeerRequest struct {
|
||||
Uri string `json:"uri"`
|
||||
Sintf string `json:"interface,omitempty"`
|
||||
}
|
||||
|
||||
type AddPeerResponse struct{}
|
||||
|
||||
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, res *AddPeerResponse) error {
|
||||
return a.core.AddPeer(req.Uri, req.Sintf)
|
||||
}
|
|
@ -7,55 +7,63 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gologme/log"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||
)
|
||||
|
||||
// TODO: Add authentication
|
||||
|
||||
type AdminSocket struct {
|
||||
core *core.Core
|
||||
log *log.Logger
|
||||
listenaddr string
|
||||
listener net.Listener
|
||||
handlers map[string]handler
|
||||
done chan struct{}
|
||||
core *core.Core
|
||||
log core.Logger
|
||||
listener net.Listener
|
||||
handlers map[string]handler
|
||||
done chan struct{}
|
||||
config struct {
|
||||
listenaddr ListenAddress
|
||||
}
|
||||
}
|
||||
|
||||
type AdminSocketRequest struct {
|
||||
Name string `json:"request"`
|
||||
Arguments json.RawMessage `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 json.RawMessage `json:"request"`
|
||||
Response json.RawMessage `json:"response"`
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
desc string // What does the endpoint do?
|
||||
args []string // List of human-readable argument names
|
||||
handler core.AddHandlerFunc // First is input map, second is output
|
||||
}
|
||||
|
||||
type ListResponse struct {
|
||||
List map[string]ListEntry `json:"list"`
|
||||
List []ListEntry `json:"list"`
|
||||
}
|
||||
|
||||
type ListEntry struct {
|
||||
Fields []string `json:"fields"`
|
||||
Command string `json:"command"`
|
||||
Description string `json:"description"`
|
||||
Fields []string `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// AddHandler is called for each admin function to add the handler and help documentation to the API.
|
||||
func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc core.AddHandlerFunc) error {
|
||||
func (a *AdminSocket) AddHandler(name, desc string, args []string, handlerfunc core.AddHandlerFunc) error {
|
||||
if _, ok := a.handlers[strings.ToLower(name)]; ok {
|
||||
return errors.New("handler already exists")
|
||||
}
|
||||
a.handlers[strings.ToLower(name)] = handler{
|
||||
desc: desc,
|
||||
args: args,
|
||||
handler: handlerfunc,
|
||||
}
|
||||
|
@ -63,100 +71,142 @@ func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc core.Ad
|
|||
}
|
||||
|
||||
// Init runs the initial admin setup.
|
||||
func (a *AdminSocket) Init(c *core.Core, nc *config.NodeConfig, log *log.Logger, options interface{}) error {
|
||||
a.core = c
|
||||
a.log = log
|
||||
a.handlers = make(map[string]handler)
|
||||
nc.RLock()
|
||||
a.listenaddr = nc.AdminListen
|
||||
nc.RUnlock()
|
||||
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{},
|
||||
}
|
||||
func New(c *core.Core, log core.Logger, opts ...SetupOption) (*AdminSocket, error) {
|
||||
a := &AdminSocket{
|
||||
core: c,
|
||||
log: log,
|
||||
handlers: make(map[string]handler),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
a._applyOption(opt)
|
||||
}
|
||||
if a.config.listenaddr == "none" || a.config.listenaddr == "" {
|
||||
return nil, nil
|
||||
}
|
||||
_ = a.AddHandler("list", "List available commands", []string{}, func(_ json.RawMessage) (interface{}, error) {
|
||||
res := &ListResponse{}
|
||||
for name, handler := range a.handlers {
|
||||
res.List[name] = ListEntry{
|
||||
Fields: handler.args,
|
||||
}
|
||||
res.List = append(res.List, ListEntry{
|
||||
Command: name,
|
||||
Description: handler.desc,
|
||||
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)
|
||||
a.done = make(chan struct{})
|
||||
go a.listen()
|
||||
return a, a.core.SetAdmin(a)
|
||||
}
|
||||
|
||||
func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
|
||||
_ = a.AddHandler("getSelf", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetSelfRequest{}
|
||||
res := &GetSelfResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getSelfHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
})
|
||||
_ = a.AddHandler("getPeers", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetPeersRequest{}
|
||||
res := &GetPeersResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getPeersHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
})
|
||||
_ = a.AddHandler("getDHT", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetDHTRequest{}
|
||||
res := &GetDHTResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getDHTHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
})
|
||||
_ = a.AddHandler("getPaths", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetPathsRequest{}
|
||||
res := &GetPathsResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getPathsHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
})
|
||||
_ = a.AddHandler("getSessions", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetSessionsRequest{}
|
||||
res := &GetSessionsResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getSessionsHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
})
|
||||
func (a *AdminSocket) SetupAdminHandlers() {
|
||||
_ = a.AddHandler(
|
||||
"getSelf", "Show details about this node", []string{},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetSelfRequest{}
|
||||
res := &GetSelfResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getSelfHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
_ = a.AddHandler(
|
||||
"getPeers", "Show directly connected peers", []string{},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetPeersRequest{}
|
||||
res := &GetPeersResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getPeersHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
_ = a.AddHandler(
|
||||
"getDHT", "Show known DHT entries", []string{},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetDHTRequest{}
|
||||
res := &GetDHTResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getDHTHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
_ = a.AddHandler(
|
||||
"getPaths", "Show established paths through this node", []string{},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetPathsRequest{}
|
||||
res := &GetPathsResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getPathsHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
_ = a.AddHandler(
|
||||
"getSessions", "Show established traffic sessions with remote nodes", []string{},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &GetSessionsRequest{}
|
||||
res := &GetSessionsResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.getSessionsHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
_ = a.AddHandler(
|
||||
"addPeer", "Add a peer to the peer list", []string{"uri", "interface"},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &AddPeerRequest{}
|
||||
res := &AddPeerResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.addPeerHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
_ = a.AddHandler(
|
||||
"removePeer", "Remove a peer from the peer list", []string{"uri", "interface"},
|
||||
func(in json.RawMessage) (interface{}, error) {
|
||||
req := &RemovePeerRequest{}
|
||||
res := &RemovePeerResponse{}
|
||||
if err := json.Unmarshal(in, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := a.removePeerHandler(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetDHT", []string{"key"}, t.proto.getDHTHandler)
|
||||
}
|
||||
|
||||
// Start runs the admin API socket to listen for / respond to admin API calls.
|
||||
func (a *AdminSocket) Start() error {
|
||||
if a.listenaddr != "none" && a.listenaddr != "" {
|
||||
a.done = make(chan struct{})
|
||||
go a.listen()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsStarted returns true if the module has been started.
|
||||
func (a *AdminSocket) IsStarted() bool {
|
||||
select {
|
||||
|
@ -171,6 +221,9 @@ func (a *AdminSocket) IsStarted() bool {
|
|||
|
||||
// Stop will stop the admin API and close the socket.
|
||||
func (a *AdminSocket) Stop() error {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
if a.listener != nil {
|
||||
select {
|
||||
case <-a.done:
|
||||
|
@ -184,31 +237,32 @@ func (a *AdminSocket) Stop() error {
|
|||
|
||||
// listen is run by start and manages API connections.
|
||||
func (a *AdminSocket) listen() {
|
||||
u, err := url.Parse(a.listenaddr)
|
||||
listenaddr := string(a.config.listenaddr)
|
||||
u, err := url.Parse(listenaddr)
|
||||
if err == nil {
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "unix":
|
||||
if _, err := os.Stat(a.listenaddr[7:]); err == nil {
|
||||
a.log.Debugln("Admin socket", a.listenaddr[7:], "already exists, trying to clean up")
|
||||
if _, err := net.DialTimeout("unix", a.listenaddr[7:], time.Second*2); err == nil || err.(net.Error).Timeout() {
|
||||
a.log.Errorln("Admin socket", a.listenaddr[7:], "already exists and is in use by another process")
|
||||
if _, err := os.Stat(listenaddr[7:]); err == nil {
|
||||
a.log.Debugln("Admin socket", listenaddr[7:], "already exists, trying to clean up")
|
||||
if _, err := net.DialTimeout("unix", listenaddr[7:], time.Second*2); err == nil || err.(net.Error).Timeout() {
|
||||
a.log.Errorln("Admin socket", listenaddr[7:], "already exists and is in use by another process")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
if err := os.Remove(a.listenaddr[7:]); err == nil {
|
||||
a.log.Debugln(a.listenaddr[7:], "was cleaned up")
|
||||
if err := os.Remove(listenaddr[7:]); err == nil {
|
||||
a.log.Debugln(listenaddr[7:], "was cleaned up")
|
||||
} else {
|
||||
a.log.Errorln(a.listenaddr[7:], "already exists and was not cleaned up:", err)
|
||||
a.log.Errorln(listenaddr[7:], "already exists and was not cleaned up:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
a.listener, err = net.Listen("unix", a.listenaddr[7:])
|
||||
a.listener, err = net.Listen("unix", listenaddr[7:])
|
||||
if err == nil {
|
||||
switch a.listenaddr[7:8] {
|
||||
switch listenaddr[7:8] {
|
||||
case "@": // maybe abstract namespace
|
||||
default:
|
||||
if err := os.Chmod(a.listenaddr[7:], 0660); err != nil {
|
||||
a.log.Warnln("WARNING:", a.listenaddr[:7], "may have unsafe permissions!")
|
||||
if err := os.Chmod(listenaddr[7:], 0660); err != nil {
|
||||
a.log.Warnln("WARNING:", listenaddr[:7], "may have unsafe permissions!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,10 +270,10 @@ func (a *AdminSocket) listen() {
|
|||
a.listener, err = net.Listen("tcp", u.Host)
|
||||
default:
|
||||
// err = errors.New(fmt.Sprint("protocol not supported: ", u.Scheme))
|
||||
a.listener, err = net.Listen("tcp", a.listenaddr)
|
||||
a.listener, err = net.Listen("tcp", listenaddr)
|
||||
}
|
||||
} else {
|
||||
a.listener, err = net.Listen("tcp", a.listenaddr)
|
||||
a.listener, err = net.Listen("tcp", listenaddr)
|
||||
}
|
||||
if err != nil {
|
||||
a.log.Errorf("Admin socket failed to listen: %v", err)
|
||||
|
@ -271,37 +325,58 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
|||
for {
|
||||
var err error
|
||||
var buf json.RawMessage
|
||||
_ = decoder.Decode(&buf)
|
||||
var req AdminSocketRequest
|
||||
var resp AdminSocketResponse
|
||||
resp.Status = "success"
|
||||
if err = json.Unmarshal(buf, &resp.Request); err == nil {
|
||||
if resp.Request.Name == "" {
|
||||
resp.Status = "error"
|
||||
resp.Response = &ErrorResponse{
|
||||
Error: "No request specified",
|
||||
}
|
||||
} else if h, ok := a.handlers[strings.ToLower(resp.Request.Name)]; ok {
|
||||
resp.Response, err = h.handler(buf)
|
||||
if err != nil {
|
||||
resp.Status = "error"
|
||||
resp.Response = &ErrorResponse{
|
||||
Error: err.Error(),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resp.Status = "error"
|
||||
resp.Response = &ErrorResponse{
|
||||
Error: fmt.Sprintf("Unknown action '%s', try 'list' for help", resp.Request.Name),
|
||||
}
|
||||
if err := func() error {
|
||||
if err = decoder.Decode(&buf); err != nil {
|
||||
return fmt.Errorf("Failed to find request")
|
||||
}
|
||||
if err = json.Unmarshal(buf, &req); err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal request")
|
||||
}
|
||||
if req.Name == "" {
|
||||
return fmt.Errorf("No request specified")
|
||||
}
|
||||
reqname := strings.ToLower(req.Name)
|
||||
handler, ok := a.handlers[reqname]
|
||||
if !ok {
|
||||
return fmt.Errorf("Unknown action '%s', try 'list' for help", reqname)
|
||||
}
|
||||
res, err := handler.handler(req.Arguments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Response, err = json.Marshal(res); err != nil {
|
||||
return fmt.Errorf("Failed to marshal response: %w", err)
|
||||
}
|
||||
resp.Status = "success"
|
||||
return nil
|
||||
}(); err != nil {
|
||||
resp.Status = "error"
|
||||
resp.Error = err.Error()
|
||||
}
|
||||
if err = encoder.Encode(resp); err != nil {
|
||||
a.log.Debugln("Encode error:", err)
|
||||
}
|
||||
if !resp.Request.KeepAlive {
|
||||
if !req.KeepAlive {
|
||||
break
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type DataUnit uint64
|
||||
|
||||
func (d DataUnit) String() string {
|
||||
switch {
|
||||
case d > 1024*1024*1024*1024:
|
||||
return fmt.Sprintf("%2.ftb", float64(d)/1024/1024/1024/1024)
|
||||
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,32 @@ import (
|
|||
type GetSessionsRequest struct{}
|
||||
|
||||
type GetSessionsResponse struct {
|
||||
Sessions map[string]SessionEntry `json:"sessions"`
|
||||
Sessions []SessionEntry `json:"sessions"`
|
||||
}
|
||||
|
||||
type SessionEntry struct {
|
||||
PublicKey string `json:"key"`
|
||||
IPAddress string `json:"address"`
|
||||
PublicKey string `json:"key"`
|
||||
RXBytes DataUnit `json:"bytes_recvd"`
|
||||
TXBytes DataUnit `json:"bytes_sent"`
|
||||
Uptime float64 `json:"uptime"`
|
||||
}
|
||||
|
||||
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[:]),
|
||||
}
|
||||
RXBytes: DataUnit(s.RXBytes),
|
||||
TXBytes: DataUnit(s.TXBytes),
|
||||
Uptime: s.Uptime.Seconds(),
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Sessions, func(i, j int) bool {
|
||||
return strings.Compare(res.Sessions[i].PublicKey, res.Sessions[j].PublicKey) < 0
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
16
src/admin/options.go
Normal file
16
src/admin/options.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package admin
|
||||
|
||||
func (c *AdminSocket) _applyOption(opt SetupOption) {
|
||||
switch v := opt.(type) {
|
||||
case ListenAddress:
|
||||
c.config.listenaddr = v
|
||||
}
|
||||
}
|
||||
|
||||
type SetupOption interface {
|
||||
isSetupOption()
|
||||
}
|
||||
|
||||
type ListenAddress string
|
||||
|
||||
func (a ListenAddress) isSetupOption() {}
|
12
src/admin/removepeer.go
Normal file
12
src/admin/removepeer.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package admin
|
||||
|
||||
type RemovePeerRequest struct {
|
||||
Uri string `json:"uri"`
|
||||
Sintf string `json:"interface,omitempty"`
|
||||
}
|
||||
|
||||
type RemovePeerResponse struct{}
|
||||
|
||||
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, res *RemovePeerResponse) error {
|
||||
return a.core.RemovePeer(req.Uri, req.Sintf)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue