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 | ArrayBufferLike = '' 34let contentLength: number = 0; 35let contentInfo: string = ''; 36let validationCode: string = ''; 37let lastValidationCode: string = ''; 38let validationCodeFlag: boolean = false; 39let startContentLengthFlag: string = ''; 40let endContentLengthFlag: string = ''; 41 42let on_connect_callback = (client: socket.TCPSocketConnection) => { 43 clientInfo = client; 44 client.on('message', on_message_callback); 45 console.info(TAG + '====>on_message success!'); 46} 47 48let on_message_callback = (value: SocketInfo) => { 49 try { 50 const dataView = new DataView(value.message); 51 let subInfo: string = ''; 52 for (let i=0; i<dataView.byteLength; i++){ 53 let info = String.fromCharCode(dataView.getUint8(i)); 54 subInfo += info; 55 } 56 console.info(`${TAG} ====> subInfo.length: ${subInfo.length}`); 57 if(subInfo.indexOf('content-length')>0){ 58 let parseInfo = subInfo; 59 parseInfo = parseInfo.replace(/[\n\f\b\f\n\r\t]/g, ' '); 60 parseInfo = parseInfo.replace(/[\']/g, "'"); 61 parseInfo = parseInfo.replace(/[\"]/g, "'"); 62 parseInfo = parseInfo.replace(/[\\]/g, '\\'); 63 let nextSpaceIndex = parseInfo.substring(parseInfo.indexOf('content-length'), parseInfo.length-1).indexOf(' '); 64 contentLength = parseInt(parseInfo.slice(parseInfo.indexOf('content-length') + 'content-length:'.length, parseInfo.indexOf('content-length') + nextSpaceIndex)) 65 console.info(TAG + '====>contentLength:' + contentLength) 66 } 67 if(subInfo.indexOf('boundary=') >0 ){ 68 validationCode = subInfo.substr(subInfo.indexOf('boundary=') + 9, 67); 69 if(validationCode != lastValidationCode){ 70 contentInfo = ''; 71 validationCodeFlag = false; 72 console.info(`${TAG} ====> clear contentInfo`); 73 } 74 lastValidationCode = validationCode; 75 console.info(TAG + '====>validationCode:' + validationCode); 76 startContentLengthFlag = `--${validationCode}`; 77 endContentLengthFlag = `--${validationCode}--`; 78 console.info(`${TAG} ====> startContentLengthFlag.length: ${startContentLengthFlag.length}`); 79 console.info(`${TAG} ====> endContentLengthFlag.length: ${endContentLengthFlag.length}`) 80 } 81 if(subInfo.indexOf(startContentLengthFlag) != subInfo.indexOf(endContentLengthFlag)){ 82 if(subInfo.indexOf(startContentLengthFlag) != -1 && validationCodeFlag === false){ 83 contentInfo += subInfo.substring(subInfo.indexOf(`--${validationCode}`), subInfo.length); 84 console.info(TAG + '====>validationCode: ' + validationCode); 85 console.info(TAG + `====>contentInfo one: ${contentInfo.length}`); 86 validationCodeFlag = true; 87 }else{ 88 contentInfo += subInfo; 89 console.info(TAG + `====>contentInfo_Length two: ${contentInfo.length}`); 90 } 91 }else{ 92 if(subInfo.indexOf('content-length') === -1){ 93 contentInfo += subInfo; 94 console.info(TAG + `====>contentInfo_Length three: ${contentInfo.length}`); 95 } 96 } 97 let contentInfoFinally:string = contentInfo.substr(contentLength-(endContentLengthFlag.length+2), endContentLengthFlag.length+2); 98 contentInfoFinally = contentInfoFinally.replace(/[\n\f\b\f\n\r\t]/g, ''); 99 if(contentInfoFinally === endContentLengthFlag){ 100 console.info(TAG + `====>contentLength: ${contentLength}`); 101 console.info(TAG + `====>contentInfo_Length: ${contentInfo.length}`); 102 console.info(TAG + `====>contentInfo: ${contentInfo}`); 103 if(contentLength === contentInfo.length){ 104 console.info(TAG + `====>contentInfo: all`); 105 messageView = 'HTTP/1.1 200 OK\r\ncontent-length:18\r\n\r\nupload successful!' 106 } else { 107 console.info(TAG + `====>contentInfo: 200 cacheDownloadErrorCode`); 108 messageView = 'HTTP/1.1 200 OK\r\ncontent-length:21\r\ntest:' + 109 'cacheDownloadErrorCode\r\n\r\ncacheDownload failed!'; 110 let buf = new ArrayBuffer(messageView.length); 111 let buffView = new Uint8Array(buf); 112 if (contentInfo.includes('test1:cacheDownloadHttpHeaders0100')){ 113 console.info(TAG + `====>cacheDownloadHttpHeaders0100 start: ${contentInfo}` ); 114 for (let i = 0, strlen = messageView.length; i < strlen; i++){ 115 console.info(TAG + `====>i: ${i}; str: ${messageView[i]}`); 116 if (i === 45) { 117 buffView[i] = 0x80; 118 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 119 } else { 120 buffView[i] = messageView.charCodeAt(i); 121 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 122 } 123 } 124 console.info(TAG + `====>cacheDownloadHttpHeaders0100 set buffer end`); 125 messageView = buffView.buffer; 126 } else if (contentInfo.includes('test2:cacheDownloadHttpHeaders0200')){ 127 console.info(TAG + `====>cacheDownloadHttpHeaders0200 start: ${contentInfo}`); 128 for (let i = 0, strlen = messageView.length; i < strlen; i++){ 129 console.info(TAG + `====>i: ${i}; str: ${messageView[i]}`); 130 if (i === 45) { 131 buffView[i] = 0xE0; 132 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 133 } else if(i === 46) { 134 buffView[i] = 0x80; 135 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 136 } else { 137 buffView[i] = messageView.charCodeAt(i); 138 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 139 } 140 } 141 console.info(TAG + `====>cacheDownloadHttpHeaders0200 set buffer end`); 142 messageView = buffView.buffer; 143 } else if (contentInfo.includes('test3:cacheDownloadHttpHeaders0300')){ 144 console.info(TAG + `====>cacheDownloadHttpHeaders0300 start: ${contentInfo}`); 145 for (let i = 0, strlen = messageView.length; i < strlen; i++){ 146 console.info(TAG + `====>i: ${i}; str: ${messageView[i]}`); 147 if (i === 45) { 148 buffView[i] = 0xF0; 149 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 150 } else if(i === 46) { 151 buffView[i] = 0x80; 152 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 153 } else if (i === 47) { 154 buffView[i] = 0x80; 155 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 156 } else { 157 buffView[i] = messageView.charCodeAt(i); 158 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 159 } 160 } 161 console.info(TAG + `====>cacheDownloadHttpHeaders0300 set buffer end`); 162 messageView = buffView.buffer; 163 } else if (contentInfo.includes('test4:cacheDownloadHttpHeaders0400')){ 164 console.info(TAG + `====>cacheDownloadHttpHeaders0400 start: ${contentInfo}`); 165 for (let i = 0, strlen = messageView.length; i < strlen; i++){ 166 console.info(TAG + `====>i: ${i}; str: ${messageView[i]}`); 167 if (i === 45) { 168 buffView[i] = 0xF4; 169 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 170 } else if(i === 46) { 171 buffView[i] = 0x90; 172 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 173 } else if (i === 47) { 174 buffView[i] = 0x80; 175 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 176 } else if (i === 48) { 177 buffView[i] = 0x80; 178 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 179 } else { 180 buffView[i] = messageView.charCodeAt(i); 181 console.info(TAG + `====> + ${messageView.charCodeAt(i)}`); 182 } 183 } 184 console.info(TAG + `====>cacheDownloadHttpHeaders0400 set buffer end`); 185 messageView = buffView.buffer; 186 } else if (contentInfo.includes('test5::"!@#$%^&*`<>(){}[]')){ 187 console.info(TAG + `====>cacheDownloadHttpHeaders0100 start: ${contentInfo}` ); 188 } else { 189 messageView = 'HTTP/1.1 400 Bad Request\r\ncontent-length:21\r\n\r\ncacheDownload failed!'; 190 } 191 } 192 contentInfo = ''; 193 let tcpSendOption: socket.TCPSendOptions ={ 194 data: messageView 195 } 196 clientInfo.send(tcpSendOption, ()=>{ 197 console.info(TAG + '====>send success!'); 198 }) 199 }else{ 200 console.info(TAG + '====>subInfo.indexOf:' + subInfo.indexOf(`--${validationCode}--`)); 201 } 202 }catch (err) { 203 console.info(TAG + '====>catch err: ' + JSON.stringify(err)); 204 } 205} 206 207 208let tcpExtraOptions: socket.TCPExtraOptions = { 209 keepAlive: true, 210 OOBInline: true, 211 TCPNoDelay: true, 212 socketLinger: { on: true, linger: 10 }, 213 receiveBufferSize: 1 * 1024, 214 sendBufferSize: 1 * 1024 * 1024, 215 reuseAddress: false, 216 socketTimeout: 3000 217} 218 219export default class Server { 220 async startServer(){ 221 await tcpServer.listen(listenAddr) 222 let socketStateBase: socket.SocketStateBase = await tcpServer.getState(); 223 console.info(TAG + '====>socketStateBase:' + JSON.stringify(socketStateBase)); 224 tcpServer.on('connect', on_connect_callback); 225 console.info(TAG + '====>on_connect success!'); 226 await tcpServer.setExtraOptions(tcpExtraOptions); 227 console.info(TAG + '====>setExtraOptions success!'); 228 } 229}