From fa1608165bd12f398d5a54631528da901b60166d Mon Sep 17 00:00:00 2001 From: fumiama Date: Sun, 24 Oct 2021 20:29:44 +0800 Subject: [PATCH] init --- gold/head/packet.go | 13 +++++-- gold/link/link.go | 46 ++++++++++------------- gold/link/link_test.go | 31 ++++++++++++++++ gold/link/local.go | 35 +++++++++++++----- gold/link/nat.go | 4 +- gold/link/peer.go | 55 ++++++++++++++++++++++++++++ gold/link/remote.go | 48 ------------------------ upper/services/tunnel/tunnel.go | 8 ++-- upper/services/tunnel/tunnel_test.go | 18 +++++---- 9 files changed, 158 insertions(+), 100 deletions(-) create mode 100644 gold/link/link_test.go create mode 100644 gold/link/peer.go delete mode 100644 gold/link/remote.go diff --git a/gold/head/packet.go b/gold/head/packet.go index ab9342d..2ff906b 100644 --- a/gold/head/packet.go +++ b/gold/head/packet.go @@ -1,5 +1,7 @@ package head +import "encoding/json" + type Packet struct { DataSZ uint32 Proto uint8 @@ -21,10 +23,13 @@ func NewPacket(proto uint8, srcPort uint16, dstPort uint16, data []byte) *Packet } } -func (p *Packet) UnMashal(data []byte) { - +func (p *Packet) UnMashal(data []byte) error { + return json.Unmarshal(data, p) } -func (p *Packet) Mashal(src string, dst string) []byte { - return nil +func (p *Packet) Mashal(src string, dst string) ([]byte, error) { + p.DataSZ = uint32(len(p.Data)) + p.Src = src + p.Dst = dst + return json.Marshal(p) } diff --git a/gold/link/link.go b/gold/link/link.go index 40f8cd0..ba8afc7 100644 --- a/gold/link/link.go +++ b/gold/link/link.go @@ -6,59 +6,53 @@ import ( "sync" "github.com/fumiama/WireGold/gold/head" + "github.com/sirupsen/logrus" ) type Link struct { - conn net.Conn - peer *Identity + PubicKey [32]byte + EndPoint string + KeepAlive int64 + pipe chan *head.Packet peerip net.IP + endpoint *net.UDPAddr hasKeepRuning bool } var ( connections = make(map[string]*Link) connmapmu sync.RWMutex + myconn *net.UDPConn ) -func Connect(peer string) (l Link, err error) { - peer = net.ParseIP(peer).String() - p, ok := IsInPeer(peer) +func Connect(peer string) (*Link, error) { + p, ok := IsInPeer(net.ParseIP(peer).String()) if ok { - connmapmu.RLock() - lnk, ok := connections[peer] - connmapmu.RUnlock() - if ok { - return *lnk, nil - } - l.conn, err = net.Dial("udp", p.EndPoint) - l.peer = p - l.peerip = net.ParseIP(peer) - connmapmu.Lock() - connections[l.peerip.String()] = &l - connmapmu.Unlock() - l.keepAlive() - } else { - err = errors.New("peer not exist") + p.keepAlive() + return p, nil } - return + return nil, errors.New("peer not exist") } func (l *Link) Close() { - l.conn.Close() connmapmu.Lock() delete(connections, l.peerip.String()) connmapmu.Unlock() } func (l *Link) Read() *head.Packet { - return <-l.peer.pipe + return <-l.pipe } func (l *Link) Write(p *head.Packet) (n int, err error) { - d := p.Mashal(me.String(), l.peerip.String()) - d, err = l.peer.Encode(d) + var d []byte + d, err = p.Mashal(me.String(), l.peerip.String()) + logrus.Debugln("[link] write data", string(d)) if err == nil { - n, err = l.conn.Write(d) + d, err = l.Encode(d) + if err == nil { + n, err = myconn.WriteToUDP(d, l.endpoint) + } } return } diff --git a/gold/link/link_test.go b/gold/link/link_test.go new file mode 100644 index 0000000..d3c844b --- /dev/null +++ b/gold/link/link_test.go @@ -0,0 +1,31 @@ +package link + +import ( + "net" + "testing" +) + +func TestUDP(t *testing.T) { + t.Log("test start") + lconn, err := net.ListenUDP("udp", &net.UDPAddr{Port: 1234}) + if err == nil { + dconn, err := net.DialUDP("udp", &net.UDPAddr{Port: 1235}, &net.UDPAddr{Port: 1234}) + if err != nil { + t.Fatal(err) + } + _, err = dconn.Write(([]byte)("1234567890")) + t.Log("write succ") + if err != nil { + t.Fatal(err) + } + d := make([]byte, 10) + _, err = lconn.Read(d) + t.Log("read succ") + if err != nil { + t.Fatal(err) + } + t.Log(d) + } else { + t.Fatal(err) + } +} diff --git a/gold/link/local.go b/gold/link/local.go index b00a180..e413fea 100644 --- a/gold/link/local.go +++ b/gold/link/local.go @@ -10,33 +10,47 @@ import ( var ( privKey [32]byte me net.IP + myend *net.UDPAddr ) -func SetMyself(privateKey [32]byte, myIP string) { +func SetMyself(privateKey [32]byte, myIP string, myEndpoint string) { privKey = privateKey + var err error + myend, err = net.ResolveUDPAddr("udp", myEndpoint) + if err != nil { + panic(err) + } me = net.ParseIP(myIP) + myconn, err = listen() + if err != nil { + panic(err) + } } -func (id *Identity) Encode(b []byte) (eb []byte, err error) { +func (l *Link) Encode(b []byte) (eb []byte, err error) { return b, nil } -func (id *Identity) Decode(b []byte) (db []byte, err error) { +func (l *Link) Decode(b []byte) (db []byte, err error) { return b, nil } -func Listen(endpoint string) error { - conn, err := net.ListenPacket("udp", endpoint) +func listen() (conn *net.UDPConn, err error) { + conn, err = net.ListenUDP("udp", myend) if err == nil { go func() { listenbuff := make([]byte, 65536) for { - _, addr, err := conn.ReadFrom(listenbuff) + lbf := listenbuff + n, addr, err := conn.ReadFromUDP(lbf) if err == nil { - p, ok := IsInPeer(addr.String()) + lbf = lbf[:n] + p, ok := IsEndpointInPeer(addr.String()) + logrus.Infoln("[link] recv from endpoint", addr) + logrus.Debugln("[link] recv:", string(lbf)) if ok { packet := head.Packet{} - d, err := p.Decode(listenbuff) + d, err := p.Decode(lbf) if err == nil { packet.UnMashal(d) r := packet.DataSZ - uint32(len(packet.Data)) @@ -45,7 +59,7 @@ func Listen(endpoint string) error { n := 0 remain := make([]byte, r) for r > 0 { - n, _, err = conn.ReadFrom(remain[i:]) + n, _, err = conn.ReadFromUDP(remain[i:]) if err == nil { i += n r -= uint32(n) @@ -56,6 +70,7 @@ func Listen(endpoint string) error { } packet.Data = append(packet.Data, remain...) } + logrus.Infoln("[link] deliver to", p.peerip) p.pipe <- &packet } } @@ -63,5 +78,5 @@ func Listen(endpoint string) error { } }() } - return err + return } diff --git a/gold/link/nat.go b/gold/link/nat.go index 9e912da..1a1e3a5 100644 --- a/gold/link/nat.go +++ b/gold/link/nat.go @@ -9,10 +9,10 @@ import ( ) func (l *Link) keepAlive() { - if l.peer.KeepAlive > 0 && !l.hasKeepRuning { + if l.KeepAlive > 0 && !l.hasKeepRuning { l.hasKeepRuning = true go func() { - t := time.NewTicker(time.Second * time.Duration(l.peer.KeepAlive)) + t := time.NewTicker(time.Second * time.Duration(l.KeepAlive)) for range t.C { _, _ = l.Write(head.NewPacket(head.ProtoHello, 0, 0, nil)) logrus.Infoln("[link.nat] send keep alive packet") diff --git a/gold/link/peer.go b/gold/link/peer.go new file mode 100644 index 0000000..4870b7b --- /dev/null +++ b/gold/link/peer.go @@ -0,0 +1,55 @@ +package link + +import ( + "net" + "sync" + + "github.com/fumiama/WireGold/gold/head" +) + +var ( + eps = make(map[string]*Link) + epmu sync.RWMutex +) + +func AddPeer(peerip string, pubicKey [32]byte, endPoint string, keepAlive int64) (l *Link) { + peerip = net.ParseIP(peerip).String() + var ok bool + l, ok = IsInPeer(peerip) + if ok { + return + } + e, err := net.ResolveUDPAddr("udp", endPoint) + if err != nil { + panic(err) + } + l = &Link{ + PubicKey: pubicKey, + EndPoint: endPoint, + KeepAlive: keepAlive, + pipe: make(chan *head.Packet, 32), + peerip: net.ParseIP(peerip), + endpoint: e, + } + connmapmu.Lock() + epmu.Lock() + connections[peerip] = l + eps[endPoint] = l + connmapmu.Unlock() + epmu.Unlock() + return +} + +func IsInPeer(peer string) (p *Link, ok bool) { + connmapmu.RLock() + p, ok = connections[peer] + connmapmu.RUnlock() + return +} + +func IsEndpointInPeer(ep string) (p *Link, ok bool) { + epmu.RLock() + p, ok = eps[ep] + epmu.RUnlock() + return +} diff --git a/gold/link/remote.go b/gold/link/remote.go deleted file mode 100644 index 8461865..0000000 --- a/gold/link/remote.go +++ /dev/null @@ -1,48 +0,0 @@ -package link - -import ( - "net" - "sync" - - "github.com/fumiama/WireGold/gold/head" -) - -type Identity struct { - PubicKey [32]byte - EndPoint string - KeepAlive int64 - pipe chan *head.Packet -} - -var ( - peers = make(map[string]*Identity) - peersmu sync.RWMutex -) - -func AddPeer(peerip string, pubicKey [32]byte, endPoint string, keepAlive int64) (i *Identity) { - peerip = net.ParseIP(peerip).String() - var ok bool - peersmu.RLock() - i, ok = peers[peerip] - peersmu.RUnlock() - if ok { - return - } - i = &Identity{ - PubicKey: pubicKey, - EndPoint: endPoint, - KeepAlive: keepAlive, - pipe: make(chan *head.Packet, 32), - } - peersmu.Lock() - peers[peerip] = i - peersmu.Unlock() - return -} - -func IsInPeer(peer string) (p *Identity, ok bool) { - peersmu.RLock() - p, ok = peers[peer] - peersmu.RUnlock() - return -} diff --git a/upper/services/tunnel/tunnel.go b/upper/services/tunnel/tunnel.go index 9792c8a..a3519ed 100644 --- a/upper/services/tunnel/tunnel.go +++ b/upper/services/tunnel/tunnel.go @@ -20,10 +20,8 @@ type Tunnel struct { func Create(peer string, srcport uint16, destport uint16) (s Tunnel, err error) { logrus.Infoln("[tunnel] create from", srcport, "to", destport) - var l link.Link - l, err = link.Connect(peer) + s.l, err = link.Connect(peer) if err == nil { - s.l = &l s.in = make(chan []byte, 4) s.out = make(chan []byte, 4) s.src = srcport @@ -68,7 +66,9 @@ func (s *Tunnel) Close() error { func (s *Tunnel) handleWrite() { for b := range s.in { + logrus.Debugln("[tunnel] write recv", b) if b == nil { + logrus.Errorln("[tunnel] write recv nil") break } logrus.Debugln("[tunnel] writing", len(b), "bytes...") @@ -86,8 +86,10 @@ func (s *Tunnel) handleRead() { for { p := s.l.Read() if p == nil { + logrus.Errorln("[tunnel] read recv nil") break } + logrus.Debugln("[tunnel] read recv", p.Data) s.out <- p.Data } } diff --git a/upper/services/tunnel/tunnel_test.go b/upper/services/tunnel/tunnel_test.go index 3452ae7..9fd9518 100644 --- a/upper/services/tunnel/tunnel_test.go +++ b/upper/services/tunnel/tunnel_test.go @@ -4,20 +4,24 @@ import ( "testing" "github.com/fumiama/WireGold/gold/link" + "github.com/sirupsen/logrus" ) func TestTunnel(t *testing.T) { - link.SetMyself([32]byte{}, "127.0.0.1:1234") - link.AddPeer("192.168.1.1", [32]byte{}, "127.0.0.1:1235", 0) - link.Listen("127.0.0.1:1234") - link.Listen("127.0.0.1:1235") - tunn, err := Create("192.168.1.1", 1, 1) + logrus.SetLevel(logrus.DebugLevel) + link.SetMyself([32]byte{}, "192.168.1.2", "127.0.0.1:1236") + link.AddPeer("192.168.1.2", [32]byte{}, "127.0.0.1:1236", 0) + tunn, err := Create("192.168.1.2", 1, 1) if err != nil { t.Error(err) } else { - tunn.Write(([]byte)("1234")) + sendb := ([]byte)("1234") + tunn.Write(sendb) p := make([]byte, 4) tunn.Read(p) - t.Log(p) + if string(sendb) != string(p) { + t.Log("error: recv", p) + t.Fail() + } } }