@libp2p/yamux 7.0.4 → 8.0.0-55b7e5fea

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/muxer.ts CHANGED
@@ -449,7 +449,8 @@ export class YamuxMuxer extends AbstractStreamMuxer<YamuxStream> {
449
449
  flag: Flag.RST,
450
450
  streamID: id,
451
451
  length: 0
452
- }); return
452
+ })
453
+ return
453
454
  }
454
455
 
455
456
  // allocate a new stream
@@ -465,7 +466,7 @@ export class YamuxMuxer extends AbstractStreamMuxer<YamuxStream> {
465
466
  let encoded: Uint8Array | Uint8ArrayList
466
467
 
467
468
  if (header.type === FrameType.Data) {
468
- if (data === undefined) {
469
+ if (data == null) {
469
470
  throw new InvalidFrameError('Invalid frame')
470
471
  }
471
472
 
package/src/stream.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { AbstractStream } from '@libp2p/utils'
2
2
  import { Uint8ArrayList } from 'uint8arraylist'
3
- import { defaultConfig } from './config.js'
4
- import { INITIAL_STREAM_WINDOW } from './constants.js'
3
+ import { INITIAL_STREAM_WINDOW, MAX_STREAM_WINDOW } from './constants.js'
5
4
  import { isDataFrame } from './decode.ts'
6
5
  import { InvalidFrameError, ReceiveWindowExceededError } from './errors.js'
7
6
  import { Flag, FrameType, HEADER_LENGTH } from './frame.js'
@@ -53,17 +52,19 @@ export class YamuxStream extends AbstractStream {
53
52
  private readonly sendFrame: (header: FrameHeader, body?: Uint8ArrayList) => boolean
54
53
 
55
54
  constructor (init: YamuxStreamInit) {
55
+ const initialWindowSize = init.initialStreamWindowSize ?? INITIAL_STREAM_WINDOW
56
+
56
57
  super({
57
58
  ...init,
58
- maxMessageSize: (init.maxMessageSize ?? defaultConfig.maxMessageSize) - HEADER_LENGTH
59
+ maxMessageSize: initialWindowSize - HEADER_LENGTH
59
60
  })
60
61
 
61
62
  this.streamId = init.streamId
62
63
  this.state = init.state
63
- this.sendWindowCapacity = INITIAL_STREAM_WINDOW
64
- this.recvWindow = init.initialStreamWindowSize ?? defaultConfig.initialStreamWindowSize
64
+ this.sendWindowCapacity = initialWindowSize
65
+ this.recvWindow = initialWindowSize
65
66
  this.recvWindowCapacity = this.recvWindow
66
- this.maxStreamWindowSize = init.maxStreamWindowSize ?? defaultConfig.maxStreamWindowSize
67
+ this.maxStreamWindowSize = init.maxStreamWindowSize ?? MAX_STREAM_WINDOW
67
68
  this.epochStart = Date.now()
68
69
  this.getRTT = init.getRTT
69
70
  this.sendFrame = init.sendFrame
@@ -82,34 +83,37 @@ export class YamuxStream extends AbstractStream {
82
83
  let sentBytes = 0
83
84
  let canSendMore = true
84
85
 
86
+ this.log?.trace('send window capacity is %d bytes', this.sendWindowCapacity)
87
+
85
88
  // send in chunks, waiting for window updates
86
- while (buf.byteLength !== 0) {
89
+ while (buf.byteLength > 0) {
87
90
  // we exhausted the send window, sending will resume later
88
91
  if (this.sendWindowCapacity === 0) {
89
92
  canSendMore = false
90
- this.log?.trace('sent %d/%d bytes, wait for send window update, status %s', sentBytes, totalBytes, this.status)
93
+ this.log?.trace('sent %d/%d bytes, exhausted send window, waiting for window update', sentBytes, totalBytes)
91
94
  break
92
95
  }
93
96
 
94
97
  // send as much as we can
95
- const toSend = Math.min(this.sendWindowCapacity, buf.length)
98
+ const toSend = Math.min(this.sendWindowCapacity, buf.byteLength)
96
99
  const flags = this.getSendFlags()
97
100
 
101
+ const data = buf.sublist(0, toSend)
102
+ buf.consume(toSend)
103
+
98
104
  const muxerSendMore = this.sendFrame({
99
105
  type: FrameType.Data,
100
106
  flag: flags,
101
107
  streamID: this.streamId,
102
108
  length: toSend
103
- }, buf.sublist(0, toSend))
109
+ }, data)
104
110
 
105
111
  this.sendWindowCapacity -= toSend
106
-
107
112
  sentBytes += toSend
108
- buf.consume(toSend)
109
113
 
110
114
  if (!muxerSendMore) {
111
115
  canSendMore = muxerSendMore
112
- this.log('sent %d/%d bytes, wait for muxer to have more send capacity', sentBytes, totalBytes)
116
+ this.log.trace('sent %d/%d bytes, wait for muxer to have more send capacity', sentBytes, totalBytes)
113
117
  break
114
118
  }
115
119
  }
@@ -177,12 +181,23 @@ export class YamuxStream extends AbstractStream {
177
181
  this.processFlags(frame.header.flag)
178
182
 
179
183
  // increase send window
180
- const available = this.sendWindowCapacity
181
184
  this.sendWindowCapacity += frame.header.length
182
185
 
183
- // if the update increments a 0 availability, notify the stream that sending can resume
184
- if (available === 0 && frame.header.length > 0) {
185
- this.log?.trace('window update of %d bytes allows more data to be sent', frame.header.length)
186
+ // change the chunk size the superclass uses
187
+ this.maxMessageSize = this.sendWindowCapacity - HEADER_LENGTH
188
+
189
+ if (this.maxMessageSize < 0) {
190
+ this.maxMessageSize = 0
191
+ }
192
+
193
+ if (this.maxMessageSize === 0) {
194
+ return
195
+ }
196
+
197
+ // if writing is paused and the update increases our send window, notify
198
+ // writers that writing can resume
199
+ if (this.writeBuffer.byteLength > 0) {
200
+ this.log?.trace('window update of %d bytes allows more data to be sent, have %d bytes queued, sending data %s', frame.header.length, this.writeBuffer.byteLength, this.sendingData)
186
201
  this.safeDispatchEvent('drain')
187
202
  }
188
203
  }
@@ -252,6 +267,15 @@ export class YamuxStream extends AbstractStream {
252
267
  * place.
253
268
  */
254
269
  sendWindowUpdate (): void {
270
+ if (this.state === StreamState.Paused) {
271
+ // we don't want any more data from the remote right now - update the
272
+ // epoch start as otherwise when we unpause we'd be looking at the epoch
273
+ // start from before we were paused
274
+ this.epochStart = Date.now()
275
+
276
+ return
277
+ }
278
+
255
279
  // determine the flags if any
256
280
  const flags = this.getSendFlags()
257
281
 
@@ -260,7 +284,8 @@ export class YamuxStream extends AbstractStream {
260
284
  // then we (up to) double the recvWindow
261
285
  const now = Date.now()
262
286
  const rtt = this.getRTT()
263
- if (flags === 0 && rtt > -1 && now - this.epochStart < rtt * 4) {
287
+
288
+ if (flags === 0 && rtt > -1 && (now - this.epochStart) <= (rtt * 4)) {
264
289
  // we've already validated that maxStreamWindowSize can't be more than MAX_UINT32
265
290
  this.recvWindow = Math.min(this.recvWindow * 2, this.maxStreamWindowSize)
266
291
  }
@@ -270,11 +295,6 @@ export class YamuxStream extends AbstractStream {
270
295
  return
271
296
  }
272
297
 
273
- if (this.state === StreamState.Paused) {
274
- // we don't want any more data from the remote right now
275
- return
276
- }
277
-
278
298
  // update the receive window
279
299
  const delta = this.recvWindow - this.recvWindowCapacity
280
300
  this.recvWindowCapacity = this.recvWindow