5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2025-01-11 07:15:42 +00:00
yggdrasil-go/src/core/proto.go

374 lines
8.5 KiB
Go
Raw Normal View History

package core
2021-05-23 00:54:52 +00:00
import (
"crypto/ed25519"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"net"
2021-05-23 00:54:52 +00:00
"time"
iwt "github.com/Arceliar/ironwood/types"
"github.com/Arceliar/phony"
"github.com/yggdrasil-network/yggdrasil-go/src/address"
2021-05-23 00:54:52 +00:00
)
const (
typeDebugDummy = iota
typeDebugGetSelfRequest
typeDebugGetSelfResponse
typeDebugGetPeersRequest
typeDebugGetPeersResponse
typeDebugGetDHTRequest
typeDebugGetDHTResponse
)
type reqInfo struct {
callback func([]byte)
timer *time.Timer // time.AfterFunc cleanup
2021-05-23 00:54:52 +00:00
}
type keyArray [ed25519.PublicKeySize]byte
2021-05-23 16:58:52 +00:00
type protoHandler struct {
2021-05-23 00:54:52 +00:00
phony.Inbox
2021-09-01 01:24:25 +00:00
2021-09-01 02:57:45 +00:00
core *Core
2021-05-23 16:58:52 +00:00
nodeinfo nodeinfo
2021-09-01 01:24:25 +00:00
2021-09-02 20:45:30 +00:00
selfRequests map[keyArray]*reqInfo
peersRequests map[keyArray]*reqInfo
dhtRequests map[keyArray]*reqInfo
2021-05-23 00:54:52 +00:00
}
func (p *protoHandler) init(core *Core) {
p.core = core
2021-05-23 16:58:52 +00:00
p.nodeinfo.init(p)
2021-09-01 01:24:25 +00:00
2022-04-17 17:02:25 +00:00
p.selfRequests = make(map[keyArray]*reqInfo)
2021-09-02 20:45:30 +00:00
p.peersRequests = make(map[keyArray]*reqInfo)
2022-04-17 17:02:25 +00:00
p.dhtRequests = make(map[keyArray]*reqInfo)
2021-05-23 00:54:52 +00:00
}
2021-09-01 01:24:25 +00:00
// Common functions
2021-05-23 16:58:52 +00:00
func (p *protoHandler) handleProto(from phony.Actor, key keyArray, bs []byte) {
if len(bs) == 0 {
return
}
switch bs[0] {
case typeProtoDummy:
case typeProtoNodeInfoRequest:
p.nodeinfo.handleReq(p, key)
case typeProtoNodeInfoResponse:
p.nodeinfo.handleRes(p, key, bs[1:])
case typeProtoDebug:
p.handleDebug(from, key, bs[1:])
2021-05-23 16:58:52 +00:00
}
}
func (p *protoHandler) handleDebug(from phony.Actor, key keyArray, bs []byte) {
p.Act(from, func() {
p._handleDebug(key, bs)
})
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleDebug(key keyArray, bs []byte) {
2021-05-23 00:54:52 +00:00
if len(bs) == 0 {
return
}
switch bs[0] {
case typeDebugDummy:
case typeDebugGetSelfRequest:
2021-05-23 16:58:52 +00:00
p._handleGetSelfRequest(key)
2021-05-23 00:54:52 +00:00
case typeDebugGetSelfResponse:
2021-05-23 16:58:52 +00:00
p._handleGetSelfResponse(key, bs[1:])
2021-05-23 00:54:52 +00:00
case typeDebugGetPeersRequest:
2021-05-23 16:58:52 +00:00
p._handleGetPeersRequest(key)
2021-05-23 00:54:52 +00:00
case typeDebugGetPeersResponse:
2021-05-23 16:58:52 +00:00
p._handleGetPeersResponse(key, bs[1:])
2021-05-23 00:54:52 +00:00
case typeDebugGetDHTRequest:
2021-05-23 16:58:52 +00:00
p._handleGetDHTRequest(key)
2021-05-23 00:54:52 +00:00
case typeDebugGetDHTResponse:
2021-05-23 16:58:52 +00:00
p._handleGetDHTResponse(key, bs[1:])
2021-05-23 00:54:52 +00:00
}
}
2021-09-01 01:24:25 +00:00
func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) {
bs := append([]byte{typeSessionProto, typeProtoDebug, dType}, data...)
_, _ = p.core.PacketConn.WriteTo(bs, iwt.Addr(key[:]))
}
// Get self
2021-05-23 16:58:52 +00:00
func (p *protoHandler) sendGetSelfRequest(key keyArray, callback func([]byte)) {
p.Act(nil, func() {
2021-09-02 20:45:30 +00:00
if info := p.selfRequests[key]; info != nil {
info.timer.Stop()
2021-09-02 20:45:30 +00:00
delete(p.selfRequests, key)
}
info := new(reqInfo)
info.callback = callback
info.timer = time.AfterFunc(time.Minute, func() {
2021-05-23 16:58:52 +00:00
p.Act(nil, func() {
2021-09-02 20:45:30 +00:00
if p.selfRequests[key] == info {
delete(p.selfRequests, key)
}
})
})
2021-09-02 20:45:30 +00:00
p.selfRequests[key] = info
2021-05-23 16:58:52 +00:00
p._sendDebug(key, typeDebugGetSelfRequest, nil)
})
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleGetSelfRequest(key keyArray) {
self := p.core.GetSelf()
res := map[string]string{
"key": hex.EncodeToString(self.Key[:]),
"coords": fmt.Sprintf("%v", self.Coords),
}
bs, err := json.Marshal(res) // FIXME this puts keys in base64, not hex
if err != nil {
return
}
2021-05-23 16:58:52 +00:00
p._sendDebug(key, typeDebugGetSelfResponse, bs)
2021-05-23 00:54:52 +00:00
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleGetSelfResponse(key keyArray, bs []byte) {
2021-09-02 20:45:30 +00:00
if info := p.selfRequests[key]; info != nil {
info.timer.Stop()
info.callback(bs)
2021-09-02 20:45:30 +00:00
delete(p.selfRequests, key)
}
2021-05-23 00:54:52 +00:00
}
2021-09-01 01:24:25 +00:00
// Get peers
2021-05-23 16:58:52 +00:00
func (p *protoHandler) sendGetPeersRequest(key keyArray, callback func([]byte)) {
p.Act(nil, func() {
2021-09-02 20:45:30 +00:00
if info := p.peersRequests[key]; info != nil {
info.timer.Stop()
2021-09-02 20:45:30 +00:00
delete(p.peersRequests, key)
}
info := new(reqInfo)
info.callback = callback
info.timer = time.AfterFunc(time.Minute, func() {
2021-05-23 16:58:52 +00:00
p.Act(nil, func() {
2021-09-02 20:45:30 +00:00
if p.peersRequests[key] == info {
delete(p.peersRequests, key)
}
})
})
2021-09-02 20:45:30 +00:00
p.peersRequests[key] = info
2021-05-23 16:58:52 +00:00
p._sendDebug(key, typeDebugGetPeersRequest, nil)
})
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleGetPeersRequest(key keyArray) {
peers := p.core.GetPeers()
2021-05-23 00:54:52 +00:00
var bs []byte
2021-05-23 16:58:52 +00:00
for _, pinfo := range peers {
tmp := append(bs, pinfo.Key[:]...)
const responseOverhead = 2 // 1 debug type, 1 getpeers type
if uint64(len(tmp))+responseOverhead > p.core.MTU() {
2021-05-23 00:54:52 +00:00
break
}
bs = tmp
}
2021-05-23 16:58:52 +00:00
p._sendDebug(key, typeDebugGetPeersResponse, bs)
2021-05-23 00:54:52 +00:00
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleGetPeersResponse(key keyArray, bs []byte) {
2021-09-02 20:45:30 +00:00
if info := p.peersRequests[key]; info != nil {
2021-05-23 00:54:52 +00:00
info.timer.Stop()
info.callback(bs)
2021-09-02 20:45:30 +00:00
delete(p.peersRequests, key)
2021-05-23 00:54:52 +00:00
}
}
2021-09-01 01:24:25 +00:00
// Get DHT
2021-05-23 16:58:52 +00:00
func (p *protoHandler) sendGetDHTRequest(key keyArray, callback func([]byte)) {
p.Act(nil, func() {
2021-09-02 20:45:30 +00:00
if info := p.dhtRequests[key]; info != nil {
info.timer.Stop()
2021-09-02 20:45:30 +00:00
delete(p.dhtRequests, key)
}
info := new(reqInfo)
info.callback = callback
info.timer = time.AfterFunc(time.Minute, func() {
2021-05-23 16:58:52 +00:00
p.Act(nil, func() {
2021-09-02 20:45:30 +00:00
if p.dhtRequests[key] == info {
delete(p.dhtRequests, key)
}
})
})
2021-09-02 20:45:30 +00:00
p.dhtRequests[key] = info
2021-05-23 16:58:52 +00:00
p._sendDebug(key, typeDebugGetDHTRequest, nil)
})
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleGetDHTRequest(key keyArray) {
dinfos := p.core.GetDHT()
2021-05-23 00:54:52 +00:00
var bs []byte
for _, dinfo := range dinfos {
tmp := append(bs, dinfo.Key[:]...)
2021-05-23 16:58:52 +00:00
const responseOverhead = 2 // 1 debug type, 1 getdht type
if uint64(len(tmp))+responseOverhead > p.core.MTU() {
2021-05-23 00:54:52 +00:00
break
}
bs = tmp
}
2021-05-23 16:58:52 +00:00
p._sendDebug(key, typeDebugGetDHTResponse, bs)
2021-05-23 00:54:52 +00:00
}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) _handleGetDHTResponse(key keyArray, bs []byte) {
2021-09-02 20:45:30 +00:00
if info := p.dhtRequests[key]; info != nil {
2021-05-23 00:54:52 +00:00
info.timer.Stop()
info.callback(bs)
2021-09-02 20:45:30 +00:00
delete(p.dhtRequests, key)
2021-05-23 00:54:52 +00:00
}
}
2021-09-01 01:24:25 +00:00
// Admin socket stuff for "Get self"
type DebugGetSelfRequest struct {
Key string `json:"key"`
}
type DebugGetSelfResponse map[string]interface{}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) getSelfHandler(in json.RawMessage) (interface{}, error) {
var req DebugGetSelfRequest
if err := json.Unmarshal(in, &req); err != nil {
return nil, err
}
var key keyArray
var kbs []byte
var err error
if kbs, err = hex.DecodeString(req.Key); err != nil {
return nil, err
}
copy(key[:], kbs)
ch := make(chan []byte, 1)
2021-05-23 16:58:52 +00:00
p.sendGetSelfRequest(key, func(info []byte) {
ch <- info
})
timer := time.NewTimer(6 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
return nil, errors.New("timeout")
case info := <-ch:
var msg json.RawMessage
if err := msg.UnmarshalJSON(info); err != nil {
return nil, err
}
ip := net.IP(address.AddrForKey(kbs)[:])
res := DebugGetSelfResponse{ip.String(): msg}
return res, nil
}
}
2021-09-01 01:24:25 +00:00
// Admin socket stuff for "Get peers"
type DebugGetPeersRequest struct {
Key string `json:"key"`
}
type DebugGetPeersResponse map[string]interface{}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) getPeersHandler(in json.RawMessage) (interface{}, error) {
var req DebugGetPeersRequest
if err := json.Unmarshal(in, &req); err != nil {
return nil, err
}
var key keyArray
var kbs []byte
var err error
if kbs, err = hex.DecodeString(req.Key); err != nil {
return nil, err
}
copy(key[:], kbs)
ch := make(chan []byte, 1)
2021-05-23 16:58:52 +00:00
p.sendGetPeersRequest(key, func(info []byte) {
ch <- info
})
timer := time.NewTimer(6 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
return nil, errors.New("timeout")
case info := <-ch:
ks := make(map[string][]string)
bs := info
for len(bs) >= len(key) {
ks["keys"] = append(ks["keys"], hex.EncodeToString(bs[:len(key)]))
bs = bs[len(key):]
}
js, err := json.Marshal(ks)
if err != nil {
return nil, err
}
var msg json.RawMessage
if err := msg.UnmarshalJSON(js); err != nil {
return nil, err
}
ip := net.IP(address.AddrForKey(kbs)[:])
res := DebugGetPeersResponse{ip.String(): msg}
return res, nil
}
}
2021-09-01 01:24:25 +00:00
// Admin socket stuff for "Get DHT"
type DebugGetDHTRequest struct {
Key string `json:"key"`
}
type DebugGetDHTResponse map[string]interface{}
2021-05-23 16:58:52 +00:00
func (p *protoHandler) getDHTHandler(in json.RawMessage) (interface{}, error) {
var req DebugGetDHTRequest
if err := json.Unmarshal(in, &req); err != nil {
return nil, err
}
var key keyArray
var kbs []byte
var err error
if kbs, err = hex.DecodeString(req.Key); err != nil {
return nil, err
}
copy(key[:], kbs)
ch := make(chan []byte, 1)
2021-05-23 16:58:52 +00:00
p.sendGetDHTRequest(key, func(info []byte) {
ch <- info
})
timer := time.NewTimer(6 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
return nil, errors.New("timeout")
case info := <-ch:
ks := make(map[string][]string)
bs := info
for len(bs) >= len(key) {
ks["keys"] = append(ks["keys"], hex.EncodeToString(bs[:len(key)]))
bs = bs[len(key):]
}
js, err := json.Marshal(ks)
if err != nil {
return nil, err
}
var msg json.RawMessage
if err := msg.UnmarshalJSON(js); err != nil {
return nil, err
}
ip := net.IP(address.AddrForKey(kbs)[:])
res := DebugGetDHTResponse{ip.String(): msg}
return res, nil
}
}