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