diff --git a/src/tuntap/debug.go b/src/tuntap/debug.go new file mode 100644 index 00000000..ee19d3f0 --- /dev/null +++ b/src/tuntap/debug.go @@ -0,0 +1,122 @@ +package tuntap + +import ( + "time" + + iwt "github.com/Arceliar/ironwood/types" + "github.com/Arceliar/phony" +) + +const ( + typeDebugDummy = iota + typeDebugGetSelfRequest + typeDebugGetSelfResponse + typeDebugGetPeersRequest + typeDebugGetPeersResponse + typeDebugGetDHTRequest + typeDebugGetDHTResponse +) + +type reqInfo struct { + ch chan []byte + timer time.Timer // time.AfterFunc cleanup +} + +type debugHandler struct { + phony.Inbox + tun *TunAdapter + sreqs struct{} // TODO + preqs map[keyArray]*reqInfo + dreqs map[keyArray]*reqInfo +} + +func (d *debugHandler) init(tun *TunAdapter) { + d.tun = tun + d.preqs = make(map[keyArray]*reqInfo) + d.dreqs = make(map[keyArray]*reqInfo) +} + +func (d *debugHandler) handleDebug(from phony.Actor, key keyArray, bs []byte) { + d.Act(from, func() { + d._handleDebug(key, bs) + }) +} + +func (d *debugHandler) _handleDebug(key keyArray, bs []byte) { + if len(bs) == 0 { + return + } + switch bs[0] { + case typeDebugDummy: + case typeDebugGetSelfRequest: + d._handleGetSelfRequest(key) + case typeDebugGetSelfResponse: + d._handleGetSelfResponse(key, bs[1:]) + case typeDebugGetPeersRequest: + d._handleGetPeersRequest(key) + case typeDebugGetPeersResponse: + d._handleGetPeersResponse(key, bs[1:]) + case typeDebugGetDHTRequest: + d._handleGetDHTRequest(key) + case typeDebugGetDHTResponse: + d._handleGetDHTResponse(key, bs[1:]) + default: + } +} + +func (d *debugHandler) _handleGetSelfRequest(key keyArray) { + // TODO +} + +func (d *debugHandler) _handleGetSelfResponse(key keyArray, bs []byte) { + // TODO +} + +func (d *debugHandler) _handleGetPeersRequest(key keyArray) { + peers := d.tun.core.GetPeers() + var bs []byte + for _, p := range peers { + tmp := append(bs, p.Key[:]...) + const responseOverhead = 1 + if uint64(len(tmp))+1 > d.tun.maxSessionMTU() { + break + } + bs = tmp + } + d._sendDebug(key, typeDebugGetPeersResponse, bs) +} + +func (d *debugHandler) _handleGetPeersResponse(key keyArray, bs []byte) { + if info := d.preqs[key]; info != nil { + info.timer.Stop() + info.ch <- bs + delete(d.preqs, key) + } +} + +func (d *debugHandler) _handleGetDHTRequest(key keyArray) { + dinfos := d.tun.core.GetDHT() + var bs []byte + for _, dinfo := range dinfos { + tmp := append(bs, dinfo.Key[:]...) + const responseOverhead = 1 + if uint64(len(tmp))+1 > d.tun.maxSessionMTU() { + break + } + bs = tmp + } + d._sendDebug(key, typeDebugGetDHTResponse, bs) +} + +func (d *debugHandler) _handleGetDHTResponse(key keyArray, bs []byte) { + if info := d.dreqs[key]; info != nil { + info.timer.Stop() + info.ch <- bs + delete(d.dreqs, key) + } +} + +func (d *debugHandler) _sendDebug(key keyArray, dType uint8, data []byte) { + bs := append([]byte{typeSessionDebug, dType}, data...) + d.tun.core.WriteTo(bs, iwt.Addr(key[:])) +} diff --git a/src/tuntap/iface.go b/src/tuntap/iface.go index a3275436..20720db4 100644 --- a/src/tuntap/iface.go +++ b/src/tuntap/iface.go @@ -88,6 +88,11 @@ func (tun *TunAdapter) write() { res := append([]byte(nil), bs[1:n]...) tun.nodeinfo.handleRes(nil, key, res) continue + case typeSessionDebug: + var key keyArray + copy(key[:], from.(iwt.Addr)) + data := append([]byte(nil), bs[1:n]...) + tun.debug.handleDebug(nil, key, data) default: continue } diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index 53546c32..36736719 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -47,6 +47,7 @@ type TunAdapter struct { isEnabled bool // Used by the writer to drop sessionTraffic if not enabled gatekeeper func(pubkey ed25519.PublicKey, initiator bool) bool nodeinfo nodeinfo + debug debugHandler } func (tun *TunAdapter) SetSessionGatekeeper(gatekeeper func(pubkey ed25519.PublicKey, initiator bool) bool) { @@ -113,6 +114,7 @@ func (tun *TunAdapter) Init(core *yggdrasil.Core, config *config.NodeState, log if err := tun.core.SetOutOfBandHandler(tun.oobHandler); err != nil { return fmt.Errorf("tun.core.SetOutOfBandHander: %w", err) } + tun.debug.init(tun) return nil } diff --git a/src/tuntap/types.go b/src/tuntap/types.go index f1267a92..102e03f0 100644 --- a/src/tuntap/types.go +++ b/src/tuntap/types.go @@ -13,4 +13,5 @@ const ( typeSessionTraffic typeSessionNodeInfoRequest typeSessionNodeInfoResponse + typeSessionDebug // Debug messages, intended to be removed at some point )