Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 1x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 9x 9x 9x 9x 18x 9x 9x 9x 9x 9x 54x 18x 36x 18x 18x 54x 9x 9x | /** * @argument encodedMessage a complete message from the lower transport layer */ export type P2PDataHandler = (encodedMessage: Uint8Array) => void export type P2PErrorHandler = (error: any) => void export type P2PHandler = () => void export type P2PEventMap = { data: P2PDataHandler error: P2PErrorHandler close: P2PHandler } /** * Provider interface for P2P protocol responsible for re-assembling full message payloads before * delivering them upstream via event emission */ export interface P2PProvider { write(encodedMessage: Uint8Array, done?: P2PHandler): void end(cb?: P2PHandler): void destroy(err?: Error): void on<T extends keyof P2PEventMap>(event: T, handler: P2PEventMap[T]): this //removeListener<T extends keyof P2PEventMap>(event: T, handler: P2PEventMap[T]): this } export class SimpleEnvelopeP2PProvider { static maxReadLength = 8 * 1024 * 1024 private declare nextProvider: P2PProvider private declare dataHandlers: Array<P2PDataHandler> private declare errorHandlers: Array<P2PErrorHandler> private declare remainingData: Uint8Array constructor(nextProvider: P2PProvider) { this.nextProvider = nextProvider this.remainingData = new Uint8Array(0) this.dataHandlers = [] this.errorHandlers = [] // process nextProvider data this.nextProvider.on('data', (data: Uint8Array) => { const newData = new Uint8Array(this.remainingData.byteLength + data.byteLength) newData.set(this.remainingData, 0) newData.set(data, this.remainingData.byteLength) this.remainingData = newData while (this.remainingData.byteLength >= 4) { const view = new DataView(this.remainingData.buffer) const messageLength = view.getUint32(0, true) Iif (messageLength > SimpleEnvelopeP2PProvider.maxReadLength) { this.emitError(new Error('Incoming Message too long')) } if (this.remainingData.byteLength < 4 + messageLength) { // need more data break } const messageBuffer = this.remainingData.subarray(4, 4 + messageLength) this.remainingData = this.remainingData.slice(4 + messageLength) this.emitData(messageBuffer) } }) // proxy error this.nextProvider.on('error', (err: any) => { this.emitError(err) }) } write(data: Uint8Array, done?: P2PHandler): void { const nextBuffer = new Uint8Array(4 + data.byteLength) const view = new DataView(nextBuffer.buffer) view.setUint32(0, data.byteLength, true) nextBuffer.set(data, 4) this.nextProvider.write(nextBuffer, done) } end(cb?: P2PHandler): void { this.nextProvider.end(cb) } destroy(err?: Error): void { this.nextProvider.destroy(err) } on<T extends keyof P2PEventMap>(event: T, handler: P2PEventMap[T]): this { if (event === 'data') { this.dataHandlers.push(handler) } else if (event === 'error') { this.errorHandlers.push(handler) } else { this.nextProvider.on(event, handler) } return this } emitData(messageBuffer: Uint8Array): void { for (const handler of this.dataHandlers) { // typescript is loosing the specificity provided by T in the assignment above handler(messageBuffer) } } emitError(err: any): void { for (const handler of this.errorHandlers) { // typescript is loosing the specificity provided by T in the assignment above handler(err) } } } |