limits.go RawHistoryFolder
1package brokerwire
2
3// Stateless bound refusals.
4//
5// The broker preamble negotiates one immutable pair of ceilings per
6// connection: MaxReceiveEnvelopeBytes bounds every envelope this side
7// accepts, and StreamChunkLimit bounds one opaque ClientStreamData or
8// ServerStreamData frame. Envelope ceilings are fixed: ordinary envelopes
9// never exceed the advertised floor, and the preamble advertisement itself
10// rides inside BrokerPreambleLimit.
11//
12// The broker has no Output/image/picker bulk category: every application
13// envelope is control-class and shares one ceiling. Stream chunk payloads
14// are bounded separately so hostile lengths never allocate.
15
16import (
17 "github.com/bnema/vev/internal/protocol/wire"
18)
19
20const (
21 // BrokerRoleClient is the broker preamble client role. It is disjoint
22 // from the session preamble roles 1/2.
23 BrokerRoleClient uint32 = 3
24 // BrokerRoleServer is the broker preamble server role.
25 BrokerRoleServer uint32 = 4
26
27 // BrokerPreambleLimit bounds the serialized broker preamble envelope.
28 BrokerPreambleLimit = 4 << 10
29
30 // MinBrokerEnvelopeBytes is the advertised-envelope floor: a broker
31 // peer must accept at least 1 MiB per envelope.
32 MinBrokerEnvelopeBytes uint64 = 1 << 20
33 // MaxBrokerEnvelopeBytes is the advertised-envelope ceiling: a broker
34 // peer must never advertise above 16 MiB (wire.AbsoluteEnvelopeLimit).
35 MaxBrokerEnvelopeBytes uint64 = wire.AbsoluteEnvelopeLimit
36
37 // MinStreamChunkBytes is the smallest legal stream chunk ceiling.
38 MinStreamChunkBytes uint64 = 1
39 // MaxStreamChunkBytes is the largest legal stream chunk ceiling:
40 // 64 KiB per opaque stream frame.
41 MaxStreamChunkBytes uint64 = 64 << 10
42)
43
44// Ceilings are the immutable per-connection ceilings negotiated once by the
45// broker preamble. MaxReceiveEnvelopeBytes bounds every envelope this side
46// accepts; StreamChunkLimit bounds one opaque stream data frame in either
47// direction.
48//
49// The preamble helpers and the connection dispatcher share this value: a
50// caller that completed the preamble reads the negotiated limits from
51// BrokerPreambleRequest or BrokerPreambleResponse and passes them to
52// EncodeClient/DecodeClient and EncodeServer/DecodeServer.
53type Ceilings struct {
54 MaxReceiveEnvelopeBytes uint64
55 StreamChunkLimit uint64
56}
57
58// brokerCeilings is the in-package alias for Ceilings. It exists only so
59// The codec tests keep their short spelling; production code uses Ceilings.
60type brokerCeilings = Ceilings
61
62// defaultBrokerCeilings advertises the local broker receive policy: the
63// full absolute envelope ceiling and the maximum stream chunk.
64func defaultBrokerCeilings() Ceilings {
65 return Ceilings{
66 MaxReceiveEnvelopeBytes: wire.AbsoluteEnvelopeLimit,
67 StreamChunkLimit: MaxStreamChunkBytes,
68 }
69}
70
71// DefaultCeilings returns the local broker receive policy: the full absolute
72// envelope ceiling and the maximum stream chunk. It is the offer a broker IPC
73// client or server advertises before negotiation.
74func DefaultCeilings() Ceilings { return defaultBrokerCeilings() }
75
76// effectiveBrokerCeilings takes the minima of both sides' advertisements.
77func effectiveBrokerCeilings(local, remote Ceilings) Ceilings {
78 return Ceilings{
79 MaxReceiveEnvelopeBytes: min(local.MaxReceiveEnvelopeBytes, remote.MaxReceiveEnvelopeBytes),
80 StreamChunkLimit: min(local.StreamChunkLimit, remote.StreamChunkLimit),
81 }
82}
83
84// EffectiveCeilings returns the element-wise minima of the two advertised
85// ceilings: one byte stream carries exactly the limits both peers accepted.
86func EffectiveCeilings(local, remote Ceilings) Ceilings {
87 return effectiveBrokerCeilings(local, remote)
88}
89
90// checkBrokerCeilings refuses a zero, below-floor, or above-ceiling
91// advertisement. Envelope bounds are the 1 MiB..16 MiB advertised window;
92// chunk bounds are 1..64 KiB.
93func checkBrokerCeilings(remote Ceilings) error {
94 if remote.MaxReceiveEnvelopeBytes < MinBrokerEnvelopeBytes ||
95 remote.MaxReceiveEnvelopeBytes > MaxBrokerEnvelopeBytes {
96 return ErrPreambleRejected
97 }
98 if remote.StreamChunkLimit < MinStreamChunkBytes ||
99 remote.StreamChunkLimit > MaxStreamChunkBytes {
100 return ErrPreambleRejected
101 }
102 return nil
103}
104
105// Validate reports whether one advertised ceiling is negotiable: an envelope
106// window inside 1 MiB..16 MiB and a stream chunk inside 1..64 KiB.
107func (c Ceilings) Validate() error { return checkBrokerCeilings(c) }
108
109// checkBrokerEnvelopeCeiling rejects one serialized broker envelope above
110// the negotiated ceiling. All broker envelopes are control-class: the
111// negotiated ceiling always applies in full.
112func checkBrokerEnvelopeCeiling(payload []byte, ceiling uint64) error {
113 if uint64(len(payload)) > ceiling {
114 return wire.ErrScanLength
115 }
116 return nil
117}
118
119// CheckPreambleSize refuses one serialized broker preamble above the 4 KiB
120// bound before scanning or allocation. Callers apply it to an encoded
121// preamble before sending and to a received payload before decode; the
122// session contract applies the identical wire.PreambleLimit.
123func CheckPreambleSize(payload []byte) error {
124 if len(payload) > BrokerPreambleLimit {
125 return ErrPreambleRejected
126 }
127 return nil
128}