From c707e4d90aef9d3d3b7d5a29e931071db6d957e6 Mon Sep 17 00:00:00 2001 From: fumiama Date: Tue, 28 Dec 2021 15:47:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=B7=AF=E7=94=B1=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- gold/link/crypto.go | 4 ++- gold/link/link.go | 2 +- gold/link/peer.go | 2 +- gold/link/query.go | 20 ++++++++++- gold/link/router.go | 51 ++++++++++++++++++++++++---- upper/services/tunnel/tunnel_test.go | 4 +-- 7 files changed, 71 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index b91f870..b579011 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,6 @@ go 1.16 require ( github.com/fumiama/go-x25519 v1.0.0 github.com/fumiama/gofastTEA v0.0.6 - github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/sirupsen/logrus v1.8.1 ) diff --git a/gold/link/crypto.go b/gold/link/crypto.go index c490fae..489840a 100644 --- a/gold/link/crypto.go +++ b/gold/link/crypto.go @@ -44,8 +44,10 @@ func NewMe(privateKey *[32]byte, myIP string, myEndpoint string) (m Me) { } m.connections = make(map[string]*Link) m.router = &Router{ - routetable: make(map[string][]*Link), + list: make([]*net.IPNet, 1, 16), + table: make(map[string]*Link, 16), } + m.router.SetDefault(nil) return } diff --git a/gold/link/link.go b/gold/link/link.go index 3577240..650dd99 100644 --- a/gold/link/link.go +++ b/gold/link/link.go @@ -75,7 +75,7 @@ func (l *Link) Write(p *head.Packet) (n int, err error) { d, err = p.Marshal(l.me.me.String(), l.peerip.String()) logrus.Debugln("[link] write data", string(d)) if err == nil { - n, err = l.me.myconn.WriteToUDP(d, l.NextHop(l.peerip).endpoint) + n, err = l.me.myconn.WriteToUDP(d, l.me.router.NextHop(l.peerip.String()+"/32").endpoint) } return } diff --git a/gold/link/peer.go b/gold/link/peer.go index cedd117..cb6c8e9 100644 --- a/gold/link/peer.go +++ b/gold/link/peer.go @@ -46,7 +46,7 @@ func (m *Me) AddPeer(peerip string, pubicKey *[32]byte, endPoint string, allowed _, cidr, err := net.ParseCIDR(ipnet) if err == nil { l.allowedips = append(l.allowedips, cidr) - l.me.router.routetable[cidr.String()] = append(l.me.router.routetable[cidr.String()], l) + l.me.router.SetItem(cidr, l) } } } diff --git a/gold/link/query.go b/gold/link/query.go index 62928d7..1d08a6c 100644 --- a/gold/link/query.go +++ b/gold/link/query.go @@ -1,6 +1,11 @@ package link -import "github.com/fumiama/WireGold/gold/head" +import ( + "encoding/json" + "errors" + + "github.com/fumiama/WireGold/gold/head" +) // 收到询问包的处理函数 func (l *Link) onQuery(packet *head.Packet) { @@ -12,3 +17,16 @@ func (l *Link) onQuery(packet *head.Packet) { // ---- 封装 Notify 到 新的 packet.Data // ---- 调用 l.Send 发送到对方 } + +// SendQuery 主动发起查询,询问对方是否可以到达 peers +func (l *Link) SendQuery(peers ...string) error { + if len(peers) == 0 { + return errors.New("len(peers) is 0") + } + data, err := json.Marshal(peers) + if err != nil { + return err + } + _, err = l.Write(head.NewPacket(head.ProtoQuery, 0, 0, data)) + return err +} diff --git a/gold/link/router.go b/gold/link/router.go index 6d2283d..bdb5678 100644 --- a/gold/link/router.go +++ b/gold/link/router.go @@ -3,11 +3,15 @@ package link import ( "net" "sync" + + "github.com/sirupsen/logrus" ) type Router struct { - routetable map[string][]*Link - routetablemu sync.RWMutex + // map[cidr]*Link + table map[string]*Link + mu sync.RWMutex + list []*net.IPNet } // Accept 判断是否应当接受 ip 发来的包 @@ -25,9 +29,42 @@ func (l *Link) IsToMe(ip net.IP) bool { return ip.Equal(l.me.me) } -// NextHop 得到前往 ip 的下一跳的 link -func (l *Link) NextHop(ip net.IP) *Link { - // TODO: 遍历 routetable,得到正确的下一跳 - // 注意使用 routetablemu 读写锁避免竞争 - return l +// SetDefault 设置默认网关 +func (r *Router) SetDefault(l *Link) { + defnet := &net.IPNet{IP: net.IPv4(0, 0, 0, 0), Mask: net.IPv4Mask(0, 0, 0, 0)} + r.mu.Lock() + r.list[len(r.list)-1] = defnet + r.table[defnet.String()] = l + r.mu.Unlock() +} + +// NextHop 得到前往 ip 的下一跳的 link +func (r *Router) NextHop(cidr string) *Link { + logrus.Infoln("[router] search for cidr", cidr) + // TODO: 遍历 r.table,得到正确的下一跳 + // 注意使用 r.mu 读写锁避免竞争 + return r.table[cidr] +} + +func (r *Router) SetItem(ip *net.IPNet, l *Link) { + r.mu.Lock() + // 从第一条表项开始匹配 + for i := 0; i < len(r.list); i++ { + if r.list[i].Contains(ip.IP) { + // 是同一个网络 + if ip.Mask.String() == r.list[i].Mask.String() { + logrus.Infoln("[router] change link of item", r.list[i], "from", r.table[r.list[i].String()], "to", l) + r.table[r.list[i].String()] = l + break + } + // 是新网络 + r.list = append(r.list, nil) + copy(r.list[i+1:], r.list[i:len(r.list)-1]) + r.list[i] = ip + r.table[ip.String()] = l + logrus.Infoln("[router] add item: net =", ip, "link =", l) + break + } + } + r.mu.Unlock() } diff --git a/upper/services/tunnel/tunnel_test.go b/upper/services/tunnel/tunnel_test.go index e600b23..223accf 100644 --- a/upper/services/tunnel/tunnel_test.go +++ b/upper/services/tunnel/tunnel_test.go @@ -28,9 +28,9 @@ func TestTunnel(t *testing.T) { t.Log("peer publ key:", hex.EncodeToString(peerpk.Public()[:])) m := link.NewMe(selfpk.Private(), "192.168.1.2", "127.0.0.1:1236") - m.AddPeer("192.168.1.3", peerpk.Public(), "127.0.0.1:1237", nil, 0, false) + m.AddPeer("192.168.1.3", peerpk.Public(), "127.0.0.1:1237", []string{"192.168.1.3/32"}, 0, false) p := link.NewMe(peerpk.Private(), "192.168.1.3", "127.0.0.1:1237") - p.AddPeer("192.168.1.2", selfpk.Public(), "127.0.0.1:1236", nil, 0, false) + p.AddPeer("192.168.1.2", selfpk.Public(), "127.0.0.1:1236", []string{"192.168.1.2/32"}, 0, false) tunnme, err := Create(&m, "192.168.1.3", 1, 1, 4096) if err != nil { t.Fatal(err)