• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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