mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-10-31 17:25:06 +03:00 
			
		
		
		
	WIP moving IP-specific checks from tuntap to core
This commit is contained in:
		
							parent
							
								
									bb66851c2b
								
							
						
					
					
						commit
						1147ee1934
					
				
					 9 changed files with 339 additions and 220 deletions
				
			
		|  | @ -1,157 +0,0 @@ | |||
| package tuntap | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/ed25519" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	iwt "github.com/Arceliar/ironwood/types" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| ) | ||||
| 
 | ||||
| const keyStoreTimeout = 2 * time.Minute | ||||
| 
 | ||||
| type keyStore struct { | ||||
| 	tun          *TunAdapter | ||||
| 	mutex        sync.Mutex | ||||
| 	keyToInfo    map[keyArray]*keyInfo | ||||
| 	addrToInfo   map[address.Address]*keyInfo | ||||
| 	addrBuffer   map[address.Address]*buffer | ||||
| 	subnetToInfo map[address.Subnet]*keyInfo | ||||
| 	subnetBuffer map[address.Subnet]*buffer | ||||
| } | ||||
| 
 | ||||
| type keyArray [ed25519.PublicKeySize]byte | ||||
| 
 | ||||
| type keyInfo struct { | ||||
| 	key     keyArray | ||||
| 	address address.Address | ||||
| 	subnet  address.Subnet | ||||
| 	timeout *time.Timer // From calling a time.AfterFunc to do cleanup | ||||
| } | ||||
| 
 | ||||
| type buffer struct { | ||||
| 	packets [][]byte | ||||
| 	timeout *time.Timer | ||||
| } | ||||
| 
 | ||||
| func (k *keyStore) init(tun *TunAdapter) { | ||||
| 	k.tun = tun | ||||
| 	k.keyToInfo = make(map[keyArray]*keyInfo) | ||||
| 	k.addrToInfo = make(map[address.Address]*keyInfo) | ||||
| 	k.addrBuffer = make(map[address.Address]*buffer) | ||||
| 	k.subnetToInfo = make(map[address.Subnet]*keyInfo) | ||||
| 	k.subnetBuffer = make(map[address.Subnet]*buffer) | ||||
| } | ||||
| 
 | ||||
