1/*
2 * Copyright (c) 2024 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 socket from '@ohos.net.socket';
17
18const TAG = 'SOCKET_SERVER'
19
20class SocketInfo {
21  message: ArrayBuffer = new ArrayBuffer(1);
22  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
23}
24
25let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance();
26let listenAddr: socket.NetAddress = {
27  address: '127.0.0.1',
28  port: 8080,
29  family: 1
30}
31
32let clientInfo: socket.TCPSocketConnection;
33let messageView: string = ''
34let contentLength: number = 0;
35let contentInfo: string = '';
36let validationCode: string = '';
37
38let on_connect_callback = (client: socket.TCPSocketConnection) => {
39  clientInfo = client;
40  client.on('message', on_message_callback);
41  console.info(TAG + '====>on_message success!')
42}
43
44let on_message_callback = (value: SocketInfo) => {
45  const dataView = new DataView(value.message);
46  let subInfo: string = '';
47  for (let i=0; i<dataView.byteLength; i++){
48    let info = String.fromCharCode(dataView.getUint8(i));
49    subInfo += info;
50  }
51  subInfo = subInfo.replace(/[\n\f\b\f\n\r\t]/g, ' ');
52  subInfo = subInfo.replace(/[\']/g, "'");
53  subInfo = subInfo.replace(/[\"]/g, "'");
54  subInfo = subInfo.replace(/[\\]/g, '\\');
55  if(subInfo.indexOf('content-length')>0){
56    let nextSpaceIndex = subInfo.substring(subInfo.indexOf('content-length'), subInfo.length-1).indexOf(' ');
57    contentLength = parseInt(subInfo.slice(subInfo.indexOf('content-length') + 'content-length:'.length, subInfo.indexOf('content-length') + nextSpaceIndex))
58    console.info(TAG + '====>contentLength:' + contentLength)
59  }
60  if(subInfo.indexOf('boundary=') >0 ){
61    validationCode = subInfo.substr(subInfo.indexOf('boundary=') + 9, 67);
62    console.info(TAG + '====>validationCode:' + validationCode);
63  }
64  if(subInfo.indexOf(`--${validationCode}`) != subInfo.indexOf(`--${validationCode}--`)){
65    if(subInfo.indexOf(`--${validationCode}`) != -1){
66      contentInfo += subInfo.substring(subInfo.indexOf(`--${validationCode}`), subInfo.length);
67      console.info(TAG + '====>contentInfo one')
68    }else{
69      contentInfo += subInfo;
70      console.info(TAG + '====>contentInfo two')
71    }
72  }else{
73    if(subInfo.indexOf('content-length') === -1){
74      contentInfo += subInfo;
75      console.info(TAG + '====>contentInfo three')
76    }
77  }
78  if(subInfo.indexOf(`--${validationCode}--`) != -1){
79    console.info(TAG + `====>contentLength: ${contentLength}`)
80    console.info(TAG + `====>contentInfo_Length: ${contentInfo.length}`)
81    console.info(TAG + `====>contentInfo: ${contentInfo}`)
82    if(contentLength === contentInfo.length){
83      messageView = 'HTTP/1.1 200 OK\r\ncontent-length:18\r\n\r\nupload successful!'
84    }else{
85      messageView = 'HTTP/1.1 200 OK\r\ncontent-length:14\r\n\r\nupload failed!'
86    }
87    contentInfo = '';
88    let tcpSendOption: socket.TCPSendOptions ={
89      data: messageView
90    }
91    clientInfo.send(tcpSendOption, ()=>{
92      console.info(TAG + '====>send success!');
93    })
94  }else{
95    console.info(TAG + '====>subInfo.indexOf:' + subInfo.indexOf(`--${validationCode}--`))
96  }
97}
98
99
100let tcpExtraOptions: socket.TCPExtraOptions = {
101  keepAlive: true,
102  OOBInline: true,
103  TCPNoDelay: true,
104  socketLinger: { on: true, linger: 10 },
105  receiveBufferSize: 1 * 1024,
106  sendBufferSize: 1 * 1024 * 1024,
107  reuseAddress: false,
108  socketTimeout: 3000
109}
110
111export default class Server {
112  async startServer(){
113    await tcpServer.listen(listenAddr)
114    let socketStateBase: socket.SocketStateBase = await tcpServer.getState();
115    console.info(TAG + '====>socketStateBase:' + JSON.stringify(socketStateBase));
116    tcpServer.on('connect', on_connect_callback);
117    console.info(TAG + '====>on_connect success!');
118    await tcpServer.setExtraOptions(tcpExtraOptions);
119    console.info(TAG + '====>setExtraOptions success!')
120  }
121}