1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci#include "uv.h"
23e66f31c5Sopenharmony_ci#include "task.h"
24e66f31c5Sopenharmony_ci#include <stdio.h>
25e66f31c5Sopenharmony_ci#include <stdlib.h>
26e66f31c5Sopenharmony_ci#include <string.h>
27e66f31c5Sopenharmony_ci
28e66f31c5Sopenharmony_ci#ifndef _WIN32
29e66f31c5Sopenharmony_ci# include <unistd.h>
30e66f31c5Sopenharmony_ci# include <sys/socket.h>
31e66f31c5Sopenharmony_ci# include <sys/un.h>
32e66f31c5Sopenharmony_ci#endif
33e66f31c5Sopenharmony_ci
34e66f31c5Sopenharmony_cistatic int send_cb_called = 0;
35e66f31c5Sopenharmony_cistatic int close_cb_called = 0;
36e66f31c5Sopenharmony_ci
37e66f31c5Sopenharmony_cistatic uv_udp_send_t send_req;
38e66f31c5Sopenharmony_ci
39e66f31c5Sopenharmony_ci
40e66f31c5Sopenharmony_cistatic void startup(void) {
41e66f31c5Sopenharmony_ci#ifdef _WIN32
42e66f31c5Sopenharmony_ci    struct WSAData wsa_data;
43e66f31c5Sopenharmony_ci    int r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
44e66f31c5Sopenharmony_ci    ASSERT_OK(r);
45e66f31c5Sopenharmony_ci#endif
46e66f31c5Sopenharmony_ci}
47e66f31c5Sopenharmony_ci
48e66f31c5Sopenharmony_ci
49e66f31c5Sopenharmony_cistatic uv_os_sock_t create_udp_socket(void) {
50e66f31c5Sopenharmony_ci  uv_os_sock_t sock;
51e66f31c5Sopenharmony_ci
52e66f31c5Sopenharmony_ci  sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
53e66f31c5Sopenharmony_ci#ifdef _WIN32
54e66f31c5Sopenharmony_ci  ASSERT_NE(sock, INVALID_SOCKET);
55e66f31c5Sopenharmony_ci#else
56e66f31c5Sopenharmony_ci  ASSERT_GE(sock, 0);
57e66f31c5Sopenharmony_ci#endif
58e66f31c5Sopenharmony_ci
59e66f31c5Sopenharmony_ci#ifndef _WIN32
60e66f31c5Sopenharmony_ci  {
61e66f31c5Sopenharmony_ci    /* Allow reuse of the port. */
62e66f31c5Sopenharmony_ci    int yes = 1;
63e66f31c5Sopenharmony_ci    int r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
64e66f31c5Sopenharmony_ci    ASSERT_OK(r);
65e66f31c5Sopenharmony_ci  }
66e66f31c5Sopenharmony_ci#endif
67e66f31c5Sopenharmony_ci
68e66f31c5Sopenharmony_ci  return sock;
69e66f31c5Sopenharmony_ci}
70e66f31c5Sopenharmony_ci
71e66f31c5Sopenharmony_ci
72e66f31c5Sopenharmony_cistatic void close_socket(uv_os_sock_t sock) {
73e66f31c5Sopenharmony_ci  int r;
74e66f31c5Sopenharmony_ci#ifdef _WIN32
75e66f31c5Sopenharmony_ci  r = closesocket(sock);
76e66f31c5Sopenharmony_ci#else
77e66f31c5Sopenharmony_ci  r = close(sock);
78e66f31c5Sopenharmony_ci#endif
79e66f31c5Sopenharmony_ci  ASSERT_OK(r);
80e66f31c5Sopenharmony_ci}
81e66f31c5Sopenharmony_ci
82e66f31c5Sopenharmony_ci
83e66f31c5Sopenharmony_cistatic void alloc_cb(uv_handle_t* handle,
84e66f31c5Sopenharmony_ci                     size_t suggested_size,
85e66f31c5Sopenharmony_ci                     uv_buf_t* buf) {
86e66f31c5Sopenharmony_ci  static char slab[65536];
87e66f31c5Sopenharmony_ci  ASSERT_LE(suggested_size, sizeof(slab));
88e66f31c5Sopenharmony_ci  buf->base = slab;
89e66f31c5Sopenharmony_ci  buf->len = sizeof(slab);
90e66f31c5Sopenharmony_ci}
91e66f31c5Sopenharmony_ci
92e66f31c5Sopenharmony_ci
93e66f31c5Sopenharmony_cistatic void close_cb(uv_handle_t* handle) {
94e66f31c5Sopenharmony_ci  ASSERT_NOT_NULL(handle);
95e66f31c5Sopenharmony_ci  close_cb_called++;
96e66f31c5Sopenharmony_ci}
97e66f31c5Sopenharmony_ci
98e66f31c5Sopenharmony_ci
99e66f31c5Sopenharmony_cistatic void recv_cb(uv_udp_t* handle,
100e66f31c5Sopenharmony_ci                       ssize_t nread,
101e66f31c5Sopenharmony_ci                       const uv_buf_t* buf,
102e66f31c5Sopenharmony_ci                       const struct sockaddr* addr,
103e66f31c5Sopenharmony_ci                       unsigned flags) {
104e66f31c5Sopenharmony_ci  int r;
105e66f31c5Sopenharmony_ci
106e66f31c5Sopenharmony_ci  if (nread < 0) {
107e66f31c5Sopenharmony_ci    ASSERT(0 && "unexpected error");
108e66f31c5Sopenharmony_ci  }
109e66f31c5Sopenharmony_ci
110e66f31c5Sopenharmony_ci  if (nread == 0) {
111e66f31c5Sopenharmony_ci    /* Returning unused buffer. Don't count towards sv_recv_cb_called */
112e66f31c5Sopenharmony_ci    ASSERT_NULL(addr);
113e66f31c5Sopenharmony_ci    return;
114e66f31c5Sopenharmony_ci  }
115e66f31c5Sopenharmony_ci
116e66f31c5Sopenharmony_ci  ASSERT_OK(flags);
117e66f31c5Sopenharmony_ci
118e66f31c5Sopenharmony_ci  ASSERT_NOT_NULL(addr);
119e66f31c5Sopenharmony_ci  ASSERT_EQ(4, nread);
120e66f31c5Sopenharmony_ci  ASSERT_OK(memcmp("PING", buf->base, nread));
121e66f31c5Sopenharmony_ci
122e66f31c5Sopenharmony_ci  r = uv_udp_recv_stop(handle);
123e66f31c5Sopenharmony_ci  ASSERT_OK(r);
124e66f31c5Sopenharmony_ci
125e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*) handle, close_cb);
126e66f31c5Sopenharmony_ci}
127e66f31c5Sopenharmony_ci
128e66f31c5Sopenharmony_ci
129e66f31c5Sopenharmony_cistatic void send_cb(uv_udp_send_t* req, int status) {
130e66f31c5Sopenharmony_ci  ASSERT_NOT_NULL(req);
131e66f31c5Sopenharmony_ci  ASSERT_OK(status);
132e66f31c5Sopenharmony_ci
133e66f31c5Sopenharmony_ci  send_cb_called++;
134e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*)req->handle, close_cb);
135e66f31c5Sopenharmony_ci}
136e66f31c5Sopenharmony_ci
137e66f31c5Sopenharmony_ci
138e66f31c5Sopenharmony_ciTEST_IMPL(udp_open) {
139e66f31c5Sopenharmony_ci  struct sockaddr_in addr;
140e66f31c5Sopenharmony_ci  uv_buf_t buf = uv_buf_init("PING", 4);
141e66f31c5Sopenharmony_ci  uv_udp_t client, client2;
142e66f31c5Sopenharmony_ci  uv_os_sock_t sock;
143e66f31c5Sopenharmony_ci  int r;
144e66f31c5Sopenharmony_ci
145e66f31c5Sopenharmony_ci  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
146e66f31c5Sopenharmony_ci
147e66f31c5Sopenharmony_ci  startup();
148e66f31c5Sopenharmony_ci  sock = create_udp_socket();
149e66f31c5Sopenharmony_ci
150e66f31c5Sopenharmony_ci  r = uv_udp_init(uv_default_loop(), &client);
151e66f31c5Sopenharmony_ci  ASSERT_OK(r);
152e66f31c5Sopenharmony_ci
153e66f31c5Sopenharmony_ci  r = uv_udp_open(&client, sock);
154e66f31c5Sopenharmony_ci  ASSERT_OK(r);
155e66f31c5Sopenharmony_ci
156e66f31c5Sopenharmony_ci  r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0);
157e66f31c5Sopenharmony_ci  ASSERT_OK(r);
158e66f31c5Sopenharmony_ci
159e66f31c5Sopenharmony_ci  r = uv_udp_recv_start(&client, alloc_cb, recv_cb);
160e66f31c5Sopenharmony_ci  ASSERT_OK(r);
161e66f31c5Sopenharmony_ci
162e66f31c5Sopenharmony_ci  r = uv_udp_send(&send_req,
163e66f31c5Sopenharmony_ci                  &client,
164e66f31c5Sopenharmony_ci                  &buf,
165e66f31c5Sopenharmony_ci                  1,
166e66f31c5Sopenharmony_ci                  (const struct sockaddr*) &addr,
167e66f31c5Sopenharmony_ci                  send_cb);
168e66f31c5Sopenharmony_ci  ASSERT_OK(r);
169e66f31c5Sopenharmony_ci
170e66f31c5Sopenharmony_ci#ifndef _WIN32
171e66f31c5Sopenharmony_ci  {
172e66f31c5Sopenharmony_ci    r = uv_udp_init(uv_default_loop(), &client2);
173e66f31c5Sopenharmony_ci    ASSERT_OK(r);
174e66f31c5Sopenharmony_ci
175e66f31c5Sopenharmony_ci    r = uv_udp_open(&client2, sock);
176e66f31c5Sopenharmony_ci    ASSERT_EQ(r, UV_EEXIST);
177e66f31c5Sopenharmony_ci
178e66f31c5Sopenharmony_ci    uv_close((uv_handle_t*) &client2, NULL);
179e66f31c5Sopenharmony_ci  }
180e66f31c5Sopenharmony_ci#else  /* _WIN32 */
181e66f31c5Sopenharmony_ci  (void)client2;
182e66f31c5Sopenharmony_ci#endif
183e66f31c5Sopenharmony_ci
184e66f31c5Sopenharmony_ci  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
185e66f31c5Sopenharmony_ci
186e66f31c5Sopenharmony_ci  ASSERT_EQ(1, send_cb_called);
187e66f31c5Sopenharmony_ci  ASSERT_EQ(1, close_cb_called);
188e66f31c5Sopenharmony_ci
189e66f31c5Sopenharmony_ci  ASSERT_OK(client.send_queue_size);
190e66f31c5Sopenharmony_ci
191e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
192e66f31c5Sopenharmony_ci  return 0;
193e66f31c5Sopenharmony_ci}
194e66f31c5Sopenharmony_ci
195e66f31c5Sopenharmony_ci
196e66f31c5Sopenharmony_ciTEST_IMPL(udp_open_twice) {
197e66f31c5Sopenharmony_ci  uv_udp_t client;
198e66f31c5Sopenharmony_ci  uv_os_sock_t sock1, sock2;
199e66f31c5Sopenharmony_ci  int r;
200e66f31c5Sopenharmony_ci
201e66f31c5Sopenharmony_ci  startup();
202e66f31c5Sopenharmony_ci  sock1 = create_udp_socket();
203e66f31c5Sopenharmony_ci  sock2 = create_udp_socket();
204e66f31c5Sopenharmony_ci
205e66f31c5Sopenharmony_ci  r = uv_udp_init(uv_default_loop(), &client);
206e66f31c5Sopenharmony_ci  ASSERT_OK(r);
207e66f31c5Sopenharmony_ci
208e66f31c5Sopenharmony_ci  r = uv_udp_open(&client, sock1);
209e66f31c5Sopenharmony_ci  ASSERT_OK(r);
210e66f31c5Sopenharmony_ci
211e66f31c5Sopenharmony_ci  r = uv_udp_open(&client, sock2);
212e66f31c5Sopenharmony_ci  ASSERT_EQ(r, UV_EBUSY);
213e66f31c5Sopenharmony_ci  close_socket(sock2);
214e66f31c5Sopenharmony_ci
215e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*) &client, NULL);
216e66f31c5Sopenharmony_ci  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
217e66f31c5Sopenharmony_ci
218e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
219e66f31c5Sopenharmony_ci  return 0;
220e66f31c5Sopenharmony_ci}
221e66f31c5Sopenharmony_ci
222e66f31c5Sopenharmony_ciTEST_IMPL(udp_open_bound) {
223e66f31c5Sopenharmony_ci  struct sockaddr_in addr;
224e66f31c5Sopenharmony_ci  uv_udp_t client;
225e66f31c5Sopenharmony_ci  uv_os_sock_t sock;
226e66f31c5Sopenharmony_ci  int r;
227e66f31c5Sopenharmony_ci
228e66f31c5Sopenharmony_ci  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
229e66f31c5Sopenharmony_ci
230e66f31c5Sopenharmony_ci  startup();
231e66f31c5Sopenharmony_ci  sock = create_udp_socket();
232e66f31c5Sopenharmony_ci
233e66f31c5Sopenharmony_ci  r = bind(sock, (struct sockaddr*) &addr, sizeof(addr));
234e66f31c5Sopenharmony_ci  ASSERT_OK(r);
235e66f31c5Sopenharmony_ci
236e66f31c5Sopenharmony_ci  r = uv_udp_init(uv_default_loop(), &client);
237e66f31c5Sopenharmony_ci  ASSERT_OK(r);
238e66f31c5Sopenharmony_ci
239e66f31c5Sopenharmony_ci  r = uv_udp_open(&client, sock);
240e66f31c5Sopenharmony_ci  ASSERT_OK(r);
241e66f31c5Sopenharmony_ci
242e66f31c5Sopenharmony_ci  r = uv_udp_recv_start(&client, alloc_cb, recv_cb);
243e66f31c5Sopenharmony_ci  ASSERT_OK(r);
244e66f31c5Sopenharmony_ci
245e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*) &client, NULL);
246e66f31c5Sopenharmony_ci  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
247e66f31c5Sopenharmony_ci
248e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
249e66f31c5Sopenharmony_ci  return 0;
250e66f31c5Sopenharmony_ci}
251e66f31c5Sopenharmony_ci
252e66f31c5Sopenharmony_ciTEST_IMPL(udp_open_connect) {
253e66f31c5Sopenharmony_ci  struct sockaddr_in addr;
254e66f31c5Sopenharmony_ci  uv_buf_t buf = uv_buf_init("PING", 4);
255e66f31c5Sopenharmony_ci  uv_udp_t client;
256e66f31c5Sopenharmony_ci  uv_udp_t server;
257e66f31c5Sopenharmony_ci  uv_os_sock_t sock;
258e66f31c5Sopenharmony_ci  int r;
259e66f31c5Sopenharmony_ci
260e66f31c5Sopenharmony_ci  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
261e66f31c5Sopenharmony_ci
262e66f31c5Sopenharmony_ci  startup();
263e66f31c5Sopenharmony_ci  sock = create_udp_socket();
264e66f31c5Sopenharmony_ci
265e66f31c5Sopenharmony_ci  r = uv_udp_init(uv_default_loop(), &client);
266e66f31c5Sopenharmony_ci  ASSERT_OK(r);
267e66f31c5Sopenharmony_ci
268e66f31c5Sopenharmony_ci  r = connect(sock, (const struct sockaddr*) &addr, sizeof(addr));
269e66f31c5Sopenharmony_ci  ASSERT_OK(r);
270e66f31c5Sopenharmony_ci
271e66f31c5Sopenharmony_ci  r = uv_udp_open(&client, sock);
272e66f31c5Sopenharmony_ci  ASSERT_OK(r);
273e66f31c5Sopenharmony_ci
274e66f31c5Sopenharmony_ci  r = uv_udp_init(uv_default_loop(), &server);
275e66f31c5Sopenharmony_ci  ASSERT_OK(r);
276e66f31c5Sopenharmony_ci
277e66f31c5Sopenharmony_ci  r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
278e66f31c5Sopenharmony_ci  ASSERT_OK(r);
279e66f31c5Sopenharmony_ci
280e66f31c5Sopenharmony_ci  r = uv_udp_recv_start(&server, alloc_cb, recv_cb);
281e66f31c5Sopenharmony_ci  ASSERT_OK(r);
282e66f31c5Sopenharmony_ci
283e66f31c5Sopenharmony_ci  r = uv_udp_send(&send_req,
284e66f31c5Sopenharmony_ci                  &client,
285e66f31c5Sopenharmony_ci                  &buf,
286e66f31c5Sopenharmony_ci                  1,
287e66f31c5Sopenharmony_ci                  NULL,
288e66f31c5Sopenharmony_ci                  send_cb);
289e66f31c5Sopenharmony_ci  ASSERT_OK(r);
290e66f31c5Sopenharmony_ci
291e66f31c5Sopenharmony_ci  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
292e66f31c5Sopenharmony_ci
293e66f31c5Sopenharmony_ci  ASSERT_EQ(1, send_cb_called);
294e66f31c5Sopenharmony_ci  ASSERT_EQ(2, close_cb_called);
295e66f31c5Sopenharmony_ci
296e66f31c5Sopenharmony_ci  ASSERT_OK(client.send_queue_size);
297e66f31c5Sopenharmony_ci
298e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
299e66f31c5Sopenharmony_ci  return 0;
300e66f31c5Sopenharmony_ci}
301e66f31c5Sopenharmony_ci
302e66f31c5Sopenharmony_ci#ifndef _WIN32
303e66f31c5Sopenharmony_ciTEST_IMPL(udp_send_unix) {
304e66f31c5Sopenharmony_ci  /* Test that "uv_udp_send()" supports sending over
305e66f31c5Sopenharmony_ci     a "sockaddr_un" address. */
306e66f31c5Sopenharmony_ci  struct sockaddr_un addr;
307e66f31c5Sopenharmony_ci  uv_udp_t handle;
308e66f31c5Sopenharmony_ci  uv_udp_send_t req;
309e66f31c5Sopenharmony_ci  uv_loop_t* loop;
310e66f31c5Sopenharmony_ci  uv_buf_t buf = uv_buf_init("PING", 4);
311e66f31c5Sopenharmony_ci  int fd;
312e66f31c5Sopenharmony_ci  int r;
313e66f31c5Sopenharmony_ci
314e66f31c5Sopenharmony_ci  loop = uv_default_loop();
315e66f31c5Sopenharmony_ci
316e66f31c5Sopenharmony_ci  memset(&addr, 0, sizeof addr);
317e66f31c5Sopenharmony_ci  addr.sun_family = AF_UNIX;
318e66f31c5Sopenharmony_ci  ASSERT_LT(strlen(TEST_PIPENAME), sizeof(addr.sun_path));
319e66f31c5Sopenharmony_ci  memcpy(addr.sun_path, TEST_PIPENAME, strlen(TEST_PIPENAME));
320e66f31c5Sopenharmony_ci
321e66f31c5Sopenharmony_ci  fd = socket(AF_UNIX, SOCK_STREAM, 0);
322e66f31c5Sopenharmony_ci  ASSERT_GE(fd, 0);
323e66f31c5Sopenharmony_ci
324e66f31c5Sopenharmony_ci  unlink(TEST_PIPENAME);
325e66f31c5Sopenharmony_ci  ASSERT_OK(bind(fd, (const struct sockaddr*)&addr, sizeof addr));
326e66f31c5Sopenharmony_ci  ASSERT_OK(listen(fd, 1));
327e66f31c5Sopenharmony_ci
328e66f31c5Sopenharmony_ci  r = uv_udp_init(loop, &handle);
329e66f31c5Sopenharmony_ci  ASSERT_OK(r);
330e66f31c5Sopenharmony_ci  r = uv_udp_open(&handle, fd);
331e66f31c5Sopenharmony_ci  ASSERT_OK(r);
332e66f31c5Sopenharmony_ci  uv_run(loop, UV_RUN_DEFAULT);
333e66f31c5Sopenharmony_ci
334e66f31c5Sopenharmony_ci  r = uv_udp_send(&req,
335e66f31c5Sopenharmony_ci                  &handle,
336e66f31c5Sopenharmony_ci                  &buf,
337e66f31c5Sopenharmony_ci                  1,
338e66f31c5Sopenharmony_ci                  (const struct sockaddr*) &addr,
339e66f31c5Sopenharmony_ci                  NULL);
340e66f31c5Sopenharmony_ci  ASSERT_OK(r);
341e66f31c5Sopenharmony_ci
342e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*)&handle, NULL);
343e66f31c5Sopenharmony_ci  uv_run(loop, UV_RUN_DEFAULT);
344e66f31c5Sopenharmony_ci  close(fd);
345e66f31c5Sopenharmony_ci  unlink(TEST_PIPENAME);
346e66f31c5Sopenharmony_ci
347e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
348e66f31c5Sopenharmony_ci  return 0;
349e66f31c5Sopenharmony_ci}
350e66f31c5Sopenharmony_ci#endif
351