• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * coap_netif.c -- Netif functions for libcoap
3  *
4  * Copyright (C) 2023 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_internal.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
coap_netif_available(coap_session_t * session)25 coap_netif_available(coap_session_t *session) {
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  */
34 int
coap_netif_available_ep(coap_endpoint_t * endpoint)35 coap_netif_available_ep(coap_endpoint_t *endpoint) {
36   return endpoint->sock.flags != COAP_SOCKET_EMPTY;
37 }
38 
39 int
coap_netif_dgrm_listen(coap_endpoint_t * endpoint,const coap_address_t * listen_addr)40 coap_netif_dgrm_listen(coap_endpoint_t *endpoint,
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   }
46   endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND | COAP_SOCKET_WANT_READ;
47   return 1;
48 }
49 #endif /* COAP_SERVER_SUPPORT */
50 
51 #if COAP_CLIENT_SUPPORT
52 int
coap_netif_dgrm_connect(coap_session_t * session,const coap_address_t * local_if,const coap_address_t * server,int default_port)53 coap_netif_dgrm_connect(coap_session_t *session, const coap_address_t *local_if,
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  */
71 ssize_t
coap_netif_dgrm_read(coap_session_t * session,coap_packet_t * packet)72 coap_netif_dgrm_read(coap_session_t *session, coap_packet_t *packet) {
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 %zd bytes (%s) state %d\n",
80                    coap_session_str(session), packet->length,
81                    coap_socket_strerror(), session->state);
82     errno = keep_errno;
83   } else if (bytes_read > 0) {
84     coap_ticks(&session->last_rx_tx);
85     coap_log_debug("*  %s: netif: recv %4zd bytes\n",
86                    coap_session_str(session), bytes_read);
87   }
88   return bytes_read;
89 }
90 
91 #if COAP_SERVER_SUPPORT
92 /*
93  * dgram
94  * return +ve Number of bytes written.
95  *         -1 Error error in errno).
96  *         -2 ICMP error response
97  */
98 ssize_t
coap_netif_dgrm_read_ep(coap_endpoint_t * endpoint,coap_packet_t * packet)99 coap_netif_dgrm_read_ep(coap_endpoint_t *endpoint, coap_packet_t *packet) {
100   ssize_t bytes_read;
101   int keep_errno;
102 
103   bytes_read = coap_socket_recv(&endpoint->sock, packet);
104   keep_errno = errno;
105   if (bytes_read == -1) {
106     coap_log_debug("*  %s: netif: failed to read %zd bytes (%s)\n",
107                    coap_endpoint_str(endpoint), packet->length,
108                    coap_socket_strerror());
109     errno = keep_errno;
110   } else if (bytes_read > 0) {
111     /* Let the caller do the logging as session available by then */
112   }
113   return bytes_read;
114 }
115 #endif /* COAP_SERVER_SUPPORT */
116 
117 /*
118  * dgram
119  * return +ve Number of bytes written.
120  *         -1 Error error in errno).
121  */
122 ssize_t
coap_netif_dgrm_write(coap_session_t * session,const uint8_t * data,size_t datalen)123 coap_netif_dgrm_write(coap_session_t *session, const uint8_t *data,
124                       size_t datalen) {
125   ssize_t bytes_written;
126   int keep_errno;
127 
128   coap_socket_t *sock = &session->sock;
129 #if COAP_SERVER_SUPPORT
130   if (sock->flags == COAP_SOCKET_EMPTY) {
131     assert(session->endpoint != NULL);
132     sock = &session->endpoint->sock;
133   }
134 #endif /* COAP_SERVER_SUPPORT */
135 
136   bytes_written = coap_socket_send(sock, session, data, datalen);
137   keep_errno = errno;
138   if (bytes_written <= 0) {
139     coap_log_debug("*  %s: netif: failed to send %zd bytes (%s) state %d\n",
140                    coap_session_str(session), datalen,
141                    coap_socket_strerror(), session->state);
142     errno = keep_errno;
143   } else {
144     coap_ticks(&session->last_rx_tx);
145     if (bytes_written == (ssize_t)datalen)
146       coap_log_debug("*  %s: netif: sent %4zd bytes\n",
147                      coap_session_str(session), bytes_written);
148     else
149       coap_log_debug("*  %s: netif: sent %4zd of %4zd bytes\n",
150                      coap_session_str(session), bytes_written, datalen);
151   }
152   return bytes_written;
153 }
154 
155 #if !COAP_DISABLE_TCP
156 #if COAP_SERVER_SUPPORT
157 int
coap_netif_strm_listen(coap_endpoint_t * endpoint,const coap_address_t * listen_addr)158 coap_netif_strm_listen(coap_endpoint_t *endpoint,
159                        const coap_address_t *listen_addr) {
160   if (!coap_socket_bind_tcp(&endpoint->sock, listen_addr,
161                             &endpoint->bind_addr)) {
162     return 0;
163   }
164   endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND |
165                           COAP_SOCKET_WANT_ACCEPT;
166   return 1;
167 }
168 
169 int
coap_netif_strm_accept(coap_endpoint_t * endpoint,coap_session_t * session)170 coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session) {
171   if (!coap_socket_accept_tcp(&endpoint->sock, &session->sock,
172                               &session->addr_info.local,
173                               &session->addr_info.remote)) {
174     return 0;
175   }
176   session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_CONNECTED |
177                          COAP_SOCKET_WANT_READ;
178   return 1;
179 }
180 #endif /* COAP_SERVER_SUPPORT */
181 
182 #if COAP_CLIENT_SUPPORT
183 int
coap_netif_strm_connect1(coap_session_t * session,const coap_address_t * local_if,const coap_address_t * server,int default_port)184 coap_netif_strm_connect1(coap_session_t *session,
185                          const coap_address_t *local_if,
186                          const coap_address_t *server, int default_port) {
187   if (!coap_socket_connect_tcp1(&session->sock, local_if, server,
188                                 default_port,
189                                 &session->addr_info.local,
190                                 &session->addr_info.remote)) {
191     return 0;
192   }
193   return 1;
194 }
195 
196 int
coap_netif_strm_connect2(coap_session_t * session)197 coap_netif_strm_connect2(coap_session_t *session) {
198   if (!coap_socket_connect_tcp2(&session->sock,
199                                 &session->addr_info.local,
200                                 &session->addr_info.remote)) {
201     return 0;
202   }
203   return 1;
204 }
205 #endif /* COAP_CLIENT_SUPPORT */
206 
207 /*
208  * strm
209  * return >=0 Number of bytes read.
210  *         -1 Error (error in errno).
211  */
212 ssize_t
coap_netif_strm_read(coap_session_t * session,uint8_t * data,size_t datalen)213 coap_netif_strm_read(coap_session_t *session, uint8_t *data, size_t datalen) {
214   ssize_t bytes_read = coap_socket_read(&session->sock, data, datalen);
215   int keep_errno = errno;
216 
217   if (bytes_read >= 0) {
218     coap_log_debug("*  %s: netif: recv %4zd bytes\n",
219                    coap_session_str(session), bytes_read);
220   } else if (bytes_read == -1 && errno != EAGAIN) {
221     coap_log_debug("*  %s: netif: failed to receive any bytes (%s) state %d\n",
222                    coap_session_str(session), coap_socket_strerror(), session->state);
223     errno = keep_errno;
224   }
225   return bytes_read;
226 }
227 
228 /*
229  * strm
230  * return +ve Number of bytes written.
231  *         -1 Error (error in errno).
232  */
233 ssize_t
coap_netif_strm_write(coap_session_t * session,const uint8_t * data,size_t datalen)234 coap_netif_strm_write(coap_session_t *session, const uint8_t *data,
235                       size_t datalen) {
236   ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen);
237   int keep_errno = errno;
238 
239   if (bytes_written <= 0) {
240     coap_log_debug("*  %s: netif: failed to send %zd bytes (%s) state %d\n",
241                    coap_session_str(session), datalen,
242                    coap_socket_strerror(), session->state);
243     errno = keep_errno;
244   } else {
245     coap_ticks(&session->last_rx_tx);
246     if (bytes_written == (ssize_t)datalen)
247       coap_log_debug("*  %s: netif: sent %4zd bytes\n",
248                      coap_session_str(session), bytes_written);
249     else
250       coap_log_debug("*  %s: netif: sent %4zd of %4zd bytes\n",
251                      coap_session_str(session), bytes_written, datalen);
252   }
253   return bytes_written;
254 }
255 #endif /* COAP_DISABLE_TCP */
256 
257 void
coap_netif_close(coap_session_t * session)258 coap_netif_close(coap_session_t *session) {
259   if (coap_netif_available(session))
260     coap_socket_close(&session->sock);
261 }
262 
263 #if COAP_SERVER_SUPPORT
264 void
coap_netif_close_ep(coap_endpoint_t * endpoint)265 coap_netif_close_ep(coap_endpoint_t *endpoint) {
266   coap_socket_close(&endpoint->sock);
267 }
268 #endif /* COAP_SERVER_SUPPORT */
269