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 1x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 9x 9x 9x 9x 18x 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
declare private nextProvider: P2PProvider
declare private dataHandlers: Array<P2PDataHandler>
declare private errorHandlers: Array<P2PErrorHandler>
declare private 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)
}
}
}
|