| func (k *keyStore) sendToAddress(addr address.Address, bs []byte) { | ||||
| 	k.mutex.Lock() | ||||
| 	if info := k.addrToInfo[addr]; info != nil { | ||||
| 		k.resetTimeout(info) | ||||
| 		k.mutex.Unlock() | ||||
| 		_, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) | ||||
| 	} else { | ||||
| 		var buf *buffer | ||||
| 		if buf = k.addrBuffer[addr]; buf == nil { | ||||
| 			buf = new(buffer) | ||||
| 			k.addrBuffer[addr] = buf | ||||
| 		} | ||||
| 		msg := append([]byte(nil), bs...) | ||||
| 		buf.packets = append(buf.packets, msg) | ||||
| 		if buf.timeout != nil { | ||||
| 			buf.timeout.Stop() | ||||
| 		} | ||||
| 		buf.timeout = time.AfterFunc(keyStoreTimeout, func() { | ||||
| 			k.mutex.Lock() | ||||
| 			defer k.mutex.Unlock() | ||||
| 			if nbuf := k.addrBuffer[addr]; nbuf == buf { | ||||
| 				delete(k.addrBuffer, addr) | ||||
| 			} | ||||
| 		}) | ||||
| 		k.mutex.Unlock() | ||||
| 		k.tun.sendKeyLookup(addr.GetKey()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) { | ||||
| 	k.mutex.Lock() | ||||
| 	if info := k.subnetToInfo[subnet]; info != nil { | ||||
| 		k.resetTimeout(info) | ||||
| 		k.mutex.Unlock() | ||||
| 		_, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) | ||||
| 	} else { | ||||
| 		var buf *buffer | ||||
| 		if buf = k.subnetBuffer[subnet]; buf == nil { | ||||
| 			buf = new(buffer) | ||||
| 			k.subnetBuffer[subnet] = buf | ||||
| 		} | ||||
| 		msg := append([]byte(nil), bs...) | ||||
| 		buf.packets = append(buf.packets, msg) | ||||
| 		if buf.timeout != nil { | ||||
| 			buf.timeout.Stop() | ||||
| 		} | ||||
| 		buf.timeout = time.AfterFunc(keyStoreTimeout, func() { | ||||
| 			k.mutex.Lock() | ||||
| 			defer k.mutex.Unlock() | ||||
| 			if nbuf := k.subnetBuffer[subnet]; nbuf == buf { | ||||
| 				delete(k.subnetBuffer, subnet) | ||||
| 			} | ||||
| 		}) | ||||
| 		k.mutex.Unlock() | ||||
| 		k.tun.sendKeyLookup(subnet.GetKey()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (k *keyStore) update(key ed25519.PublicKey) *keyInfo { | ||||
| 	k.mutex.Lock() | ||||
| 	var kArray keyArray | ||||
| 	copy(kArray[:], key) | ||||
| 	var info *keyInfo | ||||
| 	if info = k.keyToInfo[kArray]; info == nil { | ||||
| 		info = new(keyInfo) | ||||
| 		info.key = kArray | ||||
| 		info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:])) | ||||
| 		info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:])) | ||||
| 		k.keyToInfo[info.key] = info | ||||
| 		k.addrToInfo[info.address] = info | ||||
| 		k.subnetToInfo[info.subnet] = info | ||||
| 		k.resetTimeout(info) | ||||
| 		k.mutex.Unlock() | ||||
| 		if buf := k.addrBuffer[info.address]; buf != nil { | ||||
| 			for _, bs := range buf.packets { | ||||
| 				_, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) | ||||
| 			} | ||||
| 			delete(k.addrBuffer, info.address) | ||||
| 		} | ||||
| 		if buf := k.subnetBuffer[info.subnet]; buf != nil { | ||||
| 			for _, bs := range buf.packets { | ||||
| 				_, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) | ||||
| 			} | ||||
| 			delete(k.subnetBuffer, info.subnet) | ||||
| 		} | ||||
| 	} else { | ||||
| 		k.resetTimeout(info) | ||||
| 		k.mutex.Unlock() | ||||
| 	} | ||||
| 	return info | ||||
| } | ||||
| 
 | ||||
