Commit d1ebafc8 authored by Petar Radovic's avatar Petar Radovic Committed by GitHub

Advertisable address (#283)

Use advertisable address to try and help UPnP situation
parent 0231080f
......@@ -14,6 +14,7 @@ import (
"path/filepath"
"sync"
"sync/atomic"
"time"
"github.com/ethersphere/bee/pkg/addressbook"
"github.com/ethersphere/bee/pkg/api"
......@@ -151,6 +152,18 @@ func NewBee(o Options) (*Bee, error) {
}
b.p2pService = p2ps
// wait for nat manager to init
logger.Debug("initializing NAT manager")
select {
case <-p2ps.NATManager().Ready():
// this is magic sleep to give NAT time to sync the mappings
// this is a hack, kind of alchemy and should be improved
time.Sleep(3 * time.Second)
logger.Debug("NAT manager initialized")
case <-time.After(10 * time.Second):
logger.Warning("NAT manager init timeout")
}
// Construct protocols.
pingPong := pingpong.New(pingpong.Options{
Streamer: p2ps,
......
......@@ -44,8 +44,13 @@ var (
ErrInvalidSyn = errors.New("invalid syn")
)
type AdvertisableAddressResolver interface {
Resolve(observedAdddress ma.Multiaddr) (ma.Multiaddr, error)
}
type Service struct {
signer crypto.Signer
advertisableAddresser AdvertisableAddressResolver
overlay swarm.Address
lightNode bool
networkID uint64
......@@ -56,9 +61,10 @@ type Service struct {
network.Notifiee // handshake service can be the receiver for network.Notify
}
func New(overlay swarm.Address, signer crypto.Signer, networkID uint64, lighNode bool, logger logging.Logger) (*Service, error) {
func New(signer crypto.Signer, advertisableAddresser AdvertisableAddressResolver, overlay swarm.Address, networkID uint64, lighNode bool, logger logging.Logger) (*Service, error) {
return &Service{
signer: signer,
advertisableAddresser: advertisableAddresser,
overlay: overlay,
networkID: networkID,
lightNode: lighNode,
......@@ -91,24 +97,37 @@ func (s *Service) Handshake(stream p2p.Stream, peerMultiaddr ma.Multiaddr, peerI
return nil, fmt.Errorf("read synack message: %w", err)
}
remoteBzzAddress, err := s.parseCheckAck(resp.Ack, fullRemoteMABytes)
remoteBzzAddress, err := s.parseCheckAck(resp.Ack)
if err != nil {
return nil, err
}
addr, err := ma.NewMultiaddrBytes(resp.Syn.ObservedUnderlay)
observedUnderlay, err := ma.NewMultiaddrBytes(resp.Syn.ObservedUnderlay)
if err != nil {
return nil, ErrInvalidSyn
}
bzzAddress, err := bzz.NewAddress(s.signer, addr, s.overlay, s.networkID)
advertisableUnderlay, err := s.advertisableAddresser.Resolve(observedUnderlay)
if err != nil {
return nil, err
}
bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlay, s.overlay, s.networkID)
if err != nil {
return nil, err
}
advertisableUnderlayBytes, err := bzzAddress.Underlay.MarshalBinary()
if err != nil {
return nil, err
}
if err := w.WriteMsgWithTimeout(messageTimeout, &pb.Ack{
Address: &pb.BzzAddress{
Underlay: advertisableUnderlayBytes,
Overlay: bzzAddress.Overlay.Bytes(),
Signature: bzzAddress.Signature,
},
NetworkID: s.networkID,
Light: s.lightNode,
}); err != nil {
......@@ -147,12 +166,22 @@ func (s *Service) Handle(stream p2p.Stream, remoteMultiaddr ma.Multiaddr, remote
return nil, fmt.Errorf("read syn message: %w", err)
}
addr, err := ma.NewMultiaddrBytes(syn.ObservedUnderlay)
observedUnderlay, err := ma.NewMultiaddrBytes(syn.ObservedUnderlay)
if err != nil {
return nil, ErrInvalidSyn
}
bzzAddress, err := bzz.NewAddress(s.signer, addr, s.overlay, s.networkID)
advertisableUnderlay, err := s.advertisableAddresser.Resolve(observedUnderlay)
if err != nil {
return nil, err
}
bzzAddress, err := bzz.NewAddress(s.signer, advertisableUnderlay, s.overlay, s.networkID)
if err != nil {
return nil, err
}
advertisableUnderlayBytes, err := bzzAddress.Underlay.MarshalBinary()
if err != nil {
return nil, err
}
......@@ -162,8 +191,11 @@ func (s *Service) Handle(stream p2p.Stream, remoteMultiaddr ma.Multiaddr, remote
ObservedUnderlay: fullRemoteMABytes,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Underlay: advertisableUnderlayBytes,
Overlay: bzzAddress.Overlay.Bytes(),
Signature: bzzAddress.Signature,
},
NetworkID: s.networkID,
Light: s.lightNode,
},
......@@ -176,7 +208,7 @@ func (s *Service) Handle(stream p2p.Stream, remoteMultiaddr ma.Multiaddr, remote
return nil, fmt.Errorf("read ack message: %w", err)
}
remoteBzzAddress, err := s.parseCheckAck(&ack, fullRemoteMABytes)
remoteBzzAddress, err := s.parseCheckAck(&ack)
if err != nil {
return nil, err
}
......@@ -198,12 +230,12 @@ func buildFullMA(addr ma.Multiaddr, peerID libp2ppeer.ID) (ma.Multiaddr, error)
return ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s", addr.String(), peerID.Pretty()))
}
func (s *Service) parseCheckAck(ack *pb.Ack, remoteMA []byte) (*bzz.Address, error) {
func (s *Service) parseCheckAck(ack *pb.Ack) (*bzz.Address, error) {
if ack.NetworkID != s.networkID {
return nil, ErrNetworkIDIncompatible
}
bzzAddress, err := bzz.ParseAddress(remoteMA, ack.Overlay, ack.Signature, s.networkID)
bzzAddress, err := bzz.ParseAddress(ack.Address.Underlay, ack.Address.Overlay, ack.Address.Signature, s.networkID)
if err != nil {
return nil, ErrInvalidAck
}
......
......@@ -77,7 +77,9 @@ func TestHandshake(t *testing.T) {
Light: false,
}
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
aaddresser := &AdvertisableAddresserMock{}
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -94,8 +96,11 @@ func TestHandshake(t *testing.T) {
ObservedUnderlay: node1maBinary,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
},
......@@ -109,9 +114,28 @@ func TestHandshake(t *testing.T) {
}
testInfo(t, *res, node2Info)
if err := r.ReadMsg(&pb.Ack{}); err != nil {
var syn pb.Syn
if err := r.ReadMsg(&syn); err != nil {
t.Fatal(err)
}
if !bytes.Equal(syn.ObservedUnderlay, node2maBinary) {
t.Fatal("bad syn")
}
var ack pb.Ack
if err := r.ReadMsg(&ack); err != nil {
t.Fatal(err)
}
if !bytes.Equal(ack.Address.Overlay, node1BzzAddress.Overlay.Bytes()) ||
!bytes.Equal(ack.Address.Underlay, node1maBinary) ||
!bytes.Equal(ack.Address.Signature, node1BzzAddress.Signature) ||
ack.NetworkID != networkID ||
ack.Light != false {
t.Fatal("bad ack")
}
})
t.Run("Handshake - Syn write error", func(t *testing.T) {
......@@ -159,8 +183,11 @@ func TestHandshake(t *testing.T) {
ObservedUnderlay: node1maBinary,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
},
......@@ -191,8 +218,11 @@ func TestHandshake(t *testing.T) {
ObservedUnderlay: node1maBinary,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: 5,
Light: false,
},
......@@ -222,8 +252,11 @@ func TestHandshake(t *testing.T) {
ObservedUnderlay: node1maBinary,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: []byte("invalid"),
Signature: node1BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
},
......@@ -241,8 +274,50 @@ func TestHandshake(t *testing.T) {
}
})
t.Run("Handshake - error advertisable address", func(t *testing.T) {
var buffer1 bytes.Buffer
var buffer2 bytes.Buffer
stream1 := mock.NewStream(&buffer1, &buffer2)
stream2 := mock.NewStream(&buffer2, &buffer1)
testError := errors.New("test error")
aaddresser.err = testError
defer func() {
aaddresser.err = nil
}()
w, _ := protobuf.NewWriterAndReader(stream2)
if err := w.WriteMsg(&pb.SynAck{
Syn: &pb.Syn{
ObservedUnderlay: node1maBinary,
},
Ack: &pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
},
}); err != nil {
t.Fatal(err)
}
res, err := handshakeService.Handshake(stream1, node2AddrInfo.Addrs[0], node2AddrInfo.ID)
if err != testError {
t.Fatalf("expected error %v got %v", testError, err)
}
if res != nil {
t.Fatal("expected nil res")
}
})
t.Run("Handle - OK", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -259,8 +334,11 @@ func TestHandshake(t *testing.T) {
}
if err := w.WriteMsg(&pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
}); err != nil {
......@@ -284,7 +362,7 @@ func TestHandshake(t *testing.T) {
t.Fatalf("got bad syn")
}
bzzAddress, err := bzz.ParseAddress(node1maBinary, got.Ack.Overlay, got.Ack.Signature, got.Ack.NetworkID)
bzzAddress, err := bzz.ParseAddress(got.Ack.Address.Underlay, got.Ack.Address.Overlay, got.Ack.Address.Signature, got.Ack.NetworkID)
if err != nil {
t.Fatal(err)
}
......@@ -296,7 +374,7 @@ func TestHandshake(t *testing.T) {
})
t.Run("Handle - read error ", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -315,7 +393,7 @@ func TestHandshake(t *testing.T) {
})
t.Run("Handle - write error ", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -342,7 +420,7 @@ func TestHandshake(t *testing.T) {
})
t.Run("Handle - ack read error ", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -371,7 +449,7 @@ func TestHandshake(t *testing.T) {
})
t.Run("Handle - networkID mismatch ", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -388,8 +466,11 @@ func TestHandshake(t *testing.T) {
}
if err := w.WriteMsg(&pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: 5,
Light: false,
}); err != nil {
......@@ -407,7 +488,7 @@ func TestHandshake(t *testing.T) {
})
t.Run("Handle - duplicate handshake", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -424,8 +505,11 @@ func TestHandshake(t *testing.T) {
}
if err := w.WriteMsg(&pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: node2BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
}); err != nil {
......@@ -449,7 +533,7 @@ func TestHandshake(t *testing.T) {
t.Fatalf("got bad syn")
}
bzzAddress, err := bzz.ParseAddress(node1maBinary, got.Ack.Overlay, got.Ack.Signature, got.Ack.NetworkID)
bzzAddress, err := bzz.ParseAddress(got.Ack.Address.Underlay, got.Ack.Address.Overlay, got.Ack.Address.Signature, got.Ack.NetworkID)
if err != nil {
t.Fatal(err)
}
......@@ -466,7 +550,7 @@ func TestHandshake(t *testing.T) {
})
t.Run("Handle - invalid ack", func(t *testing.T) {
handshakeService, err := handshake.New(node1Info.BzzAddress.Overlay, signer1, networkID, false, logger)
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
......@@ -483,8 +567,11 @@ func TestHandshake(t *testing.T) {
}
if err := w.WriteMsg(&pb.Ack{
Address: &pb.BzzAddress{
Underlay: node2maBinary,
Overlay: node2BzzAddress.Overlay.Bytes(),
Signature: []byte("wrong signature"),
Signature: node1BzzAddress.Signature,
},
NetworkID: networkID,
Light: false,
}); err != nil {
......@@ -496,6 +583,39 @@ func TestHandshake(t *testing.T) {
t.Fatalf("expected %s, got %s", handshake.ErrInvalidAck, err)
}
})
t.Run("Handle - advertisable error", func(t *testing.T) {
handshakeService, err := handshake.New(signer1, aaddresser, node1Info.BzzAddress.Overlay, networkID, false, logger)
if err != nil {
t.Fatal(err)
}
var buffer1 bytes.Buffer
var buffer2 bytes.Buffer
stream1 := mock.NewStream(&buffer1, &buffer2)
stream2 := mock.NewStream(&buffer2, &buffer1)
testError := errors.New("test error")
aaddresser.err = testError
defer func() {
aaddresser.err = nil
}()
w := protobuf.NewWriter(stream2)
if err := w.WriteMsg(&pb.Syn{
ObservedUnderlay: node1maBinary,
}); err != nil {
t.Fatal(err)
}
res, err := handshakeService.Handle(stream1, node2AddrInfo.Addrs[0], node2AddrInfo.ID)
if err != testError {
t.Fatal("expected error")
}
if res != nil {
t.Fatal("expected nil res")
}
})
}
// testInfo validates if two Info instances are equal.
......@@ -505,3 +625,20 @@ func testInfo(t *testing.T, got, want handshake.Info) {
t.Fatalf("got info %+v, want %+v", got, want)
}
}
type AdvertisableAddresserMock struct {
advertisableAddress ma.Multiaddr
err error
}
func (a *AdvertisableAddresserMock) Resolve(observedAdddress ma.Multiaddr) (ma.Multiaddr, error) {
if a.err != nil {
return nil, a.err
}
if a.advertisableAddress != nil {
return a.advertisableAddress, nil
}
return observedAdddress, nil
}
......@@ -67,10 +67,9 @@ func (m *Syn) GetObservedUnderlay() []byte {
}
type Ack struct {
Overlay []byte `protobuf:"bytes,1,opt,name=Overlay,proto3" json:"Overlay,omitempty"`
Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"`
NetworkID uint64 `protobuf:"varint,3,opt,name=NetworkID,proto3" json:"NetworkID,omitempty"`
Light bool `protobuf:"varint,4,opt,name=Light,proto3" json:"Light,omitempty"`
Address *BzzAddress `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty"`
NetworkID uint64 `protobuf:"varint,2,opt,name=NetworkID,proto3" json:"NetworkID,omitempty"`
Light bool `protobuf:"varint,3,opt,name=Light,proto3" json:"Light,omitempty"`
}
func (m *Ack) Reset() { *m = Ack{} }
......@@ -106,16 +105,9 @@ func (m *Ack) XXX_DiscardUnknown() {
var xxx_messageInfo_Ack proto.InternalMessageInfo
func (m *Ack) GetOverlay() []byte {
func (m *Ack) GetAddress() *BzzAddress {
if m != nil {
return m.Overlay
}
return nil
}
func (m *Ack) GetSignature() []byte {
if m != nil {
return m.Signature
return m.Address
}
return nil
}
......@@ -186,31 +178,95 @@ func (m *SynAck) GetAck() *Ack {
return nil
}
type BzzAddress struct {
Underlay []byte `protobuf:"bytes,1,opt,name=Underlay,proto3" json:"Underlay,omitempty"`
Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"`
Overlay []byte `protobuf:"bytes,3,opt,name=Overlay,proto3" json:"Overlay,omitempty"`
}
func (m *BzzAddress) Reset() { *m = BzzAddress{} }
func (m *BzzAddress) String() string { return proto.CompactTextString(m) }
func (*BzzAddress) ProtoMessage() {}
func (*BzzAddress) Descriptor() ([]byte, []int) {
return fileDescriptor_a77305914d5d202f, []int{3}
}
func (m *BzzAddress) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *BzzAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_BzzAddress.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *BzzAddress) XXX_Merge(src proto.Message) {
xxx_messageInfo_BzzAddress.Merge(m, src)
}
func (m *BzzAddress) XXX_Size() int {
return m.Size()
}
func (m *BzzAddress) XXX_DiscardUnknown() {
xxx_messageInfo_BzzAddress.DiscardUnknown(m)
}
var xxx_messageInfo_BzzAddress proto.InternalMessageInfo
func (m *BzzAddress) GetUnderlay() []byte {
if m != nil {
return m.Underlay
}
return nil
}
func (m *BzzAddress) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *BzzAddress) GetOverlay() []byte {
if m != nil {
return m.Overlay
}
return nil
}
func init() {
proto.RegisterType((*Syn)(nil), "handshake.Syn")
proto.RegisterType((*Ack)(nil), "handshake.Ack")
proto.RegisterType((*SynAck)(nil), "handshake.SynAck")
proto.RegisterType((*BzzAddress)(nil), "handshake.BzzAddress")
}
func init() { proto.RegisterFile("handshake.proto", fileDescriptor_a77305914d5d202f) }
var fileDescriptor_a77305914d5d202f = []byte{
// 231 bytes of a gzipped FileDescriptorProto
// 273 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcf, 0x48, 0xcc, 0x4b,
0x29, 0xce, 0x48, 0xcc, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x0b, 0x28,
0x19, 0x72, 0x31, 0x07, 0x57, 0xe6, 0x09, 0x69, 0x71, 0x09, 0xf8, 0x27, 0x15, 0xa7, 0x16, 0x95,
0xa5, 0xa6, 0x84, 0xe6, 0xa5, 0xa4, 0x16, 0xe5, 0x24, 0x56, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0,
0x04, 0x61, 0x88, 0x2b, 0x15, 0x72, 0x31, 0x3b, 0x26, 0x67, 0x0b, 0x49, 0x70, 0xb1, 0xfb, 0x97,
0x21, 0xab, 0x84, 0x71, 0x85, 0x64, 0xb8, 0x38, 0x83, 0x33, 0xd3, 0xf3, 0x12, 0x4b, 0x4a, 0x8b,
0x52, 0x25, 0x98, 0xc0, 0x72, 0x08, 0x01, 0x90, 0xac, 0x5f, 0x6a, 0x49, 0x79, 0x7e, 0x51, 0xb6,
0xa7, 0x8b, 0x04, 0xb3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x42, 0x40, 0x48, 0x84, 0x8b, 0xd5, 0x27,
0x33, 0x3d, 0xa3, 0x44, 0x82, 0x45, 0x81, 0x51, 0x83, 0x23, 0x08, 0xc2, 0x51, 0xf2, 0xe1, 0x62,
0x0b, 0xae, 0xcc, 0x03, 0xd9, 0xaa, 0x00, 0x76, 0x2f, 0xd8, 0x46, 0x6e, 0x23, 0x3e, 0x3d, 0x84,
0xcf, 0x82, 0x2b, 0xf3, 0x82, 0xc0, 0x5e, 0x51, 0x00, 0x3b, 0x0f, 0x6c, 0x2f, 0xaa, 0x0a, 0xc7,
0xe4, 0xec, 0x20, 0x90, 0x94, 0x93, 0xcc, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e,
0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31,
0x44, 0x31, 0x15, 0x24, 0x25, 0xb1, 0x81, 0xc3, 0xc8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x51,
0xf9, 0xa1, 0xf4, 0x36, 0x01, 0x00, 0x00,
0x04, 0x61, 0x88, 0x2b, 0x65, 0x71, 0x31, 0x3b, 0x26, 0x67, 0x0b, 0xe9, 0x73, 0xb1, 0x3b, 0xa6,
0xa4, 0x14, 0xa5, 0x16, 0x17, 0x83, 0x55, 0x72, 0x1b, 0x89, 0xea, 0x21, 0xec, 0x71, 0xaa, 0xaa,
0x82, 0x4a, 0x06, 0xc1, 0x54, 0x09, 0xc9, 0x70, 0x71, 0xfa, 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65,
0x7b, 0xba, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xb0, 0x04, 0x21, 0x04, 0x84, 0x44, 0xb8, 0x58, 0x7d,
0x32, 0xd3, 0x33, 0x4a, 0x24, 0x98, 0x15, 0x18, 0x35, 0x38, 0x82, 0x20, 0x1c, 0x25, 0x1f, 0x2e,
0xb6, 0xe0, 0xca, 0x3c, 0x90, 0x75, 0x0a, 0x60, 0x87, 0x42, 0xad, 0xe2, 0x43, 0xb2, 0x2a, 0xb8,
0x32, 0x2f, 0x08, 0xec, 0x07, 0x05, 0xb0, 0xbb, 0xc0, 0x26, 0xa3, 0xaa, 0x70, 0x4c, 0xce, 0x0e,
0x02, 0x49, 0x29, 0x25, 0x70, 0x71, 0x21, 0x1c, 0x26, 0x24, 0xc5, 0xc5, 0x81, 0xe6, 0x57, 0x38,
0x1f, 0xe4, 0xd6, 0xe0, 0xcc, 0xf4, 0xbc, 0xc4, 0x92, 0xd2, 0xa2, 0x54, 0xb0, 0x89, 0x3c, 0x41,
0x08, 0x01, 0x21, 0x09, 0x2e, 0x76, 0xff, 0x32, 0x88, 0x46, 0x66, 0xb0, 0x1c, 0x8c, 0xeb, 0x24,
0x73, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c,
0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x4c, 0x05, 0x49, 0x49, 0x6c,
0xe0, 0xe0, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x63, 0xc1, 0x05, 0xdf, 0x91, 0x01, 0x00,
0x00,
}
func (m *Syn) Marshal() (dAtA []byte, err error) {
......@@ -271,24 +327,22 @@ func (m *Ack) MarshalToSizedBuffer(dAtA []byte) (int, error) {
dAtA[i] = 0
}
i--
dAtA[i] = 0x20
dAtA[i] = 0x18
}
if m.NetworkID != 0 {
i = encodeVarintHandshake(dAtA, i, uint64(m.NetworkID))
i--
dAtA[i] = 0x18
dAtA[i] = 0x10
}
if len(m.Signature) > 0 {
i -= len(m.Signature)
copy(dAtA[i:], m.Signature)
i = encodeVarintHandshake(dAtA, i, uint64(len(m.Signature)))
i--
dAtA[i] = 0x12
if m.Address != nil {
{
size, err := m.Address.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintHandshake(dAtA, i, uint64(size))
}
if len(m.Overlay) > 0 {
i -= len(m.Overlay)
copy(dAtA[i:], m.Overlay)
i = encodeVarintHandshake(dAtA, i, uint64(len(m.Overlay)))
i--
dAtA[i] = 0xa
}
......@@ -342,6 +396,50 @@ func (m *SynAck) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *BzzAddress) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *BzzAddress) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *BzzAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Overlay) > 0 {
i -= len(m.Overlay)
copy(dAtA[i:], m.Overlay)
i = encodeVarintHandshake(dAtA, i, uint64(len(m.Overlay)))
i--
dAtA[i] = 0x1a
}
if len(m.Signature) > 0 {
i -= len(m.Signature)
copy(dAtA[i:], m.Signature)
i = encodeVarintHandshake(dAtA, i, uint64(len(m.Signature)))
i--
dAtA[i] = 0x12
}
if len(m.Underlay) > 0 {
i -= len(m.Underlay)
copy(dAtA[i:], m.Underlay)
i = encodeVarintHandshake(dAtA, i, uint64(len(m.Underlay)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintHandshake(dAtA []byte, offset int, v uint64) int {
offset -= sovHandshake(v)
base := offset
......@@ -372,12 +470,8 @@ func (m *Ack) Size() (n int) {
}
var l int
_ = l
l = len(m.Overlay)
if l > 0 {
n += 1 + l + sovHandshake(uint64(l))
}
l = len(m.Signature)
if l > 0 {
if m.Address != nil {
l = m.Address.Size()
n += 1 + l + sovHandshake(uint64(l))
}
if m.NetworkID != 0 {
......@@ -406,6 +500,27 @@ func (m *SynAck) Size() (n int) {
return n
}
func (m *BzzAddress) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Underlay)
if l > 0 {
n += 1 + l + sovHandshake(uint64(l))
}
l = len(m.Signature)
if l > 0 {
n += 1 + l + sovHandshake(uint64(l))
}
l = len(m.Overlay)
if l > 0 {
n += 1 + l + sovHandshake(uint64(l))
}
return n
}
func sovHandshake(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
......@@ -530,9 +645,9 @@ func (m *Ack) Unmarshal(dAtA []byte) error {
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Overlay", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
}
var byteLen int
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
......@@ -542,61 +657,29 @@ func (m *Ack) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
if msglen < 0 {
return ErrInvalidLengthHandshake
}
postIndex := iNdEx + byteLen
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthHandshake
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Overlay = append(m.Overlay[:0], dAtA[iNdEx:postIndex]...)
if m.Overlay == nil {
m.Overlay = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthHandshake
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthHandshake
}
if postIndex > l {
return io.ErrUnexpectedEOF
if m.Address == nil {
m.Address = &BzzAddress{}
}
m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
if m.Signature == nil {
m.Signature = []byte{}
if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field NetworkID", wireType)
}
......@@ -615,7 +698,7 @@ func (m *Ack) Unmarshal(dAtA []byte) error {
break
}
}
case 4:
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Light", wireType)
}
......@@ -784,6 +867,161 @@ func (m *SynAck) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *BzzAddress) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: BzzAddress: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: BzzAddress: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Underlay", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthHandshake
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthHandshake
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Underlay = append(m.Underlay[:0], dAtA[iNdEx:postIndex]...)
if m.Underlay == nil {
m.Underlay = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthHandshake
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthHandshake
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
if m.Signature == nil {
m.Signature = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Overlay", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHandshake
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthHandshake
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthHandshake
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Overlay = append(m.Overlay[:0], dAtA[iNdEx:postIndex]...)
if m.Overlay == nil {
m.Overlay = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipHandshake(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthHandshake
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthHandshake
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipHandshake(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
......
......@@ -13,13 +13,18 @@ message Syn {
}
message Ack {
bytes Overlay = 1;
bytes Signature = 2;
uint64 NetworkID = 3;
bool Light = 4;
BzzAddress Address = 1;
uint64 NetworkID = 2;
bool Light = 3;
}
message SynAck {
Syn Syn = 1;
Ack Ack = 2;
}
message BzzAddress {
bytes Underlay = 1;
bytes Signature = 2;
bytes Overlay = 3;
}
\ No newline at end of file
......@@ -32,6 +32,7 @@ import (
protocol "github.com/libp2p/go-libp2p-core/protocol"
"github.com/libp2p/go-libp2p-peerstore/pstoremem"
libp2pquic "github.com/libp2p/go-libp2p-quic-transport"
basichost "github.com/libp2p/go-libp2p/p2p/host/basic"
"github.com/libp2p/go-tcp-transport"
ws "github.com/libp2p/go-ws-transport"
ma "github.com/multiformats/go-multiaddr"
......@@ -45,6 +46,7 @@ var (
type Service struct {
ctx context.Context
host host.Host
natManager basichost.NATManager
libp2pPeerstore peerstore.Peerstore
metrics metrics
networkID uint64
......@@ -52,7 +54,7 @@ type Service struct {
addressbook addressbook.Putter
peers *peerRegistry
topologyNotifier topology.Notifier
conectionBreaker breaker.Interface
connectionBreaker breaker.Interface
logger logging.Logger
tracer *tracing.Tracer
}
......@@ -112,11 +114,15 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay
security := libp2p.DefaultSecurity
libp2pPeerstore := pstoremem.NewPeerstore()
var natManager basichost.NATManager
opts := []libp2p.Option{
libp2p.ListenAddrStrings(listenAddrs...),
security,
// Attempt to open ports using uPNP for NATed hosts.
libp2p.NATPortMap(),
libp2p.NATManager(func(n network.Network) basichost.NATManager {
natManager = basichost.NewNATManager(n)
return natManager
}),
// Use dedicated peerstore instead the global DefaultPeerstore
libp2p.Peerstore(libp2pPeerstore),
}
......@@ -157,7 +163,9 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay
return nil, fmt.Errorf("autonat: %w", err)
}
handshakeService, err := handshake.New(overlay, signer, networkID, o.LightNode, o.Logger)
handshakeService, err := handshake.New(signer, &UpnpAddressResolver{
host: h,
}, overlay, networkID, o.LightNode, o.Logger)
if err != nil {
return nil, fmt.Errorf("handshake service: %w", err)
}
......@@ -166,17 +174,17 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay
s := &Service{
ctx: ctx,
host: h,
natManager: natManager,
handshakeService: handshakeService,
libp2pPeerstore: libp2pPeerstore,
metrics: newMetrics(),
networkID: networkID,
handshakeService: handshakeService,
peers: peerRegistry,
addressbook: o.Addressbook,
logger: o.Logger,
tracer: o.Tracer,
conectionBreaker: breaker.NewBreaker(breaker.Options{}), // todo: fill non-default options
connectionBreaker: breaker.NewBreaker(breaker.Options{}), // use default options
}
// Construct protocols.
id := protocol.ID(p2p.NewSwarmStreamName(handshake.ProtocolName, handshake.ProtocolVersion, handshake.StreamName))
matcher, err := s.protocolSemverMatcher(id)
......@@ -296,6 +304,10 @@ func (s *Service) Addresses() (addreses []ma.Multiaddr, err error) {
return addreses, nil
}
func (s *Service) NATManager() basichost.NATManager {
return s.natManager
}
func buildUnderlayAddress(addr ma.Multiaddr, peerID libp2ppeer.ID) (ma.Multiaddr, error) {
// Build host multiaddress
hostAddr, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", peerID.Pretty()))
......@@ -317,9 +329,9 @@ func (s *Service) Connect(ctx context.Context, addr ma.Multiaddr) (address *bzz.
return nil, p2p.ErrAlreadyConnected
}
if err := s.conectionBreaker.Execute(func() error { return s.host.Connect(ctx, *info) }); err != nil {
if err := s.connectionBreaker.Execute(func() error { return s.host.Connect(ctx, *info) }); err != nil {
if errors.Is(err, breaker.ErrClosed) {
return nil, p2p.NewConnectionBackoffError(err, s.conectionBreaker.ClosedUntil())
return nil, p2p.NewConnectionBackoffError(err, s.connectionBreaker.ClosedUntil())
}
return nil, err
}
......
......@@ -58,6 +58,7 @@ func newService(t *testing.T, networkID uint64, o libp2p.Options) (s *libp2p.Ser
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
cancel()
s.Close()
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libp2p
import (
"errors"
"strings"
"github.com/libp2p/go-libp2p-core/host"
libp2ppeer "github.com/libp2p/go-libp2p-core/peer"
ma "github.com/multiformats/go-multiaddr"
)
type UpnpAddressResolver struct {
host host.Host
}
// Resolve checks if there is a possible better advertisable underlay then the provided observed address.
// In some NAT situations, for example in the case when nodes are behind upnp, observer might send the observed address with a wrong port.
// In this case, observed address is compared to addresses provided by host, and if there is a same address but with different port, that one is used as advertisable address instead of provided observed one.
// TODO: this is a quickfix and it will be improved in the future
func (r *UpnpAddressResolver) Resolve(observedAddress ma.Multiaddr) (ma.Multiaddr, error) {
observableAddrInfo, err := libp2ppeer.AddrInfoFromP2pAddr(observedAddress)
if err != nil {
return nil, err
}
if len(observableAddrInfo.Addrs) < 1 {
return nil, errors.New("invalid observed address")
}
observedAddrSplit := strings.Split(observableAddrInfo.Addrs[0].String(), "/")
// if address is not in a form of '/ipversion/ip/protocol/port/...` don't compare to addresses and return it
if len(observedAddrSplit) < 5 {
return observedAddress, nil
}
observedAddressPort := observedAddrSplit[4]
// observervedAddressShort is an obaserved address without port
observervedAddressShort := strings.Join(append(observedAddrSplit[:4], observedAddrSplit[5:]...), "/")
for _, a := range r.host.Addrs() {
asplit := strings.Split(a.String(), "/")
if len(asplit) != len(observedAddrSplit) {
continue
}
aport := asplit[4]
if strings.Join(append(asplit[:4], asplit[5:]...), "/") != observervedAddressShort {
continue
}
if aport != observedAddressPort {
aaddress, err := buildUnderlayAddress(a, observableAddrInfo.ID)
if err != nil {
continue
}
return aaddress, nil
}
}
return observedAddress, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment