Repository: pion/sctp
Pull request #141 (2020-09-08 05:57:15)

Set default MaxMessageSize to 65536
## Changes
* Modified the default maxMessageSize from 65535 to 65536.
* Added getter/setter function also.

Relates to pion/webrtc#1396


codecov[bot]: # [Codecov](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=h1) Report
> Merging [#141](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=desc) into [master](https://codecov.io/gh/pion/sctp/commit/791eecfbf996d4375cec925258888ce44eecfe94?el=desc) will **increase** coverage by `0.40%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/pion/sctp/pull/141/graphs/tree.svg?width=650&height=150&src=pr&token=AB8S3U6xR9)](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #141      +/-   ##
==========================================
+ Coverage   78.83%   79.23%   +0.40%     
==========================================
  Files          43       43              
  Lines        2802     2813      +11     
==========================================
+ Hits         2209     2229      +20     
+ Misses        455      450       -5     
+ Partials      138      134       -4     
```

| Flag | Coverage Δ | |
|---|---|---|
| #go | `79.23% <100.00%> (+0.40%)` | :arrow_up: |
| #wasm | `69.88% <58.33%> (-0.03%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [association.go](https://codecov.io/gh/pion/sctp/pull/141/diff?src=pr&el=tree#diff-YXNzb2NpYXRpb24uZ28=) | `83.43% <100.00%> (+0.76%)` | :arrow_up: |
| [stream.go](https://codecov.io/gh/pion/sctp/pull/141/diff?src=pr&el=tree#diff-c3RyZWFtLmdv) | `92.85% <100.00%> (+1.24%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=footer). Last update [791eecf...f323feb](https://codecov.io/gh/pion/sctp/pull/141?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

Sean-Der: Sorry I missed this!

Patch:
diff --git a/association.go b/association.go
index 01d6f58..096659b 100644
--- a/association.go
+++ b/association.go
@@ -19,11 +19,12 @@ import (
 var globalMathRandomGenerator = randutil.NewMathRandomGenerator()
 
 const (
-	receiveMTU          uint32 = 8192 // MTU for inbound packet (from DTLS)
-	initialMTU          uint32 = 1228 // initial MTU for outgoing packets (to DTLS)
-	initialRecvBufSize  uint32 = 1024 * 1024
-	commonHeaderSize    uint32 = 12
-	dataChunkHeaderSize uint32 = 16
+	receiveMTU            uint32 = 8192 // MTU for inbound packet (from DTLS)
+	initialMTU            uint32 = 1228 // initial MTU for outgoing packets (to DTLS)
+	initialRecvBufSize    uint32 = 1024 * 1024
+	commonHeaderSize      uint32 = 12
+	dataChunkHeaderSize   uint32 = 16
+	defaultMaxMessageSize uint32 = 65536
 )
 
 // association state enums
@@ -146,6 +147,7 @@ type Association struct {
 
 	// Congestion control parameters
 	maxReceiveBufferSize uint32
+	maxMessageSize       uint32
 	cwnd                 uint32 // my congestion window size
 	rwnd                 uint32 // calculated peer's receiver windows size
 	ssthresh             uint32 // slow start threshold
@@ -196,6 +198,7 @@ type Association struct {
 type Config struct {
 	NetConn              net.Conn
 	MaxReceiveBufferSize uint32
+	MaxMessageSize       uint32
 	LoggerFactory        logging.LoggerFactory
 }
 
@@ -239,10 +242,18 @@ func createAssociation(config Config) *Association {
 		maxReceiveBufferSize = config.MaxReceiveBufferSize
 	}
 
+	var maxMessageSize uint32
+	if config.MaxMessageSize == 0 {
+		maxMessageSize = defaultMaxMessageSize
+	} else {
+		maxMessageSize = config.MaxMessageSize
+	}
+
 	tsn := globalMathRandomGenerator.Uint32()
 	a := &Association{
 		netConn:                 config.NetConn,
 		maxReceiveBufferSize:    maxReceiveBufferSize,
+		maxMessageSize:          maxMessageSize,
 		myMaxNumOutboundStreams: math.MaxUint16,
 		myMaxNumInboundStreams:  math.MaxUint16,
 		payloadQueue:            newPayloadQueue(),
@@ -2219,3 +2230,13 @@ func (a *Association) bufferedAmount() int {
 
 	return a.pendingQueue.getNumBytes() + a.inflightQueue.getNumBytes()
 }
+
+// MaxMessageSize returns the maximum message size you can send.
+func (a *Association) MaxMessageSize() uint32 {
+	return atomic.LoadUint32(&a.maxMessageSize)
+}
+
+// SetMaxMessageSize sets the maximum message size you can send.
+func (a *Association) SetMaxMessageSize(maxMsgSize uint32) {
+	atomic.StoreUint32(&a.maxMessageSize, maxMsgSize)
+}
diff --git a/stream.go b/stream.go
index c563d68..c628ce3 100644
--- a/stream.go
+++ b/stream.go
@@ -179,7 +179,8 @@ func (s *Stream) Write(p []byte) (n int, err error) {
 
 // WriteSCTP writes len(p) bytes from p to the DTLS connection
 func (s *Stream) WriteSCTP(p []byte, ppi PayloadProtocolIdentifier) (n int, err error) {
-	if len(p) > math.MaxUint16 {
+	maxMessageSize := s.association.MaxMessageSize()
+	if len(p) > int(maxMessageSize) {
 		return 0, errors.Errorf("Outbound packet larger than maximum message size %v", math.MaxUint16)
 	}
 


Test patch:
diff --git a/association_test.go b/association_test.go
index 84454dd..3b392a8 100644
--- a/association_test.go
+++ b/association_test.go
@@ -11,6 +11,7 @@ import (
 	"math/rand"
 	"net"
 	"runtime"
+	"strings"
 	"sync"
 	"testing"
 	"time"
@@ -2403,3 +2404,57 @@ func TestAssocHandleInit(t *testing.T) {
 		handleInitTest(t, shutdownSent, true)
 	})
 }
+
+func TestAssocMaxMessageSize(t *testing.T) {
+	t.Run("default", func(t *testing.T) {
+		loggerFactory := logging.NewDefaultLoggerFactory()
+		a := createAssociation(Config{
+			LoggerFactory: loggerFactory,
+		})
+		assert.NotNil(t, a, "should succeed")
+		assert.Equal(t, uint32(65536), a.MaxMessageSize(), "should match")
+
+		s := a.createStream(1, false)
+		assert.NotNil(t, s, "should succeed")
+
+		p := make([]byte, 65537)
+		var err error
+		_, err = s.WriteSCTP(p[:65536], s.defaultPayloadType)
+		assert.False(t, strings.Contains(err.Error(), "larger than maximum"), "should be false")
+
+		_, err = s.WriteSCTP(p[:65537], s.defaultPayloadType)
+		assert.True(t, strings.Contains(err.Error(), "larger than maximum"), "should be false")
+	})
+
+	t.Run("explicit", func(t *testing.T) {
+		loggerFactory := logging.NewDefaultLoggerFactory()
+		a := createAssociation(Config{
+			MaxMessageSize: 30000,
+			LoggerFactory:  loggerFactory,
+		})
+		assert.NotNil(t, a, "should succeed")
+		assert.Equal(t, uint32(30000), a.MaxMessageSize(), "should match")
+
+		s := a.createStream(1, false)
+		assert.NotNil(t, s, "should succeed")
+
+		p := make([]byte, 30001)
+		var err error
+		_, err = s.WriteSCTP(p[:30000], s.defaultPayloadType)
+		assert.False(t, strings.Contains(err.Error(), "larger than maximum"), "should be false")
+
+		_, err = s.WriteSCTP(p[:30001], s.defaultPayloadType)
+		assert.True(t, strings.Contains(err.Error(), "larger than maximum"), "should be false")
+	})
+
+	t.Run("set value", func(t *testing.T) {
+		loggerFactory := logging.NewDefaultLoggerFactory()
+		a := createAssociation(Config{
+			LoggerFactory: loggerFactory,
+		})
+		assert.NotNil(t, a, "should succeed")
+		assert.Equal(t, uint32(65536), a.MaxMessageSize(), "should match")
+		a.SetMaxMessageSize(20000)
+		assert.Equal(t, uint32(20000), a.MaxMessageSize(), "should match")
+	})
+}