mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-05-26 07:08:11 +00:00
fix(runtime): account for smux frame overhead in wire payload cap
This commit is contained in:
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/openlibrecommunity/olcrtc/internal/auth"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/client"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/control"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/crypto"
|
||||
enginebuiltin "github.com/openlibrecommunity/olcrtc/internal/engine/builtin"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/logger"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/names"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/runtime"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/server"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/transport"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/transport/datachannel"
|
||||
@@ -549,7 +549,7 @@ func validateTrafficConfig(cfg Config) error {
|
||||
|
||||
func trafficConfig(cfg Config) (transport.TrafficConfig, error) {
|
||||
if cfg.TrafficMaxPayloadSize < 0 || (cfg.TrafficMaxPayloadSize > 0 &&
|
||||
cfg.TrafficMaxPayloadSize <= crypto.WireOverhead) {
|
||||
cfg.TrafficMaxPayloadSize < runtime.MinSmuxWirePayload) {
|
||||
return transport.TrafficConfig{}, ErrTrafficMaxPayloadSizeInvalid
|
||||
}
|
||||
minDelay, err := parseOptionalNonNegativeDuration(cfg.TrafficMinDelay)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/openlibrecommunity/olcrtc/internal/control"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/crypto"
|
||||
"github.com/openlibrecommunity/olcrtc/internal/runtime"
|
||||
)
|
||||
|
||||
const testBadDuration = "nope"
|
||||
@@ -511,10 +511,10 @@ func TestValidate(t *testing.T) {
|
||||
want: ErrTrafficMaxPayloadSizeInvalid,
|
||||
},
|
||||
{
|
||||
name: "traffic rejects payload smaller than crypto overhead",
|
||||
name: "traffic rejects payload too small for encrypted smux frame",
|
||||
cfg: func() Config {
|
||||
cfg := base
|
||||
cfg.TrafficMaxPayloadSize = crypto.WireOverhead
|
||||
cfg.TrafficMaxPayloadSize = runtime.MinSmuxWirePayload - 1
|
||||
return cfg
|
||||
}(),
|
||||
want: ErrTrafficMaxPayloadSizeInvalid,
|
||||
|
||||
@@ -52,9 +52,10 @@ func TestSmuxConfig(t *testing.T) {
|
||||
t.Fatalf("smuxConfig(0) = %+v", cfg)
|
||||
}
|
||||
capped := smuxConfig(4096)
|
||||
if capped.MaxFrameSize != 4096-cryptopkg.WireOverhead {
|
||||
want := 4096 - runtime.SmuxWireOverhead
|
||||
if capped.MaxFrameSize != want {
|
||||
t.Fatalf("smuxConfig(4096).MaxFrameSize = %d, want %d",
|
||||
capped.MaxFrameSize, 4096-cryptopkg.WireOverhead)
|
||||
capped.MaxFrameSize, want)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,19 @@ import (
|
||||
"github.com/xtaci/smux"
|
||||
)
|
||||
|
||||
const (
|
||||
// SmuxFrameOverhead is the fixed smux frame header size. MaxFrameSize
|
||||
// caps only the smux payload, while muxconn encrypts and sends the whole
|
||||
// smux frame as one transport message.
|
||||
SmuxFrameOverhead = 8
|
||||
// SmuxWireOverhead is the non-payload overhead added around each smux
|
||||
// frame before it reaches the transport payload limit.
|
||||
SmuxWireOverhead = crypto.WireOverhead + SmuxFrameOverhead
|
||||
// MinSmuxWirePayload is the smallest useful encrypted transport payload
|
||||
// cap that can still carry a non-empty smux frame.
|
||||
MinSmuxWirePayload = SmuxWireOverhead + 1
|
||||
)
|
||||
|
||||
// ErrKeyRequired is returned when no encryption key is provided.
|
||||
var ErrKeyRequired = errors.New("key required (use -key <hex>)")
|
||||
|
||||
@@ -44,15 +57,15 @@ func SetupCipher(keyHex string) (*crypto.Cipher, error) {
|
||||
|
||||
// SmuxConfig returns the tuned smux config used on both ends. Both peers
|
||||
// must agree on Version and MaxFrameSize. maxWirePayload, when > 0,
|
||||
// constrains the max frame size to fit under the transport's per-message
|
||||
// payload cap minus the AEAD wire overhead.
|
||||
// constrains the smux payload size so the encrypted whole smux frame fits
|
||||
// under the transport's per-message payload cap.
|
||||
func SmuxConfig(maxWirePayload int) *smux.Config {
|
||||
cfg := smux.DefaultConfig()
|
||||
cfg.Version = 2
|
||||
cfg.KeepAliveDisabled = false
|
||||
cfg.MaxFrameSize = 32768
|
||||
if maxWirePayload > crypto.WireOverhead {
|
||||
maxFrameSize := maxWirePayload - crypto.WireOverhead
|
||||
if maxWirePayload >= MinSmuxWirePayload {
|
||||
maxFrameSize := maxWirePayload - SmuxWireOverhead
|
||||
if maxFrameSize < cfg.MaxFrameSize {
|
||||
cfg.MaxFrameSize = maxFrameSize
|
||||
}
|
||||
|
||||
@@ -44,12 +44,15 @@ func TestSmuxConfigDefault(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSmuxConfigShrinks(t *testing.T) {
|
||||
// 100-byte wire payload minus crypto overhead is far below default 32768,
|
||||
// so MaxFrameSize must shrink.
|
||||
// 100-byte wire payload minus smux+crypto overhead is far below default
|
||||
// 32768, so MaxFrameSize must shrink.
|
||||
cfg := runtime.SmuxConfig(100)
|
||||
if cfg.MaxFrameSize >= 32768 {
|
||||
t.Fatalf("MaxFrameSize = %d, want shrunk", cfg.MaxFrameSize)
|
||||
}
|
||||
if cfg.MaxFrameSize+runtime.SmuxWireOverhead != 100 {
|
||||
t.Fatalf("wire size = %d, want 100", cfg.MaxFrameSize+runtime.SmuxWireOverhead)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthTrackerEmitsOnEveryChange(t *testing.T) {
|
||||
|
||||
@@ -53,9 +53,10 @@ func TestSmuxConfig(t *testing.T) {
|
||||
t.Fatalf("smuxConfig(0) = %+v", cfg)
|
||||
}
|
||||
capped := smuxConfig(4096)
|
||||
if capped.MaxFrameSize != 4096-cryptopkg.WireOverhead {
|
||||
want := 4096 - runtime.SmuxWireOverhead
|
||||
if capped.MaxFrameSize != want {
|
||||
t.Fatalf("smuxConfig(4096).MaxFrameSize = %d, want %d",
|
||||
capped.MaxFrameSize, 4096-cryptopkg.WireOverhead)
|
||||
capped.MaxFrameSize, want)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user