Coverage Report

Created: 2026-01-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/src/coap_netif.c
Line
Count
Source
1
/*
2
 * coap_netif.c -- Netif functions for libcoap
3
 *
4
 * Copyright (C) 2023-2026 Jon Shallow <supjps-libcoap@jpshallow.com>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * This file is part of the CoAP library libcoap. Please see README for terms
9
 * of use.
10
 */
11
12
/**
13
 * @file coap_netif.c
14
 * @brief CoAP Netif handling functions
15
 */
16
17
#include "coap3/coap_libcoap_build.h"
18
#include "coap3/coap_session_internal.h"
19
20
/*
21
 * return 1 netif still in use.
22
 *        0 netif no longer available.
23
 */
24
int
25
0
coap_netif_available(coap_session_t *session) {
26
0
  return session->sock.flags != COAP_SOCKET_EMPTY;
27
0
}
28
29
#if COAP_SERVER_SUPPORT
30
/*
31
 * return 1 netif still in use.
32
 *        0 netif no longer available.
33
 */
34
int
35
0
coap_netif_available_ep(coap_endpoint_t *endpoint) {
36
0
  return endpoint->sock.flags != COAP_SOCKET_EMPTY;
37
0
}
38
39
int
40
coap_netif_dgrm_listen(coap_endpoint_t *endpoint,
41
0
                       const coap_address_t *listen_addr) {
42
0
  if (!coap_socket_bind_udp(&endpoint->sock, listen_addr,
43
0
                            &endpoint->bind_addr)) {
44
0
    return 0;
45
0
  }
46
0
  endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND | COAP_SOCKET_WANT_READ;
47
0
  return 1;
48
0
}
49
#endif /* COAP_SERVER_SUPPORT */
50
51
#if COAP_CLIENT_SUPPORT
52
int
53
coap_netif_dgrm_connect(coap_session_t *session, const coap_address_t *local_if,
54
0
                        const coap_address_t *server, int default_port) {
55
0
  if (!coap_socket_connect_udp(&session->sock, local_if, server,
56
0
                               default_port,
57
0
                               &session->addr_info.local,
58
0
                               &session->addr_info.remote)) {
59
0
    return 0;
60
0
  }
61
0
  return 1;
62
0
}
63
#endif /* COAP_CLIENT_SUPPORT */
64
65
/*
66
 * dgram
67
 * return +ve Number of bytes written.
68
 *         -1 Error error in errno).
69
 *         -2 ICMP error response
70
 */
71
ssize_t
72
0
coap_netif_dgrm_read(coap_session_t *session, coap_packet_t *packet) {
73
0
  ssize_t bytes_read;
74
0
  int keep_errno;
75
76
0
  bytes_read = coap_socket_recv(&session->sock, packet);
77
0
  keep_errno = errno;
78
0
  if (bytes_read == -1) {
79
0
    coap_log_debug("*  %s: netif: failed to read % " PRIdS " bytes (%s (%d)) state %d\n",
80
0
                   coap_session_str(session), packet->length,
81
0
                   coap_socket_strerror(), keep_errno, session->state);
82
0
    errno = keep_errno;
83
0
  } else if (bytes_read > 0) {
84
0
    coap_ticks(&session->last_rx_tx);
85
0
    memcpy(&session->addr_info, &packet->addr_info,
86
0
           sizeof(session->addr_info));
87
0
    coap_log_debug("*  %s: netif: recv %4" PRIdS " bytes\n",
88
0
                   coap_session_str(session), bytes_read);
89
0
  }
90
0
  return bytes_read;
91
0
}
92
93
#if COAP_SERVER_SUPPORT
94
/*
95
 * dgram
96
 * return +ve Number of bytes written.
97
 *         -1 Error error in errno).
98
 *         -2 ICMP error response
99
 */
