1c87c5fbaSopenharmony_ci/*
2c87c5fbaSopenharmony_ci * coap_tcp.c -- TCP functions for libcoap
3c87c5fbaSopenharmony_ci *
4c87c5fbaSopenharmony_ci * Copyright (C) 2019-2023 Olaf Bergmann <bergmann@tzi.org> and others
5c87c5fbaSopenharmony_ci *
6c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause
7c87c5fbaSopenharmony_ci *
8c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see README for terms
9c87c5fbaSopenharmony_ci * of use.
10c87c5fbaSopenharmony_ci */
11c87c5fbaSopenharmony_ci
12c87c5fbaSopenharmony_ci/**
13c87c5fbaSopenharmony_ci * @file coap_tcp.c
14c87c5fbaSopenharmony_ci * @brief CoAP TCP handling functions
15c87c5fbaSopenharmony_ci */
16c87c5fbaSopenharmony_ci
17c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h"
18c87c5fbaSopenharmony_ci
19c87c5fbaSopenharmony_ci#include <sys/types.h>
20c87c5fbaSopenharmony_ci#ifdef HAVE_SYS_SOCKET_H
21c87c5fbaSopenharmony_ci# include <sys/socket.h>
22c87c5fbaSopenharmony_ci# define OPTVAL_T(t)         (t)
23c87c5fbaSopenharmony_ci# define OPTVAL_GT(t)        (t)
24c87c5fbaSopenharmony_ci#endif
25c87c5fbaSopenharmony_ci#ifdef HAVE_SYS_IOCTL_H
26c87c5fbaSopenharmony_ci#include <sys/ioctl.h>
27c87c5fbaSopenharmony_ci#endif
28c87c5fbaSopenharmony_ci#ifdef HAVE_WS2TCPIP_H
29c87c5fbaSopenharmony_ci#include <ws2tcpip.h>
30c87c5fbaSopenharmony_ci# define OPTVAL_T(t)         (const char*)(t)
31c87c5fbaSopenharmony_ci# define OPTVAL_GT(t)        (char*)(t)
32c87c5fbaSopenharmony_ci# undef CMSG_DATA
33c87c5fbaSopenharmony_ci# define CMSG_DATA WSA_CMSG_DATA
34c87c5fbaSopenharmony_ci#endif
35c87c5fbaSopenharmony_ci
36c87c5fbaSopenharmony_ciint
37c87c5fbaSopenharmony_cicoap_tcp_is_supported(void) {
38c87c5fbaSopenharmony_ci  return !COAP_DISABLE_TCP;
39c87c5fbaSopenharmony_ci}
40c87c5fbaSopenharmony_ci
41c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
42c87c5fbaSopenharmony_ciint
43c87c5fbaSopenharmony_cicoap_socket_connect_tcp1(coap_socket_t *sock,
44c87c5fbaSopenharmony_ci                         const coap_address_t *local_if,
45c87c5fbaSopenharmony_ci                         const coap_address_t *server,
46c87c5fbaSopenharmony_ci                         int default_port,
47c87c5fbaSopenharmony_ci                         coap_address_t *local_addr,
48c87c5fbaSopenharmony_ci                         coap_address_t *remote_addr) {
49c87c5fbaSopenharmony_ci  int on = 1;
50c87c5fbaSopenharmony_ci#if !defined(RIOT_VERSION) && COAP_IPV6_SUPPORT
51c87c5fbaSopenharmony_ci  int off = 0;
52c87c5fbaSopenharmony_ci#endif /* ! RIOT_VERSION && COAP_IPV6_SUPPORT */
53c87c5fbaSopenharmony_ci#ifdef _WIN32
54c87c5fbaSopenharmony_ci  u_long u_on = 1;
55c87c5fbaSopenharmony_ci#endif
56c87c5fbaSopenharmony_ci  coap_address_t connect_addr;
57c87c5fbaSopenharmony_ci  coap_address_copy(&connect_addr, server);
58c87c5fbaSopenharmony_ci
59c87c5fbaSopenharmony_ci  sock->flags &= ~COAP_SOCKET_CONNECTED;
60c87c5fbaSopenharmony_ci  sock->fd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0);
61c87c5fbaSopenharmony_ci
62c87c5fbaSopenharmony_ci  if (sock->fd == COAP_INVALID_SOCKET) {
63c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp1: socket: %s\n",
64c87c5fbaSopenharmony_ci                  coap_socket_strerror());
65c87c5fbaSopenharmony_ci    goto error;
66c87c5fbaSopenharmony_ci  }
67c87c5fbaSopenharmony_ci
68c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION
69c87c5fbaSopenharmony_ci#ifdef _WIN32
70c87c5fbaSopenharmony_ci  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
71c87c5fbaSopenharmony_ci#else
72c87c5fbaSopenharmony_ci  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
73c87c5fbaSopenharmony_ci#endif
74c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp1: ioctl FIONBIO: %s\n",
75c87c5fbaSopenharmony_ci                  coap_socket_strerror());
76c87c5fbaSopenharmony_ci  }
77c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
78c87c5fbaSopenharmony_ci
79c87c5fbaSopenharmony_ci  switch (server->addr.sa.sa_family) {
80c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT
81c87c5fbaSopenharmony_ci  case AF_INET:
82c87c5fbaSopenharmony_ci    if (connect_addr.addr.sin.sin_port == 0)
83c87c5fbaSopenharmony_ci      connect_addr.addr.sin.sin_port = htons(default_port);
84c87c5fbaSopenharmony_ci    break;
85c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */
86c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT
87c87c5fbaSopenharmony_ci  case AF_INET6:
88c87c5fbaSopenharmony_ci    if (connect_addr.addr.sin6.sin6_port == 0)
89c87c5fbaSopenharmony_ci      connect_addr.addr.sin6.sin6_port = htons(default_port);
90c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION
91c87c5fbaSopenharmony_ci    /* Configure the socket as dual-stacked */
92c87c5fbaSopenharmony_ci    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
93c87c5fbaSopenharmony_ci                   sizeof(off)) == COAP_SOCKET_ERROR)
94c87c5fbaSopenharmony_ci      coap_log_warn("coap_socket_connect_tcp1: setsockopt IPV6_V6ONLY: %s\n",
95c87c5fbaSopenharmony_ci                    coap_socket_strerror());
96c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
97c87c5fbaSopenharmony_ci    break;
98c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */
99c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT
100c87c5fbaSopenharmony_ci  case AF_UNIX:
101c87c5fbaSopenharmony_ci    break;
102c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */
103c87c5fbaSopenharmony_ci  default:
104c87c5fbaSopenharmony_ci    coap_log_alert("coap_socket_connect_tcp1: unsupported sa_family\n");
105c87c5fbaSopenharmony_ci    break;
106c87c5fbaSopenharmony_ci  }
107c87c5fbaSopenharmony_ci
108c87c5fbaSopenharmony_ci  if (local_if && local_if->addr.sa.sa_family) {
109c87c5fbaSopenharmony_ci    coap_address_copy(local_addr, local_if);
110c87c5fbaSopenharmony_ci    if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
111c87c5fbaSopenharmony_ci      coap_log_warn("coap_socket_connect_tcp1: setsockopt SO_REUSEADDR: %s\n",
112c87c5fbaSopenharmony_ci                    coap_socket_strerror());
113c87c5fbaSopenharmony_ci    if (bind(sock->fd, &local_if->addr.sa,
114c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT
115c87c5fbaSopenharmony_ci             local_if->addr.sa.sa_family == AF_INET ?
116c87c5fbaSopenharmony_ci             (socklen_t)sizeof(struct sockaddr_in) :
117c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */
118c87c5fbaSopenharmony_ci             (socklen_t)local_if->size) == COAP_SOCKET_ERROR) {
119c87c5fbaSopenharmony_ci      coap_log_warn("coap_socket_connect_tcp1: bind: %s\n",
120c87c5fbaSopenharmony_ci                    coap_socket_strerror());
121c87c5fbaSopenharmony_ci      goto error;
122c87c5fbaSopenharmony_ci    }
123c87c5fbaSopenharmony_ci  } else {
124c87c5fbaSopenharmony_ci    local_addr->addr.sa.sa_family = server->addr.sa.sa_family;
125c87c5fbaSopenharmony_ci  }
126c87c5fbaSopenharmony_ci
127c87c5fbaSopenharmony_ci  if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
128c87c5fbaSopenharmony_ci#ifdef _WIN32
129c87c5fbaSopenharmony_ci    if (WSAGetLastError() == WSAEWOULDBLOCK) {
130c87c5fbaSopenharmony_ci#else
131c87c5fbaSopenharmony_ci    if (errno == EINPROGRESS) {
132c87c5fbaSopenharmony_ci#endif
133c87c5fbaSopenharmony_ci      /*
134c87c5fbaSopenharmony_ci       * COAP_SOCKET_CONNECTED needs to be set here as there will be reads/writes
135c87c5fbaSopenharmony_ci       * by underlying TLS libraries during connect() and we do not want to
136c87c5fbaSopenharmony_ci       * assert() in coap_read_session() or coap_write_session() when called by coap_read()
137c87c5fbaSopenharmony_ci       */
138c87c5fbaSopenharmony_ci      sock->flags |= COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED;
139c87c5fbaSopenharmony_ci      return 1;
140c87c5fbaSopenharmony_ci    }
141c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp1: connect: %s\n",
142c87c5fbaSopenharmony_ci                  coap_socket_strerror());
143c87c5fbaSopenharmony_ci    goto error;
144c87c5fbaSopenharmony_ci  }
145c87c5fbaSopenharmony_ci
146c87c5fbaSopenharmony_ci  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
147c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp1: getsockname: %s\n",
148c87c5fbaSopenharmony_ci                  coap_socket_strerror());
149c87c5fbaSopenharmony_ci  }
150c87c5fbaSopenharmony_ci
151c87c5fbaSopenharmony_ci  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
152c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp1: getpeername: %s\n",
153c87c5fbaSopenharmony_ci                  coap_socket_strerror());
154c87c5fbaSopenharmony_ci  }
155c87c5fbaSopenharmony_ci
156c87c5fbaSopenharmony_ci  sock->flags |= COAP_SOCKET_CONNECTED;
157c87c5fbaSopenharmony_ci  return 1;
158c87c5fbaSopenharmony_ci
159c87c5fbaSopenharmony_cierror:
160c87c5fbaSopenharmony_ci  coap_socket_close(sock);
161c87c5fbaSopenharmony_ci  return 0;
162c87c5fbaSopenharmony_ci}
163c87c5fbaSopenharmony_ci
164c87c5fbaSopenharmony_ciint
165c87c5fbaSopenharmony_cicoap_socket_connect_tcp2(coap_socket_t *sock,
166c87c5fbaSopenharmony_ci                         coap_address_t *local_addr,
167c87c5fbaSopenharmony_ci                         coap_address_t *remote_addr) {
168c87c5fbaSopenharmony_ci  int error = 0;
169c87c5fbaSopenharmony_ci#ifdef _WIN32
170c87c5fbaSopenharmony_ci  int optlen = (int)sizeof(error);
171c87c5fbaSopenharmony_ci#else
172c87c5fbaSopenharmony_ci  socklen_t optlen = (socklen_t)sizeof(error);
173c87c5fbaSopenharmony_ci#endif
174c87c5fbaSopenharmony_ci
175c87c5fbaSopenharmony_ci  sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CAN_CONNECT);
176c87c5fbaSopenharmony_ci
177c87c5fbaSopenharmony_ci  if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error),
178c87c5fbaSopenharmony_ci                 &optlen) == COAP_SOCKET_ERROR) {
179c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_finish_connect_tcp: getsockopt: %s\n",
180c87c5fbaSopenharmony_ci                  coap_socket_strerror());
181c87c5fbaSopenharmony_ci  }
182c87c5fbaSopenharmony_ci
183c87c5fbaSopenharmony_ci  if (error) {
184c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_finish_connect_tcp: connect failed: %s\n",
185c87c5fbaSopenharmony_ci                  coap_socket_format_errno(error));
186c87c5fbaSopenharmony_ci    coap_socket_close(sock);
187c87c5fbaSopenharmony_ci    return 0;
188c87c5fbaSopenharmony_ci  }
189c87c5fbaSopenharmony_ci
190c87c5fbaSopenharmony_ci  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
191c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp: getsockname: %s\n",
192c87c5fbaSopenharmony_ci                  coap_socket_strerror());
193c87c5fbaSopenharmony_ci  }
194c87c5fbaSopenharmony_ci
195c87c5fbaSopenharmony_ci  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
196c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_connect_tcp: getpeername: %s\n",
197c87c5fbaSopenharmony_ci                  coap_socket_strerror());
198c87c5fbaSopenharmony_ci  }
199c87c5fbaSopenharmony_ci
200c87c5fbaSopenharmony_ci  return 1;
201c87c5fbaSopenharmony_ci}
202c87c5fbaSopenharmony_ci
203c87c5fbaSopenharmony_ciint
204c87c5fbaSopenharmony_cicoap_socket_bind_tcp(coap_socket_t *sock,
205c87c5fbaSopenharmony_ci                     const coap_address_t *listen_addr,
206c87c5fbaSopenharmony_ci                     coap_address_t *bound_addr) {
207c87c5fbaSopenharmony_ci  int on = 1;
208c87c5fbaSopenharmony_ci#if !defined(RIOT_VERSION) && COAP_IPV6_SUPPORT
209c87c5fbaSopenharmony_ci  int off = 0;
210c87c5fbaSopenharmony_ci#endif /* ! RIOT_VERSION && COAP_IPV6_SUPPORT */
211c87c5fbaSopenharmony_ci#ifdef _WIN32
212c87c5fbaSopenharmony_ci  u_long u_on = 1;
213c87c5fbaSopenharmony_ci#endif
214c87c5fbaSopenharmony_ci
215c87c5fbaSopenharmony_ci  sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_STREAM, 0);
216c87c5fbaSopenharmony_ci
217c87c5fbaSopenharmony_ci  if (sock->fd == COAP_INVALID_SOCKET) {
218c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_bind_tcp: socket: %s\n",
219c87c5fbaSopenharmony_ci                  coap_socket_strerror());
220c87c5fbaSopenharmony_ci    goto error;
221c87c5fbaSopenharmony_ci  }
222c87c5fbaSopenharmony_ci
223c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION
224c87c5fbaSopenharmony_ci#ifdef _WIN32
225c87c5fbaSopenharmony_ci  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
226c87c5fbaSopenharmony_ci#else
227c87c5fbaSopenharmony_ci  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
228c87c5fbaSopenharmony_ci#endif
229c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_bind_tcp: ioctl FIONBIO: %s\n",
230c87c5fbaSopenharmony_ci                  coap_socket_strerror());
231c87c5fbaSopenharmony_ci  }
232c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
233c87c5fbaSopenharmony_ci  if (setsockopt(sock->fd, SOL_SOCKET, SO_KEEPALIVE, OPTVAL_T(&on),
234c87c5fbaSopenharmony_ci                 sizeof(on)) == COAP_SOCKET_ERROR)
235c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_bind_tcp: setsockopt SO_KEEPALIVE: %s\n",
236c87c5fbaSopenharmony_ci                  coap_socket_strerror());
237c87c5fbaSopenharmony_ci
238c87c5fbaSopenharmony_ci  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
239c87c5fbaSopenharmony_ci                 sizeof(on)) == COAP_SOCKET_ERROR)
240c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_bind_tcp: setsockopt SO_REUSEADDR: %s\n",
241c87c5fbaSopenharmony_ci                  coap_socket_strerror());
242c87c5fbaSopenharmony_ci
243c87c5fbaSopenharmony_ci  switch (listen_addr->addr.sa.sa_family) {
244c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT
245c87c5fbaSopenharmony_ci  case AF_INET:
246c87c5fbaSopenharmony_ci    break;
247c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */
248c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT
249c87c5fbaSopenharmony_ci  case AF_INET6:
250c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION
251c87c5fbaSopenharmony_ci    /* Configure the socket as dual-stacked */
252c87c5fbaSopenharmony_ci    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
253c87c5fbaSopenharmony_ci                   sizeof(off)) == COAP_SOCKET_ERROR)
254c87c5fbaSopenharmony_ci      coap_log_alert("coap_socket_bind_tcp: setsockopt IPV6_V6ONLY: %s\n",
255c87c5fbaSopenharmony_ci                     coap_socket_strerror());
256c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
257c87c5fbaSopenharmony_ci    break;
258c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */
259c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT
260c87c5fbaSopenharmony_ci  case AF_UNIX:
261c87c5fbaSopenharmony_ci    break;
262c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */
263c87c5fbaSopenharmony_ci  default:
264c87c5fbaSopenharmony_ci    coap_log_alert("coap_socket_bind_tcp: unsupported sa_family\n");
265c87c5fbaSopenharmony_ci  }
266c87c5fbaSopenharmony_ci
267c87c5fbaSopenharmony_ci  if (bind(sock->fd, &listen_addr->addr.sa,
268c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT
269c87c5fbaSopenharmony_ci           listen_addr->addr.sa.sa_family == AF_INET ?
270c87c5fbaSopenharmony_ci           (socklen_t)sizeof(struct sockaddr_in) :
271c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */
272c87c5fbaSopenharmony_ci           (socklen_t)listen_addr->size) == COAP_SOCKET_ERROR) {
273c87c5fbaSopenharmony_ci    coap_log_alert("coap_socket_bind_tcp: bind: %s\n",
274c87c5fbaSopenharmony_ci                   coap_socket_strerror());
275c87c5fbaSopenharmony_ci    goto error;
276c87c5fbaSopenharmony_ci  }
277c87c5fbaSopenharmony_ci
278c87c5fbaSopenharmony_ci  bound_addr->size = (socklen_t)sizeof(*bound_addr);
279c87c5fbaSopenharmony_ci  if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
280c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_bind_tcp: getsockname: %s\n",
281c87c5fbaSopenharmony_ci                  coap_socket_strerror());
282c87c5fbaSopenharmony_ci    goto error;
283c87c5fbaSopenharmony_ci  }
284c87c5fbaSopenharmony_ci
285c87c5fbaSopenharmony_ci  if (listen(sock->fd, 5) == COAP_SOCKET_ERROR) {
286c87c5fbaSopenharmony_ci    coap_log_alert("coap_socket_bind_tcp: listen: %s\n",
287c87c5fbaSopenharmony_ci                   coap_socket_strerror());
288c87c5fbaSopenharmony_ci    goto  error;
289c87c5fbaSopenharmony_ci  }
290c87c5fbaSopenharmony_ci
291c87c5fbaSopenharmony_ci  return 1;
292c87c5fbaSopenharmony_ci
293c87c5fbaSopenharmony_cierror:
294c87c5fbaSopenharmony_ci  coap_socket_close(sock);
295c87c5fbaSopenharmony_ci  return 0;
296c87c5fbaSopenharmony_ci}
297c87c5fbaSopenharmony_ci
298c87c5fbaSopenharmony_ciint
299c87c5fbaSopenharmony_cicoap_socket_accept_tcp(coap_socket_t *server,
300c87c5fbaSopenharmony_ci                       coap_socket_t *new_client,
301c87c5fbaSopenharmony_ci                       coap_address_t *local_addr,
302c87c5fbaSopenharmony_ci                       coap_address_t *remote_addr) {
303c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION
304c87c5fbaSopenharmony_ci#ifdef _WIN32
305c87c5fbaSopenharmony_ci  u_long u_on = 1;
306c87c5fbaSopenharmony_ci#else
307c87c5fbaSopenharmony_ci  int on = 1;
308c87c5fbaSopenharmony_ci#endif
309c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
310c87c5fbaSopenharmony_ci
311c87c5fbaSopenharmony_ci  server->flags &= ~COAP_SOCKET_CAN_ACCEPT;
312c87c5fbaSopenharmony_ci
313c87c5fbaSopenharmony_ci  new_client->fd = accept(server->fd, &remote_addr->addr.sa,
314c87c5fbaSopenharmony_ci                          &remote_addr->size);
315c87c5fbaSopenharmony_ci  if (new_client->fd == COAP_INVALID_SOCKET) {
316c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_accept_tcp: accept: %s\n",
317c87c5fbaSopenharmony_ci                  coap_socket_strerror());
318c87c5fbaSopenharmony_ci    return 0;
319c87c5fbaSopenharmony_ci  }
320c87c5fbaSopenharmony_ci
321c87c5fbaSopenharmony_ci  if (getsockname(new_client->fd, &local_addr->addr.sa, &local_addr->size) < 0)
322c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_accept_tcp: getsockname: %s\n",
323c87c5fbaSopenharmony_ci                  coap_socket_strerror());
324c87c5fbaSopenharmony_ci
325c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION
326c87c5fbaSopenharmony_ci#ifdef _WIN32
327c87c5fbaSopenharmony_ci  if (ioctlsocket(new_client->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
328c87c5fbaSopenharmony_ci#else
329c87c5fbaSopenharmony_ci  if (ioctl(new_client->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
330c87c5fbaSopenharmony_ci#endif
331c87c5fbaSopenharmony_ci    coap_log_warn("coap_socket_accept_tcp: ioctl FIONBIO: %s\n",
332c87c5fbaSopenharmony_ci                  coap_socket_strerror());
333c87c5fbaSopenharmony_ci  }
334c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */
335c87c5fbaSopenharmony_ci  return 1;
336c87c5fbaSopenharmony_ci}
337c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
338