1/* 2 * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 */ 15import socket from '@ohos.net.socket'; 16import type Socket from '../model/Socket'; 17import Logger from '../utils/Logger'; 18 19const TAG = 'Socket TlsSocket'; 20 21/** 22 * 证书文件可能过期,需要自行生成 23 */ 24const key = 25 '-----BEGIN RSA PRIVATE KEY-----\r\n' + 26 'MIIEowIBAAKCAQEAoDQ2S1RvsS5d9EZhVfWziC4+kWV2jqcJ3jnU9KSHx8y4sbis\r\n' + 27 '4EegBWFjHIXoHSV6JWBSet63LfYohZoamJkYncZ+W4aHcFVUDub/Oae7Zjsvpzlb\r\n' + 28 'isD9wD7x4xp0PEqOe2WYfGmMeF7Itp/4BYT8hysRRrU0kzNQiNZY2De9n27M6i0R\r\n' + 29 'if323rd7WKyGT/JO1Ap5r+I4D7YzoKSkhBfWCCvgzM8Tf7SeKqyFCXVtX6FlFnyO\r\n' + 30 'H1falcfTzgMf0uKXlrjyh00IXTLbgCVTAQl0/B1E9h1PKlzmTqPLNk0Lg+xQd8JG\r\n' + 31 'MjN6YTs59XMTEPtb/SCS63UIaGKCHEvL/tRGqwIDAQABAoIBAEjnec3OHwYCk78W\r\n' + 32 'SDVWGt1eLhr8kXdZjKQUrVSniyLhhytZX1KxRaEtMG1KgtbAt1VLAD3qHHJOEyK5\r\n' + 33 'fmDzSsCCE/6Sug/kxNwDQyJ5sk5ToNv4vi/mo5NZEbrHzx2g0DZXhY0Ye1RLzgtN\r\n' + 34 'wRDB9CmO7829qK9UKtIauVOsCh8DFOnkk5RSqrkHjfQMJhkJnFqLnHss4PxDlrB0\r\n' + 35 'dTGmMTl9D41rVI4NXEvso3Io/aZt9OEvh3vCfZyvDWFdnoNCaGIjJn2hSE+WqvYP\r\n' + 36 '7aPF+pYA3u4mv0rvrXWrXb09zaD/WPpv4bsa5UnfXcM6q1vEi6iG9NThHnN1GW3h\r\n' + 37 'dwZLqAECgYEAzDj7fAaJ9SNWxTvJF+y5yZMxw5ij4J4Z/jheHA6xA7llRjqKf/F1\r\n' + 38 'l4on67YStA34G33lUfI29N6DUK1qPeXy6duredKug5H49sZ1nFYBjRj3A7OzyXs9\r\n' + 39 'Jz+1sWPFiOg/SieothzJPYfhOCnmT+2g4wqJnx2RZziCWvs8xfy3cqkCgYEAyNI2\r\n' + 40 'ACZInaYSF++d/OaoIYJtHU+/MtVHcfBrkOvT2BQlkJfOLFVfEwuQ09esegK6oemV\r\n' + 41 'POdGT3lbOV9ncQZ5MUMxp6s2o7AKshNGeuTRzu0Tq/ryeJ9Wv0l/g3/jtW8RDyfr\r\n' + 42 'uXc6two0T4G59Xx8vlQ3HMRcmMUh9wjuS29pVzMCgYB1YcdCyWtgSFimcy+pnbpH\r\n' + 43 '31/6IfEHuTgNhA6rp9Ic5uIMFLfoxDunx5QcioGDlofmHV3C1Sq7Ym4t4A8x1srh\r\n' + 44 'mg6crfj6zNtB1F5jZpfrps7MBO0wwLIsrhTcChHPGFbQY604R6FvyXstUf/8LwSL\r\n' + 45 'm1Hw8AjUQInEi6Wp0xEKSQKBgHKUxizlqw8QH0i69kjDDnE4KqvLwYrud/pBtA4X\r\n' + 46 'EGM8c4aBpyhSeZGzSqokZ4uiHPye+wCp8MsNsggVMD8j82gxL5a8MMvKeP/L0a3y\r\n' + 47 '+ub3C/9XiptaRrOT6waLpM/zlCcynuPObJjdYKVwnjq8EazC/kMSosajy9JYrSYr\r\n' + 48 'Zk5TAoGBAL2gxQyU2swvRemOA5PnLviqf++TUZdbCKlW7x1Xoj1xJVFH9Ql0ocGD\r\n' + 49 'cgEiYCSS4eaEbUnsMtAStUwXBH9DPVQRUOpxCvAuMFnP5OeUEAZ6rKrp5E3iuDz2\r\n' + 50 'dbxwe2wphU8yH+wC1xWd4uFKK2MRUH+3XAR02MmzGaXTarDHO1fN\r\n' + 51 '-----END RSA PRIVATE KEY-----\r\n'; 52 53const cert = 54 '-----BEGIN CERTIFICATE-----\r\n' + 55 'MIIC+DCCAeACFE+6YAe2yhFoBO5u1tsROSqQcaqYMA0GCSqGSIb3DQEBBQUAMDMx\r\n' + 56 'MTAvBgNVBAoMKHd3dy50ZXN0LmNvbSBEb2RneSBDZXJ0aWZpY2F0ZSBBdXRob3Jp\r\n' + 57 'dHkwHhcNMjMwNDE0MDM1NzQzWhcNMzYxMjIxMDM1NzQzWjA+MSgwJgYDVQQKDB93\r\n' + 58 'd3cudGVzdC5jb20gRGV2aWNlIENlcnRpZmljYXRlMRIwEAYDVQQDDAkxMjcuMC4w\r\n' + 59 'LjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgNDZLVG+xLl30RmFV\r\n' + 60 '9bOILj6RZXaOpwneOdT0pIfHzLixuKzgR6AFYWMchegdJXolYFJ63rct9iiFmhqY\r\n' + 61 'mRidxn5bhodwVVQO5v85p7tmOy+nOVuKwP3APvHjGnQ8So57ZZh8aYx4Xsi2n/gF\r\n' + 62 'hPyHKxFGtTSTM1CI1ljYN72fbszqLRGJ/fbet3tYrIZP8k7UCnmv4jgPtjOgpKSE\r\n' + 63 'F9YIK+DMzxN/tJ4qrIUJdW1foWUWfI4fV9qVx9POAx/S4peWuPKHTQhdMtuAJVMB\r\n' + 64 'CXT8HUT2HU8qXOZOo8s2TQuD7FB3wkYyM3phOzn1cxMQ+1v9IJLrdQhoYoIcS8v+\r\n' + 65 '1EarAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAAcEuP2YbnjMb69hPtvKlrDxW71K\r\n' + 66 'O9PJnDc40eZ6ZFnepTgCmyZrBepgCVylBwCh2OMze9ovwrw8gnNI5MVHijb1EFh6\r\n' + 67 'j2JPTQ+giG9SVxrpyrbNyRydKeBUz8RqhXHRlS6RfDReL4sG2KDkYO3XHaaU2Bu0\r\n' + 68 'ErKqDXbBcFkCuUanM2JWL9F5i0brqdGQ8+dmCac8Tz2ABkRF+ZlpqDg1IO3OHryD\r\n' + 69 'hIOxG8Ehshk0rpYBQv1McR4ezancG/eswxrFKu0L3SxFeFA7gz+Rv7Fdeb67Uupr\r\n' + 70 'VY4NzyUuHYBoJMjJMsUH7sNdKUNQz66G89jG6K/kPOaCpVzmK6miJiX2oPg=\r\n' + 71 '-----END CERTIFICATE-----\r\n'; 72 73const ca = 74 '-----BEGIN CERTIFICATE-----\r\n' + 75 'MIIC7TCCAdUCFC8NFFp/DPsC5oZ52erAUBE3SVxBMA0GCSqGSIb3DQEBBQUAMDMx\r\n' + 76 'MTAvBgNVBAoMKHd3dy50ZXN0LmNvbSBEb2RneSBDZXJ0aWZpY2F0ZSBBdXRob3Jp\r\n' + 77 'dHkwHhcNMjMwNDE0MDM1NzQzWhcNMzYxMjIxMDM1NzQzWjAzMTEwLwYDVQQKDCh3\r\n' + 78 'd3cudGVzdC5jb20gRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkq\r\n' + 79 'hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8IEpaZ6WaHbuNHzQ5gr5XH0ozRxrnF3\r\n' + 80 '2uKxtu/YkfEBQriM8ZlT2lTBjEy748lxPx3SS8OkPu8opE1E16UlSSGtI0gQAPUI\r\n' + 81 '3Jkdx0z3xj9iKSp14J+3ZZ61i+K3fDBkdZSEk+0KjinzjERvsgkkzDk4ZQCORwcV\r\n' + 82 'jsUi+M3dqQm8ARELQgTRkTBfof+F2vOR0Ufc5m14z50TvhnMRUw+fEcDe5cnKok0\r\n' + 83 'C1QUgwC9m6Q9fzS1JMdPYMdFZQJ12ACr1B7g5m/i6xCxuqBxmtP/2DiqhsSIMQy4\r\n' + 84 'XDU4CyPneoWQMz4nObJymxDvoAe86foFfPWzM6sAEZeGxJUooI19dQIDAQABMA0G\r\n' + 85 'CSqGSIb3DQEBBQUAA4IBAQAQ1vZ9QWS/YS5cVuv5wvXxHu2M2LKWOzDvb7FTn46q\r\n' + 86 'irTOCVx0H1su6wktGMuFsgYNkKdd2xTiJeggDqHGMNkTul9XbY5VM0sWJaXoYrPQ\r\n' + 87 '55BylXSl4miGIkVWTYHZNgeSBzE1vIRWuvXgo0DGWJ8a1NpUxYG0DCkGY1UPipo9\r\n' + 88 'YTjnK8Rtx6fsyg3Wn3G5HG+8xMkOGsamCYTee8ASxHbdziS8U4VLAAhZgvyPI1ZK\r\n' + 89 'uhLreTaRrguLyz4qpX/JrLhkrOkwZN+ueHToQGIOV1pleEXRNO0y9JZ4tZCkKbsH\r\n' + 90 'G4o77ax02PiiQ0R5Np1ju5t+s63NXV/bURIjhRafb2B5\r\n' + 91 '-----END CERTIFICATE-----\r\n'; 92 93export default class TlsSocket implements Socket { 94 private tlsSocket: socket.TLSSocket = null; 95 96 /** 97 * 创建Socket 98 * @param localIp 99 * @param port 100 */ 101 async createSocket(localIp: string, port: number): Promise<boolean> { 102 Logger.info(`${TAG} tls bind localIp: ${localIp}`); 103 try { 104 if (this.tlsSocket) { 105 await this.closeSocket(); 106 } 107 108 this.tlsSocket = socket.constructTLSSocketInstance(); 109 110 await this.tlsSocket.bind({ 111 address: localIp, 112 port: port, 113 family: 1, 114 }); 115 Logger.info(`${TAG} tls bind sucess`); 116 return true; 117 } catch (e) { 118 Logger.error(`${TAG} tls bind error ${JSON.stringify(e)}}`); 119 } 120 return false; 121 } 122 123 /** 124 * 连接Socket 125 * @param address 126 * @param port 127 */ 128 async connectSocket(address: string, port: number): Promise<boolean> { 129 Logger.info(`${TAG} tls connectSocket address: ${address}`); 130 try { 131 if (!this.tlsSocket) { 132 return false; 133 } 134 135 if (await this.isConnected()) { 136 Logger.info(`${TAG} tls connectSocket sucess`); 137 return true; 138 } 139 140 let options = { 141 address: { 142 address: address, 143 port: port, 144 family: 1, 145 }, 146 secureOptions: { 147 key: key, 148 cert: cert, 149 ca: [ca], 150 protocols: [socket.Protocol.TLSv12], 151 cipherSuite: 'ALL:@SECLEVEL=0', 152 }, 153 }; 154 155 await this.tlsSocket.connect(options); 156 157 await this.tlsSocket.setExtraOptions({}); 158 Logger.info(`${TAG} tls connectSocket sucess`); 159 return true; 160 } catch (e) { 161 Logger.error(`${TAG} tls connectSocket error ${JSON.stringify(e)}}`); 162 } 163 return false; 164 } 165 166 /** 167 * 关闭Socket 168 */ 169 async closeSocket(): Promise<void> { 170 if (!this.tlsSocket) { 171 return; 172 } 173 await this.tlsSocket.close(); 174 this.tlsSocket.off('connect'); 175 this.tlsSocket.off('message'); 176 this.tlsSocket = null; 177 } 178 179 /** 180 * 发送数据 181 * @param data 182 */ 183 async sendData(data: string): Promise<void> { 184 if (!this.tlsSocket) { 185 return; 186 } 187 Logger.info(`${TAG} tls sendData data ${JSON.stringify(data)}`); 188 try { 189 await this.tlsSocket.send(data); 190 } catch (e) { 191 Logger.error(`${TAG} tls sendData error ${JSON.stringify(e)}}`); 192 } 193 } 194 195 /** 196 * 判断是否连接 197 */ 198 async isConnected(): Promise<boolean> { 199 if (!this.tlsSocket) { 200 return false; 201 } 202 203 try { 204 let state = await this.tlsSocket.getState(); 205 if (state.isConnected) { 206 return true; 207 } 208 } catch (e) { 209 Logger.error(`${TAG} tls getState error ${JSON.stringify(e)}}`); 210 } 211 return false; 212 } 213 214 /** 215 * 订阅消息 216 * @param callback 217 */ 218 setOnMessageReceivedListener(callback): void { 219 if (!this.tlsSocket) { 220 return; 221 } 222 223 this.tlsSocket.on('message', (data) => { 224 Logger.info(`${TAG} TLS data: ` + JSON.stringify(data)); 225 let buffer = data.message; 226 callback(buffer); 227 }); 228 } 229 230 /** 231 * TLS 关闭事件订阅 232 * @param callback 233 */ 234 setOnCloseListener(callback): void { 235 Logger.info(`${TAG} TLS setOnCloseListener into`); 236 this.tlsSocket.on('close', () => { 237 Logger.info(`${TAG} TLS setOnCloseListener onClose:`); 238 callback(); 239 this.closeSocket(); 240 }); 241 242 this.tlsSocket.on('error', (data) => { 243 Logger.info( 244 `${TAG} TLS setOnCloseListener onClose:` + JSON.stringify(data) 245 ); 246 callback(); 247 this.closeSocket(); 248 }); 249 } 250} 251