Browse Source

webrtc: set sctp receive buffer size to 100kB (#2745)

pull/2746/head
sukun 8 months ago
committed by GitHub
parent
commit
96e0780491
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      p2p/test/transport/rcmgr_test.go
  2. 4
      p2p/transport/webrtc/listener.go
  3. 21
      p2p/transport/webrtc/stream.go
  4. 4
      p2p/transport/webrtc/stream_write.go
  5. 6
      p2p/transport/webrtc/transport.go

4
p2p/test/transport/rcmgr_test.go

@ -86,6 +86,10 @@ func TestResourceManagerIsUsed(t *testing.T) {
}
return nil
})
if tc.Name == "WebRTC" {
// webrtc receive buffer is a fix sized buffer allocated up front
connScope.EXPECT().ReserveMemory(gomock.Any(), gomock.Any())
}
connScope.EXPECT().Done().MinTimes(1)
var allStreamsDone sync.WaitGroup

4
p2p/transport/webrtc/listener.go

@ -209,6 +209,10 @@ func (l *listener) setupConnection(
// in a release.
settingEngine.SetReceiveMTU(udpmux.ReceiveBufSize)
settingEngine.DetachDataChannels()
settingEngine.SetSCTPMaxReceiveBufferSize(sctpReceiveBufferSize)
if err := scope.ReserveMemory(sctpReceiveBufferSize, network.ReservationPriorityMedium); err != nil {
return nil, err
}
w, err = newWebRTCConnection(settingEngine, l.config)
if err != nil {

21
p2p/transport/webrtc/stream.go

@ -17,24 +17,19 @@ import (
const (
// maxMessageSize is the maximum message size of the Protobuf message we send / receive.
maxMessageSize = 16384
// Pion SCTP association has an internal receive buffer of 1MB (roughly, 1MB per connection).
// We can change this value in the SettingEngine before creating the peerconnection.
// https://github.com/pion/webrtc/blob/v3.1.49/sctptransport.go#L341
maxBufferedAmount = 2 * maxMessageSize
// 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
// bufferedAmountLowThreshold and maxBufferedAmount are bound
// to a stream but congestion control is done on the whole
// SCTP association. This means that a single stream can monopolize
// the complete congestion control window (cwnd) if it does not
// read stream data and it's remote continues to send. We can
// add messages to the send buffer once there is space for 1 full
// sized message.
bufferedAmountLowThreshold = maxBufferedAmount / 2
// Proto overhead assumption is 5 bytes
protoOverhead = 5
@ -120,7 +115,7 @@ func newStream(
}
// released when the controlMessageReader goroutine exits
s.controlMessageReaderDone.Add(1)
s.dataChannel.SetBufferedAmountLowThreshold(bufferedAmountLowThreshold)
s.dataChannel.SetBufferedAmountLowThreshold(sendBufferLowThreshold)
s.dataChannel.OnBufferedAmountLow(func() {
s.notifyWriteStateChanged()

4
p2p/transport/webrtc/stream_write.go

@ -112,9 +112,9 @@ func (s *stream) SetWriteDeadline(t time.Time) error {
func (s *stream) availableSendSpace() int {
buffered := int(s.dataChannel.BufferedAmount())
availableSpace := maxBufferedAmount - buffered
availableSpace := maxSendBuffer - buffered
if availableSpace+maxTotalControlMessagesSize < 0 { // this should never happen, but better check
log.Errorw("data channel buffered more data than the maximum amount", "max", maxBufferedAmount, "buffered", buffered)
log.Errorw("data channel buffered more data than the maximum amount", "max", maxSendBuffer, "buffered", buffered)
}
return availableSpace
}

6
p2p/transport/webrtc/transport.go

@ -79,6 +79,8 @@ const (
DefaultDisconnectedTimeout = 20 * time.Second
DefaultFailedTimeout = 30 * time.Second
DefaultKeepaliveTimeout = 15 * time.Second
sctpReceiveBufferSize = 100_000
)
type WebRTCTransport struct {
@ -314,6 +316,10 @@ func (t *WebRTCTransport) dial(ctx context.Context, scope network.ConnManagement
// If you run pion on a system with only the loopback interface UP,
// it will not connect to anything.
settingEngine.SetIncludeLoopbackCandidate(true)
settingEngine.SetSCTPMaxReceiveBufferSize(sctpReceiveBufferSize)
if err := scope.ReserveMemory(sctpReceiveBufferSize, network.ReservationPriorityMedium); err != nil {
return nil, err
}
w, err = newWebRTCConnection(settingEngine, t.webrtcConfig)
if err != nil {

Loading…
Cancel
Save