@@ -6,6 +6,7 @@ import pDefer from 'p-defer'
6
6
import { pEvent , TimeoutError } from 'p-event'
7
7
import pTimeout from 'p-timeout'
8
8
import { raceSignal } from 'race-signal'
9
+ import { encodingLength } from 'uint8-varint'
9
10
import { Uint8ArrayList } from 'uint8arraylist'
10
11
import { Message } from './pb/message.js'
11
12
import type { DataChannelOptions } from './index.js'
@@ -35,22 +36,40 @@ export const MAX_BUFFERED_AMOUNT = 2 * 1024 * 1024
35
36
export const BUFFERED_AMOUNT_LOW_TIMEOUT = 30 * 1000
36
37
37
38
/**
38
- * protobuf field definition overhead + length encoding prefix length
39
+ * Max message size that can be sent to the DataChannel. In browsers this is
40
+ * 256KiB but go-libp2p and rust-libp2p only support 16KiB at the time of
41
+ * writing.
42
+ *
43
+ * @see https://blog.mozilla.org/webrtc/large-data-channel-messages/
44
+ * @see https://issues.webrtc.org/issues/40644524
39
45
*/
40
- export const PROTOBUF_OVERHEAD = 7
46
+ export const MAX_MESSAGE_SIZE = 16 * 1024
41
47
42
48
/**
43
- * Length of varint, in bytes
49
+ * max protobuf overhead:
50
+ *
51
+ * ```
52
+ * [message-length][flag-field-id+type][flag-field-length][flag-field][message-field-id+type][message-field-length][message-field]
53
+ * ```
44
54
*/
45
- export const VARINT_LENGTH = 2
55
+ function calculateProtobufOverhead ( maxMessageSize = MAX_MESSAGE_SIZE ) : number {
56
+ // these have a fixed size
57
+ const messageLength = encodingLength ( maxMessageSize - encodingLength ( maxMessageSize ) )
58
+ const flagField = 1 + encodingLength ( Object . keys ( Message . Flag ) . length - 1 ) // id+type/value
59
+ const messageFieldIdType = 1 // id+type
60
+ const available = maxMessageSize - messageLength - flagField - messageFieldIdType
61
+
62
+ // let message-length/message-data fill the rest of the message
63
+ const messageFieldLengthLength = encodingLength ( available )
64
+
65
+ return messageLength + flagField + messageFieldIdType + messageFieldLengthLength
66
+ }
46
67
47
68
/**
48
- * Max message size that can be sent to the DataChannel
49
- *
50
- * @see https://blog.mozilla.org/webrtc/large-data-channel-messages/
51
- * @see https://issues.webrtc.org/issues/40644524
69
+ * The protobuf message overhead includes the maximum amount of all bytes in the
70
+ * protobuf that aren't message field bytes
52
71
*/
53
- export const MAX_MESSAGE_SIZE = 256 * 1024
72
+ export const PROTOBUF_OVERHEAD = calculateProtobufOverhead ( )
54
73
55
74
/**
56
75
* When closing streams we send a FIN then wait for the remote to
@@ -132,7 +151,7 @@ export class WebRTCStream extends AbstractStream {
132
151
this . incomingData = pushable < Uint8Array > ( )
133
152
this . bufferedAmountLowEventTimeout = init . bufferedAmountLowEventTimeout ?? BUFFERED_AMOUNT_LOW_TIMEOUT
134
153
this . maxBufferedAmount = init . maxBufferedAmount ?? MAX_BUFFERED_AMOUNT
135
- this . maxMessageSize = ( init . maxMessageSize ?? MAX_MESSAGE_SIZE ) - PROTOBUF_OVERHEAD - VARINT_LENGTH
154
+ this . maxMessageSize = ( init . maxMessageSize ?? MAX_MESSAGE_SIZE ) - PROTOBUF_OVERHEAD
136
155
this . receiveFinAck = pDefer ( )
137
156
this . finAckTimeout = init . closeTimeout ?? FIN_ACK_TIMEOUT
138
157
this . openTimeout = init . openTimeout ?? OPEN_TIMEOUT
0 commit comments