• 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 mergedArray = new Uint8Array(
33      bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length + buf.length
34    );
35    mergedArray.set(bannerValue);
36    mergedArray.set(authTypeValue, bannerValue.length);
37    mergedArray.set(sessionIdValue, bannerValue.length + authTypeValue.length);
38    mergedArray.set(connectKey, bannerValue.length + authTypeValue.length + sessionIdValue.length);
39    mergedArray.set(buf, bannerValue.length + authTypeValue.length + sessionIdValue.length + connectKey.length);
40    return mergedArray;
41  }
42
43  static serializePayloadProtect(payloadProtect: PayloadProtect): Uint8Array {
44    let channelId = this.serializeU32(1, payloadProtect.channelId);
45    let commandFlag = this.serializeU32(2, payloadProtect.commandFlag);
46    let checkSum = this.serializeU8(3, payloadProtect.checkSum);
47    let vCode = this.serializeU8(4, payloadProtect.vCode);
48    let mergedArray = new Uint8Array(channelId.length + commandFlag.length + checkSum.length + vCode.length);
49    mergedArray.set(channelId);
50    mergedArray.set(commandFlag, channelId.length);
51    mergedArray.set(checkSum, channelId.length + commandFlag.length);
52    mergedArray.set(vCode, channelId.length + commandFlag.length + checkSum.length);
53    return mergedArray;
54  }
55
56  static serializeTransferConfig(transferConfig: TransferConfig): Uint8Array {
57    let fileSizeValue = this.serializeU64(1, transferConfig.fileSize);
58    let atimeValue = this.serializeU64(2, transferConfig.atime);
59    let mtimeValue = this.serializeU64(3, transferConfig.mtime);
60    let optionsValue = this.serializeToString(4, transferConfig.options);
61    let pathValue = this.serializeToString(5, transferConfig.path);
62    let optionalNameValue = this.serializeToString(6, transferConfig.optionalName);
63    let updateIfNewValue = this.serializeU32(7, transferConfig.updateIfNew ? 1 : 0);
64    let compressTypeValue = this.serializeU8(8, transferConfig.compressType);
65    let holdTimestampValue = this.serializeU32(9, transferConfig.holdTimestamp ? 1 : 0);
66    let functionNameValue = this.serializeToString(10, transferConfig.functionName);
67    let clientCwdValue = this.serializeToString(11, transferConfig.clientCwd);
68    let reserve1Value = this.serializeToString(12, transferConfig.reserve1);
69    let reserve2Value = this.serializeToString(13, transferConfig.reserve2);
70    let mergedArray = new Uint8Array(
71      fileSizeValue.length +
72        atimeValue.length +
73        mtimeValue.length +
74        optionsValue.length +
75        pathValue.length +
76        optionalNameValue.length +
77        updateIfNewValue.length +
78        compressTypeValue.length +
79        holdTimestampValue.length +
80        functionNameValue.length +
81        clientCwdValue.length +
82        reserve1Value.length +
83        reserve2Value.length
84    );
85    let offset = 0;
86    mergedArray.set(fileSizeValue);
87    offset += fileSizeValue.length;
88    mergedArray.set(atimeValue, offset);
89    offset += atimeValue.length;
90    mergedArray.set(mtimeValue, offset);
91    offset += mtimeValue.length;
92    mergedArray.set(optionsValue, offset);
93    offset += optionsValue.length;
94    mergedArray.set(pathValue, offset);
95    offset += pathValue.length;
96    mergedArray.set(optionalNameValue, offset);
97    offset += optionalNameValue.length;
98    mergedArray.set(updateIfNewValue, offset);
99    offset += updateIfNewValue.length;
100    mergedArray.set(compressTypeValue, offset);
101    offset += compressTypeValue.length;
102    mergedArray.set(holdTimestampValue, offset);
103    offset += holdTimestampValue.length;
104    mergedArray.set(functionNameValue, offset);
105    offset += functionNameValue.length;
106    mergedArray.set(clientCwdValue, offset);
107    offset += clientCwdValue.length;
108    mergedArray.set(reserve1Value, offset);
109    offset += reserve1Value.length;
110    mergedArray.set(reserve2Value, offset);
111    return mergedArray;
112  }
113
114  static serializeTransferPayload(transferPayload: TransferPayload): Uint8Array {
115    let indexValue = this.serializeU64(1, transferPayload.index);
116    let compressTypeValue = this.serializeU8(2, transferPayload.compressType);
117    let compressSizeValue = this.serializeU32(3, transferPayload.compressSize);
118    let uncompressSizeValue = this.serializeU32(4, transferPayload.uncompressSize);
119    let mergedArray = new Uint8Array(
120      indexValue.length + compressTypeValue.length + compressSizeValue.length + uncompressSizeValue.length
121    );
122    let offset = 0;
123    mergedArray.set(indexValue);
124    offset += indexValue.length;
125    mergedArray.set(compressTypeValue, offset);
126    offset += compressTypeValue.length;
127    mergedArray.set(compressSizeValue, offset);
128    offset += compressSizeValue.length;
129    mergedArray.set(uncompressSizeValue, offset);
130    return mergedArray;
131  }
132
133  static serializeToString(tag: number, value: string): Uint8Array {
134    let number = this.makeTagWireType(tag, WireType.LENGTH_DELIMETED);
135    let data = this.writeVarIntU32(number);
136    let dataLength = this.writeVarIntU32(value.length);
137    const encoder = new TextEncoder();
138    const buffer = encoder.encode(value);
139    let stringValue = new Uint8Array(data.length + dataLength.length + buffer.length);
140    stringValue.set(data);
141    stringValue.set(dataLength, data.length);
142    stringValue.set(buffer, data.length + dataLength.length);
143    return stringValue;
144  }
145
146  static serializeU8(tag: number, value: number): Uint8Array {
147    return this.serializeU32(tag, value);
148  }
149
150  static serializeU32(tag: number, value: number): Uint8Array {
151    let makeTagWireType = this.writeTagWriteType(tag, WireType.VARINT);
152    let writeVarInt = this.writeVarIntU32(value);
153    let mergedArray = new Uint8Array(makeTagWireType.length + writeVarInt.length);
154    mergedArray.set(makeTagWireType);
155    mergedArray.set(writeVarInt, makeTagWireType.length);
156    return mergedArray;
157  }
158
159  static serializeU64(tag: number, value: number): Uint8Array {
160    let makeTagWireType = this.writeTagWriteType(tag, WireType.VARINT);
161    let writeVarInt = this.writeVarIntU64(value);
162    let mergedArray = new Uint8Array(makeTagWireType.length + writeVarInt.length);
163    mergedArray.set(makeTagWireType);
164    mergedArray.set(writeVarInt, makeTagWireType.length);
165    return mergedArray;
166  }
167
168  static writeTagWriteType(tag: number, wireType: number): Uint8Array {
169    let number = this.makeTagWireType(tag, wireType);
170    return this.writeVarIntU32(number);
171  }
172
173  static makeTagWireType(tag: number, wireType: number): number {
174    return (tag << 3) | wireType;
175  }
176
177  static writeVarIntU64(u64value: number): Uint8Array {
178    let uint64buffer: number[] = [];
179    for (let index = 0; index < 10; index++) {
180      uint64buffer[index] = u64value & 0b01111111;
181      u64value = u64value >> 7;
182      if (u64value) {
183        uint64buffer[index] = uint64buffer[index] | 0b10000000;
184      } else {
185        break;
186      }
187    }
188    return new Uint8Array(uint64buffer);
189  }
190
191  static writeVarIntU32(u32value: number): Uint8Array {
192    let u32buffer: number[] = [];
193    for (let index = 0; index < 5; index++) {
194      u32buffer[index] = u32value & 0b01111111;
195      u32value = u32value >> 7;
196      if (u32value) {
197        u32buffer[index] = u32buffer[index] | 0b10000000;
198      } else {
199        break;
200      }
201    }
202    return new Uint8Array(u32buffer);
203  }
204
205  static parseHandshake(data: Uint8Array): SessionHandShake {
206    // banner
207    let bannerBuffer = data.buffer;
208    let bannerTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(bannerBuffer));
209    let bannerLengthBuf = bannerBuffer.slice(1);
210    let bannerSize = this.readVarIntU32(new DataView(bannerLengthBuf));
211    let bannerDataBuffer = bannerLengthBuf.slice(1);
212    let banner = this.parseString(bannerDataBuffer, bannerSize);
213
214    // authType
215    let authBuffer = bannerDataBuffer.slice(bannerSize);
216    let authTypeTag = this.getTag(WireType.VARINT, new DataView(authBuffer));
217    let authDataBuffer = authBuffer.slice(1);
218    let authTypeDataView = new DataView(authDataBuffer);
219    let authType = this.parseU8(authTypeDataView, 1);
220
221    // sessionId
222    let sessionIdBuffer = authDataBuffer.slice(1);
223    let sessionIdTag = this.getTag(WireType.VARINT, new DataView(sessionIdBuffer));
224    let sessionDataBuffer = sessionIdBuffer.slice(1);
225    let sessionIdDataView = new DataView(sessionDataBuffer);
226    let sessionId = this.parseU32(sessionIdDataView, 3);
227
228    // connectKey
229    let connectKeyBuffer = sessionDataBuffer.slice(3);
230    let connectKeyTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(connectKeyBuffer));
231    let connectLengthBuffer = connectKeyBuffer.slice(1);
232    let connectKeyDataView = new DataView(connectLengthBuffer);
233    let connectKeySize = this.readVarIntU32(connectKeyDataView);
234    let connectDataBuffer = connectLengthBuffer.slice(1);
235    let connectKey = this.parseString(connectDataBuffer, connectKeySize);
236
237    // buf
238    let bufBuffer = connectDataBuffer.slice(connectKeySize);
239    let bufTag = this.getTag(WireType.LENGTH_DELIMETED, new DataView(bufBuffer));
240    let lengthBuffer = bufBuffer.slice(1);
241    let bufDataView = new DataView(lengthBuffer);
242    let bufSize = this.readVarIntU32(bufDataView);
243    let dataBuffer = lengthBuffer.slice(1);
244    let buf = this.parseString(dataBuffer, bufSize);
245    return new SessionHandShake(banner, authType, sessionId, connectKey, buf);
246  }
247
248  static parseTransferConfig(data: ArrayBuffer): TransferConfig {
249    let uint8Array = new Uint8Array(data);
250    // channelId
251    let dataBuffer = uint8Array.buffer;
252    let channelTag = this.getTag(WireType.VARINT, new DataView(dataBuffer));
253    let channelDataBuffer = dataBuffer.slice(1);
254    let channelDataView = new DataView(channelDataBuffer);
255    let fileSize = this.parseU64(channelDataView, 1);
256    return new TransferConfig(fileSize, 0, 0, '', '', '', false, 0, false, '', '', '', '');
257  }
258
259  static parsePayloadProtect(data: ArrayBuffer): PayloadProtect {
260    let uint8Array = new Uint8Array(data);
261
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 channelId = this.parseU32(channelDataView, 1);
268
269    // commandFlag
270    let commandTagBuffer = channelDataBuffer.slice(1);
271    let commandTag = this.getTag(WireType.VARINT, new DataView(commandTagBuffer));
272    let commandDataBuffer = commandTagBuffer.slice(1);
273    let commandDataView = new DataView(commandDataBuffer);
274    let commandFlag = this.parseU32(commandDataView, 1);
275
276    // checkSum
277    let checkSumTagBuffer = commandDataBuffer.slice(1);
278    let checkSumTag = this.getTag(WireType.VARINT, new DataView(checkSumTagBuffer));
279    let checkSumDataBuffer = checkSumTagBuffer.slice(1);
280    let checkSumDataView = new DataView(checkSumDataBuffer);
281    let checkSum = this.parseU8(checkSumDataView, 1);
282
283    // vCode
284    let vCodeTagBuffer = checkSumDataBuffer.slice(1);
285    let vCodeTag = this.getTag(WireType.VARINT, new DataView(vCodeTagBuffer));
286    let vCodeDataBuffer = vCodeTagBuffer.slice(1);
287    let vCodeDataView = new DataView(vCodeDataBuffer);
288    let vCode = this.parseU8(vCodeDataView, 1);
289
290    return new PayloadProtect(channelId, commandFlag, checkSum, vCode);
291  }
292
293  static parseString(buffer: ArrayBuffer, size: number): string {
294    let arrayBuffer = buffer.slice(0, size);
295    let textDecoder = new TextDecoder();
296    return textDecoder.decode(arrayBuffer);
297  }
298
299  static parseU8(dataView: DataView, size: number): number {
300    return this.parseU32(dataView, size);
301  }
302
303  static parseU32(dataView: DataView, size: number): number {
304    return this.readVarIntU32(dataView);
305  }
306
307  static parseU64(dataView: DataView, size: number): number {
308    return this.readVarIntU64(dataView);
309  }
310
311  static readVarIntU32(dataView: DataView): number {
312    let u32IntValue: number = 0;
313    for (let u32IntIndex = 0; u32IntIndex < 5; u32IntIndex++) {
314      if (dataView.byteLength < u32IntIndex + 1) {
315        return -1;
316      }
317      let int8 = dataView.getUint8(u32IntIndex);
318      let readValue = int8 & 0b01111111;
319      u32IntValue |= readValue << (7 * u32IntIndex);
320      if (!(int8 & 0b10000000)) {
321        return u32IntValue;
322      }
323    }
324    return -1;
325  }
326
327  static readVarIntU64(dataView: DataView): number {
328    let u62IntValue: number = 0;
329    for (let u62IntIndex = 0; u62IntIndex < 10; u62IntIndex++) {
330      if (dataView.byteLength < u62IntIndex + 1) {
331        return -1;
332      }
333      let int8 = dataView.getUint8(u62IntIndex);
334      let readValue = int8 & 0b01111111;
335      u62IntValue |= readValue << (7 * u62IntIndex);
336      if (!(int8 & 0b10000000)) {
337        return u62IntValue;
338      }
339    }
340    return -1;
341  }
342
343  static readTagWireType(tagKey: number) {
344    let wireNewType: WireType = tagKey & 0b0111;
345    return tagKey >> 3;
346  }
347
348  static getTag(wireType: WireType, dataView: DataView) {
349    let tagKey = this.readVarIntU32(dataView);
350    return this.readTagWireType(tagKey);
351  }
352}
353