Repository: libp2p/go-libp2p
Pull request #1439 (2022-04-22 17:07:36)

move go-libp2p-yamux here
Part of #1187.


Patch:
diff --git a/defaults.go b/defaults.go
index 4c881114..72ee19cb 100644
--- a/defaults.go
+++ b/defaults.go
@@ -5,6 +5,7 @@ package libp2p
 import (
 	"crypto/rand"
 
+	yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux"
 	"github.com/libp2p/go-libp2p/p2p/net/connmgr"
 	quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
 	"github.com/libp2p/go-libp2p/p2p/transport/tcp"
@@ -16,7 +17,6 @@ import (
 	"github.com/libp2p/go-libp2p-peerstore/pstoremem"
 	rcmgr "github.com/libp2p/go-libp2p-resource-manager"
 	tls "github.com/libp2p/go-libp2p-tls"
-	yamux "github.com/libp2p/go-libp2p-yamux"
 	"github.com/multiformats/go-multiaddr"
 )
 
diff --git a/go.mod b/go.mod
index 13441b6d..6a804cb9 100644
--- a/go.mod
+++ b/go.mod
@@ -28,12 +28,12 @@ require (
 	github.com/libp2p/go-libp2p-testing v0.9.2
 	github.com/libp2p/go-libp2p-tls v0.4.1
 	github.com/libp2p/go-libp2p-transport-upgrader v0.7.1
-	github.com/libp2p/go-libp2p-yamux v0.9.1
 	github.com/libp2p/go-msgio v0.2.0
 	github.com/libp2p/go-netroute v0.2.0
 	github.com/libp2p/go-reuseport v0.1.0
 	github.com/libp2p/go-reuseport-transport v0.1.0
 	github.com/libp2p/go-stream-muxer-multistream v0.4.0
+	github.com/libp2p/go-yamux/v3 v3.1.1
 	github.com/libp2p/zeroconf/v2 v2.1.1
 	github.com/lucas-clemente/quic-go v0.27.0
 	github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd
@@ -85,11 +85,11 @@ require (
 	github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect
 	github.com/libp2p/go-libp2p-quic-transport v0.17.0 // indirect
 	github.com/libp2p/go-libp2p-swarm v0.10.2 // indirect
+	github.com/libp2p/go-libp2p-yamux v0.9.1 // indirect
 	github.com/libp2p/go-mplex v0.4.0 // indirect
 	github.com/libp2p/go-nat v0.1.0 // indirect
 	github.com/libp2p/go-openssl v0.0.7 // indirect
 	github.com/libp2p/go-tcp-transport v0.5.1 // indirect
-	github.com/libp2p/go-yamux/v3 v3.1.1 // indirect
 	github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
 	github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect
 	github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect
diff --git a/p2p/muxer/yamux/conn.go b/p2p/muxer/yamux/conn.go
new file mode 100644
index 00000000..5be7ed36
--- /dev/null
+++ b/p2p/muxer/yamux/conn.go
@@ -0,0 +1,44 @@
+package sm_yamux
+
+import (
+	"context"
+
+	"github.com/libp2p/go-libp2p-core/network"
+
+	"github.com/libp2p/go-yamux/v3"
+)
+
+// conn implements mux.MuxedConn over yamux.Session.
+type conn yamux.Session
+
+var _ network.MuxedConn = &conn{}
+
+// Close closes underlying yamux
+func (c *conn) Close() error {
+	return c.yamux().Close()
+}
+
+// IsClosed checks if yamux.Session is in closed state.
+func (c *conn) IsClosed() bool {
+	return c.yamux().IsClosed()
+}
+
+// OpenStream creates a new stream.
+func (c *conn) OpenStream(ctx context.Context) (network.MuxedStream, error) {
+	s, err := c.yamux().OpenStream(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	return (*stream)(s), nil
+}
+
+// AcceptStream accepts a stream opened by the other side.
+func (c *conn) AcceptStream() (network.MuxedStream, error) {
+	s, err := c.yamux().AcceptStream()
+	return (*stream)(s), err
+}
+
+func (c *conn) yamux() *yamux.Session {
+	return (*yamux.Session)(c)
+}
diff --git a/p2p/muxer/yamux/stream.go b/p2p/muxer/yamux/stream.go
new file mode 100644
index 00000000..1a93916a
--- /dev/null
+++ b/p2p/muxer/yamux/stream.go
@@ -0,0 +1,64 @@
+package sm_yamux
+
+import (
+	"time"
+
+	"github.com/libp2p/go-libp2p-core/network"
+
+	"github.com/libp2p/go-yamux/v3"
+)
+
+// stream implements mux.MuxedStream over yamux.Stream.
+type stream yamux.Stream
+
+var _ network.MuxedStream = &stream{}
+
+func (s *stream) Read(b []byte) (n int, err error) {
+	n, err = s.yamux().Read(b)
+	if err == yamux.ErrStreamReset {
+		err = network.ErrReset
+	}
+
+	return n, err
+}
+
+func (s *stream) Write(b []byte) (n int, err error) {
+	n, err = s.yamux().Write(b)
+	if err == yamux.ErrStreamReset {
+		err = network.ErrReset
+	}
+
+	return n, err
+}
+
+func (s *stream) Close() error {
+	return s.yamux().Close()
+}
+
+func (s *stream) Reset() error {
+	return s.yamux().Reset()
+}
+
+func (s *stream) CloseRead() error {
+	return s.yamux().CloseRead()
+}
+
+func (s *stream) CloseWrite() error {
+	return s.yamux().CloseWrite()
+}
+
+func (s *stream) SetDeadline(t time.Time) error {
+	return s.yamux().SetDeadline(t)
+}
+
+func (s *stream) SetReadDeadline(t time.Time) error {
+	return s.yamux().SetReadDeadline(t)
+}
+
+func (s *stream) SetWriteDeadline(t time.Time) error {
+	return s.yamux().SetWriteDeadline(t)
+}
+
+func (s *stream) yamux() *yamux.Stream {
+	return (*yamux.Stream)(s)
+}
diff --git a/p2p/muxer/yamux/transport.go b/p2p/muxer/yamux/transport.go
new file mode 100644
index 00000000..ea2cd0e5
--- /dev/null
+++ b/p2p/muxer/yamux/transport.go
@@ -0,0 +1,53 @@
+package sm_yamux
+
+import (
+	"io/ioutil"
+	"math"
+	"net"
+
+	"github.com/libp2p/go-libp2p-core/network"
+
+	"github.com/libp2p/go-yamux/v3"
+)
+
+var DefaultTransport *Transport
+
+func init() {
+	config := yamux.DefaultConfig()
+	// We've bumped this to 16MiB as this critically limits throughput.
+	//
+	// 1MiB means a best case of 10MiB/s (83.89Mbps) on a connection with
+	// 100ms latency. The default gave us 2.4MiB *best case* which was
+	// totally unacceptable.
+	config.MaxStreamWindowSize = uint32(16 * 1024 * 1024)
+	// don't spam
+	config.LogOutput = ioutil.Discard
+	// We always run over a security transport that buffers internally
+	// (i.e., uses a block cipher).
+	config.ReadBufSize = 0
+	// Effectively disable the incoming streams limit.
+	// This is now dynamically limited by the resource manager.
+	config.MaxIncomingStreams = math.MaxUint32
+	DefaultTransport = (*Transport)(config)
+}
+
+// Transport implements mux.Multiplexer that constructs
+// yamux-backed muxed connections.
+type Transport yamux.Config
+
+var _ network.Multiplexer = &Transport{}
+
+func (t *Transport) NewConn(nc net.Conn, isServer bool, scope network.PeerScope) (network.MuxedConn, error) {
+	var s *yamux.Session
+	var err error
+	if isServer {
+		s, err = yamux.Server(nc, t.Config(), scope)
+	} else {
+		s, err = yamux.Client(nc, t.Config(), scope)
+	}
+	return (*conn)(s), err
+}
+
+func (t *Transport) Config() *yamux.Config {
+	return (*yamux.Config)(t)
+}


Test patch:
diff --git a/config/muxer_test.go b/config/muxer_test.go
index 76aada10..96de6e1f 100644
--- a/config/muxer_test.go
+++ b/config/muxer_test.go
@@ -4,13 +4,12 @@ import (
 	"testing"
 
 	bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
+	yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux"
 	swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
 
 	"github.com/libp2p/go-libp2p-core/host"
 	"github.com/libp2p/go-libp2p-core/network"
 	"github.com/libp2p/go-libp2p-core/peer"
-
-	yamux "github.com/libp2p/go-libp2p-yamux"
 )
 
 func TestMuxerSimple(t *testing.T) {
diff --git a/p2p/muxer/yamux/transport_test.go b/p2p/muxer/yamux/transport_test.go
new file mode 100644
index 00000000..48136c48
--- /dev/null
+++ b/p2p/muxer/yamux/transport_test.go
@@ -0,0 +1,15 @@
+package sm_yamux
+
+import (
+	"testing"
+
+	tmux "github.com/libp2p/go-libp2p-testing/suites/mux"
+)
+
+func TestDefaultTransport(t *testing.T) {
+	// Yamux doesn't have any backpressure when it comes to opening streams.
+	// If the peer opens too many streams, those are just reset.
+	delete(tmux.Subtests, "github.com/libp2p/go-libp2p-testing/suites/mux.SubtestStress1Conn1000Stream10Msg")
+
+	tmux.SubtestAll(t, DefaultTransport)
+}
diff --git a/p2p/net/swarm/dial_worker_test.go b/p2p/net/swarm/dial_worker_test.go
index 2fec019a..b90092c5 100644
--- a/p2p/net/swarm/dial_worker_test.go
+++ b/p2p/net/swarm/dial_worker_test.go
@@ -8,6 +8,7 @@ import (
 	"testing"
 	"time"
 
+	yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux"
 	quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
 	"github.com/libp2p/go-libp2p/p2p/transport/tcp"
 
@@ -19,7 +20,6 @@ import (
 	"github.com/libp2p/go-libp2p-peerstore/pstoremem"
 	tnet "github.com/libp2p/go-libp2p-testing/net"
 	tptu "github.com/libp2p/go-libp2p-transport-upgrader"
-	yamux "github.com/libp2p/go-libp2p-yamux"
 	msmux "github.com/libp2p/go-stream-muxer-multistream"
 	ma "github.com/multiformats/go-multiaddr"
 
diff --git a/p2p/net/swarm/testing/testing.go b/p2p/net/swarm/testing/testing.go
index c529e814..70359b02 100644
--- a/p2p/net/swarm/testing/testing.go
+++ b/p2p/net/swarm/testing/testing.go
@@ -4,6 +4,7 @@ import (
 	"testing"
 	"time"
 
+	yamux "github.com/libp2p/go-libp2p/p2p/muxer/yamux"
 	"github.com/libp2p/go-libp2p/p2p/net/swarm"
 	quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
 	"github.com/libp2p/go-libp2p/p2p/transport/tcp"
@@ -22,7 +23,6 @@ import (
 	"github.com/libp2p/go-libp2p-peerstore/pstoremem"
 	tnet "github.com/libp2p/go-libp2p-testing/net"
 	tptu "github.com/libp2p/go-libp2p-transport-upgrader"
-	yamux "github.com/libp2p/go-libp2p-yamux"
 	msmux "github.com/libp2p/go-stream-muxer-multistream"
 	ma "github.com/multiformats/go-multiaddr"
 	"github.com/stretchr/testify/require"