100
ssize_t
101
0
coap_netif_dgrm_read_ep(coap_endpoint_t *endpoint, coap_packet_t *packet) {
102
0
  ssize_t bytes_read;
103
0
  int keep_errno;
104
105
0
  bytes_read = coap_socket_recv(&endpoint->sock, packet);
106
0
  keep_errno = errno;
107
0
  if (bytes_read == -1) {
108
0
    if (errno != EAGAIN) {
109
0
      coap_log_debug("*  %s: netif: failed to read % " PRIdS " bytes (%s)\n",
110
0
                     coap_endpoint_str(endpoint), packet->length,
111
0
                     coap_socket_strerror());
112
0
      errno = keep_errno;
113
0
    }
114
0
  } else if (bytes_read > 0) {
115
    /* Let the caller do the logging as session available by then */
116
0
  }
117
0
  return bytes_read;
118
0
}
119
#endif /* COAP_SERVER_SUPPORT */
120
121
/*
122
 * dgram
123
 * return +ve Number of bytes written.
124
 *         -1 Error error in errno).
125
 */
126
ssize_t
127
coap_netif_dgrm_write(coap_session_t *session, const uint8_t *data,
128
0
                      size_t datalen) {
129
0
  ssize_t bytes_written;
130
0
  int keep_errno;
131
132
0
  coap_socket_t *sock = &session->sock;
133
0
#if COAP_SERVER_SUPPORT
134
0
  if (sock->flags == COAP_SOCKET_EMPTY) {
135
0
    if (session->endpoint != NULL)
136
0
      sock = &session->endpoint->sock;
137
0
  }
138
0
#endif /* COAP_SERVER_SUPPORT */
139
140
0
  bytes_written = coap_socket_send(sock, session, data, datalen);
141
0
  keep_errno = errno;
142
0
  if (bytes_written <= 0) {
143
0
    coap_log_debug("*  %s: netif: failed to send % " PRIdS " bytes (%s (%d)) state %d\n",
144
0
                   coap_session_str(session), datalen,
145
0
                   coap_socket_strerror(), errno, session->state);
146
0
    errno = keep_errno;
147
0
  } else {
148
0
    coap_ticks(&session->last_rx_tx);
149
0
    if (bytes_written == (ssize_t)datalen)
150
0
      coap_log_debug("*  %s: netif: sent %4" PRIdS " bytes\n",
151
0
                     coap_session_str(session), bytes_written);
152
0
    else
153
0
      coap_log_debug("*  %s: netif: sent %4" PRIdS " of %4" PRIdS " bytes\n",
154
0
                     coap_session_str(session), bytes_written, datalen);
155
0
  }
156
0
  return bytes_written;
157
0
}
158
159
void
160
0
coap_netif_dgrm_close(coap_session_t *session) {
161
0
  if (coap_netif_available(session))
162
0
    coap_socket_dgrm_close(&session->sock);
163
0
}
164
165
#if !COAP_DISABLE_TCP
166
#if COAP_SERVER_SUPPORT
167
int
168
coap_netif_strm_listen(coap_endpoint_t *endpoint,
169
0
                       const coap_address_t *listen_addr) {
170
0
  if (!coap_socket_bind_tcp(&endpoint->sock, listen_addr,
171
0
                            &endpoint->bind_addr)) {
172
0
    return 0;
173
0
  }
174
0
  endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND |
175
0
                          COAP_SOCKET_WANT_ACCEPT;
176
0
  return 1;
177
0
}
178
179
int
180
0
coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session, void *extra) {
181
0
  if (!coap_socket_accept_tcp(&endpoint->sock, &session->sock,
182
0
                              &session->addr_info.local,
183
0
                              &session->addr_info.remote, extra)) {
184
0
    return 0;
185
0
  }
186
0
  session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_CONNECTED |
187
0
                         COAP_SOCKET_WANT_READ;
188
0
  return 1;
189
0
}
190
#endif /* COAP_SERVER_SUPPORT */
191
192
#if COAP_CLIENT_SUPPORT
193
int
194
coap_netif_strm_connect1(coap_session_t *session,
195
                         const coap_address_t *local_if,
196
0
                         const coap_address_t *server, int default_port) {
197
0
  if (!coap_socket_connect_tcp1(&session->sock, local_if, server,
198
0
                                default_port,
199
0
                                &session->addr_info.local,
200
0
                                &session->addr_info.remote)) {
201
0
    return 0;
202
0
  }
203
0
  return 1;
204
0
}
205
206
int
207
0
coap_netif_strm_connect2(coap_session_t *session) {
208
0
  if (!coap_socket_connect_tcp2(&session->sock,
209
0
                                &session->addr_info.local,
210
0
                                &session->addr_info.remote)) {
211
0
    return 0;
212
0
  }
213
0
  return 1;
214
0
}
215
#endif /* COAP_CLIENT_SUPPORT */
216
217
/*
218
 * strm
219
 * return >=0 Number of bytes read.
220
 *         -1 Error (error in errno).
221
 */
