@libp2p/yamux 7.0.4

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.
Files changed (49) hide show
  1. package/README.md +127 -0
  2. package/dist/index.min.js +4 -0
  3. package/dist/index.min.js.map +7 -0
  4. package/dist/src/config.d.ts +26 -0
  5. package/dist/src/config.d.ts.map +1 -0
  6. package/dist/src/config.js +37 -0
  7. package/dist/src/config.js.map +1 -0
  8. package/dist/src/constants.d.ts +12 -0
  9. package/dist/src/constants.d.ts.map +1 -0
  10. package/dist/src/constants.js +22 -0
  11. package/dist/src/constants.js.map +1 -0
  12. package/dist/src/decode.d.ts +34 -0
  13. package/dist/src/decode.d.ts.map +1 -0
  14. package/dist/src/decode.js +75 -0
  15. package/dist/src/decode.js.map +1 -0
  16. package/dist/src/encode.d.ts +3 -0
  17. package/dist/src/encode.d.ts.map +1 -0
  18. package/dist/src/encode.js +19 -0
  19. package/dist/src/encode.js.map +1 -0
  20. package/dist/src/errors.d.ts +40 -0
  21. package/dist/src/errors.d.ts.map +1 -0
  22. package/dist/src/errors.js +70 -0
  23. package/dist/src/errors.js.map +1 -0
  24. package/dist/src/frame.d.ts +54 -0
  25. package/dist/src/frame.d.ts.map +1 -0
  26. package/dist/src/frame.js +36 -0
  27. package/dist/src/frame.js.map +1 -0
  28. package/dist/src/index.d.ts +85 -0
  29. package/dist/src/index.d.ts.map +1 -0
  30. package/dist/src/index.js +84 -0
  31. package/dist/src/index.js.map +1 -0
  32. package/dist/src/muxer.d.ts +91 -0
  33. package/dist/src/muxer.d.ts.map +1 -0
  34. package/dist/src/muxer.js +428 -0
  35. package/dist/src/muxer.js.map +1 -0
  36. package/dist/src/stream.d.ts +96 -0
  37. package/dist/src/stream.d.ts.map +1 -0
  38. package/dist/src/stream.js +240 -0
  39. package/dist/src/stream.js.map +1 -0
  40. package/package.json +188 -0
  41. package/src/config.ts +66 -0
  42. package/src/constants.ts +25 -0
  43. package/src/decode.ts +104 -0
  44. package/src/encode.ts +26 -0
  45. package/src/errors.ts +89 -0
  46. package/src/frame.ts +64 -0
  47. package/src/index.ts +90 -0
  48. package/src/muxer.ts +506 -0
  49. package/src/stream.ts +293 -0
