libcoap 4.3.5-develop-eafc023
Loading...
Searching...
No Matches
coap_netif.c
Go to the documentation of this file.
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
16
19
20/*
21 * return 1 netif still in use.
22 * 0 netif no longer available.
23 */
24int
26 return session->sock.flags != COAP_SOCKET_EMPTY;
27}
28
29#if COAP_SERVER_SUPPORT
30/*
31 * return 1 netif still in use.
32 * 0 netif no longer available.
33 */
34int
36 return endpoint->sock.flags != COAP_SOCKET_EMPTY;
37}
38
39int
41 const coap_address_t *listen_addr) {
42 if (!coap_socket_bind_udp(&endpoint->sock, listen_addr,
43 &endpoint->bind_addr)) {
44 return 0;
45 }
47 return 1;
48}
49#endif /* COAP_SERVER_SUPPORT */
50
51#if COAP_CLIENT_SUPPORT
52int
54 const coap_address_t *server, int default_port) {
55 if (!coap_socket_connect_udp(&session->sock, local_if, server,
56 default_port,
57 &session->addr_info.local,
58 &session->addr_info.remote)) {
59 return 0;
60 }
61 return 1;
62}
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 */
71ssize_t
73 ssize_t bytes_read;
74 int keep_errno;
75
76 bytes_read = coap_socket_recv(&session->sock, packet);
77 keep_errno = errno;
78 if (bytes_read == -1) {
79 coap_log_debug("* %s: netif: failed to read % " PRIdS " bytes (%s (%d)) state %d\n",
80 coap_session_str(session), packet->length,
81 coap_socket_strerror(), keep_errno, session->state);
82 errno = keep_errno;
83 } else if (bytes_read == -2) {
84#ifdef HAVE_LINUX_ERRQUEUE_H
85 coap_icmp_info_t *info = (coap_icmp_info_t *)packet->payload;
86
87 if (session->last_data_write && session->last_data_write->length >= info->length) {
88 if (memcmp(session->last_data_write->s, &info[1], info->length) == 0) {
89 /* There is a match - need to handle failure */
90 coap_log_debug("* %s: netif: failed to read % " PRIdS " bytes (%s (%d)) state %d\n",
91 coap_session_str(session), packet->length,
92 coap_socket_strerror(), keep_errno, session->state);
93 return -2;
94 }
95 }
96#endif /* HAVE_LINUX_ERRQUEUE_H */
97 bytes_read = -1;
98 } else if (bytes_read > 0) {
99 coap_ticks(&session->last_rx_tx);
100 memcpy(&session->addr_info, &packet->addr_info,
101 sizeof(session->addr_info));
102 coap_log_debug("* %s: netif: recv %4" PRIdS " bytes\n",
103 coap_session_str(session), bytes_read);
104 }
105 return bytes_read;
106}
107
108#if COAP_SERVER_SUPPORT
109/*
110 * dgram
111 * return +ve Number of bytes written.
112 * -1 Error error in errno).
113 * -2 ICMP error response
114 */
115ssize_t
117 ssize_t bytes_read;
118 int keep_errno;
119
120 bytes_read = coap_socket_recv(&endpoint->sock, packet);
121 keep_errno = errno;
122 if (bytes_read == -1) {
123 if (errno != EAGAIN) {
124 coap_log_debug("* %s: netif: failed to read % " PRIdS " bytes (%s)\n",
125 coap_endpoint_str(endpoint), packet->length,
127 errno = keep_errno;
128 }
129 } else if (bytes_read > 0) {
130 /* Let the caller do the logging as session available by then */
131 }
132 return bytes_read;
133}
134#endif /* COAP_SERVER_SUPPORT */
135
136/*
137 * dgram
138 * return +ve Number of bytes written.
139 * -1 Error error in errno).
140 */
141ssize_t
142coap_netif_dgrm_write(coap_session_t *session, const uint8_t *data,
143 size_t datalen) {
144 ssize_t bytes_written;
145 int keep_errno;
146
147 coap_socket_t *sock = &session->sock;
148#if COAP_SERVER_SUPPORT
149 if (sock->flags == COAP_SOCKET_EMPTY) {
150 if (session->endpoint != NULL)
151 sock = &session->endpoint->sock;
152 }
153#endif /* COAP_SERVER_SUPPORT */
154
155 bytes_written = coap_socket_send(sock, session, data, datalen);
156 keep_errno = errno;
157 if (bytes_written <= 0) {
158 coap_log_debug("* %s: netif: failed to send % " PRIdS " bytes (%s (%d)) state %d\n",
159 coap_session_str(session), datalen,
160 coap_socket_strerror(), errno, session->state);
161 errno = keep_errno;
162 } else {
163 coap_ticks(&session->last_rx_tx);
164 if (bytes_written == (ssize_t)datalen)
165 coap_log_debug("* %s: netif: sent %4" PRIdS " bytes\n",
166 coap_session_str(session), bytes_written);
167 else
168 coap_log_debug("* %s: netif: sent %4" PRIdS " of %4" PRIdS " bytes\n",
169 coap_session_str(session), bytes_written, datalen);
170 }
171#ifdef HAVE_LINUX_ERRQUEUE_H
172 if (session->type == COAP_SESSION_TYPE_CLIENT) {
173 coap_delete_str_const(session->last_data_write);
174 session->last_data_write = coap_new_str_const(data, datalen);
175 }
176#endif /* HAVE_LINUX_ERRQUEUE_H */
177 return bytes_written;
178}
179
180void
185
186#if !COAP_DISABLE_TCP
187#if COAP_SERVER_SUPPORT
188int
190 const coap_address_t *listen_addr) {
191 if (!coap_socket_bind_tcp(&endpoint->sock, listen_addr,
192 &endpoint->bind_addr)) {
193 return 0;
194 }
195 endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND |
197 return 1;
198}
199
200int
201coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session, void *extra) {
202 if (!coap_socket_accept_tcp(&endpoint->sock, &session->sock,
203 &session->addr_info.local,
204 &session->addr_info.remote, extra)) {
205 return 0;
206 }
209 return 1;
210}
211#endif /* COAP_SERVER_SUPPORT */
212
213#if COAP_CLIENT_SUPPORT
214int
216 const coap_address_t *local_if,
217 const coap_address_t *server, int default_port) {
218 if (!coap_socket_connect_tcp1(&session->sock, local_if, server,
219 default_port,
220 &session->addr_info.local,
221 &session->addr_info.remote)) {
222 return 0;
223 }
224 return 1;
225}
226
227int
229 if (!coap_socket_connect_tcp2(&session->sock,
230 &session->addr_info.local,
231 &session->addr_info.remote)) {
232 return 0;
233 }
234 return 1;
235}
236#endif /* COAP_CLIENT_SUPPORT */
237
238/*
239 * strm
240 * return >=0 Number of bytes read.
241 * -1 Error (error in errno).
242 */
243ssize_t
244coap_netif_strm_read(coap_session_t *session, uint8_t *data, size_t datalen) {
245 ssize_t bytes_read = coap_socket_read(&session->sock, data, datalen);
246 int keep_errno = errno;
247
248 if (bytes_read >= 0) {
249 coap_log_debug("* %s: netif: read %4" PRIdS " bytes\n",
250 coap_session_str(session), bytes_read);
251 } else if (bytes_read == -1 && errno != EAGAIN) {
252 coap_log_debug("* %s: netif: failed to receive any bytes (%s) state %d\n",
253 coap_session_str(session), coap_socket_strerror(), session->state);
254 errno = keep_errno;
255 }
256 return bytes_read;
257}
258
259/*
260 * strm
261 * return +ve Number of bytes written.
262 * -1 Error (error in errno).
263 */
264ssize_t
265coap_netif_strm_write(coap_session_t *session, const uint8_t *data,
266 size_t datalen) {
267 ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen);
268 int keep_errno = errno;
269
270 if (bytes_written <= 0) {
271 coap_log_debug("* %s: netif: failed to send % " PRIdS " bytes (%s) state %d\n",
272 coap_session_str(session), datalen,
273 coap_socket_strerror(), session->state);
274 errno = keep_errno;
275 } else {
276 coap_ticks(&session->last_rx_tx);
277 if (bytes_written == (ssize_t)datalen)
278 coap_log_debug("* %s: netif: sent %4" PRIdS " bytes\n",
279 coap_session_str(session), bytes_written);
280 else
281 coap_log_debug("* %s: netif: sent %4" PRIdS " of %4" PRIdS " bytes\n",
282 coap_session_str(session), bytes_written, datalen);
283 }
284 return bytes_written;
285}
286
287void
292#endif /* COAP_DISABLE_TCP */
293
294#if COAP_SERVER_SUPPORT
295void
297 if (COAP_PROTO_NOT_RELIABLE(endpoint->proto)) {
298 coap_socket_dgrm_close(&endpoint->sock);
299#if ! COAP_DISABLE_TCP
300 } else {
301 coap_socket_strm_close(&endpoint->sock);
302#endif /* ! COAP_DISABLE_TCP */
303 }
304}
305#endif /* COAP_SERVER_SUPPORT */
struct coap_endpoint_t coap_endpoint_t
#define PRIdS
const char * coap_socket_strerror(void)
Definition coap_io.c:966
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
#define COAP_SOCKET_BOUND
the socket is bound
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
#define COAP_SOCKET_CONNECTED
the socket is connected
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Library specific build wrapper for coap_internal.h.
#define NULL
Definition coap_option.h:30
CoAP session internal information.
void coap_ticks(coap_tick_t *t)
Returns the current value of an internal tick counter.
Definition coap_time.c:90
ssize_t coap_socket_recv(coap_socket_t *sock, coap_packet_t *packet)
Function interface for reading data.
ssize_t coap_socket_send(coap_socket_t *sock, coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for data transmission.
void coap_socket_dgrm_close(coap_socket_t *sock)
Function interface to close off a datagram socket.
#define coap_log_debug(...)
Definition coap_debug.h:126
const char * coap_endpoint_str(const coap_endpoint_t *endpoint)
Get endpoint description.
const char * coap_session_str(const coap_session_t *session)
Get session description.
void coap_netif_dgrm_close(coap_session_t *session)
Layer function interface for netif datagram close for a session.
Definition coap_netif.c:181
int coap_netif_strm_connect2(coap_session_t *session)
Layer function interface for Netif stream connect (tcp).
ssize_t coap_netif_dgrm_write(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for netif datagram data transmission.
Definition coap_netif.c:142
int coap_netif_dgrm_listen(coap_endpoint_t *endpoint, const coap_address_t *listen_addr)
Layer function interface for Netif datagram listem (udp).
ssize_t coap_netif_dgrm_read(coap_session_t *session, coap_packet_t *packet)
Function interface for layer data datagram receiving for sessions.
Definition coap_netif.c:72
void coap_netif_close_ep(coap_endpoint_t *endpoint)
Layer function interface for Netif close for a endpoint.
int coap_netif_strm_connect1(coap_session_t *session, const coap_address_t *local_if, const coap_address_t *server, int default_port)
Layer function interface for Netif stream connect (tcp).
ssize_t coap_netif_dgrm_read_ep(coap_endpoint_t *endpoint, coap_packet_t *packet)
Function interface for layer data datagram receiving for endpoints.
int coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session, void *extra)
Layer function interface for Netif stream accept.
void coap_netif_strm_close(coap_session_t *session)
Layer function interface for netif stream close for a session.
Definition coap_netif.c:288
int coap_netif_strm_listen(coap_endpoint_t *endpoint, const coap_address_t *listen_addr)
Layer function interface for Netif stream listem (tcp).
ssize_t coap_netif_strm_write(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for netif stream data transmission.
Definition coap_netif.c:265
int coap_netif_dgrm_connect(coap_session_t *session, const coap_address_t *local_if, const coap_address_t *server, int default_port)
Layer function interface for Netif datagram connect (udp).
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
Definition coap_netif.c:25
ssize_t coap_netif_strm_read(coap_session_t *session, uint8_t *data, size_t datalen)
Function interface for layer data stream receiving.
Definition coap_netif.c:244
int coap_netif_available_ep(coap_endpoint_t *endpoint)
Function interface to check whether netif for endpoint is still available.
#define COAP_PROTO_NOT_RELIABLE(p)
@ COAP_SESSION_TYPE_CLIENT
client-side
void coap_delete_str_const(coap_str_const_t *s)
Deletes the given const string and releases any memory allocated.
Definition coap_str.c:65
coap_str_const_t * coap_new_str_const(const uint8_t *data, size_t size)
Returns a new const string object with at least size+1 bytes storage allocated, and the provided data...
Definition coap_str.c:55
int coap_socket_bind_tcp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Create a new TCP socket and then listen for new incoming TCP sessions.
ssize_t coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len)
Function interface for data stream receiving off a socket.
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Function interface for data stream sending off a socket.
int coap_socket_connect_tcp1(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr)
Create a new TCP socket and initiate the connection.
int coap_socket_accept_tcp(coap_socket_t *server, coap_socket_t *new_client, coap_address_t *local_addr, coap_address_t *remote_addr, void *extra)
Accept a new incoming TCP session.
void coap_socket_strm_close(coap_socket_t *sock)
Function interface to close off a stream socket.
int coap_socket_connect_tcp2(coap_socket_t *sock, coap_address_t *local_addr, coap_address_t *remote_addr)
Complete the TCP Connection.
coap_address_t remote
remote address and port
Definition coap_io.h:58
coap_address_t local
local address and port
Definition coap_io.h:59
Multi-purpose address abstraction.
size_t length
length of payload
coap_addr_tuple_t addr_info
local and remote addresses
unsigned char * payload
payload
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_addr_tuple_t addr_info
remote/local address info
coap_session_type_t type
client or server side socket
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values