mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-03-06 23:39:38 +01:00
feat(transport): unify protocol encode/decode functions
This commit is contained in:
@@ -2,3 +2,4 @@ export * as v1 from './protocol-v1';
|
||||
export * as bridge from './protocol-bridge';
|
||||
export * as trzd from './protocol-trzd';
|
||||
export * from './errors';
|
||||
export * from './types';
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
|
||||
import { TransportProtocolDecode } from '../types';
|
||||
|
||||
/**
|
||||
* Reads meta information from buffer
|
||||
*/
|
||||
@@ -10,11 +12,13 @@ const readHeader = (buffer: ByteBuffer) => {
|
||||
return { typeId, length };
|
||||
};
|
||||
|
||||
export const decode = (byteBuffer: ByteBuffer) => {
|
||||
const { typeId } = readHeader(byteBuffer);
|
||||
export const decode: TransportProtocolDecode = bytes => {
|
||||
const byteBuffer = ByteBuffer.wrap(bytes, undefined, undefined, true);
|
||||
const { typeId, length } = readHeader(byteBuffer);
|
||||
|
||||
return {
|
||||
typeId,
|
||||
length,
|
||||
buffer: byteBuffer,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
|
||||
import { HEADER_SIZE } from '../protocol-v1/constants';
|
||||
|
||||
type Options = {
|
||||
messageType: number;
|
||||
};
|
||||
import { TransportProtocolEncode } from '../types';
|
||||
|
||||
// this file is basically combination of "trezor v1 protocol" and "bridge protocol"
|
||||
// there is actually no officially described bridge protocol, but in fact there is one
|
||||
// it is because bridge does some parts of the protocol itself (like chunking)
|
||||
export const encode = (data: ByteBuffer, options: Options) => {
|
||||
export const encode: TransportProtocolEncode = (data, options) => {
|
||||
const { messageType } = options;
|
||||
const fullSize = HEADER_SIZE - 2 + data.limit;
|
||||
|
||||
@@ -28,5 +25,5 @@ export const encode = (data: ByteBuffer, options: Options) => {
|
||||
|
||||
// todo: it would be nicer to return Buffer instead of ByteBuffer. The problem is that ByteBuffer.Buffer.toString behaves differently in web and node.
|
||||
// anyway, for now we can keep this legacy behavior
|
||||
return encodedByteBuffer;
|
||||
return [encodedByteBuffer];
|
||||
};
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
|
||||
// Decode `trzd` protocol used for decoding of dynamically loaded `@trezor/protobuf` messages
|
||||
// https://github.com/trezor/trezor-firmware/blob/087becd2caa5618eecab37ac3f2ca51172e52eb9/docs/common/ethereum-definitions.md#definition-format
|
||||
|
||||
export const decode = (bytes: ArrayBuffer) => {
|
||||
const byteBuffer = ByteBuffer.wrap(bytes);
|
||||
byteBuffer.LE(true); // use little endian byte order
|
||||
// 5 bytes magic `trzd`
|
||||
const magic = byteBuffer.readBytes(5).toUTF8();
|
||||
// 1 byte
|
||||
const definitionType = byteBuffer.readUint8();
|
||||
// 4 bytes
|
||||
const dataVersion = byteBuffer.readUint32();
|
||||
const protobufLength = byteBuffer.readUint8();
|
||||
// 2 bytes
|
||||
const protobufLength = byteBuffer.readUint16();
|
||||
// N bytes
|
||||
const protobufPayload = byteBuffer.slice(12, 12 + protobufLength);
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,6 +2,7 @@ import ByteBuffer from 'bytebuffer';
|
||||
|
||||
import * as ERRORS from '../errors';
|
||||
import { MESSAGE_HEADER_BYTE, MESSAGE_MAGIC_HEADER_BYTE } from './constants';
|
||||
import { TransportProtocolDecode } from '../types';
|
||||
|
||||
/**
|
||||
* Reads meta information from chunked buffer
|
||||
@@ -18,7 +19,7 @@ const readHeaderChunked = (buffer: ByteBuffer) => {
|
||||
|
||||
// Parses first raw input that comes from Trezor and returns some information about the whole message.
|
||||
// [compatibility]: accept Buffer just like decode does. But this would require changes in lower levels
|
||||
export const decodeChunked = (bytes: ArrayBuffer) => {
|
||||
export const decode: TransportProtocolDecode = bytes => {
|
||||
// convert to ByteBuffer so it's easier to read
|
||||
const byteBuffer = ByteBuffer.wrap(bytes, undefined, undefined, true);
|
||||
|
||||
@@ -33,5 +34,5 @@ export const decodeChunked = (bytes: ArrayBuffer) => {
|
||||
throw new Error(ERRORS.PROTOCOL_MALFORMED);
|
||||
}
|
||||
|
||||
return { length, typeId, restBuffer: byteBuffer };
|
||||
return { length, typeId, buffer: byteBuffer };
|
||||
};
|
||||
|
||||
@@ -6,12 +6,9 @@ import {
|
||||
BUFFER_SIZE,
|
||||
MESSAGE_MAGIC_HEADER_BYTE,
|
||||
} from './constants';
|
||||
import { TransportProtocolEncode } from '../types';
|
||||
|
||||
type Options = {
|
||||
messageType: number;
|
||||
};
|
||||
|
||||
export const encode = (data: ByteBuffer, options: Options): Buffer[] => {
|
||||
export const encode: TransportProtocolEncode = (data, options) => {
|
||||
const { messageType } = options;
|
||||
const fullSize = HEADER_SIZE + data.limit;
|
||||
|
||||
@@ -38,7 +35,7 @@ export const encode = (data: ByteBuffer, options: Options): Buffer[] => {
|
||||
|
||||
// size with one reserved byte for header
|
||||
|
||||
const result = [];
|
||||
const result: ByteBuffer[] = [];
|
||||
// How many pieces will there actually be
|
||||
// slice and dice
|
||||
for (let i = 0; i < chunkCount; i++) {
|
||||
@@ -53,7 +50,7 @@ export const encode = (data: ByteBuffer, options: Options): Buffer[] => {
|
||||
slice.compact();
|
||||
|
||||
buffer.append(slice);
|
||||
result.push(buffer.buffer);
|
||||
result.push(buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
19
packages/protocol/src/types.ts
Normal file
19
packages/protocol/src/types.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export type TransportProtocolDecode = (bytes: ArrayBuffer) => {
|
||||
length: number;
|
||||
typeId: number;
|
||||
buffer: ByteBuffer;
|
||||
};
|
||||
|
||||
export interface TransportProtocolEncodeOptions {
|
||||
messageType: number;
|
||||
}
|
||||
|
||||
export type TransportProtocolEncode = (
|
||||
data: ByteBuffer,
|
||||
options: TransportProtocolEncodeOptions,
|
||||
) => ByteBuffer[];
|
||||
|
||||
export interface TransportProtocol {
|
||||
encode: TransportProtocolEncode;
|
||||
decode: TransportProtocolDecode;
|
||||
}
|
||||
@@ -7,13 +7,15 @@ describe('protocol-bridge', () => {
|
||||
let chunks;
|
||||
// encode small chunk, message without data
|
||||
chunks = bridge.encode(new ByteBuffer(0), { messageType: 55 });
|
||||
expect(chunks.limit).toEqual(6);
|
||||
expect(chunks.length).toEqual(1);
|
||||
expect(chunks[0].limit).toEqual(6);
|
||||
|
||||
// encode big chunk, message with data
|
||||
chunks = bridge.encode(new ByteBuffer(371), { messageType: 55 });
|
||||
expect(chunks.slice(0, 6).toString('hex')).toEqual('003700000173');
|
||||
expect(chunks.readUint32(2)).toEqual(371);
|
||||
expect(chunks.buffer.length).toEqual(371 + 6);
|
||||
expect(chunks.length).toEqual(1);
|
||||
expect(chunks[0].slice(0, 6).toString('hex')).toEqual('003700000173');
|
||||
expect(chunks[0].readUint32(2)).toEqual(371);
|
||||
expect(chunks[0].buffer.length).toEqual(371 + 6);
|
||||
});
|
||||
|
||||
it('decode', () => {
|
||||
@@ -22,7 +24,8 @@ describe('protocol-bridge', () => {
|
||||
data.fill(getFeatures, 0, 2);
|
||||
data.writeUint32BE(379, 2);
|
||||
|
||||
const read = bridge.decode(ByteBuffer.fromHex(data.toString('hex')));
|
||||
const read = bridge.decode(data);
|
||||
expect(read.typeId).toEqual(55);
|
||||
expect(read.length).toEqual(379);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,17 +8,17 @@ describe('protocol-v1', () => {
|
||||
// encode only one chunk, message without data
|
||||
chunks = v1.encode(new ByteBuffer(0), { messageType: 55 });
|
||||
expect(chunks.length).toEqual(1);
|
||||
expect(chunks[0].length).toEqual(64);
|
||||
expect(chunks[0].limit).toEqual(64);
|
||||
|
||||
// encode multiple chunks, message with data
|
||||
chunks = v1.encode(new ByteBuffer(371), { messageType: 55 });
|
||||
expect(chunks.length).toEqual(7);
|
||||
chunks.forEach((chunk, index) => {
|
||||
expect(chunk.length).toEqual(64);
|
||||
expect(chunk.limit).toEqual(64);
|
||||
if (index === 0) {
|
||||
// first chunk with additional data
|
||||
expect(chunk.slice(0, 9).toString('hex')).toEqual('3f2323003700000173');
|
||||
expect(chunk.readUInt32BE(5)).toEqual(371);
|
||||
expect(chunk.readUint32(5)).toEqual(371);
|
||||
} else {
|
||||
// following chunk starts with MESSAGE_MAGIC_HEADER_BYTE
|
||||
expect(chunk.slice(0, 5).toString('hex')).toEqual('3f00000000');
|
||||
@@ -32,7 +32,7 @@ describe('protocol-v1', () => {
|
||||
data.fill(getFeatures, 0, 5);
|
||||
data.writeUint32BE(379, 5);
|
||||
|
||||
const read = v1.decodeChunked(data);
|
||||
const read = v1.decode(data);
|
||||
expect(read.typeId).toEqual(55);
|
||||
expect(read.length).toEqual(379);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { createDeferred, Deferred } from '@trezor/utils';
|
||||
import { v1 as v1Protocol } from '@trezor/protocol';
|
||||
|
||||
import { AbstractTransport, AbstractTransportParams, AcquireInput, ReleaseInput } from './abstract';
|
||||
import { AbstractApi } from '../api/abstract';
|
||||
import { buildAndSend } from '../utils/send';
|
||||
import { buildBuffers } from '../utils/send';
|
||||
import { receiveAndParse } from '../utils/receive';
|
||||
import { SessionsClient } from '../sessions/client';
|
||||
import * as ERRORS from '../errors';
|
||||
@@ -192,26 +193,25 @@ export abstract class AbstractApiTransport extends AbstractTransport {
|
||||
const { path } = getPathBySessionResponse.payload;
|
||||
|
||||
try {
|
||||
await buildAndSend(
|
||||
this.messages,
|
||||
(buffer: Buffer) =>
|
||||
this.api.write(path, buffer).then(result => {
|
||||
if (!result.success) {
|
||||
// todo:
|
||||
throw new Error(result.error);
|
||||
}
|
||||
}),
|
||||
name,
|
||||
data,
|
||||
);
|
||||
|
||||
const message = await receiveAndParse(this.messages, () =>
|
||||
this.api.read(path).then(result => {
|
||||
if (result.success) {
|
||||
return result.payload;
|
||||
const buffers = buildBuffers(this.messages, name, data, v1Protocol.encode);
|
||||
for (const chunk of buffers) {
|
||||
this.api.write(path, chunk.buffer).then(result => {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
throw new Error(result.error);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const message = await receiveAndParse(
|
||||
this.messages,
|
||||
() =>
|
||||
this.api.read(path).then(result => {
|
||||
if (result.success) {
|
||||
return result.payload;
|
||||
}
|
||||
throw new Error(result.error);
|
||||
}),
|
||||
v1Protocol.decode,
|
||||
);
|
||||
|
||||
return this.success(message);
|
||||
@@ -252,17 +252,14 @@ export abstract class AbstractApiTransport extends AbstractTransport {
|
||||
const { path } = getPathBySessionResponse.payload;
|
||||
|
||||
try {
|
||||
await buildAndSend(
|
||||
this.messages,
|
||||
(buffer: Buffer) =>
|
||||
this.api.write(path, buffer).then(result => {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
}),
|
||||
name,
|
||||
data,
|
||||
);
|
||||
const buffers = buildBuffers(this.messages, name, data, v1Protocol.encode);
|
||||
for (const chunk of buffers) {
|
||||
this.api.write(path, chunk.buffer).then(result => {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
return this.success(undefined);
|
||||
} catch (err) {
|
||||
if (err.message === ERRORS.DEVICE_DISCONNECTED_DURING_ACTION) {
|
||||
@@ -285,13 +282,16 @@ export abstract class AbstractApiTransport extends AbstractTransport {
|
||||
const { path } = getPathBySessionResponse.payload;
|
||||
|
||||
try {
|
||||
const message = await receiveAndParse(this.messages, () =>
|
||||
this.api.read(path).then(result => {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
return result.payload;
|
||||
}),
|
||||
const message = await receiveAndParse(
|
||||
this.messages,
|
||||
() =>
|
||||
this.api.read(path).then(result => {
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
return result.payload;
|
||||
}),
|
||||
v1Protocol.decode,
|
||||
);
|
||||
|
||||
return this.success(message);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { versionUtils, createDeferred, Deferred, createTimeoutPromise } from '@trezor/utils';
|
||||
import { PROTOCOL_MALFORMED } from '@trezor/protocol';
|
||||
import { PROTOCOL_MALFORMED, bridge as bridgeProtocol } from '@trezor/protocol';
|
||||
import { bridgeApiCall } from '../utils/bridgeApiCall';
|
||||
import * as bridgeApiResult from '../utils/bridgeApiResult';
|
||||
import { buildOne } from '../utils/send';
|
||||
import { receiveOne } from '../utils/receive';
|
||||
import { buildBuffers } from '../utils/send';
|
||||
import { receiveAndParse } from '../utils/receive';
|
||||
import { AbstractTransport, AbstractTransportParams, AcquireInput, ReleaseInput } from './abstract';
|
||||
|
||||
import * as ERRORS from '../errors';
|
||||
@@ -228,19 +228,21 @@ export class BridgeTransport extends AbstractTransport {
|
||||
}) {
|
||||
return this.scheduleAction(
|
||||
async signal => {
|
||||
const { messages } = this;
|
||||
const o = buildOne(messages, name, data);
|
||||
const outData = o.toString('hex');
|
||||
const [bytes] = buildBuffers(this.messages, name, data, bridgeProtocol.encode);
|
||||
const response = await this._post(`/call`, {
|
||||
params: session,
|
||||
body: outData,
|
||||
body: bytes.toString('hex'),
|
||||
signal,
|
||||
});
|
||||
if (!response.success) {
|
||||
return response;
|
||||
}
|
||||
const jsonData = receiveOne(this.messages, response.payload);
|
||||
return this.success(jsonData);
|
||||
const message = await receiveAndParse(
|
||||
this.messages,
|
||||
() => Promise.resolve(Buffer.from(response.payload, 'hex')),
|
||||
bridgeProtocol.decode,
|
||||
);
|
||||
return this.success(message);
|
||||
},
|
||||
{ timeout: undefined },
|
||||
);
|
||||
@@ -256,12 +258,10 @@ export class BridgeTransport extends AbstractTransport {
|
||||
name: string;
|
||||
}) {
|
||||
return this.scheduleAction(async signal => {
|
||||
const { messages } = this;
|
||||
const outData = buildOne(messages, name, data).toString('hex');
|
||||
const [bytes] = buildBuffers(this.messages, name, data, bridgeProtocol.encode);
|
||||
const response = await this._post('/post', {
|
||||
params: session,
|
||||
body: outData,
|
||||
|
||||
body: bytes.toString('hex'),
|
||||
signal,
|
||||
});
|
||||
if (!response.success) {
|
||||
@@ -275,16 +275,18 @@ export class BridgeTransport extends AbstractTransport {
|
||||
return this.scheduleAction(async signal => {
|
||||
const response = await this._post('/read', {
|
||||
params: session,
|
||||
|
||||
signal,
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
return response;
|
||||
}
|
||||
const jsonData = receiveOne(this.messages, response.payload);
|
||||
|
||||
return this.success(jsonData);
|
||||
const message = await receiveAndParse(
|
||||
this.messages,
|
||||
() => Promise.resolve(Buffer.from(response.payload, 'hex')),
|
||||
bridgeProtocol.decode,
|
||||
);
|
||||
return this.success(message);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,7 @@ import ByteBuffer from 'bytebuffer';
|
||||
import { Root } from 'protobufjs/light';
|
||||
|
||||
import { decode as decodeProtobuf, createMessageFromType } from '@trezor/protobuf';
|
||||
import { v1 as protocolV1, bridge as bridgeProtocol } from '@trezor/protocol';
|
||||
|
||||
export function receiveOne(messages: Root, data: string) {
|
||||
const bytebuffer = ByteBuffer.wrap(data, 'hex');
|
||||
|
||||
const { typeId, buffer } = bridgeProtocol.decode(bytebuffer);
|
||||
const { Message, messageName } = createMessageFromType(messages, typeId);
|
||||
const message = decodeProtobuf(Message, buffer);
|
||||
return {
|
||||
message,
|
||||
type: messageName,
|
||||
};
|
||||
}
|
||||
import { TransportProtocolDecode } from '@trezor/protocol';
|
||||
|
||||
async function receiveRest(
|
||||
parsedInput: ByteBuffer,
|
||||
@@ -34,20 +22,27 @@ async function receiveRest(
|
||||
return receiveRest(parsedInput, receiver, expectedLength);
|
||||
}
|
||||
|
||||
async function receiveBuffer(receiver: () => Promise<ArrayBuffer>) {
|
||||
async function receiveBuffer(
|
||||
receiver: () => Promise<ArrayBuffer>,
|
||||
decoder: TransportProtocolDecode,
|
||||
) {
|
||||
const data = await receiver();
|
||||
const { length, typeId, restBuffer } = protocolV1.decodeChunked(data);
|
||||
const { length, typeId, buffer } = decoder(data);
|
||||
const decoded = new ByteBuffer(length);
|
||||
|
||||
if (length) {
|
||||
decoded.append(restBuffer);
|
||||
decoded.append(buffer);
|
||||
}
|
||||
await receiveRest(decoded, receiver, length);
|
||||
return { received: decoded, typeId };
|
||||
}
|
||||
|
||||
export async function receiveAndParse(messages: Root, receiver: () => Promise<ArrayBuffer>) {
|
||||
const { received, typeId } = await receiveBuffer(receiver);
|
||||
export async function receiveAndParse(
|
||||
messages: Root,
|
||||
receiver: () => Promise<ArrayBuffer>,
|
||||
decoder: TransportProtocolDecode,
|
||||
) {
|
||||
const { received, typeId } = await receiveBuffer(receiver, decoder);
|
||||
const { Message, messageName } = createMessageFromType(messages, typeId);
|
||||
received.reset();
|
||||
const message = decodeProtobuf(Message, received);
|
||||
|
||||
@@ -3,42 +3,17 @@
|
||||
// Logic of "call" is broken to two parts - sending and receiving
|
||||
import { Root } from 'protobufjs/light';
|
||||
import { encode as encodeProtobuf, createMessageFromName } from '@trezor/protobuf';
|
||||
import { v1 as protocolV1, bridge as bridgeProtocol } from '@trezor/protocol';
|
||||
import { TransportProtocolEncode } from '@trezor/protocol';
|
||||
|
||||
// Sends more buffers to device.
|
||||
async function sendBuffers(sender: (data: Buffer) => Promise<void>, buffers: Array<Buffer>) {
|
||||
for (const buffer of buffers) {
|
||||
await sender(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Sends message to device.
|
||||
// Resolves if everything gets sent
|
||||
export function buildOne(messages: Root, name: string, data: Record<string, unknown>) {
|
||||
const { Message, messageType } = createMessageFromName(messages, name);
|
||||
|
||||
const buffer = encodeProtobuf(Message, data);
|
||||
return bridgeProtocol.encode(buffer, {
|
||||
messageType,
|
||||
});
|
||||
}
|
||||
|
||||
export const buildBuffers = (messages: Root, name: string, data: Record<string, unknown>) => {
|
||||
export const buildBuffers = (
|
||||
messages: Root,
|
||||
name: string,
|
||||
data: Record<string, unknown>,
|
||||
encoder: TransportProtocolEncode,
|
||||
) => {
|
||||
const { Message, messageType } = createMessageFromName(messages, name);
|
||||
const buffer = encodeProtobuf(Message, data);
|
||||
return protocolV1.encode(buffer, {
|
||||
return encoder(buffer, {
|
||||
messageType,
|
||||
});
|
||||
};
|
||||
|
||||
// Sends message to device.
|
||||
// Resolves if everything gets sent
|
||||
export function buildAndSend(
|
||||
messages: Root,
|
||||
sender: (data: Buffer) => Promise<void>,
|
||||
name: string,
|
||||
data: Record<string, unknown>,
|
||||
) {
|
||||
const buffers = buildBuffers(messages, name, data);
|
||||
return sendBuffers(sender, buffers);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as protobuf from 'protobufjs/light';
|
||||
|
||||
import { buildOne, buildBuffers } from '../src/utils/send';
|
||||
import { receiveOne, receiveAndParse } from '../src/utils/receive';
|
||||
import { v1 as v1Protocol, bridge as bridgeProtocol } from '@trezor/protocol';
|
||||
import { buildBuffers } from '../src/utils/send';
|
||||
import { receiveAndParse } from '../src/utils/receive';
|
||||
|
||||
const messages = {
|
||||
StellarPaymentOp: {
|
||||
@@ -96,25 +96,44 @@ const parsedMessages = protobuf.Root.fromJSON({
|
||||
describe('encoding json -> protobuf -> json', () => {
|
||||
fixtures.forEach(f => {
|
||||
describe(`${f.name} - payload length ${f.in.source_account.length}`, () => {
|
||||
test('buildOne - receiveOne', () => {
|
||||
// encoded message
|
||||
const encodedMessage = buildOne(parsedMessages, f.name, f.in);
|
||||
test('bridgeProtocol: buildBuffers - receiveAndParse', async () => {
|
||||
const result = buildBuffers(parsedMessages, f.name, f.in, bridgeProtocol.encode);
|
||||
// bridgeProtocol returns only one big chunk
|
||||
expect(result.length).toBe(1);
|
||||
const [chunk] = result;
|
||||
const { length } = Buffer.from(f.in.source_account);
|
||||
// chunk length cannot be less than message header/constant (28) + variable source_account length
|
||||
// additional bytes are expected (encoded Uint32) if message length is greater
|
||||
expect(chunk.buffer.length).toBeGreaterThanOrEqual(28 + length);
|
||||
let i = -1;
|
||||
const decoded = await receiveAndParse(
|
||||
parsedMessages,
|
||||
() => {
|
||||
i++;
|
||||
return Promise.resolve(result[i].buffer);
|
||||
},
|
||||
bridgeProtocol.decode,
|
||||
);
|
||||
// then decode message and check, whether decoded message matches original json
|
||||
const decodedMessage = receiveOne(parsedMessages, encodedMessage.toString('hex'));
|
||||
expect(decodedMessage.type).toEqual(f.name);
|
||||
expect(decodedMessage.message).toEqual(f.in);
|
||||
expect(decoded.type).toEqual(f.name);
|
||||
expect(decoded.message).toEqual(f.in);
|
||||
});
|
||||
|
||||
test('buildBuffers - receiveAndParse', async () => {
|
||||
const result = buildBuffers(parsedMessages, f.name, f.in);
|
||||
result.forEach(r => {
|
||||
expect(r.byteLength).toBeLessThanOrEqual(64);
|
||||
test('v1Protocol: buildBuffers - receiveAndParse', async () => {
|
||||
const result = buildBuffers(parsedMessages, f.name, f.in, v1Protocol.encode);
|
||||
// each protocol chunks are equal 64 bytes
|
||||
result.forEach(chunk => {
|
||||
expect(chunk.buffer.length).toEqual(64);
|
||||
});
|
||||
let i = -1;
|
||||
const decoded = await receiveAndParse(parsedMessages, () => {
|
||||
i++;
|
||||
return Promise.resolve(result[i]);
|
||||
});
|
||||
const decoded = await receiveAndParse(
|
||||
parsedMessages,
|
||||
() => {
|
||||
i++;
|
||||
return Promise.resolve(result[i].buffer);
|
||||
},
|
||||
v1Protocol.decode,
|
||||
);
|
||||
// then decode message and check, whether decoded message matches original json
|
||||
expect(decoded.type).toEqual(f.name);
|
||||
expect(decoded.message).toEqual(f.in);
|
||||
|
||||
Reference in New Issue
Block a user