222
ssize_t
223
0
coap_netif_strm_read(coap_session_t *session, uint8_t *data, size_t datalen) {
224
0
  ssize_t bytes_read = coap_socket_read(&session->sock, data, datalen);
225
0
  int keep_errno = errno;
226
227
0
  if (bytes_read >= 0) {
228
0
    coap_log_debug("*  %s: netif: recv %4" PRIdS " bytes\n",
229
0
                   coap_session_str(session), bytes_read);
230
0
  } else if (bytes_read == -1 && errno != EAGAIN) {
231
0
    coap_log_debug("*  %s: netif: failed to receive any bytes (%s) state %d\n",
232
0
                   coap_session_str(session), coap_socket_strerror(), session->state);
233
0
    errno = keep_errno;
234
0
  }
235
0
  return bytes_read;
236
0
}
237
238
/*
239
 * strm
240
 * return +ve Number of bytes written.
241
 *         -1 Error (error in errno).
242
 */
243
ssize_t
244
coap_netif_strm_write(coap_session_t *session, const uint8_t *data,
245
0
                      size_t datalen) {
246
0
  ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen);
247
0
  int keep_errno = errno;
248
249
0
  if (bytes_written <= 0) {
250
0
    coap_log_debug("*  %s: netif: failed to send % " PRIdS " bytes (%s) state %d\n",
251
0
                   coap_session_str(session), datalen,
252
0
                   coap_socket_strerror(), session->state);
253
0
    errno = keep_errno;
254
0
  } else {
255
0
    coap_ticks(&session->last_rx_tx);
256
0
    if (bytes_written == (ssize_t)datalen)
257
0
      coap_log_debug("*  %s: netif: sent %4" PRIdS " bytes\n",
258
0
                     coap_session_str(session), bytes_written);
259
0
    else
260
0
      coap_log_debug("*  %s: netif: sent %4" PRIdS " of %4" PRIdS " bytes\n",
261
0
                     coap_session_str(session), bytes_written, datalen);
262
0
  }
263
0
  return bytes_written;
264
0
}
265
266
void
267
0
coap_netif_strm_close(coap_session_t *session) {
268
0
  if (coap_netif_available(session))
269
0
    coap_socket_strm_close(&session->sock);
270
0
}
271
#endif /* COAP_DISABLE_TCP */
272
273
#if COAP_SERVER_SUPPORT
274
void
275
0
coap_netif_close_ep(coap_endpoint_t *endpoint) {
276
0
  if (COAP_PROTO_NOT_RELIABLE(endpoint->proto)) {
277
0
    coap_socket_dgrm_close(&endpoint->sock);
278
0
#if ! COAP_DISABLE_TCP
279
0
  } else {
280
0
    coap_socket_strm_close(&endpoint->sock);
281
0
#endif /* ! COAP_DISABLE_TCP */
282
0
  }
283
0
}
284
#endif /* COAP_SERVER_SUPPORT */