From f4a9646ae849731c7d1ef18600204c27aff15699 Mon Sep 17 00:00:00 2001 From: Angelo Capossele <angelocapossele@gmail.com> Date: Mon, 20 Jan 2020 14:57:55 +0000 Subject: [PATCH] :sparkles: adds open port check (#143) * :sparkles: adds open port check * Use gossip.server to check port * Use same messages in gossip and autopeering * Give correct error message when unreachable Co-authored-by: Wolfgang Welz <welzwo@gmail.com> --- packages/autopeering/discover/manager.go | 4 +-- packages/autopeering/discover/manager_test.go | 12 +++---- packages/autopeering/discover/protocol.go | 2 +- .../autopeering/discover/protocol_test.go | 14 ++++---- plugins/autopeering/autopeering.go | 26 +++++++++++--- plugins/gossip/gossip.go | 36 +++++++++++++++++-- 6 files changed, 71 insertions(+), 23 deletions(-) diff --git a/packages/autopeering/discover/manager.go b/packages/autopeering/discover/manager.go index 055dd9bb..5fbded48 100644 --- a/packages/autopeering/discover/manager.go +++ b/packages/autopeering/discover/manager.go @@ -25,7 +25,7 @@ const ( type network interface { local() *peer.Local - ping(*peer.Peer) error + Ping(*peer.Peer) error discoveryRequest(*peer.Peer) ([]*peer.Peer, error) } @@ -139,7 +139,7 @@ func (m *manager) doReverify(done chan<- struct{}) { var err error for i := 0; i < reverifyTries; i++ { - err = m.net.ping(unwrapPeer(p)) + err = m.net.Ping(unwrapPeer(p)) if err == nil { break } else { diff --git a/packages/autopeering/discover/manager_test.go b/packages/autopeering/discover/manager_test.go index fba880e4..09037123 100644 --- a/packages/autopeering/discover/manager_test.go +++ b/packages/autopeering/discover/manager_test.go @@ -22,7 +22,7 @@ func (m *NetworkMock) local() *peer.Local { return m.loc } -func (m *NetworkMock) ping(p *peer.Peer) error { +func (m *NetworkMock) Ping(p *peer.Peer) error { args := m.Called(p) return args.Error(0) } @@ -70,7 +70,7 @@ func TestMgrVerifyDiscoveredPeer(t *testing.T) { p := newDummyPeer("p") // expect ping of peer p - m.On("ping", p).Return(nil).Once() + m.On("Ping", p).Return(nil).Once() // ignore discoveryRequest calls m.On("discoveryRequest", mock.Anything).Return([]*peer.Peer{}, nil).Maybe() @@ -90,7 +90,7 @@ func TestMgrReverifyPeer(t *testing.T) { p := newDummyPeer("p") // expect ping of peer p - m.On("ping", p).Return(nil).Once() + m.On("Ping", p).Return(nil).Once() // ignore discoveryRequest calls m.On("discoveryRequest", mock.Anything).Return([]*peer.Peer{}, nil).Maybe() @@ -113,7 +113,7 @@ func TestMgrRequestDiscoveredPeer(t *testing.T) { // expect discoveryRequest on the discovered peer m.On("discoveryRequest", p1).Return([]*peer.Peer{p2}, nil).Once() // ignore any ping - m.On("ping", mock.Anything).Return(nil).Maybe() + m.On("Ping", mock.Anything).Return(nil).Maybe() mgr.addVerifiedPeer(p1) mgr.addDiscoveredPeer(p2) @@ -129,7 +129,7 @@ func TestMgrAddManyVerifiedPeers(t *testing.T) { p := newDummyPeer("p") // expect ping of peer p - m.On("ping", p).Return(nil).Once() + m.On("Ping", p).Return(nil).Once() // ignore discoveryRequest calls m.On("discoveryRequest", mock.Anything).Return([]*peer.Peer{}, nil).Maybe() @@ -157,7 +157,7 @@ func TestMgrDeleteUnreachablePeer(t *testing.T) { p := newDummyPeer("p") // expect ping of peer p, but return error - m.On("ping", p).Return(server.ErrTimeout).Times(reverifyTries) + m.On("Ping", p).Return(server.ErrTimeout).Times(reverifyTries) // ignore discoveryRequest calls m.On("discoveryRequest", mock.Anything).Return([]*peer.Peer{}, nil).Maybe() diff --git a/packages/autopeering/discover/protocol.go b/packages/autopeering/discover/protocol.go index 756f5fe1..3cbe4936 100644 --- a/packages/autopeering/discover/protocol.go +++ b/packages/autopeering/discover/protocol.go @@ -149,7 +149,7 @@ func (p *Protocol) HandleMessage(s *server.Server, fromAddr string, fromID peer. // ------ message senders ------ // ping sends a ping to the specified peer and blocks until a reply is received or timeout. -func (p *Protocol) ping(to *peer.Peer) error { +func (p *Protocol) Ping(to *peer.Peer) error { return <-p.sendPing(to.Address(), to.ID()) } diff --git a/packages/autopeering/discover/protocol_test.go b/packages/autopeering/discover/protocol_test.go index 223c2c3e..e2628651 100644 --- a/packages/autopeering/discover/protocol_test.go +++ b/packages/autopeering/discover/protocol_test.go @@ -89,11 +89,11 @@ func TestProtPingPong(t *testing.T) { peerB := getPeer(srvB) // send a ping from node A to B - t.Run("A->B", func(t *testing.T) { assert.NoError(t, protA.ping(peerB)) }) + t.Run("A->B", func(t *testing.T) { assert.NoError(t, protA.Ping(peerB)) }) time.Sleep(graceTime) // send a ping from node B to A - t.Run("B->A", func(t *testing.T) { assert.NoError(t, protB.ping(peerA)) }) + t.Run("B->A", func(t *testing.T) { assert.NoError(t, protB.Ping(peerA)) }) time.Sleep(graceTime) } @@ -109,7 +109,7 @@ func TestProtPingTimeout(t *testing.T) { peerB := getPeer(srvB) // send a ping from node A to B - err := protA.ping(peerB) + err := protA.Ping(peerB) assert.EqualError(t, err, server.ErrTimeout.Error()) } @@ -125,7 +125,7 @@ func TestProtVerifiedPeers(t *testing.T) { peerB := getPeer(srvB) // send a ping from node A to B - assert.NoError(t, protA.ping(peerB)) + assert.NoError(t, protA.Ping(peerB)) time.Sleep(graceTime) // protA should have peerB as the single verified peer @@ -148,7 +148,7 @@ func TestProtVerifiedPeer(t *testing.T) { peerB := getPeer(srvB) // send a ping from node A to B - assert.NoError(t, protA.ping(peerB)) + assert.NoError(t, protA.Ping(peerB)) time.Sleep(graceTime) // we should have peerB as a verified peer @@ -248,14 +248,14 @@ func BenchmarkPingPong(b *testing.B) { peerB := getPeer(srvB) // send initial ping to ensure that every peer is verified - err := protA.ping(peerB) + err := protA.Ping(peerB) require.NoError(b, err) time.Sleep(graceTime) b.ResetTimer() for n := 0; n < b.N; n++ { // send a ping from node A to B - _ = protA.ping(peerB) + _ = protA.Ping(peerB) } b.StopTimer() diff --git a/plugins/autopeering/autopeering.go b/plugins/autopeering/autopeering.go index f2cac97d..33fb047a 100644 --- a/plugins/autopeering/autopeering.go +++ b/plugins/autopeering/autopeering.go @@ -15,6 +15,7 @@ import ( "github.com/iotaledger/goshimmer/packages/autopeering/transport" "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/goshimmer/plugins/autopeering/local" + "github.com/iotaledger/goshimmer/plugins/cli" "github.com/iotaledger/goshimmer/plugins/gossip" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" @@ -53,7 +54,7 @@ func configureAP() { } func start(shutdownSignal <-chan struct{}) { - defer log.Info("Stopping Auto Peering server ... done") + defer log.Info("Stopping " + name + " ... done") addr := local.GetInstance().Services().Get(service.PeeringKey) udpAddr, err := net.ResolveUDPAddr(addr.Network(), addr.String()) @@ -92,17 +93,22 @@ func start(shutdownSignal <-chan struct{}) { Discovery.Start(srv) defer Discovery.Close() + //check that discovery is working and the port is open + log.Info("Testing service ...") + checkConnection(srv, &local.GetInstance().Peer) + log.Info("Testing service ... done") + if Selection != nil { // start the peering on that connection Selection.Start(srv) defer Selection.Close() } - log.Infof("Auto Peering started: address=%s", srv.LocalAddr()) - log.Debugf("Auto Peering server started: PubKey=%s", base64.StdEncoding.EncodeToString(local.GetInstance().PublicKey())) + log.Infof(name+" started: address=%s/udp", srv.LocalAddr()) + log.Debugf(name+" server started: PubKey=%s", base64.StdEncoding.EncodeToString(local.GetInstance().PublicKey())) <-shutdownSignal - log.Info("Stopping Auto Peering server ...") + log.Info("Stopping " + name + " ...") } func parseEntryNodes() (result []*peer.Peer, err error) { @@ -128,3 +134,15 @@ func parseEntryNodes() (result []*peer.Peer, err error) { return result, nil } + +func checkConnection(srv *server.Server, self *peer.Peer) { + if err := Discovery.Ping(self); err != nil { + if err == server.ErrTimeout { + log.Errorf("Error testing service: %s", err) + addr := self.Services().Get(service.PeeringKey) + log.Panicf("Please check that %s is publicly reachable at %s/%s", + cli.AppName, addr.String(), addr.Network()) + } + log.Panicf("Error: %s", err) + } +} diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go index 2e53b336..b6ea302a 100644 --- a/plugins/gossip/gossip.go +++ b/plugins/gossip/gossip.go @@ -4,12 +4,15 @@ import ( "fmt" "net" "strconv" + "sync" + "github.com/iotaledger/goshimmer/packages/autopeering/peer" "github.com/iotaledger/goshimmer/packages/autopeering/peer/service" gp "github.com/iotaledger/goshimmer/packages/gossip" "github.com/iotaledger/goshimmer/packages/gossip/server" "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/goshimmer/plugins/autopeering/local" + "github.com/iotaledger/goshimmer/plugins/cli" "github.com/iotaledger/goshimmer/plugins/tangle" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/typeutils" @@ -39,7 +42,7 @@ func configureGossip() { } func start(shutdownSignal <-chan struct{}) { - defer log.Info("Stopping Gossip ... done") + defer log.Info("Stopping " + name + " ... done") srv, err := server.ListenTCP(local.GetInstance(), log) if err != nil { @@ -47,13 +50,40 @@ func start(shutdownSignal <-chan struct{}) { } defer srv.Close() + //check that the server is working and the port is open + log.Info("Testing service ...") + checkConnection(srv, &local.GetInstance().Peer) + log.Info("Testing service ... done") + mgr.Start(srv) defer mgr.Close() - log.Infof("Gossip started: address=%v", mgr.LocalAddr()) + log.Infof(name+" started: address=%s/%s", mgr.LocalAddr().String(), mgr.LocalAddr().Network()) <-shutdownSignal - log.Info("Stopping Gossip ...") + log.Info("Stopping " + name + " ...") +} + +func checkConnection(srv *server.TCP, self *peer.Peer) { + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + conn, err := srv.AcceptPeer(self) + if err != nil { + return + } + _ = conn.Close() + }() + conn, err := srv.DialPeer(self) + if err != nil { + log.Errorf("Error testing: %s", err) + addr := self.Services().Get(service.GossipKey) + log.Panicf("Please check that %s is publicly reachable at %s/%s", + cli.AppName, addr.String(), addr.Network()) + } + _ = conn.Close() + wg.Wait() } func loadTransaction(hash []byte) ([]byte, error) { -- GitLab