diff --git a/p2p/net/conn/dial_test.go b/p2p/net/conn/dial_test.go index c91fd5bf3a4f09be0f10d34ded034bfd41ff7a00..2179cbd35b4e7daee294c376e3113f3815705056 100644 --- a/p2p/net/conn/dial_test.go +++ b/p2p/net/conn/dial_test.go @@ -1,6 +1,7 @@ package conn import ( + "bytes" "fmt" "io" "net" @@ -349,3 +350,50 @@ func TestMultistreamHeader(t *testing.T) { t.Fatal(err) } } + +func TestFailedAccept(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + p1 := tu.RandPeerNetParamsOrFatal(t) + + l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey) + if err != nil { + t.Fatal(err) + } + + p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. + + done := make(chan struct{}) + go func() { + defer close(done) + con, err := net.Dial("tcp", l1.Addr().String()) + if err != nil { + t.Error("first dial failed: ", err) + } + + // write some garbage + con.Write(bytes.Repeat([]byte{255}, 1000)) + + con.Close() + + con, err = net.Dial("tcp", l1.Addr().String()) + if err != nil { + t.Error("second dial failed: ", err) + } + defer con.Close() + + err = msmux.SelectProtoOrFail(SecioTag, con) + if err != nil { + t.Error("msmux select failed: ", err) + } + }() + + c, err := l1.Accept() + if err != nil { + t.Fatal("connections after a failed accept should still work: ", err) + } + + c.Close() + <-done +} diff --git a/p2p/net/conn/listen.go b/p2p/net/conn/listen.go index 33b09756f58ecab5c2d303797eef1e006600f0bc..3d81cbafa78011eb453b8fe02695e03e6964916b 100644 --- a/p2p/net/conn/listen.go +++ b/p2p/net/conn/listen.go @@ -106,7 +106,8 @@ func (l *listener) Accept() (net.Conn, error) { _, _, err = l.mux.Negotiate(maconn) if err != nil { - return nil, err + log.Info("negotiation of crypto protocol failed: ", err) + continue } c, err := newSingleConn(ctx, l.local, "", maconn)