| func (k *keyStore) resetTimeout(info *keyInfo) { | ||||
| 	if info.timeout != nil { | ||||
| 		info.timeout.Stop() | ||||
| 	} | ||||
| 	info.timeout = time.AfterFunc(keyStoreTimeout, func() { | ||||
| 		k.mutex.Lock() | ||||
| 		defer k.mutex.Unlock() | ||||
| 		if nfo := k.keyToInfo[info.key]; nfo == info { | ||||
| 			delete(k.keyToInfo, info.key) | ||||
| 		} | ||||
| 		if nfo := k.addrToInfo[info.address]; nfo == info { | ||||
| 			delete(k.addrToInfo, info.address) | ||||
| 		} | ||||
| 		if nfo := k.subnetToInfo[info.subnet]; nfo == info { | ||||
| 			delete(k.subnetToInfo, info.subnet) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
|  | @ -1,189 +0,0 @@ | |||
| package tuntap | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"net" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	iwt "github.com/Arceliar/ironwood/types" | ||||
| 	"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" | ||||
| ) | ||||
| 
 | ||||
| // NodeInfoPayload represents a RequestNodeInfo response, in bytes. | ||||
| type NodeInfoPayload []byte | ||||
| 
 | ||||
| type nodeinfo struct { | ||||
| 	phony.Inbox | ||||
| 	proto      *protoHandler | ||||
| 	myNodeInfo NodeInfoPayload | ||||
| 	callbacks  map[keyArray]nodeinfoCallback | ||||
| } | ||||
| 
 | ||||
| type nodeinfoCallback struct { | ||||
| 	call    func(nodeinfo NodeInfoPayload) | ||||
| 	created time.Time | ||||
| } | ||||
| 
 | ||||
| // Initialises the nodeinfo cache/callback maps, and starts a goroutine to keep | ||||
| // the cache/callback maps clean of stale entries | ||||
| func (m *nodeinfo) init(proto *protoHandler) { | ||||
| 	m.Act(nil, func() { | ||||
| 		m._init(proto) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _init(proto *protoHandler) { | ||||
| 	m.proto = proto | ||||
| 	m.callbacks = make(map[keyArray]nodeinfoCallback) | ||||
| 	m._cleanup() | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _cleanup() { | ||||
| 	for boxPubKey, callback := range m.callbacks { | ||||
| 		if time.Since(callback.created) > time.Minute { | ||||
| 			delete(m.callbacks, boxPubKey) | ||||
| 		} | ||||
| 	} | ||||
| 	time.AfterFunc(time.Second*30, func() { | ||||
| 		m.Act(nil, m._cleanup) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _addCallback(sender keyArray, call func(nodeinfo NodeInfoPayload)) { | ||||
| 	m.callbacks[sender] = nodeinfoCallback{ | ||||
| 		created: time.Now(), | ||||
| 		call:    call, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Handles the callback, if there is one | ||||
| func (m *nodeinfo) _callback(sender keyArray, nodeinfo NodeInfoPayload) { | ||||
| 	if callback, ok := m.callbacks[sender]; ok { | ||||
| 		callback.call(nodeinfo) | ||||
| 		delete(m.callbacks, sender) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _getNodeInfo() NodeInfoPayload { | ||||
| 	return m.myNodeInfo | ||||
| } | ||||
| 
 | ||||
| // Set the current node's nodeinfo | ||||
| func (m *nodeinfo) setNodeInfo(given interface{}, privacy bool) (err error) { | ||||
| 	phony.Block(m, func() { | ||||
| 		err = m._setNodeInfo(given, privacy) | ||||
| 	}) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _setNodeInfo(given interface{}, privacy bool) error { | ||||
| 	defaults := map[string]interface{}{ | ||||
| 		"buildname":     version.BuildName(), | ||||
| 		"buildversion":  version.BuildVersion(), | ||||
| 		"buildplatform": runtime.GOOS, | ||||
| 		"buildarch":     runtime.GOARCH, | ||||
| 	} | ||||
| 	newnodeinfo := make(map[string]interface{}) | ||||
| 	if !privacy { | ||||
| 		for k, v := range defaults { | ||||
| 			newnodeinfo[k] = v | ||||
| 		} | ||||
| 	} | ||||
| 	if nodeinfomap, ok := given.(map[string]interface{}); ok { | ||||
| 		for key, value := range nodeinfomap { | ||||
| 			if _, ok := defaults[key]; ok { | ||||
| 				if strvalue, strok := value.(string); strok && strings.EqualFold(strvalue, "null") || value == nil { | ||||
| 					delete(newnodeinfo, key) | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 			newnodeinfo[key] = value | ||||
| 		} | ||||
| 	} | ||||
| 	newjson, err := json.Marshal(newnodeinfo) | ||||
| 	if err == nil { | ||||
| 		if len(newjson) > 16384 { | ||||
| 			return errors.New("NodeInfo exceeds max length of 16384 bytes") | ||||
| 		} | ||||
| 		m.myNodeInfo = newjson | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) sendReq(from phony.Actor, key keyArray, callback func(nodeinfo NodeInfoPayload)) { | ||||
| 	m.Act(from, func() { | ||||
| 		m._sendReq(key, callback) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _sendReq(key keyArray, callback func(nodeinfo NodeInfoPayload)) { | ||||
| 	if callback != nil { | ||||
| 		m._addCallback(key, callback) | ||||
| 	} | ||||
| 	_, _ = m.proto.tun.core.WriteTo([]byte{typeSessionProto, typeProtoNodeInfoRequest}, iwt.Addr(key[:])) | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) handleReq(from phony.Actor, key keyArray) { | ||||
| 	m.Act(from, func() { | ||||
| 		m._sendRes(key) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) handleRes(from phony.Actor, key keyArray, info NodeInfoPayload) { | ||||
| 	m.Act(from, func() { | ||||
| 		m._callback(key, info) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (m *nodeinfo) _sendRes(key keyArray) { | ||||
| 	bs := append([]byte{typeSessionProto, typeProtoNodeInfoResponse}, m._getNodeInfo()...) | ||||
| 	_, _ = m.proto.tun.core.WriteTo(bs, iwt.Addr(key[:])) | ||||
| } | ||||
| 
 | ||||
| // Admin socket stuff | ||||
| 
 | ||||
| type GetNodeInfoRequest struct { | ||||
| 	Key string `json:"key"` | ||||
| } | ||||
| type GetNodeInfoResponse map[string]interface{} | ||||
| 
 | ||||
| func (m *nodeinfo) nodeInfoAdminHandler(in json.RawMessage) (interface{}, error) { | ||||
| 	var req GetNodeInfoRequest | ||||
| 	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) | ||||
| 	m.sendReq(nil, key, func(info NodeInfoPayload) { | ||||
| 		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 := GetNodeInfoResponse{ip.String(): msg} | ||||
| 		return res, nil | ||||
| 	} | ||||
| } | ||||
|  | @ -1,349 +0,0 @@ | |||
| package tuntap | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"time" | ||||
| 
 | ||||
| 	iwt "github.com/Arceliar/ironwood/types" | ||||
| 	"github.com/Arceliar/phony" | ||||
| 
 | ||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	typeDebugDummy = iota | ||||
| 	typeDebugGetSelfRequest | ||||
| 	typeDebugGetSelfResponse | ||||
| 	typeDebugGetPeersRequest | ||||
| 	typeDebugGetPeersResponse | ||||
| 	typeDebugGetDHTRequest | ||||
| 	typeDebugGetDHTResponse | ||||
| ) | ||||
| 
 | ||||
| type reqInfo struct { | ||||
| 	callback func([]byte) | ||||
| 	timer    *time.Timer // time.AfterFunc cleanup | ||||
| } | ||||
| 
 | ||||
| type protoHandler struct { | ||||
| 	phony.Inbox | ||||
| 	tun      *TunAdapter | ||||
| 	nodeinfo nodeinfo | ||||
| 	sreqs    map[keyArray]*reqInfo | ||||
| 	preqs    map[keyArray]*reqInfo | ||||
| 	dreqs    map[keyArray]*reqInfo | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) init(tun *TunAdapter) { | ||||
| 	p.tun = tun | ||||
| 	p.nodeinfo.init(p) | ||||
| 	p.sreqs = make(map[keyArray]*reqInfo) | ||||
| 	p.preqs = make(map[keyArray]*reqInfo) | ||||
| 	p.dreqs = make(map[keyArray]*reqInfo) | ||||
| } | ||||
| 
 | ||||
| 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(key, bs[1:]) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleDebug(key keyArray, bs []byte) { | ||||
| 	if len(bs) == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 	switch bs[0] { | ||||
| 	case typeDebugDummy: | ||||
| 	case typeDebugGetSelfRequest: | ||||
| 		p._handleGetSelfRequest(key) | ||||
| 	case typeDebugGetSelfResponse: | ||||
| 		p._handleGetSelfResponse(key, bs[1:]) | ||||
| 	case typeDebugGetPeersRequest: | ||||
| 		p._handleGetPeersRequest(key) | ||||
| 	case typeDebugGetPeersResponse: | ||||
| 		p._handleGetPeersResponse(key, bs[1:]) | ||||
| 	case typeDebugGetDHTRequest: | ||||
| 		p._handleGetDHTRequest(key) | ||||
| 	case typeDebugGetDHTResponse: | ||||
| 		p._handleGetDHTResponse(key, bs[1:]) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) sendGetSelfRequest(key keyArray, callback func([]byte)) { | ||||
| 	p.Act(nil, func() { | ||||
| 		if info := p.sreqs[key]; info != nil { | ||||
| 			info.timer.Stop() | ||||
| 			delete(p.sreqs, key) | ||||
| 		} | ||||
| 		info := new(reqInfo) | ||||
| 		info.callback = callback | ||||
| 		info.timer = time.AfterFunc(time.Minute, func() { | ||||
| 			p.Act(nil, func() { | ||||
| 				if p.sreqs[key] == info { | ||||
| 					delete(p.sreqs, key) | ||||
| 				} | ||||
| 			}) | ||||
| 		}) | ||||
| 		p.sreqs[key] = info | ||||
| 		p._sendDebug(key, typeDebugGetSelfRequest, nil) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleGetSelfRequest(key keyArray) { | ||||
| 	self := p.tun.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 | ||||
| 	} | ||||
| 	p._sendDebug(key, typeDebugGetSelfResponse, bs) | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleGetSelfResponse(key keyArray, bs []byte) { | ||||
| 	if info := p.sreqs[key]; info != nil { | ||||
| 		info.timer.Stop() | ||||
| 		info.callback(bs) | ||||
| 		delete(p.sreqs, key) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) sendGetPeersRequest(key keyArray, callback func([]byte)) { | ||||
| 	p.Act(nil, func() { | ||||
| 		if info := p.preqs[key]; info != nil { | ||||
| 			info.timer.Stop() | ||||
| 			delete(p.preqs, key) | ||||
| 		} | ||||
| 		info := new(reqInfo) | ||||
| 		info.callback = callback | ||||
| 		info.timer = time.AfterFunc(time.Minute, func() { | ||||
| 			p.Act(nil, func() { | ||||
| 				if p.preqs[key] == info { | ||||
| 					delete(p.preqs, key) | ||||
| 				} | ||||
| 			}) | ||||
| 		}) | ||||
| 		p.preqs[key] = info | ||||
| 		p._sendDebug(key, typeDebugGetPeersRequest, nil) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleGetPeersRequest(key keyArray) { | ||||
| 	peers := p.tun.core.GetPeers() | ||||
| 	var bs []byte | ||||
| 	for _, pinfo := range peers { | ||||
| 		tmp := append(bs, pinfo.Key[:]...) | ||||
| 		const responseOverhead = 2 // 1 debug type, 1 getpeers type | ||||
| 		if uint64(len(tmp))+responseOverhead > p.tun.maxSessionMTU() { | ||||
| 			break | ||||
| 		} | ||||
| 		bs = tmp | ||||
| 	} | ||||
| 	p._sendDebug(key, typeDebugGetPeersResponse, bs) | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleGetPeersResponse(key keyArray, bs []byte) { | ||||
| 	if info := p.preqs[key]; info != nil { | ||||
| 		info.timer.Stop() | ||||
| 		info.callback(bs) | ||||
| 		delete(p.preqs, key) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) sendGetDHTRequest(key keyArray, callback func([]byte)) { | ||||
| 	p.Act(nil, func() { | ||||
| 		if info := p.dreqs[key]; info != nil { | ||||
| 			info.timer.Stop() | ||||
| 			delete(p.dreqs, key) | ||||
| 		} | ||||
| 		info := new(reqInfo) | ||||
| 		info.callback = callback | ||||
| 		info.timer = time.AfterFunc(time.Minute, func() { | ||||
| 			p.Act(nil, func() { | ||||
| 				if p.dreqs[key] == info { | ||||
| 					delete(p.dreqs, key) | ||||
| 				} | ||||
| 			}) | ||||
| 		}) | ||||
| 		p.dreqs[key] = info | ||||
| 		p._sendDebug(key, typeDebugGetDHTRequest, nil) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleGetDHTRequest(key keyArray) { | ||||
| 	dinfos := p.tun.core.GetDHT() | ||||
| 	var bs []byte | ||||
| 	for _, dinfo := range dinfos { | ||||
| 		tmp := append(bs, dinfo.Key[:]...) | ||||
| 		const responseOverhead = 2 // 1 debug type, 1 getdht type | ||||
| 		if uint64(len(tmp))+responseOverhead > p.tun.maxSessionMTU() { | ||||
| 			break | ||||
| 		} | ||||
| 		bs = tmp | ||||
| 	} | ||||
| 	p._sendDebug(key, typeDebugGetDHTResponse, bs) | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _handleGetDHTResponse(key keyArray, bs []byte) { | ||||
| 	if info := p.dreqs[key]; info != nil { | ||||
| 		info.timer.Stop() | ||||
| 		info.callback(bs) | ||||
| 		delete(p.dreqs, key) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) { | ||||
| 	bs := append([]byte{typeSessionProto, typeProtoDebug, dType}, data...) | ||||
| 	_, _ = p.tun.core.WriteTo(bs, iwt.Addr(key[:])) | ||||
| } | ||||
| 
 | ||||
| // Admin socket stuff | ||||
| 
 | ||||
| type DebugGetSelfRequest struct { | ||||
| 	Key string `json:"key"` | ||||
| } | ||||
| 
 | ||||
| type DebugGetSelfResponse map[string]interface{} | ||||
| 
 | ||||
| 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) | ||||
| 	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 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type DebugGetPeersRequest struct { | ||||
| 	Key string `json:"key"` | ||||
| } | ||||
| 
 | ||||
| type DebugGetPeersResponse map[string]interface{} | ||||
| 
 | ||||
| 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) | ||||
| 	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 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type DebugGetDHTRequest struct { | ||||
| 	Key string `json:"key"` | ||||
| } | ||||
| 
 | ||||
| type DebugGetDHTResponse map[string]interface{} | ||||
| 
 | ||||
| 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) | ||||
| 	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 | ||||
| 	} | ||||
| } | ||||
|  | @ -189,41 +189,3 @@ func (tun *TunAdapter) _stop() error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (tun *TunAdapter) oobHandler(fromKey, toKey ed25519.PublicKey, data []byte) { | ||||
| 	if len(data) != 1+ed25519.SignatureSize { | ||||
| 		return | ||||
| 	} | ||||
| 	sig := data[1:] | ||||
| 	switch data[0] { | ||||
| 	case typeKeyLookup: | ||||
| 		snet := *address.SubnetForKey(toKey) | ||||
| 		if snet == tun.subnet && ed25519.Verify(fromKey, toKey[:], sig) { | ||||
| 			// This is looking for at least our subnet (possibly our address) | ||||
| 			// Send a response | ||||
| 			tun.sendKeyResponse(fromKey) | ||||
| 		} | ||||
| 	case typeKeyResponse: | ||||
| 		// TODO keep a list of something to match against... | ||||
| 		// Ignore the response if it doesn't match anything of interest... | ||||
| 		if ed25519.Verify(fromKey, toKey[:], sig) { | ||||
| 			tun.store.update(fromKey) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (tun *TunAdapter) sendKeyLookup(partial ed25519.PublicKey) { | ||||
| 	sig := ed25519.Sign(tun.core.PrivateKey(), partial[:]) | ||||
| 	bs := append([]byte{typeKeyLookup}, sig...) | ||||
| 	_ = tun.core.SendOutOfBand(partial, bs) | ||||
| } | ||||
| 
 | ||||
| func (tun *TunAdapter) sendKeyResponse(dest ed25519.PublicKey) { | ||||
| 	sig := ed25519.Sign(tun.core.PrivateKey(), dest[:]) | ||||
| 	bs := append([]byte{typeKeyResponse}, sig...) | ||||
| 	_ = tun.core.SendOutOfBand(dest, bs) | ||||
| } | ||||
| 
 | ||||
| func (tun *TunAdapter) maxSessionMTU() uint64 { | ||||
| 	const sessionTypeOverhead = 1 | ||||
| 	return tun.core.MTU() - sessionTypeOverhead | ||||
| } | ||||
|  |  | |||
|  | @ -1,23 +0,0 @@ | |||
| package tuntap | ||||
| 
 | ||||
| // Out-of-band packet types | ||||
| const ( | ||||
| 	typeKeyDummy = iota // nolint:deadcode,varcheck | ||||
| 	typeKeyLookup | ||||
| 	typeKeyResponse | ||||
| ) | ||||
| 
 | ||||
| // In-band packet types | ||||
| const ( | ||||
| 	typeSessionDummy = iota // nolint:deadcode,varcheck | ||||
| 	typeSessionTraffic | ||||
| 	typeSessionProto | ||||
| ) | ||||
| 
 | ||||
| // Protocol packet types | ||||
| const ( | ||||
| 	typeProtoDummy = iota | ||||
| 	typeProtoNodeInfoRequest | ||||
| 	typeProtoNodeInfoResponse | ||||
| 	typeProtoDebug = 255 | ||||
| ) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Arceliar
						Arceliar