• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { WireType } from '../message/WireType';
17import { SessionHandShake } from '../message/SessionHandShake';
18import { PayloadProtect } from '../message/PayloadProtect';
19import { TransferConfig } from '../message/TransferConfig';
20import { TransferPayload } from '../message/TransferPayload';
21import { log } from '../../log/Log';
22
23export class Serialize {
24  static bannerByteLength: number = 8;
25
26  static serializeSessionHandShake(handShake: SessionHandShake): Uint8Array {
27    let bannerValue = this.serializeToString(1, handShake.banner);
28    let authTypeValue = this.serializeU8(2, handShake.authType);
29    let sessionIdValue = this.serializeU32(3, handShake.sessionId);
30    let connectKey = this.serializeToString(4, handShake.connectKey);
31    let buf = this.serializeToString(5, handShake.buf);
32    let version = this.serializeToString(6, handShake.version);
33    let mergedArray = new Uint8Array(
34      bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length + buf.length + version.length
35    );
36    mergedArray.set(bannerValue);
37    mergedArray.set(authTypeValue, bannerValue.length);
38    mergedArray.set(sessionIdValue, bannerValue.length + authTypeValue.length);
39    mergedArray.set(connectKey, bannerValue.length + authTypeValue.length + sessionIdValue.length);
40    mergedArray.set(buf, bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length);
41    mergedArray.set(version, bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length + buf.length);
42    return mergedArray;
43  }
44
45  static serializePayloadProtect(payloadProtect: PayloadProtect): Uint8Array {
46    let channelId = this.serializeU32(1, payloadProtect.channelId);
47    let commandFlag = this.serializeU32(2, payloadProtect.commandFlag);
48    let checkSum = this.serializeU8(3, payloadProtect.checkSum);
49    let vCode = this.serializeU8(4, payloadProtect.vCode);
50    let mergedArray = new Uint8Array(channelId.length + commandFlag.length + checkSum.length + vCode.length);
51    mergedArray.set(channelId);
52    mergedArray.set(commandFlag, channelId.length);
53    mergedArray.set(checkSum, channelId.length + commandFlag.length);
54    mergedArray.set(vCode, channelId.length + commandFlag.length + checkSum.length);
55    return mergedArray;
56  }
57
58  static serializeTransferConfig(transferConfig: TransferConfig): Uint8Array {
59    let fileSizeValue = this.serializeU64(1, transferConfig.fileSize);
60    let atimeValue = this.serializeU64(2, transferConfig.atime);
61    let mtimeValue = this.serializeU64(3, transferConfig.mtime);
62    let optionsValue = this.serializeToString(4, transferConfig.options);
63    let pathValue = this.serializeToString(5, transferConfig.path);
64    let optionalNameValue = this.serializeToString(6, transferConfig.optionalName);
65    let updateIfNewValue = this.serializeU32(7, transferConfig.updateIfNew ? 1 : 0);
66    let compressTypeValue = this.serializeU8(8, transferConfig.compressType);
67    let holdTimestampValue = this.serializeU32(9, transferConfig.holdTimestamp ? 1 : 0);
68    let functionNameValue = this.serializeToString(10, transferConfig.functionName);
69    let clientCwdValue = this.serializeToString(11, transferConfig.clientCwd);
70    let reserve1Value = this.serializeToString(12, transferConfig.reserve1);
71    let reserve2Value = this.serializeToString(13, transferConfig.reserve2);
72    let mergedArray = new Uint8Array(
73      fileSizeValue.length +
74        atimeValue.length +
75        mtimeValue.length +
76        optionsValue.length +
77        pathValue.length +
78        optionalNameValue.length +
79        updateIfNewValue.length +
80        compressTypeValue.length +
81        holdTimestampValue.length +
82        functionNameValue.length +
83        clientCwdValue.length +
84        reserve1Value.length +
85        reserve2Value.length
86    );
87    let offset = 0;
88    mergedArray.set(fileSizeValue);
89    offset += fileSizeValue.length;
90    mergedArray.set(atimeValue, offset);
91    offset += atimeValue.length;
92    mergedArray.set(mtimeValue, offset);
93    offset += mtimeValue.length;
94    mergedArray.set(optionsValue, offset);
95    offset += optionsValue.length;
96    mergedArray.set(pathValue, offset);
97    offset += pathValue.length;
98    mergedArray.set(optionalNameValue, offset);
99    offset += optionalNameValue.length;
100    mergedArray.set(updateIfNewValue, offset);
101    offset += updateIfNewValue.length;
102    mergedArray.set(compressTypeValue, offset);
103    offset += compressTypeValue.length;
104    mergedArray.set(holdTimestampValue, offset);
105    offset += holdTimestampValue.length;
106    mergedArray.set(functionNameValue, offset);
107    offset += functionNameValue.length;
108    mergedArray.set(clientCwdValue, offset);
109    offset += clientCwdValue.length;
110    mergedArray.set(reserve1Value, offset);
111    offset += reserve1Value.length;
112    mergedArray.set(reserve2Value, offset);
113    return mergedArray;
114  }
115
116  static serializeTransferPayload(transferPayload: TransferPayload): Uint8Array {
117    let indexValue = this.serializeU64(1, transferPayload.index);
118    let compressTypeValue = this.serializeU8(2, transferPayload.compressType);
119    let compressSizeValue = this.serializeU32(3, transferPayload.compressSize);
120    let uncompressSizeValue = this.serializeU32(4, transferPayload.uncompressSize);
121    let mergedArray = new Uint8Array(
122      indexValue.length + compressTypeValue.length + compressSizeValue.length + uncompressSizeValue.length
123    );
124    let offset = 0;
125    mergedArray.set(indexValue);
126    offset += indexValue.length;
127    mergedArray.set(compressTypeValue, offset);
128    offset += compressTypeValue.length;
129    mergedArray.set(compressSizeValue, offset);
130    offset += compressSizeValue.length;
131    mergedArray.set(uncompressSizeValue, offset);
132    return mergedArray;
133  }
134
135  static serializeToString(tag: number, value: string): Uint8Array {
136    let number = this.makeTagWireType(tag, WireType.LENGTH_DELIMETED);
137    let data = this.writeVarIntU32(number);
138    let dataLength = this.writeVarIntU32(value.length);
139    const encoder = new TextEncoder();
140    const buffer = encoder.encode(value);
141    let stringValue = new Uint8Array(data.length + dataLength.length + buffer.length);
142    stringValue.set(data);
143    stringValue.set(dataLength, data.length);
144    stringValue.set(buffer, data.length + dataLength.length);
145    return stringValue;
146  }
147
148  static serializeU8(tag: number, value: number): Uint8Array {
149    return this.serializeU32(tag, value);
150  }
151
152  static serializeU32(tag: number, value: number): Uint8Array {
153    let makeTagWireType = this.writeTagWriteType(tag, WireType.VARINT);
154    let writeVarInt = this.writeVarIntU32(value);
155    let mergedArray = new Uint8Array(makeTagWireType.length + writeVarInt.length);
156    mergedArray.set(makeTagWireType);
157    mergedArray.set(writeVarInt, makeTagWireType.length);
158    return mergedArray;
159  }
160
161  static serializeU64(tag: number, value: number): Uint8Array {
162    let makeTagWireType = this.writeTagWriteType(tag, WireType.VARINT);
163    let writeVarInt = this.writeVarIntU64(value);
164    let mergedArray = new Uint8Array(makeTagWireType.length + writeVarInt.length);
165    mergedArray.set(makeTagWireType);
166    mergedArray.set(writeVarInt, makeTagWireType.length);
167    return mergedArray;
168  }
169
170  static writeTagWriteType(tag: number, wireType: number): Uint8Array {
171    let number = this.makeTagWireType(tag, wireType);
172    return this.writeVarIntU32(number);
173  }
174
175  static makeTagWireType(tag: number, wireType: number): number {
176    return (tag << 3) | wireType;
177  }
178
179  static writeVarIntU64(u64value: number): Uint8Array {
180    let uint64buffer: number[] = [];
181    for (let index = 0; index < 10; index++) {
182      uint64buffer[index] = u64value & 0b01111111;
183      u64value = u64value >> 7;
184      if (u64value) {
185        uint64buffer[index] = uint64buffer[index] | 0b10000000;
186      } else {
187        break;
188      }
189    }
190    return new Uint8Array(uint64buffer);
191  }
192
193  static writeVarIntU32(u32value: number): Uint8Array {
194    let u32buffer: number[] = [];
195    for (let index = 0; index < 5; index++) {
196      u32buffer[index] = u32value & 0b01111111;
197      u32value = u32value >> 7;
198      if (u32value) {
199        u32buffer[index] = u32buffer[index] | 0b10000000;
200      } else {
201        break;
202      }
203    }
204    return new Uint8Array(u32buffer);
205  }
206
207  static parseHandshake(data: Uint8Array): SessionHandShake {
208    // banner
209    let bannerBuffer = data.buffer;
210    let bannerTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(bannerBuffer));
211    let bannerLengthBuf = bannerBuffer.slice(this.writeVarIntU32(this.makeTagWireType(bannerTag, WireType.LENGTH_DELIMETED)).length);
212    let bannerSize = this.readVarIntU32(new DataView(bannerLengthBuf));
213    let bannerDataBuffer = bannerLengthBuf.slice(this.writeVarIntU32(bannerSize).length);
214    // @ts-ignore
215    let banner = this.parseString(bannerDataBuffer, bannerSize);
216
217    // authType
218    let authBuffer = bannerDataBuffer.slice(bannerSize);
219    let authTypeTag = this.getTag(WireType.VARINT, new DataView(authBuffer));
220    let authDataBuffer = authBuffer.slice(this.writeVarIntU32(this.makeTagWireType(authTypeTag, WireType.VARINT)).length);
221    let authType = this.parseU8(new DataView(authDataBuffer), 1);
222    let authTypeLenth = this.writeVarIntU32(authType).length;
223
224    // sessionId
225    let sessionIdBuffer = authDataBuffer.slice(authTypeLenth);
226    let sessionIdTag = this.getTag(WireType.VARINT, new DataView(sessionIdBuffer));
227    let sessionDataBuffer = sessionIdBuffer.slice(this.writeVarIntU32(this.makeTagWireType(sessionIdTag, WireType.VARINT)).length);
228    let sessionId = this.parseU32(new DataView(sessionDataBuffer), 3);
229    let sessionIdLenth = this.writeVarIntU32(sessionId).length;
230
231    // connectKey
232    let connectKeyBuffer = sessionDataBuffer.slice(sessionIdLenth);
233    let connectKeyTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(connectKeyBuffer));
234    let connectLengthBuffer = connectKeyBuffer.slice(this.writeVarIntU32(this.makeTagWireType(connectKeyTag, WireType.LENGTH_DELIMETED)).length);
235    let connectKeySize = this.readVarIntU32(new DataView(connectLengthBuffer));
236    let connectDataBuffer = connectLengthBuffer.slice(this.writeVarIntU32(connectKeySize).length);
237    // @ts-ignore
238    let connectKey = this.parseString(connectDataBuffer, connectKeySize);
239
240    // buf
241    let bufBuffer = connectDataBuffer.slice(connectKeySize);
242    let bufTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(bufBuffer));
243    let lengthBuffer = bufBuffer.slice(this.writeVarIntU32(this.makeTagWireType(bufTag, WireType.LENGTH_DELIMETED)).length);
244    let bufSize = this.readVarIntU32(new DataView(lengthBuffer));
245    let dataBuffer = lengthBuffer.slice(this.writeVarIntU32(bufSize).length);
246    // @ts-ignore
247    let buf = this.parseString(dataBuffer, bufSize);
248
249    // version
250    let versionBuffer = dataBuffer.slice(bufSize);
251    let versionTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(versionBuffer));
252    let versionLengthBuffer = versionBuffer.slice(this.writeVarIntU32(this.makeTagWireType(versionTag, WireType.LENGTH_DELIMETED)).length);
253    let versionSize = this.readVarIntU32(new DataView(versionLengthBuffer));
254    let versionDataBuffer = versionLengthBuffer.slice(this.writeVarIntU32(versionSize).length);
255    // @ts-ignore
256    let version = this.parseString(versionDataBuffer, versionSize);
257    return new SessionHandShake(banner, authType, sessionId, connectKey, buf, version);
258  }
259
260  static parseTransferConfig(data: ArrayBuffer): TransferConfig {
261    let uint8Array = new Uint8Array(data);
262    // channelId
263    let dataBuffer = uint8Array.buffer;
264    let channelTag = this.getTag(WireType.VARINT, new DataView(dataBuffer));
265    let channelDataBuffer = dataBuffer.slice(1);
266    let channelDataView = new DataView(channelDataBuffer);
267    let fileSize = this.parseU64(channelDataView, 1);
268    return new TransferConfig(fileSize, 0, 0, '', '', '', false, 0, false, '', '', '', '');
269  }
270
271  static parsePayloadProtect(data: ArrayBuffer): PayloadProtect {
272    let uint8Array = new Uint8Array(data);
273
274    // channelId
275    let dataBuffer = uint8Array.buffer;
276    let channelTag = this.getTag(WireType.VARINT, new DataView(dataBuffer));
277    let channelDataBuffer = dataBuffer.slice(1);
278    let channelDataView = new DataView(channelDataBuffer);
279    let channelId = this.parseU32(channelDataView, 1);
280
281    // commandFlag
282    let commandTagBuffer = channelDataBuffer.slice(1);
283    let commandTag = this.getTag(WireType.VARINT, new DataView(commandTagBuffer));
284    let commandDataBuffer = commandTagBuffer.slice(1);
285    let commandDataView = new DataView(commandDataBuffer);
286    let commandFlag = this.parseU32(commandDataView, 1);
287
288    // checkSum
289    let checkSumTagBuffer = commandDataBuffer.slice(1);
290    let checkSumTag = this.getTag(WireType.VARINT, new DataView(checkSumTagBuffer));
291    let checkSumDataBuffer = checkSumTagBuffer.slice(1);
292    let checkSumDataView = new DataView(checkSumDataBuffer);
293    let checkSum = this.parseU8(checkSumDataView, 1);
294
295    // vCode
296    let vCodeTagBuffer = checkSumDataBuffer.slice(1);
297    let vCodeTag = this.getTag(WireType.VARINT, new DataView(vCodeTagBuffer));
298    let vCodeDataBuffer = vCodeTagBuffer.slice(1);
299    let vCodeDataView = new DataView(vCodeDataBuffer);
300    let vCode = this.parseU8(vCodeDataView, 1);
301
302    return new PayloadProtect(channelId, commandFlag, checkSum, vCode);
303  }
304
305  static parseString(buffer: ArrayBuffer, size: number): string {
306    let arrayBuffer = buffer.slice(0, size);
307    let textDecoder = new TextDecoder();
308    return textDecoder.decode(arrayBuffer);
309  }
310
311  static parseU8(dataView: DataView, size: number): number {
312    return this.parseU32(dataView, size);
313  }
314
315  static parseU32(dataView: DataView, size: number): number {
316    return this.readVarIntU32(dataView);
317  }
318
319  static parseU64(dataView: DataView, size: number): number {
320    return this.readVarIntU64(dataView);
321  }
322
323  static readVarIntU32(dataView: DataView): number {
324    let u32IntValue: number = 0;
325    for (let u32IntIndex = 0; u32IntIndex < 5; u32IntIndex++) {
326      if (dataView.byteLength < u32IntIndex + 1) {
327        return -1;
328      }
329      let int8 = dataView.getUint8(u32IntIndex);
330      let readValue = int8 & 0b01111111;
331      u32IntValue |= readValue << (7 * u32IntIndex);
332      if (!(int8 & 0b10000000)) {
333        return u32IntValue;
334      }
335    }
336    return -1;
337  }
338
339  static readVarIntU64(dataView: DataView): number {
340    let u62IntValue: number = 0;
341    for (let u62IntIndex = 0; u62IntIndex < 10; u62IntIndex++) {
342      if (dataView.byteLength < u62IntIndex + 1) {
343        return -1;
344      }
345      let int8 = dataView.getUint8(u62IntIndex);
346      let readValue = int8 & 0b01111111;
347      u62IntValue |= readValue << (7 * u62IntIndex);
348      if (!(int8 & 0b10000000)) {
349        return u62IntValue;
350      }
351    }
352    return -1;
353  }
354
355  static readTagWireType(tagKey: number): number {
356    let wireNewType: WireType = tagKey & 0b0111;
357    return tagKey >> 3;
358  }
359
360  static getTag(wireType: WireType, dataView: DataView): number {
361    let tagKey = this.readVarIntU32(dataView);
362    return this.readTagWireType(tagKey);
363  }
364}
365