@@ -0,0 +1,12 @@
1
+ export declare const PROTOCOL_ERRORS: Set<string>;
2
+ /**
3
+ * INITIAL_STREAM_WINDOW is the initial stream window size.
4
+ *
5
+ * Not an implementation choice, this is defined in the specification
6
+ */
7
+ export declare const INITIAL_STREAM_WINDOW: number;
8
+ /**
9
+ * Default max stream window
10
+ */
11
+ export declare const MAX_STREAM_WINDOW: number;
12
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,aAQ1B,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAAa,CAAA;AAE/C;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAmB,CAAA"}
@@ -0,0 +1,22 @@
1
+ // Protocol violation errors
2
+ import { BothClientsError, DecodeInvalidVersionError, InvalidFrameError, NotMatchingPingError, ReceiveWindowExceededError, StreamAlreadyExistsError, UnRequestedPingError } from './errors.js';
3
+ export const PROTOCOL_ERRORS = new Set([
4
+ InvalidFrameError.name,
5
+ UnRequestedPingError.name,
6
+ NotMatchingPingError.name,
7
+ StreamAlreadyExistsError.name,
8
+ DecodeInvalidVersionError.name,
9
+ BothClientsError.name,
10
+ ReceiveWindowExceededError.name
11
+ ]);
12
+ /**
13
+ * INITIAL_STREAM_WINDOW is the initial stream window size.
14
+ *
15
+ * Not an implementation choice, this is defined in the specification
16
+ */
17
+ export const INITIAL_STREAM_WINDOW = 256 * 1024;
18
+ /**
19
+ * Default max stream window
20
+ */
21
+ export const MAX_STREAM_WINDOW = 16 * 1024 * 1024;
22
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAE9L,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IACrC,iBAAiB,CAAC,IAAI;IACtB,oBAAoB,CAAC,IAAI;IACzB,oBAAoB,CAAC,IAAI;IACzB,wBAAwB,CAAC,IAAI;IAC7B,yBAAyB,CAAC,IAAI;IAC9B,gBAAgB,CAAC,IAAI;IACrB,0BAA0B,CAAC,IAAI;CAChC,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,GAAG,IAAI,CAAA;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { Uint8ArrayList } from 'uint8arraylist';
2
+ import type { FrameHeader } from './frame.js';
3
+ export interface Frame {
4
+ header: FrameHeader;
5
+ data?: Uint8ArrayList;
6
+ }
7
+ export interface DataFrame {
8
+ header: FrameHeader;
9
+ data: Uint8ArrayList;
10
+ }
11
+ export declare function isDataFrame(frame: Frame): frame is DataFrame;
12
+ /**
13
+ * Decode a header from the front of a buffer
14
+ *
15
+ * @param data - Assumed to have enough bytes for a header
16
+ */
17
+ export declare function decodeHeader(data: Uint8Array): FrameHeader;
18
+ /**
19
+ * Decodes yamux frames from a source
20
+ */
21
+ export declare class Decoder {
22
+ /** Buffer for in-progress frames */
23
+ private readonly buffer;
24
+ constructor();
25
+ /**
26
+ * Emits frames from the decoder source.
27
+ *
28
+ * Note: If `readData` is emitted, it _must_ be called before the next iteration
29
+ * Otherwise an error is thrown
30
+ */
31
+ emitFrames(buf: Uint8Array | Uint8ArrayList): Generator<Frame>;
32
+ private readFrame;
33
+ }
34
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../src/decode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,WAAW,CAAA;IACnB,IAAI,CAAC,EAAE,cAAc,CAAA;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,WAAW,CAAA;IACnB,IAAI,EAAE,cAAc,CAAA;CACrB;AAED,wBAAgB,WAAW,CAAE,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,SAAS,CAE7D;AAOD;;;;GAIG;AACH,wBAAgB,YAAY,CAAE,IAAI,EAAE,UAAU,GAAG,WAAW,CAW3D;AAED;;GAEG;AACH,qBAAa,OAAO;IAClB,oCAAoC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;;IAMvC;;;;;OAKG;IACD,UAAU,CAAE,GAAG,EAAE,UAAU,GAAG,cAAc,GAAG,SAAS,CAAC,KAAK,CAAC;IAgBjE,OAAO,CAAC,SAAS;CA4BlB"}
@@ -0,0 +1,75 @@
1
+ import { Uint8ArrayList } from 'uint8arraylist';
2
+ import { InvalidFrameError } from './errors.js';
3
+ import { FrameType, HEADER_LENGTH, YAMUX_VERSION } from './frame.js';
4
+ export function isDataFrame(frame) {
5
+ return frame.header.type === FrameType.Data && frame.data !== null;
6
+ }
7
+ // used to bit shift in decoding
8
+ // native bit shift can overflow into a negative number, so we bit shift by
9
+ // multiplying by a power of 2
10
+ const twoPow24 = 2 ** 24;
11
+ /**
12
+ * Decode a header from the front of a buffer
13
+ *
14
+ * @param data - Assumed to have enough bytes for a header
15
+ */
16
+ export function decodeHeader(data) {
17
+ if (data[0] !== YAMUX_VERSION) {
18
+ throw new InvalidFrameError('Invalid frame version');
19
+ }
20
+ return {
21
+ type: data[1],
22
+ flag: (data[2] << 8) + data[3],
23
+ streamID: (data[4] * twoPow24) + (data[5] << 16) + (data[6] << 8) + data[7],
24
+ length: (data[8] * twoPow24) + (data[9] << 16) + (data[10] << 8) + data[11]
25
+ };
26
+ }
27
+ /**
28
+ * Decodes yamux frames from a source
29
+ */
30
+ export class Decoder {
31
+ /** Buffer for in-progress frames */
32
+ buffer;
33
+ constructor() {
34
+ this.buffer = new Uint8ArrayList();
35
+ }
36
+ /**
37
+ * Emits frames from the decoder source.
38
+ *
39
+ * Note: If `readData` is emitted, it _must_ be called before the next iteration
40
+ * Otherwise an error is thrown
41
+ */
42
+ *emitFrames(buf) {
43
+ this.buffer.append(buf);
44
+ // Loop to consume as many bytes from the buffer as possible
45
+ // Eg: when a single chunk contains several frames
46
+ while (true) {
47
+ const frame = this.readFrame();
48
+ if (frame === undefined) {
49
+ break;
50
+ }
51
+ yield frame;
52
+ }
53
+ }
54
+ readFrame() {
55
+ let frameSize = HEADER_LENGTH;
56
+ if (this.buffer.byteLength < HEADER_LENGTH) {
57
+ // not enough data yet
58
+ return;
59
+ }
60
+ const header = decodeHeader(this.buffer.subarray(0, HEADER_LENGTH));
61
+ if (header.type === FrameType.Data) {
62
+ frameSize += header.length;
63
+ if (this.buffer.byteLength < frameSize) {
64
+ // not enough data yet
65
+ return;
66
+ }
67
+ const data = this.buffer.sublist(HEADER_LENGTH, frameSize);
68
+ this.buffer.consume(frameSize);
69
+ return { header, data };
70
+ }
71
+ this.buffer.consume(frameSize);
72
+ return { header };
73
+ }
74
+ }
75
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../../src/decode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FrameHeader } from './frame.js';
2
+ export declare function encodeHeader(header: FrameHeader): Uint8Array;
3
+ //# sourceMappingURL=encode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../src/encode.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,YAAY,CAAE,MAAM,EAAE,WAAW,GAAG,UAAU,CAsB7D"}
@@ -0,0 +1,19 @@
1
+ import { HEADER_LENGTH } from './frame.js';
2
+ export function encodeHeader(header) {
3
+ const frame = new Uint8Array(HEADER_LENGTH);
4
+ // always assume version 0
5
+ // frameView.setUint8(0, header.version)
6
+ frame[1] = header.type;
7
+ frame[2] = header.flag >>> 8;
8
+ frame[3] = header.flag;
9
+ frame[4] = header.streamID >>> 24;
10
+ frame[5] = header.streamID >>> 16;
11
+ frame[6] = header.streamID >>> 8;
12
+ frame[7] = header.streamID;
13
+ frame[8] = header.length >>> 24;
14
+ frame[9] = header.length >>> 16;
15
+ frame[10] = header.length >>> 8;
16
+ frame[11] = header.length;
17
+ return frame;
18
+ }
19
+ //# sourceMappingURL=encode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.js","sourceRoot":"","sources":["../../src/encode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG1C,MAAM,UAAU,YAAY,CAAE,MAAmB;IAC/C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,aAAa,CAAC,CAAA;IAE3C,0BAA0B;IAC1B,wCAAwC;IAExC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAA;IAEtB,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,KAAK,CAAC,CAAA;IAC5B,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAA;IAEtB,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAA;IACjC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAA;IACjC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAA;IAChC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAA;IAE1B,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,EAAE,CAAA;IAC/B,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,EAAE,CAAA;IAC/B,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAA;IAC/B,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;IAEzB,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { GoAwayCode } from './frame.ts';
2
+ export declare class ProtocolError extends Error {
3
+ static name: string;
4
+ reason: GoAwayCode;
5
+ constructor(message: string, reason: GoAwayCode);
6
+ }
7
+ export declare function isProtocolError(err?: any): err is ProtocolError;
8
+ export declare class InvalidFrameError extends ProtocolError {
9
+ static name: string;
10
+ constructor(message?: string);
11
+ }
12
+ export declare class UnRequestedPingError extends ProtocolError {
13
+ static name: string;
14
+ constructor(message?: string);
15
+ }
16
+ export declare class NotMatchingPingError extends ProtocolError {
17
+ static name: string;
18
+ constructor(message?: string);
19
+ }
20
+ export declare class InvalidStateError extends Error {
21
+ static name: string;
22
+ constructor(message?: string);
23
+ }
24
+ export declare class StreamAlreadyExistsError extends ProtocolError {
25
+ static name: string;
26
+ constructor(message?: string);
27
+ }
28
+ export declare class DecodeInvalidVersionError extends ProtocolError {
29
+ static name: string;
30
+ constructor(message?: string);
31
+ }
32
+ export declare class BothClientsError extends ProtocolError {
33
+ static name: string;
34
+ constructor(message?: string);
35
+ }
36
+ export declare class ReceiveWindowExceededError extends ProtocolError {
37
+ static name: string;
38
+ constructor(message?: string);
39
+ }
40
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,qBAAa,aAAc,SAAQ,KAAK;IACtC,MAAM,CAAC,IAAI,SAAkB;IAEtB,MAAM,EAAE,UAAU,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;CAKjD;AAED,wBAAgB,eAAe,CAAE,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,IAAI,aAAa,CAEhE;AAED,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,MAAM,CAAC,IAAI,SAAsB;gBAEpB,OAAO,SAA0B;CAI/C;AAED,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,MAAM,CAAC,IAAI,SAAyB;gBAEvB,OAAO,SAA4B;CAIjD;AAED,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,MAAM,CAAC,IAAI,SAAyB;gBAEvB,OAAO,SAA4B;CAIjD;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,MAAM,CAAC,IAAI,SAAsB;gBAEpB,OAAO,SAAkB;CAIvC;AAED,qBAAa,wBAAyB,SAAQ,aAAa;IACzD,MAAM,CAAC,IAAI,SAA6B;gBAE3B,OAAO,SAA0B;CAI/C;AAED,qBAAa,yBAA0B,SAAQ,aAAa;IAC1D,MAAM,CAAC,IAAI,SAA8B;gBAE5B,OAAO,SAA2B;CAIhD;AAED,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,MAAM,CAAC,IAAI,SAAqB;gBAEnB,OAAO,SAAiB;CAItC;AAED,qBAAa,0BAA2B,SAAQ,aAAa;IAC3D,MAAM,CAAC,IAAI,SAA+B;gBAE7B,OAAO,SAA4B;CAIjD"}
@@ -0,0 +1,70 @@
1
+ import { GoAwayCode } from "./frame.js";
2
+ export class ProtocolError extends Error {
3
+ static name = 'ProtocolError';
4
+ reason;
5
+ constructor(message, reason) {
6
+ super(message);
7
+ this.name = 'ProtocolError';
8
+ this.reason = reason;
9
+ }
10
+ }
11
+ export function isProtocolError(err) {
12
+ return err?.reason !== null;
13
+ }
14
+ export class InvalidFrameError extends ProtocolError {
15
+ static name = 'InvalidFrameError';
16
+ constructor(message = 'The frame was invalid') {
17
+ super(message, GoAwayCode.ProtocolError);
18
+ this.name = 'InvalidFrameError';
19
+ }
20
+ }
21
+ export class UnRequestedPingError extends ProtocolError {
22
+ static name = 'UnRequestedPingError';
23
+ constructor(message = 'Un-requested ping error') {
24
+ super(message, GoAwayCode.ProtocolError);
25
+ this.name = 'UnRequestedPingError';
26
+ }
27
+ }
28
+ export class NotMatchingPingError extends ProtocolError {
29
+ static name = 'NotMatchingPingError';
30
+ constructor(message = 'Not matching ping error') {
31
+ super(message, GoAwayCode.ProtocolError);
32
+ this.name = 'NotMatchingPingError';
33
+ }
34
+ }
35
+ export class InvalidStateError extends Error {
36
+ static name = 'InvalidStateError';
37
+ constructor(message = 'Invalid state') {
38
+ super(message);
39
+ this.name = 'InvalidStateError';
40
+ }
41
+ }
42
+ export class StreamAlreadyExistsError extends ProtocolError {
43
+ static name = 'StreamAlreadyExistsError';
44
+ constructor(message = 'Stream already exists') {
45
+ super(message, GoAwayCode.ProtocolError);
46
+ this.name = 'StreamAlreadyExistsError';
47
+ }
48
+ }
49
+ export class DecodeInvalidVersionError extends ProtocolError {
50
+ static name = 'DecodeInvalidVersionError';
51
+ constructor(message = 'Decode invalid version') {
52
+ super(message, GoAwayCode.ProtocolError);
53
+ this.name = 'DecodeInvalidVersionError';
54
+ }
55
+ }
56
+ export class BothClientsError extends ProtocolError {
57
+ static name = 'BothClientsError';
58
+ constructor(message = 'Both clients') {
59
+ super(message, GoAwayCode.ProtocolError);
60
+ this.name = 'BothClientsError';
61
+ }
62
+ }
63
+ export class ReceiveWindowExceededError extends ProtocolError {
64
+ static name = 'ReceiveWindowExceededError';
65
+ constructor(message = 'Receive window exceeded') {
66
+ super(message, GoAwayCode.ProtocolError);
67
+ this.name = 'ReceiveWindowExceededError';
68
+ }
69
+ }
70
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,MAAM,CAAC,IAAI,GAAG,eAAe,CAAA;IAEtB,MAAM,CAAY;IAEzB,YAAa,OAAe,EAAE,MAAkB;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;;AAGH,MAAM,UAAU,eAAe,CAAE,GAAS;IACxC,OAAO,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;AAC7B,CAAC;AAED,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,MAAM,CAAC,IAAI,GAAG,mBAAmB,CAAA;IAEjC,YAAa,OAAO,GAAG,uBAAuB;QAC5C,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;;AAGH,MAAM,OAAO,oBAAqB,SAAQ,aAAa;IACrD,MAAM,CAAC,IAAI,GAAG,sBAAsB,CAAA;IAEpC,YAAa,OAAO,GAAG,yBAAyB;QAC9C,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;;AAGH,MAAM,OAAO,oBAAqB,SAAQ,aAAa;IACrD,MAAM,CAAC,IAAI,GAAG,sBAAsB,CAAA;IAEpC,YAAa,OAAO,GAAG,yBAAyB;QAC9C,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;;AAGH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,MAAM,CAAC,IAAI,GAAG,mBAAmB,CAAA;IAEjC,YAAa,OAAO,GAAG,eAAe;QACpC,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;;AAGH,MAAM,OAAO,wBAAyB,SAAQ,aAAa;IACzD,MAAM,CAAC,IAAI,GAAG,0BAA0B,CAAA;IAExC,YAAa,OAAO,GAAG,uBAAuB;QAC5C,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAA;IACxC,CAAC;;AAGH,MAAM,OAAO,yBAA0B,SAAQ,aAAa;IAC1D,MAAM,CAAC,IAAI,GAAG,2BAA2B,CAAA;IAEzC,YAAa,OAAO,GAAG,wBAAwB;QAC7C,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACzC,CAAC;;AAGH,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IACjD,MAAM,CAAC,IAAI,GAAG,kBAAkB,CAAA;IAEhC,YAAa,OAAO,GAAG,cAAc;QACnC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;IAChC,CAAC;;AAGH,MAAM,OAAO,0BAA2B,SAAQ,aAAa;IAC3D,MAAM,CAAC,IAAI,GAAG,4BAA4B,CAAA;IAE1C,YAAa,OAAO,GAAG,yBAAyB;QAC9C,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAA;IAC1C,CAAC"}
@@ -0,0 +1,54 @@
1
+ export declare enum FrameType {
2
+ /** Used to transmit data. May transmit zero length payloads depending on the flags. */
3
+ Data = 0,
4
+ /** Used to updated the senders receive window size. This is used to implement per-session flow control. */
5
+ WindowUpdate = 1,
6
+ /** Used to measure RTT. It can also be used to heart-beat and do keep-alive over TCP. */
7
+ Ping = 2,
8
+ /** Used to close a session. */
9
+ GoAway = 3
10
+ }
11
+ export declare enum Flag {
12
+ /** Signals the start of a new stream. May be sent with a data or window update message. Also sent with a ping to indicate outbound. */
13
+ SYN = 1,
14
+ /** Acknowledges the start of a new stream. May be sent with a data or window update message. Also sent with a ping to indicate response. */
15
+ ACK = 2,
16
+ /** Performs a half-close of a stream. May be sent with a data message or window update. */
17
+ FIN = 4,
18
+ /** Reset a stream immediately. May be sent with a data or window update message. */
19
+ RST = 8
20
+ }
21
+ export declare const YAMUX_VERSION = 0;
22
+ export declare enum GoAwayCode {
23
+ NormalTermination = 0,
24
+ ProtocolError = 1,
25
+ InternalError = 2
26
+ }
27
+ export declare const HEADER_LENGTH = 12;
28
+ export interface FrameHeader {
29
+ /**
30
+ * The version field is used for future backward compatibility.
31
+ * At the current time, the field is always set to 0, to indicate the initial version.
32
+ */
33
+ version?: number;
34
+ /** The type field is used to switch the frame message type. */
35
+ type: FrameType;
36
+ /** The flags field is used to provide additional information related to the message type. */
37
+ flag: number;
38
+ /**
39
+ * The StreamID field is used to identify the logical stream the frame is addressing.
40
+ * The client side should use odd ID's, and the server even.
41
+ * This prevents any collisions. Additionally, the 0 ID is reserved to represent the session.
42
+ */
43
+ streamID: number;
44
+ /**
45
+ * The meaning of the length field depends on the message type:
46
+ * Data - provides the length of bytes following the header
47
+ * Window update - provides a delta update to the window size
48
+ * Ping - Contains an opaque value, echoed back
49
+ * Go Away - Contains an error code
50
+ */
51
+ length: number;
52
+ }
53
+ export declare function stringifyHeader(header: FrameHeader): string;
54
+ //# sourceMappingURL=frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/frame.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,uFAAuF;IACvF,IAAI,IAAM;IACV,2GAA2G;IAC3G,YAAY,IAAM;IAClB,yFAAyF;IACzF,IAAI,IAAM;IACV,+BAA+B;IAC/B,MAAM,IAAM;CACb;AAED,oBAAY,IAAI;IACd,uIAAuI;IACvI,GAAG,IAAM;IACT,4IAA4I;IAC5I,GAAG,IAAM;IACT,2FAA2F;IAC3F,GAAG,IAAM;IACT,oFAAoF;IACpF,GAAG,IAAM;CACV;AAID,eAAO,MAAM,aAAa,IAAI,CAAA;AAE9B,oBAAY,UAAU;IACpB,iBAAiB,IAAM;IACvB,aAAa,IAAM;IACnB,aAAa,IAAM;CACpB;AAED,eAAO,MAAM,aAAa,KAAK,CAAA;AAE/B,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,IAAI,EAAE,SAAS,CAAA;IACf,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,eAAe,CAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAG5D"}
@@ -0,0 +1,36 @@
1
+ export var FrameType;
2
+ (function (FrameType) {
3
+ /** Used to transmit data. May transmit zero length payloads depending on the flags. */
4
+ FrameType[FrameType["Data"] = 0] = "Data";
5
+ /** Used to updated the senders receive window size. This is used to implement per-session flow control. */
6
+ FrameType[FrameType["WindowUpdate"] = 1] = "WindowUpdate";
7
+ /** Used to measure RTT. It can also be used to heart-beat and do keep-alive over TCP. */
8
+ FrameType[FrameType["Ping"] = 2] = "Ping";
9
+ /** Used to close a session. */
10
+ FrameType[FrameType["GoAway"] = 3] = "GoAway";
11
+ })(FrameType || (FrameType = {}));
12
+ export var Flag;
13
+ (function (Flag) {
14
+ /** Signals the start of a new stream. May be sent with a data or window update message. Also sent with a ping to indicate outbound. */
15
+ Flag[Flag["SYN"] = 1] = "SYN";
16
+ /** Acknowledges the start of a new stream. May be sent with a data or window update message. Also sent with a ping to indicate response. */
17
+ Flag[Flag["ACK"] = 2] = "ACK";
18
+ /** Performs a half-close of a stream. May be sent with a data message or window update. */
19
+ Flag[Flag["FIN"] = 4] = "FIN";
20
+ /** Reset a stream immediately. May be sent with a data or window update message. */
21
+ Flag[Flag["RST"] = 8] = "RST";
22
+ })(Flag || (Flag = {}));
23
+ const flagCodes = Object.values(Flag).filter((x) => typeof x !== 'string');
24
+ export const YAMUX_VERSION = 0;
25
+ export var GoAwayCode;
26
+ (function (GoAwayCode) {
27
+ GoAwayCode[GoAwayCode["NormalTermination"] = 0] = "NormalTermination";
28
+ GoAwayCode[GoAwayCode["ProtocolError"] = 1] = "ProtocolError";
29
+ GoAwayCode[GoAwayCode["InternalError"] = 2] = "InternalError";
30
+ })(GoAwayCode || (GoAwayCode = {}));
31
+ export const HEADER_LENGTH = 12;
32
+ export function stringifyHeader(header) {
33
+ const flags = flagCodes.filter(f => (header.flag & f) === f).map(f => Flag[f]).join('|');
34
+ return `streamID=${header.streamID} type=${FrameType[header.type]} flag=${flags} length=${header.length}`;
35
+ }
36
+ //# sourceMappingURL=frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/frame.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,SASX;AATD,WAAY,SAAS;IACnB,uFAAuF;IACvF,yCAAU,CAAA;IACV,2GAA2G;IAC3G,yDAAkB,CAAA;IAClB,yFAAyF;IACzF,yCAAU,CAAA;IACV,+BAA+B;IAC/B,6CAAY,CAAA;AACd,CAAC,EATW,SAAS,KAAT,SAAS,QASpB;AAED,MAAM,CAAN,IAAY,IASX;AATD,WAAY,IAAI;IACd,uIAAuI;IACvI,6BAAS,CAAA;IACT,4IAA4I;IAC5I,6BAAS,CAAA;IACT,2FAA2F;IAC3F,6BAAS,CAAA;IACT,oFAAoF;IACpF,6BAAS,CAAA;AACX,CAAC,EATW,IAAI,KAAJ,IAAI,QASf;AAED,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAW,CAAA;AAEpF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAA;AAE9B,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,qEAAuB,CAAA;IACvB,6DAAmB,CAAA;IACnB,6DAAmB,CAAA;AACrB,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAA;AA4B/B,MAAM,UAAU,eAAe,CAAE,MAAmB;IAClD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxF,OAAO,YAAY,MAAM,CAAC,QAAQ,SAAS,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,WAAW,MAAM,CAAC,MAAM,EAAE,CAAA;AAC3G,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * This module is a JavaScript implementation of [Yamux from Hashicorp](https://github.com/hashicorp/yamux/blob/master/spec.md) designed to be used with [js-libp2p](https://github.com/libp2p/js-libp2p).
5
+ *
6
+ * @example Configure libp2p with Yamux
7
+ *
8
+ * ```typescript
9
+ * import { createLibp2p } from 'libp2p'
10
+ * import { yamux } from '@libp2p/yamux'
11
+ *
12
+ * const node = await createLibp2p({
13
+ * // ... other options
14
+ * streamMuxers: [
15
+ * yamux()
16
+ * ]
17
+ * })
18
+ * ```
19
+ *
20
+ * @example Using the low-level API
21
+ *
22
+ * ```js
23
+ * import { yamux } from '@libp2p/yamux'
24
+ * import { pipe } from 'it-pipe'
25
+ * import { duplexPair } from 'it-pair/duplex'
26
+ * import all from 'it-all'
27
+ *
28
+ * // Connect two yamux muxers to demo basic stream multiplexing functionality
29
+ *
30
+ * const clientMuxer = yamux({
31
+ * client: true,
32
+ * onIncomingStream: stream => {
33
+ * // echo data on incoming streams
34
+ * pipe(stream, stream)
35
+ * },
36
+ * onStreamEnd: stream => {
37
+ * // do nothing
38
+ * }
39
+ * })()
40
+ *
41
+ * const serverMuxer = yamux({
42
+ * client: false,
43
+ * onIncomingStream: stream => {
44
+ * // echo data on incoming streams
45
+ * pipe(stream, stream)
46
+ * },
47
+ * onStreamEnd: stream => {
48
+ * // do nothing
49
+ * }
50
+ * })()
51
+ *
52
+ * // `p` is our "connections", what we use to connect the two sides
53
+ * // In a real application, a connection is usually to a remote computer
54
+ * const p = duplexPair()
55
+ *
56
+ * // connect the muxers together
57
+ * pipe(p[0], clientMuxer, p[0])
58
+ * pipe(p[1], serverMuxer, p[1])
59
+ *
60
+ * // now either side can open streams
61
+ * const stream0 = clientMuxer.newStream()
62
+ * const stream1 = serverMuxer.newStream()
63
+ *
64
+ * // Send some data to the other side
65
+ * const encoder = new TextEncoder()
66
+ * const data = [encoder.encode('hello'), encoder.encode('world')]
67
+ * pipe(data, stream0)
68
+ *
69
+ * // Receive data back
70
+ * const result = await pipe(stream0, all)
71
+ *
72
+ * // close a stream
73
+ * stream1.close()
74
+ *
75
+ * // close the muxer
76
+ * clientMuxer.close()
77
+ * ```
78
+ */
79
+ import type { YamuxMuxer, YamuxMuxerInit } from './muxer.js';
80
+ import type { StreamMuxerFactory } from '@libp2p/interface';
81
+ export { GoAwayCode } from './frame.js';
82
+ export type { FrameHeader, FrameType } from './frame.js';
83
+ export type { YamuxMuxerInit };
84
+ export declare function yamux(init?: YamuxMuxerInit): () => StreamMuxerFactory<YamuxMuxer>;
85
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACxD,YAAY,EAAE,cAAc,EAAE,CAAA;AAE9B,wBAAgB,KAAK,CAAE,IAAI,GAAE,cAAmB,GAAG,MAAM,kBAAkB,CAAC,UAAU,CAAC,CAEtF"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * This module is a JavaScript implementation of [Yamux from Hashicorp](https://github.com/hashicorp/yamux/blob/master/spec.md) designed to be used with [js-libp2p](https://github.com/libp2p/js-libp2p).
5
+ *
6
+ * @example Configure libp2p with Yamux
7
+ *
8
+ * ```typescript
9
+ * import { createLibp2p } from 'libp2p'
10
+ * import { yamux } from '@libp2p/yamux'
11
+ *
12
+ * const node = await createLibp2p({
13
+ * // ... other options
14
+ * streamMuxers: [
15
+ * yamux()
16
+ * ]
17
+ * })
18
+ * ```
19
+ *
20
+ * @example Using the low-level API
21
+ *
22
+ * ```js
23
+ * import { yamux } from '@libp2p/yamux'
24
+ * import { pipe } from 'it-pipe'
25
+ * import { duplexPair } from 'it-pair/duplex'
26
+ * import all from 'it-all'
27
+ *
28
+ * // Connect two yamux muxers to demo basic stream multiplexing functionality
29
+ *
30
+ * const clientMuxer = yamux({
31
+ * client: true,
32
+ * onIncomingStream: stream => {
33
+ * // echo data on incoming streams
34
+ * pipe(stream, stream)
35
+ * },
36
+ * onStreamEnd: stream => {
37
+ * // do nothing
38
+ * }
39
+ * })()
40
+ *
41
+ * const serverMuxer = yamux({
42
+ * client: false,
43
+ * onIncomingStream: stream => {
44
+ * // echo data on incoming streams
45
+ * pipe(stream, stream)
46
+ * },
47
+ * onStreamEnd: stream => {
48
+ * // do nothing
49
+ * }
50
+ * })()
51
+ *
52
+ * // `p` is our "connections", what we use to connect the two sides
53
+ * // In a real application, a connection is usually to a remote computer
54
+ * const p = duplexPair()
55
+ *
56
+ * // connect the muxers together
57
+ * pipe(p[0], clientMuxer, p[0])
58
+ * pipe(p[1], serverMuxer, p[1])
59
+ *
60
+ * // now either side can open streams
61
+ * const stream0 = clientMuxer.newStream()
62
+ * const stream1 = serverMuxer.newStream()
63
+ *
64
+ * // Send some data to the other side
65
+ * const encoder = new TextEncoder()
66
+ * const data = [encoder.encode('hello'), encoder.encode('world')]
67
+ * pipe(data, stream0)
68
+ *
69
+ * // Receive data back
70
+ * const result = await pipe(stream0, all)
71
+ *
72
+ * // close a stream
73
+ * stream1.close()
74
+ *
75
+ * // close the muxer
76
+ * clientMuxer.close()
77
+ * ```
78
+ */
79
+ import { Yamux } from './muxer.js';
80
+ export { GoAwayCode } from './frame.js';
81
+ export function yamux(init = {}) {
82
+ return () => new Yamux(init);
83
+ }
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAIlC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAIvC,MAAM,UAAU,KAAK,CAAE,OAAuB,EAAE;IAC9C,OAAO,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAA;AAC9B,CAAC"}