1c87c5fbaSopenharmony_ci/* 2c87c5fbaSopenharmony_ci * coap_netif.c -- Netif functions for libcoap 3c87c5fbaSopenharmony_ci * 4c87c5fbaSopenharmony_ci * Copyright (C) 2023 Jon Shallow <supjps-libcoap@jpshallow.com> 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_netif.c 14c87c5fbaSopenharmony_ci * @brief CoAP Netif handling functions 15c87c5fbaSopenharmony_ci */ 16c87c5fbaSopenharmony_ci 17c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h" 18c87c5fbaSopenharmony_ci#include "coap3/coap_session_internal.h" 19c87c5fbaSopenharmony_ci 20c87c5fbaSopenharmony_ci/* 21c87c5fbaSopenharmony_ci * return 1 netif still in use. 22c87c5fbaSopenharmony_ci * 0 netif no longer available. 23c87c5fbaSopenharmony_ci */ 24c87c5fbaSopenharmony_ciint 25c87c5fbaSopenharmony_cicoap_netif_available(coap_session_t *session) { 26c87c5fbaSopenharmony_ci return session->sock.flags != COAP_SOCKET_EMPTY; 27c87c5fbaSopenharmony_ci} 28c87c5fbaSopenharmony_ci 29c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 30c87c5fbaSopenharmony_ci/* 31c87c5fbaSopenharmony_ci * return 1 netif still in use. 32c87c5fbaSopenharmony_ci * 0 netif no longer available. 33c87c5fbaSopenharmony_ci */ 34c87c5fbaSopenharmony_ciint 35c87c5fbaSopenharmony_cicoap_netif_available_ep(coap_endpoint_t *endpoint) { 36c87c5fbaSopenharmony_ci return endpoint->sock.flags != COAP_SOCKET_EMPTY; 37c87c5fbaSopenharmony_ci} 38c87c5fbaSopenharmony_ci 39c87c5fbaSopenharmony_ciint 40c87c5fbaSopenharmony_cicoap_netif_dgrm_listen(coap_endpoint_t *endpoint, 41c87c5fbaSopenharmony_ci const coap_address_t *listen_addr) { 42c87c5fbaSopenharmony_ci if (!coap_socket_bind_udp(&endpoint->sock, listen_addr, 43c87c5fbaSopenharmony_ci &endpoint->bind_addr)) { 44c87c5fbaSopenharmony_ci return 0; 45c87c5fbaSopenharmony_ci } 46c87c5fbaSopenharmony_ci endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND | COAP_SOCKET_WANT_READ; 47c87c5fbaSopenharmony_ci return 1; 48c87c5fbaSopenharmony_ci} 49c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 50c87c5fbaSopenharmony_ci 51c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 52c87c5fbaSopenharmony_ciint 53c87c5fbaSopenharmony_cicoap_netif_dgrm_connect(coap_session_t *session, const coap_address_t *local_if, 54c87c5fbaSopenharmony_ci const coap_address_t *server, int default_port) { 55c87c5fbaSopenharmony_ci if (!coap_socket_connect_udp(&session->sock, local_if, server, 56c87c5fbaSopenharmony_ci default_port, 57c87c5fbaSopenharmony_ci &session->addr_info.local, 58c87c5fbaSopenharmony_ci &session->addr_info.remote)) { 59c87c5fbaSopenharmony_ci return 0; 60c87c5fbaSopenharmony_ci } 61c87c5fbaSopenharmony_ci return 1; 62c87c5fbaSopenharmony_ci} 63c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 64c87c5fbaSopenharmony_ci 65c87c5fbaSopenharmony_ci/* 66c87c5fbaSopenharmony_ci * dgram 67c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 68c87c5fbaSopenharmony_ci * -1 Error error in errno). 69c87c5fbaSopenharmony_ci * -2 ICMP error response 70c87c5fbaSopenharmony_ci */ 71c87c5fbaSopenharmony_cissize_t 72c87c5fbaSopenharmony_cicoap_netif_dgrm_read(coap_session_t *session, coap_packet_t *packet) { 73c87c5fbaSopenharmony_ci ssize_t bytes_read; 74c87c5fbaSopenharmony_ci int keep_errno; 75c87c5fbaSopenharmony_ci 76c87c5fbaSopenharmony_ci bytes_read = coap_socket_recv(&session->sock, packet); 77c87c5fbaSopenharmony_ci keep_errno = errno; 78c87c5fbaSopenharmony_ci if (bytes_read == -1) { 79c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: failed to read %zd bytes (%s) state %d\n", 80c87c5fbaSopenharmony_ci coap_session_str(session), packet->length, 81c87c5fbaSopenharmony_ci coap_socket_strerror(), session->state); 82c87c5fbaSopenharmony_ci errno = keep_errno; 83c87c5fbaSopenharmony_ci } else if (bytes_read > 0) { 84c87c5fbaSopenharmony_ci coap_ticks(&session->last_rx_tx); 85c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: recv %4zd bytes\n", 86c87c5fbaSopenharmony_ci coap_session_str(session), bytes_read); 87c87c5fbaSopenharmony_ci } 88c87c5fbaSopenharmony_ci return bytes_read; 89c87c5fbaSopenharmony_ci} 90c87c5fbaSopenharmony_ci 91c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 92c87c5fbaSopenharmony_ci/* 93c87c5fbaSopenharmony_ci * dgram 94c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 95c87c5fbaSopenharmony_ci * -1 Error error in errno). 96c87c5fbaSopenharmony_ci * -2 ICMP error response 97c87c5fbaSopenharmony_ci */ 98c87c5fbaSopenharmony_cissize_t 99c87c5fbaSopenharmony_cicoap_netif_dgrm_read_ep(coap_endpoint_t *endpoint, coap_packet_t *packet) { 100c87c5fbaSopenharmony_ci ssize_t bytes_read; 101c87c5fbaSopenharmony_ci int keep_errno; 102c87c5fbaSopenharmony_ci 103c87c5fbaSopenharmony_ci bytes_read = coap_socket_recv(&endpoint->sock, packet); 104c87c5fbaSopenharmony_ci keep_errno = errno; 105c87c5fbaSopenharmony_ci if (bytes_read == -1) { 106c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: failed to read %zd bytes (%s)\n", 107c87c5fbaSopenharmony_ci coap_endpoint_str(endpoint), packet->length, 108c87c5fbaSopenharmony_ci coap_socket_strerror()); 109c87c5fbaSopenharmony_ci errno = keep_errno; 110c87c5fbaSopenharmony_ci } else if (bytes_read > 0) { 111c87c5fbaSopenharmony_ci /* Let the caller do the logging as session available by then */ 112c87c5fbaSopenharmony_ci } 113c87c5fbaSopenharmony_ci return bytes_read; 114c87c5fbaSopenharmony_ci} 115c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 116c87c5fbaSopenharmony_ci 117c87c5fbaSopenharmony_ci/* 118c87c5fbaSopenharmony_ci * dgram 119c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 120c87c5fbaSopenharmony_ci * -1 Error error in errno). 121c87c5fbaSopenharmony_ci */ 122c87c5fbaSopenharmony_cissize_t 123c87c5fbaSopenharmony_cicoap_netif_dgrm_write(coap_session_t *session, const uint8_t *data, 124c87c5fbaSopenharmony_ci size_t datalen) { 125c87c5fbaSopenharmony_ci ssize_t bytes_written; 126c87c5fbaSopenharmony_ci int keep_errno; 127c87c5fbaSopenharmony_ci 128c87c5fbaSopenharmony_ci coap_socket_t *sock = &session->sock; 129c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 130c87c5fbaSopenharmony_ci if (sock->flags == COAP_SOCKET_EMPTY) { 131c87c5fbaSopenharmony_ci assert(session->endpoint != NULL); 132c87c5fbaSopenharmony_ci sock = &session->endpoint->sock; 133c87c5fbaSopenharmony_ci } 134c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 135c87c5fbaSopenharmony_ci 136c87c5fbaSopenharmony_ci bytes_written = coap_socket_send(sock, session, data, datalen); 137c87c5fbaSopenharmony_ci keep_errno = errno; 138c87c5fbaSopenharmony_ci if (bytes_written <= 0) { 139c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: failed to send %zd bytes (%s) state %d\n", 140c87c5fbaSopenharmony_ci coap_session_str(session), datalen, 141c87c5fbaSopenharmony_ci coap_socket_strerror(), session->state); 142c87c5fbaSopenharmony_ci errno = keep_errno; 143c87c5fbaSopenharmony_ci } else { 144c87c5fbaSopenharmony_ci coap_ticks(&session->last_rx_tx); 145c87c5fbaSopenharmony_ci if (bytes_written == (ssize_t)datalen) 146c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: sent %4zd bytes\n", 147c87c5fbaSopenharmony_ci coap_session_str(session), bytes_written); 148c87c5fbaSopenharmony_ci else 149c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: sent %4zd of %4zd bytes\n", 150c87c5fbaSopenharmony_ci coap_session_str(session), bytes_written, datalen); 151c87c5fbaSopenharmony_ci } 152c87c5fbaSopenharmony_ci return bytes_written; 153c87c5fbaSopenharmony_ci} 154c87c5fbaSopenharmony_ci 155c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 156c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 157c87c5fbaSopenharmony_ciint 158c87c5fbaSopenharmony_cicoap_netif_strm_listen(coap_endpoint_t *endpoint, 159c87c5fbaSopenharmony_ci const coap_address_t *listen_addr) { 160c87c5fbaSopenharmony_ci if (!coap_socket_bind_tcp(&endpoint->sock, listen_addr, 161c87c5fbaSopenharmony_ci &endpoint->bind_addr)) { 162c87c5fbaSopenharmony_ci return 0; 163c87c5fbaSopenharmony_ci } 164c87c5fbaSopenharmony_ci endpoint->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND | 165c87c5fbaSopenharmony_ci COAP_SOCKET_WANT_ACCEPT; 166c87c5fbaSopenharmony_ci return 1; 167c87c5fbaSopenharmony_ci} 168c87c5fbaSopenharmony_ci 169c87c5fbaSopenharmony_ciint 170c87c5fbaSopenharmony_cicoap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session) { 171c87c5fbaSopenharmony_ci if (!coap_socket_accept_tcp(&endpoint->sock, &session->sock, 172c87c5fbaSopenharmony_ci &session->addr_info.local, 173c87c5fbaSopenharmony_ci &session->addr_info.remote)) { 174c87c5fbaSopenharmony_ci return 0; 175c87c5fbaSopenharmony_ci } 176c87c5fbaSopenharmony_ci session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_CONNECTED | 177c87c5fbaSopenharmony_ci COAP_SOCKET_WANT_READ; 178c87c5fbaSopenharmony_ci return 1; 179c87c5fbaSopenharmony_ci} 180c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 181c87c5fbaSopenharmony_ci 182c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 183c87c5fbaSopenharmony_ciint 184c87c5fbaSopenharmony_cicoap_netif_strm_connect1(coap_session_t *session, 185c87c5fbaSopenharmony_ci const coap_address_t *local_if, 186c87c5fbaSopenharmony_ci const coap_address_t *server, int default_port) { 187c87c5fbaSopenharmony_ci if (!coap_socket_connect_tcp1(&session->sock, local_if, server, 188c87c5fbaSopenharmony_ci default_port, 189c87c5fbaSopenharmony_ci &session->addr_info.local, 190c87c5fbaSopenharmony_ci &session->addr_info.remote)) { 191c87c5fbaSopenharmony_ci return 0; 192c87c5fbaSopenharmony_ci } 193c87c5fbaSopenharmony_ci return 1; 194c87c5fbaSopenharmony_ci} 195c87c5fbaSopenharmony_ci 196c87c5fbaSopenharmony_ciint 197c87c5fbaSopenharmony_cicoap_netif_strm_connect2(coap_session_t *session) { 198c87c5fbaSopenharmony_ci if (!coap_socket_connect_tcp2(&session->sock, 199c87c5fbaSopenharmony_ci &session->addr_info.local, 200c87c5fbaSopenharmony_ci &session->addr_info.remote)) { 201c87c5fbaSopenharmony_ci return 0; 202c87c5fbaSopenharmony_ci } 203c87c5fbaSopenharmony_ci return 1; 204c87c5fbaSopenharmony_ci} 205c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 206c87c5fbaSopenharmony_ci 207c87c5fbaSopenharmony_ci/* 208c87c5fbaSopenharmony_ci * strm 209c87c5fbaSopenharmony_ci * return >=0 Number of bytes read. 210c87c5fbaSopenharmony_ci * -1 Error (error in errno). 211c87c5fbaSopenharmony_ci */ 212c87c5fbaSopenharmony_cissize_t 213c87c5fbaSopenharmony_cicoap_netif_strm_read(coap_session_t *session, uint8_t *data, size_t datalen) { 214c87c5fbaSopenharmony_ci ssize_t bytes_read = coap_socket_read(&session->sock, data, datalen); 215c87c5fbaSopenharmony_ci int keep_errno = errno; 216c87c5fbaSopenharmony_ci 217c87c5fbaSopenharmony_ci if (bytes_read >= 0) { 218c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: recv %4zd bytes\n", 219c87c5fbaSopenharmony_ci coap_session_str(session), bytes_read); 220c87c5fbaSopenharmony_ci } else if (bytes_read == -1 && errno != EAGAIN) { 221c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: failed to receive any bytes (%s) state %d\n", 222c87c5fbaSopenharmony_ci coap_session_str(session), coap_socket_strerror(), session->state); 223c87c5fbaSopenharmony_ci errno = keep_errno; 224c87c5fbaSopenharmony_ci } 225c87c5fbaSopenharmony_ci return bytes_read; 226c87c5fbaSopenharmony_ci} 227c87c5fbaSopenharmony_ci 228c87c5fbaSopenharmony_ci/* 229c87c5fbaSopenharmony_ci * strm 230c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 231c87c5fbaSopenharmony_ci * -1 Error (error in errno). 232c87c5fbaSopenharmony_ci */ 233c87c5fbaSopenharmony_cissize_t 234c87c5fbaSopenharmony_cicoap_netif_strm_write(coap_session_t *session, const uint8_t *data, 235c87c5fbaSopenharmony_ci size_t datalen) { 236c87c5fbaSopenharmony_ci ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen); 237c87c5fbaSopenharmony_ci int keep_errno = errno; 238c87c5fbaSopenharmony_ci 239c87c5fbaSopenharmony_ci if (bytes_written <= 0) { 240c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: failed to send %zd bytes (%s) state %d\n", 241c87c5fbaSopenharmony_ci coap_session_str(session), datalen, 242c87c5fbaSopenharmony_ci coap_socket_strerror(), session->state); 243c87c5fbaSopenharmony_ci errno = keep_errno; 244c87c5fbaSopenharmony_ci } else { 245c87c5fbaSopenharmony_ci coap_ticks(&session->last_rx_tx); 246c87c5fbaSopenharmony_ci if (bytes_written == (ssize_t)datalen) 247c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: sent %4zd bytes\n", 248c87c5fbaSopenharmony_ci coap_session_str(session), bytes_written); 249c87c5fbaSopenharmony_ci else 250c87c5fbaSopenharmony_ci coap_log_debug("* %s: netif: sent %4zd of %4zd bytes\n", 251c87c5fbaSopenharmony_ci coap_session_str(session), bytes_written, datalen); 252c87c5fbaSopenharmony_ci } 253c87c5fbaSopenharmony_ci return bytes_written; 254c87c5fbaSopenharmony_ci} 255c87c5fbaSopenharmony_ci#endif /* COAP_DISABLE_TCP */ 256c87c5fbaSopenharmony_ci 257c87c5fbaSopenharmony_civoid 258c87c5fbaSopenharmony_cicoap_netif_close(coap_session_t *session) { 259c87c5fbaSopenharmony_ci if (coap_netif_available(session)) 260c87c5fbaSopenharmony_ci coap_socket_close(&session->sock); 261c87c5fbaSopenharmony_ci} 262c87c5fbaSopenharmony_ci 263c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 264c87c5fbaSopenharmony_civoid 265c87c5fbaSopenharmony_cicoap_netif_close_ep(coap_endpoint_t *endpoint) { 266c87c5fbaSopenharmony_ci coap_socket_close(&endpoint->sock); 267c87c5fbaSopenharmony_ci} 268c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 269