Repository: libp2p/go-libp2p
Pull request #3242 (2025-03-19 15:01:09)

chore(certificate): update test vectors
this PR updates test vectors for tls certificate, following pending PR in specs https://github.com/libp2p/specs/pull/665.
this PR also serves as demo that new test vector values are passing tests. 

this PR is in draft until specs are reviewed. i'll make sure to close it, or mark for review after it gets approved.



vladopajic: dear maintainers, it would be nice to approve workflows to show that tests are passing. thanks!
sukunrt: Apologies for the delay. I'll get to this tomorrow or day after. 
MarcoPolo: Once you get this out of draft we can merge
vladopajic: @MarcoPolo it's out of draft now.

Patch:
diff --git a/go.mod b/go.mod
index 94f2ce44..690e96c4 100644
--- a/go.mod
+++ b/go.mod
@@ -46,11 +46,11 @@ require (
 	github.com/multiformats/go-varint v0.0.7
 	github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
 	github.com/pion/datachannel v1.5.10
-	github.com/pion/ice/v4 v4.0.6
+	github.com/pion/ice/v4 v4.0.8
 	github.com/pion/logging v0.2.3
-	github.com/pion/sctp v1.8.36
+	github.com/pion/sctp v1.8.37
 	github.com/pion/stun v0.6.1
-	github.com/pion/webrtc/v4 v4.0.10
+	github.com/pion/webrtc/v4 v4.0.14
 	github.com/prometheus/client_golang v1.21.0
 	github.com/prometheus/client_model v0.6.1
 	github.com/quic-go/quic-go v0.50.0
@@ -89,8 +89,8 @@ require (
 	github.com/pion/mdns/v2 v2.0.7 // indirect
 	github.com/pion/randutil v0.1.0 // indirect
 	github.com/pion/rtcp v1.2.15 // indirect
-	github.com/pion/rtp v1.8.11 // indirect
-	github.com/pion/sdp/v3 v3.0.10 // indirect
+	github.com/pion/rtp v1.8.13 // indirect
+	github.com/pion/sdp/v3 v3.0.11 // indirect
 	github.com/pion/srtp/v3 v3.0.4 // indirect
 	github.com/pion/stun/v3 v3.0.0 // indirect
 	github.com/pion/transport/v2 v2.2.10 // indirect
diff --git a/go.sum b/go.sum
index 6a213822..e895b5bf 100644
--- a/go.sum
+++ b/go.sum
@@ -194,8 +194,8 @@ github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
 github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
 github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
 github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
-github.com/pion/ice/v4 v4.0.6 h1:jmM9HwI9lfetQV/39uD0nY4y++XZNPhvzIPCb8EwxUM=
-github.com/pion/ice/v4 v4.0.6/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
+github.com/pion/ice/v4 v4.0.8 h1:ajNx0idNG+S+v9Phu4LSn2cs8JEfTsA1/tEjkkAVpFY=
+github.com/pion/ice/v4 v4.0.8/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
 github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
 github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
 github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
@@ -207,12 +207,12 @@ github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
 github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
 github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
 github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
-github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
-github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
-github.com/pion/sctp v1.8.36 h1:owNudmnz1xmhfYje5L/FCav3V9wpPRePHle3Zi+P+M0=
-github.com/pion/sctp v1.8.36/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
-github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
-github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
+github.com/pion/rtp v1.8.13 h1:8uSUPpjSL4OlwZI8Ygqu7+h2p9NPFB+yAZ461Xn5sNg=
+github.com/pion/rtp v1.8.13/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
+github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
+github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
+github.com/pion/sdp/v3 v3.0.11 h1:VhgVSopdsBKwhCFoyyPmT1fKMeV9nLMrEKxNOdy3IVI=
+github.com/pion/sdp/v3 v3.0.11/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
 github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
 github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
 github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
@@ -227,8 +227,8 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1
 github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
 github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
 github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
-github.com/pion/webrtc/v4 v4.0.10 h1:Hq/JLjhqLxi+NmCtE8lnRPDr8H4LcNvwg8OxVcdv56Q=
-github.com/pion/webrtc/v4 v4.0.10/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck=
+github.com/pion/webrtc/v4 v4.0.14 h1:nyds/sFRR+HvmWoBa6wrL46sSfpArE0qR883MBW96lg=
+github.com/pion/webrtc/v4 v4.0.14/go.mod h1:R3+qTnQTS03UzwDarYecgioNf7DYgTsldxnCXB821Kk=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
diff --git a/p2p/host/resource-manager/conn_limiter.go b/p2p/host/resource-manager/conn_limiter.go
index 717249e8..73c288f0 100644
--- a/p2p/host/resource-manager/conn_limiter.go
+++ b/p2p/host/resource-manager/conn_limiter.go
@@ -114,8 +114,8 @@ type connLimiter struct {
 	// Subnet limits.
 	connLimitPerSubnetV4 []ConnLimitPerSubnet
 	connLimitPerSubnetV6 []ConnLimitPerSubnet
-	ip4connsPerLimit     []map[string]int
-	ip6connsPerLimit     []map[string]int
+	ip4connsPerLimit     []map[netip.Prefix]int
+	ip6connsPerLimit     []map[netip.Prefix]int
 }
 
 func newConnLimiter() *connLimiter {
@@ -180,7 +180,7 @@ func (cl *connLimiter) addConn(ip netip.Addr) bool {
 	}
 
 	if len(connsPerLimit) == 0 && len(limits) > 0 {
-		connsPerLimit = make([]map[string]int, len(limits))
+		connsPerLimit = make([]map[netip.Prefix]int, len(limits))
 		if isIP6 {
 			cl.ip6connsPerLimit = connsPerLimit
 		} else {
@@ -193,13 +193,12 @@ func (cl *connLimiter) addConn(ip netip.Addr) bool {
 		if err != nil {
 			return false
 		}
-		masked := prefix.String()
-		counts, ok := connsPerLimit[i][masked]
+		counts, ok := connsPerLimit[i][prefix]
 		if !ok {
 			if connsPerLimit[i] == nil {
-				connsPerLimit[i] = make(map[string]int)
+				connsPerLimit[i] = make(map[netip.Prefix]int)
 			}
-			connsPerLimit[i][masked] = 0
+			connsPerLimit[i][prefix] = 0
 		}
 		if counts+1 > limit.ConnCount {
 			return false
@@ -209,8 +208,7 @@ func (cl *connLimiter) addConn(ip netip.Addr) bool {
 	// All limit checks passed, now we update the counts
 	for i, limit := range limits {
 		prefix, _ := ip.Prefix(limit.PrefixLength)
-		masked := prefix.String()
-		connsPerLimit[i][masked]++
+		connsPerLimit[i][prefix]++
 	}
 
 	return true
@@ -258,7 +256,7 @@ func (cl *connLimiter) rmConn(ip netip.Addr) {
 	if len(connsPerLimit) == 0 && len(limits) > 0 {
 		// Initialize just in case. We should have already initialized in
 		// addConn, but if the callers calls rmConn first we don't want to panic
-		connsPerLimit = make([]map[string]int, len(limits))
+		connsPerLimit = make([]map[netip.Prefix]int, len(limits))
 		if isIP6 {
 			cl.ip6connsPerLimit = connsPerLimit
 		} else {
@@ -273,16 +271,15 @@ func (cl *connLimiter) rmConn(ip netip.Addr) {
 			log.Errorf("unexpected error getting prefix: %v", err)
 			continue
 		}
-		masked := prefix.String()
-		counts, ok := connsPerLimit[i][masked]
+		counts, ok := connsPerLimit[i][prefix]
 		if !ok || counts == 0 {
 			// Unexpected, but don't panic
-			log.Errorf("unexpected conn count for %s ok=%v count=%v", masked, ok, counts)
+			log.Errorf("unexpected conn count for %s ok=%v count=%v", prefix, ok, counts)
 			continue
 		}
-		connsPerLimit[i][masked]--
-		if connsPerLimit[i][masked] <= 0 {
-			delete(connsPerLimit[i], masked)
+		connsPerLimit[i][prefix]--
+		if connsPerLimit[i][prefix] <= 0 {
+			delete(connsPerLimit[i], prefix)
 		}
 	}
 }
diff --git a/p2p/transport/webrtc/connection.go b/p2p/transport/webrtc/connection.go
index 77b293fa..d75c309c 100644
--- a/p2p/transport/webrtc/connection.go
+++ b/p2p/transport/webrtc/connection.go
@@ -188,7 +188,7 @@ func (c *connection) OpenStream(ctx context.Context) (network.MuxedStream, error
 		dc.Close()
 		return nil, fmt.Errorf("detach channel failed for stream(%d): %w", streamID, err)
 	}
-	str := newStream(dc, rwc, func() { c.removeStream(streamID) })
+	str := newStream(dc, rwc, maxSendMessageSize, func() { c.removeStream(streamID) })
 	if err := c.addStream(str); err != nil {
 		str.Reset()
 		return nil, fmt.Errorf("failed to add stream(%d) to connection: %w", streamID, err)
@@ -201,7 +201,7 @@ func (c *connection) AcceptStream() (network.MuxedStream, error) {
 	case <-c.ctx.Done():
 		return nil, c.closeErr
 	case dc := <-c.acceptQueue:
-		str := newStream(dc.channel, dc.stream, func() { c.removeStream(*dc.channel.ID()) })
+		str := newStream(dc.channel, dc.stream, maxSendMessageSize, func() { c.removeStream(*dc.channel.ID()) })
 		if err := c.addStream(str); err != nil {
 			str.Reset()
 			return nil, err
diff --git a/p2p/transport/webrtc/listener.go b/p2p/transport/webrtc/listener.go
index 3534fd2c..0ec05ec0 100644
--- a/p2p/transport/webrtc/listener.go
+++ b/p2p/transport/webrtc/listener.go
@@ -253,7 +253,7 @@ func (l *listener) setupConnection(
 	if err != nil {
 		return nil, err
 	}
-	handshakeChannel := newStream(w.HandshakeDataChannel, rwc, func() {})
+	handshakeChannel := newStream(w.HandshakeDataChannel, rwc, maxSendMessageSize, nil)
 	// we do not yet know A's peer ID so accept any inbound
 	remotePubKey, err := l.transport.noiseHandshake(ctx, w.PeerConnection, handshakeChannel, "", crypto.SHA256, true)
 	if err != nil {
diff --git a/p2p/transport/webrtc/stream.go b/p2p/transport/webrtc/stream.go
index 39873c9d..c92457cc 100644
--- a/p2p/transport/webrtc/stream.go
+++ b/p2p/transport/webrtc/stream.go
@@ -15,22 +15,9 @@ import (
 )
 
 const (
-	// maxMessageSize is the maximum message size of the Protobuf message we send / receive.
-	maxMessageSize = 16384
-	// maxSendBuffer is the maximum data we enqueue on the underlying data channel for writes.
-	// The underlying SCTP layer has an unbounded buffer for writes. We limit the amount enqueued
-	// per stream is limited to avoid a single stream monopolizing the entire connection.
-	maxSendBuffer = 2 * maxMessageSize
-	// sendBufferLowThreshold is the threshold below which we write more data on the underlying
-	// data channel. We want a notification as soon as we can write 1 full sized message.
-	sendBufferLowThreshold = maxSendBuffer - maxMessageSize
-	// maxTotalControlMessagesSize is the maximum total size of all control messages we will
-	// write on this stream.
-	// 4 control messages of size 10 bytes + 10 bytes buffer. This number doesn't need to be
-	// exact. In the worst case, we enqueue these many bytes more in the webrtc peer connection
-	// send queue.
-	maxTotalControlMessagesSize = 50
-
+	// maxSendMessageSize is the maximum message size of the Protobuf message we send / receive.
+	// NOTE: Change `varintOverhead` if you change this.
+	maxSendMessageSize = 16384
 	// Proto overhead assumption is 5 bytes
 	protoOverhead = 5
 	// Varint overhead is assumed to be 2 bytes. This is safe since
@@ -40,9 +27,20 @@ const (
 	// is less than or equal to 2 ^ 14, the varint will not be more than
 	// 2 bytes in length.
 	varintOverhead = 2
+
+	// maxTotalControlMessagesSize is the maximum total size of all control messages we will
+	// write on this stream.
+	// 4 control messages of size 10 bytes + 10 bytes buffer. This number doesn't need to be
+	// exact. In the worst case, we enqueue these many bytes more in the webrtc peer connection
+	// send queue.
+	maxTotalControlMessagesSize = 50
+
 	// maxFINACKWait is the maximum amount of time a stream will wait to read
 	// FIN_ACK before closing the data channel
 	maxFINACKWait = 10 * time.Second
+
+	// maxReceiveMessageSize is the maximum message size of the Protobuf message we receive.
+	maxReceiveMessageSize = 256<<10 + 1<<10 // 1kB buffer
 )
 
 type receiveState uint8
@@ -79,11 +77,12 @@ type stream struct {
 	nextMessage  *pb.Message
 	receiveState receiveState
 
-	writer            pbio.Writer // concurrent writes prevented by mx
-	writeStateChanged chan struct{}
-	sendState         sendState
-	writeDeadline     time.Time
-	writeError        error
+	writer             pbio.Writer // concurrent writes prevented by mx
+	writeStateChanged  chan struct{}
+	sendState          sendState
+	writeDeadline      time.Time
+	writeError         error
+	maxSendMessageSize int
 
 	controlMessageReaderOnce sync.Once
 	// controlMessageReaderEndTime is the end time for reading FIN_ACK from the control
@@ -105,20 +104,21 @@ var _ network.MuxedStream = &stream{}
 func newStream(
 	channel *webrtc.DataChannel,
 	rwc datachannel.ReadWriteCloser,
+	maxSendMessageSize int,
 	onDone func(),
 ) *stream {
 	s := &stream{
-		reader:            pbio.NewDelimitedReader(rwc, maxMessageSize),
-		writer:            pbio.NewDelimitedWriter(rwc),
-		writeStateChanged: make(chan struct{}, 1),
-		id:                *channel.ID(),
-		dataChannel:       rwc.(*datachannel.DataChannel),
-		onDone:            onDone,
+		reader:             pbio.NewDelimitedReader(rwc, maxReceiveMessageSize),
+		writer:             pbio.NewDelimitedWriter(rwc),
+		writeStateChanged:  make(chan struct{}, 1),
+		id:                 *channel.ID(),
+		dataChannel:        rwc.(*datachannel.DataChannel),
+		onDone:             onDone,
+		maxSendMessageSize: maxSendMessageSize,
 	}
-	s.dataChannel.SetBufferedAmountLowThreshold(sendBufferLowThreshold)
+	s.dataChannel.SetBufferedAmountLowThreshold(uint64(s.sendBufferLowThreshold()))
 	s.dataChannel.OnBufferedAmountLow(func() {
 		s.notifyWriteStateChanged()
-
 	})
 	return s
 }
diff --git a/p2p/transport/webrtc/stream_write.go b/p2p/transport/webrtc/stream_write.go
index 01fddac3..86299551 100644
--- a/p2p/transport/webrtc/stream_write.go
+++ b/p2p/transport/webrtc/stream_write.go
@@ -84,7 +84,7 @@ func (s *stream) Write(b []byte) (int, error) {
 			s.mx.Lock()
 			continue
 		}
-		end := maxMessageSize
+		end := s.maxSendMessageSize
 		if end > availableSpace {
 			end = availableSpace
 		}
@@ -110,11 +110,24 @@ func (s *stream) SetWriteDeadline(t time.Time) error {
 	return nil
 }
 
+// sendBufferSize() is the maximum data we enqueue on the underlying data channel for writes.
+// The underlying SCTP layer has an unbounded buffer for writes. We limit the amount enqueued
+// per stream is limited to avoid a single stream monopolizing the entire connection.
+func (s *stream) sendBufferSize() int {
+	return 2 * s.maxSendMessageSize
+}
+
+// sendBufferLowThreshold() is the threshold below which we write more data on the underlying
+// data channel. We want a notification as soon as we can write 1 full sized message.
+func (s *stream) sendBufferLowThreshold() int {
+	return s.sendBufferSize() - s.maxSendMessageSize
+}
+
 func (s *stream) availableSendSpace() int {
 	buffered := int(s.dataChannel.BufferedAmount())
-	availableSpace := maxSendBuffer - buffered
+	availableSpace := s.sendBufferSize() - buffered
 	if availableSpace+maxTotalControlMessagesSize < 0 { // this should never happen, but better check
-		log.Errorw("data channel buffered more data than the maximum amount", "max", maxSendBuffer, "buffered", buffered)
+		log.Errorw("data channel buffered more data than the maximum amount", "max", s.sendBufferSize(), "buffered", buffered)
 	}
 	return availableSpace
 }
diff --git a/p2p/transport/webrtc/transport.go b/p2p/transport/webrtc/transport.go
index 6f16fb72..f3322c81 100644
--- a/p2p/transport/webrtc/transport.go
+++ b/p2p/transport/webrtc/transport.go
@@ -68,7 +68,13 @@ const (
 	DefaultFailedTimeout       = 30 * time.Second
 	DefaultKeepaliveTimeout    = 15 * time.Second
 
-	sctpReceiveBufferSize = 100_000
+	// sctpReceiveBufferSize is the size of the buffer for incoming messages.
+	//
+	// This is enough space for enqueuing 10 full sized messages.
+	// Besides throughput, this only matters if an application is using multiple dependent
+	// streams, say streams 1 & 2. It reads from stream 1 only after receiving message from
+	// stream 2. A buffer of 10 messages should serve all such situations.
+	sctpReceiveBufferSize = 10 * maxReceiveMessageSize
 )
 
 type WebRTCTransport struct {
@@ -367,7 +373,7 @@ func (t *WebRTCTransport) dial(ctx context.Context, scope network.ConnManagement
 	if err != nil {
 		return nil, err
 	}
-	channel := newStream(w.HandshakeDataChannel, detached, func() {})
+	channel := newStream(w.HandshakeDataChannel, detached, maxSendMessageSize, nil)
 
 	remotePubKey, err := t.noiseHandshake(ctx, w.PeerConnection, channel, p, remoteHashFunction, false)
 	if err != nil {


Test patch:
diff --git a/p2p/host/resource-manager/conn_limiter_test.go b/p2p/host/resource-manager/conn_limiter_test.go
index 89ce5d53..5c06b65a 100644
--- a/p2p/host/resource-manager/conn_limiter_test.go
+++ b/p2p/host/resource-manager/conn_limiter_test.go
@@ -24,6 +24,22 @@ func TestItLimits(t *testing.T) {
 		require.NoError(t, err)
 		require.True(t, cl.addConn(otherIP))
 	})
+
+	t.Run("IPv4 removal", func(t *testing.T) {
+		ip, err := netip.ParseAddr("1.2.3.4")
+		require.NoError(t, err)
+		cl := newConnLimiter()
+		cl.connLimitPerSubnetV4[0].ConnCount = 1
+		require.True(t, cl.addConn(ip))
+
+		// should fail the second time
+		require.False(t, cl.addConn(ip))
+		// remove the connection
+		cl.rmConn(ip)
+		// should succeed now
+		require.True(t, cl.addConn(ip))
+	})
+
 	t.Run("IPv6", func(t *testing.T) {
 		ip, err := netip.ParseAddr("1:2:3:4::1")
 		require.NoError(t, err)
diff --git a/p2p/security/tls/crypto_test.go b/p2p/security/tls/crypto_test.go
index efec9490..6171d178 100644
--- a/p2p/security/tls/crypto_test.go
+++ b/p2p/security/tls/crypto_test.go
@@ -5,6 +5,7 @@ import (
 	"encoding/hex"
 	"testing"
 
+	"github.com/libp2p/go-libp2p/core/crypto/pb"
 	"github.com/libp2p/go-libp2p/core/peer"
 
 	"github.com/stretchr/testify/assert"
@@ -53,31 +54,35 @@ func TestNewIdentityCertificates(t *testing.T) {
 
 func TestVectors(t *testing.T) {
 	type testcase struct {
-		name   string
-		data   string
-		peerID string
-		error  string
+		name    string
+		data    string
+		peerID  string
+		keyType pb.KeyType
+		error   string
 	}
 
 	testcases := []testcase{
 		{
-			name:   "ED25519 Peer ID",
-			data:   "308201773082011ea003020102020900f5bd0debaa597f52300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d030107034200046bf9871220d71dcb3483ecdfcbfcc7c103f8509d0974b3c18ab1f1be1302d643103a08f7a7722c1b247ba3876fe2c59e26526f479d7718a85202ddbe47562358a37f307d307b060a2b0601040183a25a01010101ff046a30680424080112207fda21856709c5ae12fd6e8450623f15f11955d384212b89f56e7e136d2e17280440aaa6bffabe91b6f30c35e3aa4f94b1188fed96b0ffdd393f4c58c1c047854120e674ce64c788406d1c2c4b116581fd7411b309881c3c7f20b46e54c7e6fe7f0f300a06082a8648ce3d040302034700304402207d1a1dbd2bda235ff2ec87daf006f9b04ba076a5a5530180cd9c2e8f6399e09d0220458527178c7e77024601dbb1b256593e9b96d961b96349d1f560114f61a87595",
-			peerID: "12D3KooWJRSrypvnpHgc6ZAgyCni4KcSmbV7uGRaMw5LgMKT18fq",
+			name:    "ED25519 Peer ID",
+			data:    "308201ae30820156a0030201020204499602d2300a06082a8648ce3d040302302031123010060355040a13096c69627032702e696f310a300806035504051301313020170d3735303130313133303030305a180f34303936303130313133303030305a302031123010060355040a13096c69627032702e696f310a300806035504051301313059301306072a8648ce3d020106082a8648ce3d030107034200040c901d423c831ca85e27c73c263ba132721bb9d7a84c4f0380b2a6756fd601331c8870234dec878504c174144fa4b14b66a651691606d8173e55bd37e381569ea37c307a3078060a2b0601040183a25a0101046a3068042408011220a77f1d92fedb59dddaea5a1c4abd1ac2fbde7d7b879ed364501809923d7c11b90440d90d2769db992d5e6195dbb08e706b6651e024fda6cfb8846694a435519941cac215a8207792e42849cccc6cd8136c6e4bde92a58c5e08cfd4206eb5fe0bf909300a06082a8648ce3d0403020346003043021f50f6b6c52711a881778718238f650c9fb48943ae6ee6d28427dc6071ae55e702203625f116a7a454db9c56986c82a25682f7248ea1cb764d322ea983ed36a31b77",
+			peerID:  "12D3KooWM6CgA9iBFZmcYAHA6A2qvbAxqfkmrYiRQuz3XEsk4Ksv",
+			keyType: pb.KeyType_Ed25519,
 		},
 		{
-			name:   "ECDSA Peer ID",
-			data:   "308201c030820166a003020102020900eaf419a6e3edb4a6300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d030107034200048dbf1116c7c608d6d5292bd826c3feb53483a89fce434bf64538a359c8e07538ff71f6766239be6a146dcc1a5f3bb934bcd4ae2ae1d4da28ac68b4a20593f06ba381c63081c33081c0060a2b0601040183a25a01010101ff0481ae3081ab045f0803125b3059301306072a8648ce3d020106082a8648ce3d0301070342000484b93fa456a74bd0153919f036db7bc63c802f055bc7023395d0203de718ee0fc7b570b767cdd858aca6c7c4113ff002e78bd2138ac1a3b26dde3519e06979ad04483046022100bc84014cea5a41feabdf4c161096564b9ccf4b62fbef4fe1cd382c84e11101780221009204f086a84cb8ed8a9ddd7868dc90c792ee434adf62c66f99a08a5eba11615b300a06082a8648ce3d0403020348003045022054b437be9a2edf591312d68ff24bf91367ad4143f76cf80b5658f232ade820da022100e23b48de9df9c25d4c83ddddf75d2676f0b9318ee2a6c88a736d85eab94a912f",
-			peerID: "QmZcrvr3r4S3QvwFdae3c2EWTfo792Y14UpzCZurhmiWeX",
+			name:    "ECDSA Peer ID",
+			data:    "308201f63082019da0030201020204499602d2300a06082a8648ce3d040302302031123010060355040a13096c69627032702e696f310a300806035504051301313020170d3735303130313133303030305a180f34303936303130313133303030305a302031123010060355040a13096c69627032702e696f310a300806035504051301313059301306072a8648ce3d020106082a8648ce3d030107034200040c901d423c831ca85e27c73c263ba132721bb9d7a84c4f0380b2a6756fd601331c8870234dec878504c174144fa4b14b66a651691606d8173e55bd37e381569ea381c23081bf3081bc060a2b0601040183a25a01010481ad3081aa045f0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004bf30511f909414ebdd3242178fd290f093a551cf75c973155de0bb5a96fedf6cb5d52da7563e794b512f66e60c7f55ba8a3acf3dd72a801980d205e8a1ad29f2044730450220064ea8124774caf8f50e57f436aa62350ce652418c019df5d98a3ac666c9386a022100aa59d704a931b5f72fb9222cb6cc51f954d04a4e2e5450f8805fe8918f71eaae300a06082a8648ce3d04030203470030440220799395b0b6c1e940a7e4484705f610ab51ed376f19ff9d7c16757cfbf61b8d4302206205c03fbb0f95205c779be86581d3e31c01871ad5d1f3435bcf375cb0e5088a",
+			peerID:  "QmfXbAwNjJLXfesgztEHe8HwgVDCMMpZ9Eax1HYq6hn9uE",
+			keyType: pb.KeyType_ECDSA,
 		},
 		{
-			name:   "secp256k1 Peer ID",
-			data:   "3082018230820128a003020102020900f3b305f55622cfdf300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d0301070342000458f7e9581748ff9bdd933b655cc0e5552a1248f840658cc221dec2186b5a2fe4641b86ab7590a3422cdbb1000cf97662f27e5910d7569f22feed8829c8b52e0fa38188308185308182060a2b0601040183a25a01010101ff0471306f042508021221026b053094d1112bce799dc8026040ae6d4eb574157929f1598172061f753d9b1b04463044022040712707e97794c478d93989aaa28ae1f71c03af524a8a4bd2d98424948a782302207b61b7f074b696a25fb9e0059141a811cccc4cc28042d9301b9b2a4015e87470300a06082a8648ce3d04030203480030450220143ae4d86fdc8675d2480bb6912eca5e39165df7f572d836aa2f2d6acfab13f8022100831d1979a98f0c4a6fb5069ca374de92f1a1205c962a6d90ad3d7554cb7d9df4",
-			peerID: "16Uiu2HAm2dSCBFxuge46aEt7U1oejtYuBUZXxASHqmcfVmk4gsbx",
+			name:    "secp256k1 Peer ID",
+			data:    "308201ba3082015fa0030201020204499602d2300a06082a8648ce3d040302302031123010060355040a13096c69627032702e696f310a300806035504051301313020170d3735303130313133303030305a180f34303936303130313133303030305a302031123010060355040a13096c69627032702e696f310a300806035504051301313059301306072a8648ce3d020106082a8648ce3d030107034200040c901d423c831ca85e27c73c263ba132721bb9d7a84c4f0380b2a6756fd601331c8870234dec878504c174144fa4b14b66a651691606d8173e55bd37e381569ea38184308181307f060a2b0601040183a25a01010471306f0425080212210206dc6968726765b820f050263ececf7f71e4955892776c0970542efd689d2382044630440220145e15a991961f0d08cd15425bb95ec93f6ffa03c5a385eedc34ecf464c7a8ab022026b3109b8a3f40ef833169777eb2aa337cfb6282f188de0666d1bcec2a4690dd300a06082a8648ce3d0403020349003046022100e1a217eeef9ec9204b3f774a08b70849646b6a1e6b8b27f93dc00ed58545d9fe022100b00dafa549d0f03547878338c7b15e7502888f6d45db387e5ae6b5d46899cef0",
+			peerID:  "16Uiu2HAkutTMoTzDw1tCvSRtu6YoixJwS46S1ZFxW8hSx9fWHiPs",
+			keyType: pb.KeyType_Secp256k1,
 		},
 		{
 			name:  "Invalid certificate",
-			data:  "308201773082011da003020102020830a73c5d896a1109300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004bbe62df9a7c1c46b7f1f21d556deec5382a36df146fb29c7f1240e60d7d5328570e3b71d99602b77a65c9b3655f62837f8d66b59f1763b8c9beba3be07778043a37f307d307b060a2b0601040183a25a01010101ff046a3068042408011220ec8094573afb9728088860864f7bcea2d4fd412fef09a8e2d24d482377c20db60440ecabae8354afa2f0af4b8d2ad871e865cb5a7c0c8d3dbdbf42de577f92461a0ebb0a28703e33581af7d2a4f2270fc37aec6261fcc95f8af08f3f4806581c730a300a06082a8648ce3d040302034800304502202dfb17a6fa0f94ee0e2e6a3b9fb6e986f311dee27392058016464bd130930a61022100ba4b937a11c8d3172b81e7cd04aedb79b978c4379c2b5b24d565dd5d67d3cb3c",
+			data:  "308201f73082019da0030201020204499602d2300a06082a8648ce3d040302302031123010060355040a13096c69627032702e696f310a300806035504051301313020170d3735303130313133303030305a180f34303936303130313133303030305a302031123010060355040a13096c69627032702e696f310a300806035504051301313059301306072a8648ce3d020106082a8648ce3d030107034200040c901d423c831ca85e27c73c263ba132721bb9d7a84c4f0380b2a6756fd601331c8870234dec878504c174144fa4b14b66a651691606d8173e55bd37e381569ea381c23081bf3081bc060a2b0601040183a25a01010481ad3081aa045f0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004bf30511f909414ebdd3242178fd290f093a551cf75c973155de0bb5a96fedf6cb5d52da7563e794b512f66e60c7f55ba8a3acf3dd72a801980d205e8a1ad29f204473045022100bb6e03577b7cc7a3cd1558df0da2b117dfdcc0399bc2504ebe7de6f65cade72802206de96e2a5be9b6202adba24ee0362e490641ac45c240db71fe955f2c5cf8df6e300a06082a8648ce3d0403020348003045022100e847f267f43717358f850355bdcabbefb2cfbf8a3c043b203a14788a092fe8db022027c1d04a2d41fd6b57a7e8b3989e470325de4406e52e084e34a3fd56eef0d0df",
 			error: "signature invalid",
 		},
 	}
@@ -96,6 +101,7 @@ func TestVectors(t *testing.T) {
 				return
 			}
 			require.NoError(t, err)
+			require.Equal(t, tc.keyType, key.Type())
 			id, err := peer.IDFromPublicKey(key)
 			require.NoError(t, err)
 			expectedID, err := peer.Decode(tc.peerID)
diff --git a/p2p/transport/webrtc/stream_test.go b/p2p/transport/webrtc/stream_test.go
index 4153ff83..461ed27f 100644
--- a/p2p/transport/webrtc/stream_test.go
+++ b/p2p/transport/webrtc/stream_test.go
@@ -3,6 +3,7 @@ package libp2pwebrtc
 import (
 	"crypto/rand"
 	"errors"
+	"fmt"
 	"io"
 	"os"
 	"sync/atomic"
@@ -148,8 +149,8 @@ func TestStreamSimpleReadWriteClose(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
 	var clientDone, serverDone atomic.Bool
-	clientStr := newStream(client.dc, client.rwc, func() { clientDone.Store(true) })
-	serverStr := newStream(server.dc, server.rwc, func() { serverDone.Store(true) })
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { clientDone.Store(true) })
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() { serverDone.Store(true) })
 
 	// send a foobar from the client
 	n, err := clientStr.Write([]byte("foobar"))
@@ -194,8 +195,8 @@ func TestStreamSimpleReadWriteClose(t *testing.T) {
 func TestStreamPartialReads(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
-	clientStr := newStream(client.dc, client.rwc, func() {})
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	_, err := serverStr.Write([]byte("foobar"))
 	require.NoError(t, err)
@@ -217,8 +218,8 @@ func TestStreamPartialReads(t *testing.T) {
 func TestStreamSkipEmptyFrames(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
-	clientStr := newStream(client.dc, client.rwc, func() {})
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	for i := 0; i < 10; i++ {
 		require.NoError(t, serverStr.writer.WriteMsg(&pb.Message{}))
@@ -252,7 +253,7 @@ func TestStreamSkipEmptyFrames(t *testing.T) {
 func TestStreamReadReturnsOnClose(t *testing.T) {
 	client, _ := getDetachedDataChannels(t)
 
-	clientStr := newStream(client.dc, client.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
 	errChan := make(chan error, 1)
 	go func() {
 		_, err := clientStr.Read([]byte{0})
@@ -275,8 +276,8 @@ func TestStreamResets(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
 	var clientDone, serverDone atomic.Bool
-	clientStr := newStream(client.dc, client.rwc, func() { clientDone.Store(true) })
-	serverStr := newStream(server.dc, server.rwc, func() { serverDone.Store(true) })
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { clientDone.Store(true) })
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() { serverDone.Store(true) })
 
 	// send a foobar from the client
 	_, err := clientStr.Write([]byte("foobar"))
@@ -311,8 +312,8 @@ func TestStreamResets(t *testing.T) {
 func TestStreamReadDeadlineAsync(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
-	clientStr := newStream(client.dc, client.rwc, func() {})
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	timeout := 100 * time.Millisecond
 	if os.Getenv("CI") != "" {
@@ -342,8 +343,8 @@ func TestStreamReadDeadlineAsync(t *testing.T) {
 func TestStreamWriteDeadlineAsync(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
-	clientStr := newStream(client.dc, client.rwc, func() {})
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 	_ = serverStr
 
 	b := make([]byte, 1024)
@@ -372,8 +373,8 @@ func TestStreamWriteDeadlineAsync(t *testing.T) {
 func TestStreamReadAfterClose(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
-	clientStr := newStream(client.dc, client.rwc, func() {})
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	serverStr.Close()
 	b := make([]byte, 1)
@@ -384,8 +385,8 @@ func TestStreamReadAfterClose(t *testing.T) {
 
 	client, server = getDetachedDataChannels(t)
 
-	clientStr = newStream(client.dc, client.rwc, func() {})
-	serverStr = newStream(server.dc, server.rwc, func() {})
+	clientStr = newStream(client.dc, client.rwc, maxSendMessageSize, func() {})
+	serverStr = newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	serverStr.Reset()
 	b = make([]byte, 1)
@@ -399,8 +400,8 @@ func TestStreamCloseAfterFINACK(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
 	done := make(chan bool, 1)
-	clientStr := newStream(client.dc, client.rwc, func() { done <- true })
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { done <- true })
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	go func() {
 		err := clientStr.Close()
@@ -427,8 +428,8 @@ func TestStreamFinAckAfterStopSending(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
 	done := make(chan bool, 1)
-	clientStr := newStream(client.dc, client.rwc, func() { done <- true })
-	serverStr := newStream(server.dc, server.rwc, func() {})
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { done <- true })
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() {})
 
 	go func() {
 		clientStr.CloseRead()
@@ -460,8 +461,8 @@ func TestStreamConcurrentClose(t *testing.T) {
 
 	start := make(chan bool, 2)
 	done := make(chan bool, 2)
-	clientStr := newStream(client.dc, client.rwc, func() { done <- true })
-	serverStr := newStream(server.dc, server.rwc, func() { done <- true })
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { done <- true })
+	serverStr := newStream(server.dc, server.rwc, maxSendMessageSize, func() { done <- true })
 
 	go func() {
 		start <- true
@@ -495,7 +496,7 @@ func TestStreamResetAfterClose(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
 	done := make(chan bool, 2)
-	clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { done <- true })
 	clientStr.Close()
 
 	select {
@@ -520,7 +521,7 @@ func TestStreamDataChannelCloseOnFINACK(t *testing.T) {
 	client, server := getDetachedDataChannels(t)
 
 	done := make(chan bool, 1)
-	clientStr := newStream(client.dc, client.rwc, func() { done <- true })
+	clientStr := newStream(client.dc, client.rwc, maxSendMessageSize, func() { done <- true })
 
 	clientStr.Close()
 
@@ -540,24 +541,35 @@ func TestStreamDataChannelCloseOnFINACK(t *testing.T) {
 }
 
 func TestStreamChunking(t *testing.T) {
-	client, server := getDetachedDataChannels(t)
-
-	clientStr := newStream(client.dc, client.rwc, func() {})
-	serverStr := newStream(server.dc, server.rwc, func() {})
-
-	const N = (16 << 10) + 1000
-	go func() {
-		data := make([]byte, N)
-		_, err := clientStr.Write(data)
-		require.NoError(t, err)
-	}()
-
-	data := make([]byte, N)
-	n, err := serverStr.Read(data)
-	require.NoError(t, err)
-	require.LessOrEqual(t, n, 16<<10)
-
-	nn, err := serverStr.Read(data)
-	require.NoError(t, err)
-	require.Equal(t, nn+n, N)
+	for _, msgSize := range []int{16 << 10, 32 << 10, 64 << 10, 128 << 10, 256 << 10} {
+		t.Run(fmt.Sprintf("msgSize=%d", msgSize), func(t *testing.T) {
+			client, server := getDetachedDataChannels(t)
+			defer client.dc.Close()
+			defer server.dc.Close()
+
+			clientStr := newStream(client.dc, client.rwc, msgSize, nil)
+			// server should read large messages even if it can only send 16 kB messages.
+			serverStr := newStream(server.dc, server.rwc, 16<<10, nil)
+
+			N := msgSize + 1000
+			input := make([]byte, N)
+			_, err := rand.Read(input)
+			require.NoError(t, err)
+			go func() {
+				n, err := clientStr.Write(input)
+				require.NoError(t, err)
+				require.Equal(t, n, len(input))
+			}()
+
+			data := make([]byte, N)
+			n, err := serverStr.Read(data)
+			require.NoError(t, err)
+			require.LessOrEqual(t, n, msgSize)
+			// shouldn't be much less than msgSize
+			require.GreaterOrEqual(t, n, msgSize-100)
+			_, err = serverStr.Read(data[n:])
+			require.NoError(t, err)
+			require.Equal(t, input, data)
+		})
+	}
 }
diff --git a/p2p/transport/webrtc/transport_test.go b/p2p/transport/webrtc/transport_test.go
index 13b50412..83f65c8c 100644
--- a/p2p/transport/webrtc/transport_test.go
+++ b/p2p/transport/webrtc/transport_test.go
@@ -546,7 +546,7 @@ func TestTransportWebRTC_Deadline(t *testing.T) {
 		require.NoError(t, err)
 
 		stream.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
-		largeBuffer := make([]byte, 2*1024*1024)
+		largeBuffer := make([]byte, 20*1024*1024)
 		_, err = stream.Write(largeBuffer)
 		require.ErrorIs(t, err, os.ErrDeadlineExceeded)
 
diff --git a/test-plans/go.mod b/test-plans/go.mod
index d363d183..ef231457 100644
--- a/test-plans/go.mod
+++ b/test-plans/go.mod
@@ -59,22 +59,22 @@ require (
 	github.com/pion/datachannel v1.5.10 // indirect
 	github.com/pion/dtls/v2 v2.2.12 // indirect
 	github.com/pion/dtls/v3 v3.0.4 // indirect
-	github.com/pion/ice/v4 v4.0.6 // indirect
+	github.com/pion/ice/v4 v4.0.8 // indirect
 	github.com/pion/interceptor v0.1.37 // indirect
 	github.com/pion/logging v0.2.3 // indirect
 	github.com/pion/mdns/v2 v2.0.7 // indirect
 	github.com/pion/randutil v0.1.0 // indirect
 	github.com/pion/rtcp v1.2.15 // indirect
-	github.com/pion/rtp v1.8.11 // indirect
-	github.com/pion/sctp v1.8.36 // indirect
-	github.com/pion/sdp/v3 v3.0.10 // indirect
+	github.com/pion/rtp v1.8.13 // indirect
+	github.com/pion/sctp v1.8.37 // indirect
+	github.com/pion/sdp/v3 v3.0.11 // indirect
 	github.com/pion/srtp/v3 v3.0.4 // indirect
 	github.com/pion/stun v0.6.1 // indirect
 	github.com/pion/stun/v3 v3.0.0 // indirect
 	github.com/pion/transport/v2 v2.2.10 // indirect
 	github.com/pion/transport/v3 v3.0.7 // indirect
 	github.com/pion/turn/v4 v4.0.0 // indirect
-	github.com/pion/webrtc/v4 v4.0.10 // indirect
+	github.com/pion/webrtc/v4 v4.0.14 // indirect
 	github.com/prometheus/client_golang v1.21.0 // indirect
 	github.com/prometheus/client_model v0.6.1 // indirect
 	github.com/prometheus/common v0.62.0 // indirect
diff --git a/test-plans/go.sum b/test-plans/go.sum
index 58987e3c..cfb9eba5 100644
--- a/test-plans/go.sum
+++ b/test-plans/go.sum
@@ -193,8 +193,8 @@ github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
 github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
 github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
 github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
-github.com/pion/ice/v4 v4.0.6 h1:jmM9HwI9lfetQV/39uD0nY4y++XZNPhvzIPCb8EwxUM=
-github.com/pion/ice/v4 v4.0.6/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
+github.com/pion/ice/v4 v4.0.8 h1:ajNx0idNG+S+v9Phu4LSn2cs8JEfTsA1/tEjkkAVpFY=
+github.com/pion/ice/v4 v4.0.8/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
 github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
 github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
 github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
@@ -206,12 +206,12 @@ github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
 github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
 github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
 github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
-github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
-github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
-github.com/pion/sctp v1.8.36 h1:owNudmnz1xmhfYje5L/FCav3V9wpPRePHle3Zi+P+M0=
-github.com/pion/sctp v1.8.36/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
-github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
-github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
+github.com/pion/rtp v1.8.13 h1:8uSUPpjSL4OlwZI8Ygqu7+h2p9NPFB+yAZ461Xn5sNg=
+github.com/pion/rtp v1.8.13/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
+github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
+github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
+github.com/pion/sdp/v3 v3.0.11 h1:VhgVSopdsBKwhCFoyyPmT1fKMeV9nLMrEKxNOdy3IVI=
+github.com/pion/sdp/v3 v3.0.11/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
 github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
 github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
 github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
@@ -226,8 +226,8 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1
 github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
 github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
 github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
-github.com/pion/webrtc/v4 v4.0.10 h1:Hq/JLjhqLxi+NmCtE8lnRPDr8H4LcNvwg8OxVcdv56Q=
-github.com/pion/webrtc/v4 v4.0.10/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck=
+github.com/pion/webrtc/v4 v4.0.14 h1:nyds/sFRR+HvmWoBa6wrL46sSfpArE0qR883MBW96lg=
+github.com/pion/webrtc/v4 v4.0.14/go.mod h1:R3+qTnQTS03UzwDarYecgioNf7DYgTsldxnCXB821Kk=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=