1c87c5fbaSopenharmony_ci/* 2c87c5fbaSopenharmony_ci * Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org> 3c87c5fbaSopenharmony_ci * 2014 chrysn <chrysn@fsfe.org> 4c87c5fbaSopenharmony_ci * 2022-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 9c87c5fbaSopenharmony_ci * README for terms of use. 10c87c5fbaSopenharmony_ci */ 11c87c5fbaSopenharmony_ci 12c87c5fbaSopenharmony_ci/** 13c87c5fbaSopenharmony_ci * @file coap_io_lwip.c 14c87c5fbaSopenharmony_ci * @brief LwIP specific functions 15c87c5fbaSopenharmony_ci */ 16c87c5fbaSopenharmony_ci 17c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h" 18c87c5fbaSopenharmony_ci#include <lwip/udp.h> 19c87c5fbaSopenharmony_ci#include <lwip/timeouts.h> 20c87c5fbaSopenharmony_ci#include <lwip/tcpip.h> 21c87c5fbaSopenharmony_ci 22c87c5fbaSopenharmony_civoid 23c87c5fbaSopenharmony_cicoap_lwip_dump_memory_pools(coap_log_t log_level) { 24c87c5fbaSopenharmony_ci#if MEMP_STATS && LWIP_STATS_DISPLAY 25c87c5fbaSopenharmony_ci int i; 26c87c5fbaSopenharmony_ci 27c87c5fbaSopenharmony_ci /* Save time if not needed */ 28c87c5fbaSopenharmony_ci if (log_level > coap_get_log_level()) 29c87c5fbaSopenharmony_ci return; 30c87c5fbaSopenharmony_ci 31c87c5fbaSopenharmony_ci coap_log(log_level, "* LwIP custom memory pools information\n"); 32c87c5fbaSopenharmony_ci /* 33c87c5fbaSopenharmony_ci * Make sure LwIP and libcoap have been built with the same 34c87c5fbaSopenharmony_ci * -DCOAP_CLIENT_ONLY or -DCOAP_SERVER_ONLY options for 35c87c5fbaSopenharmony_ci * MEMP_MAX to be correct. 36c87c5fbaSopenharmony_ci */ 37c87c5fbaSopenharmony_ci for (i = 0; i < MEMP_MAX; i++) { 38c87c5fbaSopenharmony_ci coap_log(log_level, "* %-17s avail %3d in-use %3d peak %3d failed %3d\n", 39c87c5fbaSopenharmony_ci memp_pools[i]->stats->name, memp_pools[i]->stats->avail, 40c87c5fbaSopenharmony_ci memp_pools[i]->stats->used, memp_pools[i]->stats->max, 41c87c5fbaSopenharmony_ci memp_pools[i]->stats->err); 42c87c5fbaSopenharmony_ci } 43c87c5fbaSopenharmony_ci#endif /* MEMP_STATS && LWIP_STATS_DISPLAY */ 44c87c5fbaSopenharmony_ci} 45c87c5fbaSopenharmony_ci 46c87c5fbaSopenharmony_civoid 47c87c5fbaSopenharmony_cicoap_lwip_set_input_wait_handler(coap_context_t *context, 48c87c5fbaSopenharmony_ci coap_lwip_input_wait_handler_t handler, 49c87c5fbaSopenharmony_ci void *input_arg) { 50c87c5fbaSopenharmony_ci context->input_wait = handler; 51c87c5fbaSopenharmony_ci context->input_arg = input_arg; 52c87c5fbaSopenharmony_ci} 53c87c5fbaSopenharmony_ci 54c87c5fbaSopenharmony_civoid 55c87c5fbaSopenharmony_cicoap_io_process_timeout(void *arg) { 56c87c5fbaSopenharmony_ci coap_context_t *context = (coap_context_t *)arg; 57c87c5fbaSopenharmony_ci coap_tick_t before; 58c87c5fbaSopenharmony_ci unsigned int num_sockets; 59c87c5fbaSopenharmony_ci unsigned int timeout; 60c87c5fbaSopenharmony_ci 61c87c5fbaSopenharmony_ci coap_ticks(&before); 62c87c5fbaSopenharmony_ci timeout = coap_io_prepare_io(context, NULL, 0, &num_sockets, before); 63c87c5fbaSopenharmony_ci if (context->timer_configured) { 64c87c5fbaSopenharmony_ci sys_untimeout(coap_io_process_timeout, (void *)context); 65c87c5fbaSopenharmony_ci context->timer_configured = 0; 66c87c5fbaSopenharmony_ci } 67c87c5fbaSopenharmony_ci if (timeout == 0) { 68c87c5fbaSopenharmony_ci /* Garbage collect 1 sec hence */ 69c87c5fbaSopenharmony_ci timeout = 1000; 70c87c5fbaSopenharmony_ci } 71c87c5fbaSopenharmony_ci#ifdef COAP_DEBUG_WAKEUP_TIMES 72c87c5fbaSopenharmony_ci coap_log_info("****** Next wakeup msecs %u (1)\n", 73c87c5fbaSopenharmony_ci timeout); 74c87c5fbaSopenharmony_ci#endif /* COAP_DEBUG_WAKEUP_TIMES */ 75c87c5fbaSopenharmony_ci sys_timeout(timeout, coap_io_process_timeout, context); 76c87c5fbaSopenharmony_ci context->timer_configured = 1; 77c87c5fbaSopenharmony_ci} 78c87c5fbaSopenharmony_ci 79c87c5fbaSopenharmony_ciint 80c87c5fbaSopenharmony_cicoap_io_process(coap_context_t *context, uint32_t timeout_ms) { 81c87c5fbaSopenharmony_ci coap_tick_t before; 82c87c5fbaSopenharmony_ci coap_tick_t now; 83c87c5fbaSopenharmony_ci unsigned int num_sockets; 84c87c5fbaSopenharmony_ci unsigned int timeout; 85c87c5fbaSopenharmony_ci 86c87c5fbaSopenharmony_ci coap_ticks(&before); 87c87c5fbaSopenharmony_ci timeout = coap_io_prepare_io(context, NULL, 0, &num_sockets, before); 88c87c5fbaSopenharmony_ci if (timeout_ms != 0 && timeout_ms != COAP_IO_NO_WAIT && 89c87c5fbaSopenharmony_ci timeout > timeout_ms) { 90c87c5fbaSopenharmony_ci timeout = timeout_ms; 91c87c5fbaSopenharmony_ci } 92c87c5fbaSopenharmony_ci 93c87c5fbaSopenharmony_ci LOCK_TCPIP_CORE(); 94c87c5fbaSopenharmony_ci 95c87c5fbaSopenharmony_ci if (context->timer_configured) { 96c87c5fbaSopenharmony_ci sys_untimeout(coap_io_process_timeout, (void *)context); 97c87c5fbaSopenharmony_ci context->timer_configured = 0; 98c87c5fbaSopenharmony_ci } 99c87c5fbaSopenharmony_ci if (timeout == 0) { 100c87c5fbaSopenharmony_ci /* Garbage collect 1 sec hence */ 101c87c5fbaSopenharmony_ci timeout = 1000; 102c87c5fbaSopenharmony_ci } 103c87c5fbaSopenharmony_ci#ifdef COAP_DEBUG_WAKEUP_TIMES 104c87c5fbaSopenharmony_ci coap_log_info("****** Next wakeup msecs %u (2)\n", 105c87c5fbaSopenharmony_ci timeout); 106c87c5fbaSopenharmony_ci#endif /* COAP_DEBUG_WAKEUP_TIMES */ 107c87c5fbaSopenharmony_ci sys_timeout(timeout, coap_io_process_timeout, context); 108c87c5fbaSopenharmony_ci context->timer_configured = 1; 109c87c5fbaSopenharmony_ci 110c87c5fbaSopenharmony_ci UNLOCK_TCPIP_CORE(); 111c87c5fbaSopenharmony_ci 112c87c5fbaSopenharmony_ci if (context->input_wait) { 113c87c5fbaSopenharmony_ci context->input_wait(context->input_arg, timeout); 114c87c5fbaSopenharmony_ci } 115c87c5fbaSopenharmony_ci 116c87c5fbaSopenharmony_ci LOCK_TCPIP_CORE(); 117c87c5fbaSopenharmony_ci 118c87c5fbaSopenharmony_ci sys_check_timeouts(); 119c87c5fbaSopenharmony_ci 120c87c5fbaSopenharmony_ci UNLOCK_TCPIP_CORE(); 121c87c5fbaSopenharmony_ci 122c87c5fbaSopenharmony_ci coap_ticks(&now); 123c87c5fbaSopenharmony_ci return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND); 124c87c5fbaSopenharmony_ci} 125c87c5fbaSopenharmony_ci 126c87c5fbaSopenharmony_ci/* 127c87c5fbaSopenharmony_ci * Not used for LwIP (done with coap_recvc()), but need dummy function. 128c87c5fbaSopenharmony_ci */ 129c87c5fbaSopenharmony_cissize_t 130c87c5fbaSopenharmony_cicoap_socket_recv(coap_socket_t *sock, coap_packet_t *packet) { 131c87c5fbaSopenharmony_ci (void)sock; 132c87c5fbaSopenharmony_ci (void)packet; 133c87c5fbaSopenharmony_ci assert(0); 134c87c5fbaSopenharmony_ci return -1; 135c87c5fbaSopenharmony_ci} 136c87c5fbaSopenharmony_ci 137c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 138c87c5fbaSopenharmony_ci/** Callback from lwIP when a package was received for a client. 139c87c5fbaSopenharmony_ci * 140c87c5fbaSopenharmony_ci * The current implementation deals this to coap_dispatch immediately, but 141c87c5fbaSopenharmony_ci * other mechanisms (as storing the package in a queue and later fetching it 142c87c5fbaSopenharmony_ci * when coap_io_do_io is called) can be envisioned. 143c87c5fbaSopenharmony_ci * 144c87c5fbaSopenharmony_ci * It handles everything coap_io_do_io does on other implementations. 145c87c5fbaSopenharmony_ci */ 146c87c5fbaSopenharmony_cistatic void 147c87c5fbaSopenharmony_cicoap_recvc(void *arg, struct udp_pcb *upcb, struct pbuf *p, 148c87c5fbaSopenharmony_ci const ip_addr_t *addr, u16_t port) { 149c87c5fbaSopenharmony_ci coap_pdu_t *pdu = NULL; 150c87c5fbaSopenharmony_ci coap_session_t *session = (coap_session_t *)arg; 151c87c5fbaSopenharmony_ci int result = -1; 152c87c5fbaSopenharmony_ci (void)upcb; 153c87c5fbaSopenharmony_ci (void)addr; 154c87c5fbaSopenharmony_ci (void)port; 155c87c5fbaSopenharmony_ci 156c87c5fbaSopenharmony_ci assert(session); 157c87c5fbaSopenharmony_ci LWIP_ASSERT("Proto not supported for LWIP", COAP_PROTO_NOT_RELIABLE(session->proto)); 158c87c5fbaSopenharmony_ci 159c87c5fbaSopenharmony_ci if (p->len < 4) { 160c87c5fbaSopenharmony_ci /* Minimum size of CoAP header - ignore runt */ 161c87c5fbaSopenharmony_ci return; 162c87c5fbaSopenharmony_ci } 163c87c5fbaSopenharmony_ci 164c87c5fbaSopenharmony_ci coap_log_debug("* %s: lwip: recv %4d bytes\n", 165c87c5fbaSopenharmony_ci coap_session_str(session), p->len); 166c87c5fbaSopenharmony_ci if (session->proto == COAP_PROTO_DTLS) { 167c87c5fbaSopenharmony_ci if (session->tls) { 168c87c5fbaSopenharmony_ci result = coap_dtls_receive(session, p->payload, p->len); 169c87c5fbaSopenharmony_ci if (result < 0) 170c87c5fbaSopenharmony_ci goto error; 171c87c5fbaSopenharmony_ci } 172c87c5fbaSopenharmony_ci pbuf_free(p); 173c87c5fbaSopenharmony_ci } else { 174c87c5fbaSopenharmony_ci pdu = coap_pdu_from_pbuf(p); 175c87c5fbaSopenharmony_ci if (!pdu) 176c87c5fbaSopenharmony_ci goto error; 177c87c5fbaSopenharmony_ci 178c87c5fbaSopenharmony_ci if (!coap_pdu_parse(session->proto, p->payload, p->len, pdu)) { 179c87c5fbaSopenharmony_ci goto error; 180c87c5fbaSopenharmony_ci } 181c87c5fbaSopenharmony_ci coap_dispatch(session->context, session, pdu); 182c87c5fbaSopenharmony_ci } 183c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 184c87c5fbaSopenharmony_ci return; 185c87c5fbaSopenharmony_ci 186c87c5fbaSopenharmony_cierror: 187c87c5fbaSopenharmony_ci /* 188c87c5fbaSopenharmony_ci * https://rfc-editor.org/rfc/rfc7252#section-4.2 MUST send RST 189c87c5fbaSopenharmony_ci * https://rfc-editor.org/rfc/rfc7252#section-4.3 MAY send RST 190c87c5fbaSopenharmony_ci */ 191c87c5fbaSopenharmony_ci if (session) 192c87c5fbaSopenharmony_ci coap_send_rst(session, pdu); 193c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 194c87c5fbaSopenharmony_ci return; 195c87c5fbaSopenharmony_ci} 196c87c5fbaSopenharmony_ci#endif /* ! COAP_CLIENT_SUPPORT */ 197c87c5fbaSopenharmony_ci 198c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 199c87c5fbaSopenharmony_ci 200c87c5fbaSopenharmony_cistatic void 201c87c5fbaSopenharmony_cicoap_free_packet(coap_packet_t *packet) { 202c87c5fbaSopenharmony_ci coap_free_type(COAP_PACKET, packet); 203c87c5fbaSopenharmony_ci} 204c87c5fbaSopenharmony_ci 205c87c5fbaSopenharmony_ci/** Callback from lwIP when a package was received for a server. 206c87c5fbaSopenharmony_ci * 207c87c5fbaSopenharmony_ci * The current implementation deals this to coap_dispatch immediately, but 208c87c5fbaSopenharmony_ci * other mechanisms (as storing the package in a queue and later fetching it 209c87c5fbaSopenharmony_ci * when coap_io_do_io is called) can be envisioned. 210c87c5fbaSopenharmony_ci * 211c87c5fbaSopenharmony_ci * It handles everything coap_io_do_io does on other implementations. 212c87c5fbaSopenharmony_ci */ 213c87c5fbaSopenharmony_cistatic void 214c87c5fbaSopenharmony_cicoap_recvs(void *arg, struct udp_pcb *upcb, struct pbuf *p, 215c87c5fbaSopenharmony_ci const ip_addr_t *addr, u16_t port) { 216c87c5fbaSopenharmony_ci coap_endpoint_t *ep = (coap_endpoint_t *)arg; 217c87c5fbaSopenharmony_ci coap_pdu_t *pdu = NULL; 218c87c5fbaSopenharmony_ci coap_session_t *session = NULL; 219c87c5fbaSopenharmony_ci coap_tick_t now; 220c87c5fbaSopenharmony_ci coap_packet_t *packet; 221c87c5fbaSopenharmony_ci int result = -1; 222c87c5fbaSopenharmony_ci 223c87c5fbaSopenharmony_ci if (p->len < 4) { 224c87c5fbaSopenharmony_ci /* Minimum size of CoAP header - ignore runt */ 225c87c5fbaSopenharmony_ci return; 226c87c5fbaSopenharmony_ci } 227c87c5fbaSopenharmony_ci 228c87c5fbaSopenharmony_ci packet = coap_malloc_type(COAP_PACKET, sizeof(coap_packet_t)); 229c87c5fbaSopenharmony_ci 230c87c5fbaSopenharmony_ci /* this is fatal because due to the short life of the packet, never should 231c87c5fbaSopenharmony_ci there be more than one coap_packet_t required */ 232c87c5fbaSopenharmony_ci LWIP_ASSERT("Insufficient coap_packet_t resources.", packet != NULL); 233c87c5fbaSopenharmony_ci /* Need to do this as there may be holes in addr_info */ 234c87c5fbaSopenharmony_ci memset(&packet->addr_info, 0, sizeof(packet->addr_info)); 235c87c5fbaSopenharmony_ci packet->length = p->len; 236c87c5fbaSopenharmony_ci packet->payload = p->payload; 237c87c5fbaSopenharmony_ci packet->addr_info.remote.port = port; 238c87c5fbaSopenharmony_ci packet->addr_info.remote.addr = *addr; 239c87c5fbaSopenharmony_ci packet->addr_info.local.port = upcb->local_port; 240c87c5fbaSopenharmony_ci packet->addr_info.local.addr = *ip_current_dest_addr(); 241c87c5fbaSopenharmony_ci packet->ifindex = netif_get_index(ip_current_netif()); 242c87c5fbaSopenharmony_ci 243c87c5fbaSopenharmony_ci coap_ticks(&now); 244c87c5fbaSopenharmony_ci 245c87c5fbaSopenharmony_ci session = coap_endpoint_get_session(ep, packet, now); 246c87c5fbaSopenharmony_ci if (!session) 247c87c5fbaSopenharmony_ci goto error; 248c87c5fbaSopenharmony_ci LWIP_ASSERT("Proto not supported for LWIP", COAP_PROTO_NOT_RELIABLE(session->proto)); 249c87c5fbaSopenharmony_ci 250c87c5fbaSopenharmony_ci coap_log_debug("* %s: lwip: recv %4d bytes\n", 251c87c5fbaSopenharmony_ci coap_session_str(session), p->len); 252c87c5fbaSopenharmony_ci 253c87c5fbaSopenharmony_ci if (session->proto == COAP_PROTO_DTLS) { 254c87c5fbaSopenharmony_ci if (session->type == COAP_SESSION_TYPE_HELLO) 255c87c5fbaSopenharmony_ci result = coap_dtls_hello(session, p->payload, p->len); 256c87c5fbaSopenharmony_ci else if (session->tls) 257c87c5fbaSopenharmony_ci result = coap_dtls_receive(session, p->payload, p->len); 258c87c5fbaSopenharmony_ci if (session->type == COAP_SESSION_TYPE_HELLO && result == 1) 259c87c5fbaSopenharmony_ci coap_session_new_dtls_session(session, now); 260c87c5fbaSopenharmony_ci pbuf_free(p); 261c87c5fbaSopenharmony_ci } else { 262c87c5fbaSopenharmony_ci pdu = coap_pdu_from_pbuf(p); 263c87c5fbaSopenharmony_ci if (!pdu) 264c87c5fbaSopenharmony_ci goto error; 265c87c5fbaSopenharmony_ci 266c87c5fbaSopenharmony_ci if (!coap_pdu_parse(ep->proto, p->payload, p->len, pdu)) { 267c87c5fbaSopenharmony_ci goto error; 268c87c5fbaSopenharmony_ci } 269c87c5fbaSopenharmony_ci coap_dispatch(ep->context, session, pdu); 270c87c5fbaSopenharmony_ci } 271c87c5fbaSopenharmony_ci 272c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 273c87c5fbaSopenharmony_ci coap_free_packet(packet); 274c87c5fbaSopenharmony_ci return; 275c87c5fbaSopenharmony_ci 276c87c5fbaSopenharmony_cierror: 277c87c5fbaSopenharmony_ci /* 278c87c5fbaSopenharmony_ci * https://rfc-editor.org/rfc/rfc7252#section-4.2 MUST send RST 279c87c5fbaSopenharmony_ci * https://rfc-editor.org/rfc/rfc7252#section-4.3 MAY send RST 280c87c5fbaSopenharmony_ci */ 281c87c5fbaSopenharmony_ci if (session) 282c87c5fbaSopenharmony_ci coap_send_rst(session, pdu); 283c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 284c87c5fbaSopenharmony_ci coap_free_packet(packet); 285c87c5fbaSopenharmony_ci return; 286c87c5fbaSopenharmony_ci} 287c87c5fbaSopenharmony_ci 288c87c5fbaSopenharmony_ci#endif /* ! COAP_SERVER_SUPPORT */ 289c87c5fbaSopenharmony_ci 290c87c5fbaSopenharmony_cissize_t 291c87c5fbaSopenharmony_cicoap_socket_send_pdu(coap_socket_t *sock, coap_session_t *session, 292c87c5fbaSopenharmony_ci coap_pdu_t *pdu) { 293c87c5fbaSopenharmony_ci /* FIXME: we can't check this here with the existing infrastructure, but we 294c87c5fbaSopenharmony_ci * should actually check that the pdu is not held by anyone but us. the 295c87c5fbaSopenharmony_ci * respective pbuf is already exclusively owned by the pdu. */ 296c87c5fbaSopenharmony_ci struct pbuf *pbuf; 297c87c5fbaSopenharmony_ci int err; 298c87c5fbaSopenharmony_ci 299c87c5fbaSopenharmony_ci pbuf_realloc(pdu->pbuf, pdu->used_size + coap_pdu_parse_header_size(session->proto, 300c87c5fbaSopenharmony_ci pdu->pbuf->payload)); 301c87c5fbaSopenharmony_ci 302c87c5fbaSopenharmony_ci if (coap_debug_send_packet()) { 303c87c5fbaSopenharmony_ci /* Need to take a copy as we may be re-using the origin in a retransmit */ 304c87c5fbaSopenharmony_ci pbuf = pbuf_clone(PBUF_TRANSPORT, PBUF_RAM, pdu->pbuf); 305c87c5fbaSopenharmony_ci if (pbuf == NULL) 306c87c5fbaSopenharmony_ci return -1; 307c87c5fbaSopenharmony_ci err = udp_sendto(sock->pcb, pbuf, &session->addr_info.remote.addr, 308c87c5fbaSopenharmony_ci session->addr_info.remote.port); 309c87c5fbaSopenharmony_ci pbuf_free(pbuf); 310c87c5fbaSopenharmony_ci if (err < 0) 311c87c5fbaSopenharmony_ci return -1; 312c87c5fbaSopenharmony_ci } 313c87c5fbaSopenharmony_ci return pdu->used_size; 314c87c5fbaSopenharmony_ci} 315c87c5fbaSopenharmony_ci 316c87c5fbaSopenharmony_ci/* 317c87c5fbaSopenharmony_ci * dgram 318c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 319c87c5fbaSopenharmony_ci * -1 Error error in errno). 320c87c5fbaSopenharmony_ci */ 321c87c5fbaSopenharmony_cissize_t 322c87c5fbaSopenharmony_cicoap_socket_send(coap_socket_t *sock, const coap_session_t *session, 323c87c5fbaSopenharmony_ci const uint8_t *data, size_t data_len) { 324c87c5fbaSopenharmony_ci struct pbuf *pbuf; 325c87c5fbaSopenharmony_ci int err; 326c87c5fbaSopenharmony_ci 327c87c5fbaSopenharmony_ci if (coap_debug_send_packet()) { 328c87c5fbaSopenharmony_ci pbuf = pbuf_alloc(PBUF_TRANSPORT, data_len, PBUF_RAM); 329c87c5fbaSopenharmony_ci if (pbuf == NULL) 330c87c5fbaSopenharmony_ci return -1; 331c87c5fbaSopenharmony_ci memcpy(pbuf->payload, data, data_len); 332c87c5fbaSopenharmony_ci 333c87c5fbaSopenharmony_ci LOCK_TCPIP_CORE(); 334c87c5fbaSopenharmony_ci 335c87c5fbaSopenharmony_ci err = udp_sendto(sock->pcb, pbuf, &session->addr_info.remote.addr, 336c87c5fbaSopenharmony_ci session->addr_info.remote.port); 337c87c5fbaSopenharmony_ci 338c87c5fbaSopenharmony_ci UNLOCK_TCPIP_CORE(); 339c87c5fbaSopenharmony_ci 340c87c5fbaSopenharmony_ci pbuf_free(pbuf); 341c87c5fbaSopenharmony_ci if (err < 0) 342c87c5fbaSopenharmony_ci return -1; 343c87c5fbaSopenharmony_ci } 344c87c5fbaSopenharmony_ci return data_len; 345c87c5fbaSopenharmony_ci} 346c87c5fbaSopenharmony_ci 347c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 348c87c5fbaSopenharmony_ciint 349c87c5fbaSopenharmony_cicoap_socket_bind_udp(coap_socket_t *sock, 350c87c5fbaSopenharmony_ci const coap_address_t *listen_addr, 351c87c5fbaSopenharmony_ci coap_address_t *bound_addr) { 352c87c5fbaSopenharmony_ci int err; 353c87c5fbaSopenharmony_ci coap_address_t l_listen = *listen_addr; 354c87c5fbaSopenharmony_ci 355c87c5fbaSopenharmony_ci sock->pcb = udp_new_ip_type(IPADDR_TYPE_ANY); 356c87c5fbaSopenharmony_ci if (sock->pcb == NULL) 357c87c5fbaSopenharmony_ci return 0; 358c87c5fbaSopenharmony_ci 359c87c5fbaSopenharmony_ci#if LWIP_IPV6 && LWIP_IPV4 360c87c5fbaSopenharmony_ci if (l_listen.addr.type == IPADDR_TYPE_V6) 361c87c5fbaSopenharmony_ci l_listen.addr.type = IPADDR_TYPE_ANY; 362c87c5fbaSopenharmony_ci#endif /* LWIP_IPV6 && LWIP_IPV4 */ 363c87c5fbaSopenharmony_ci udp_recv(sock->pcb, coap_recvs, (void *)sock->endpoint); 364c87c5fbaSopenharmony_ci err = udp_bind(sock->pcb, &l_listen.addr, l_listen.port); 365c87c5fbaSopenharmony_ci if (err) { 366c87c5fbaSopenharmony_ci udp_remove(sock->pcb); 367c87c5fbaSopenharmony_ci sock->pcb = NULL; 368c87c5fbaSopenharmony_ci } 369c87c5fbaSopenharmony_ci *bound_addr = l_listen; 370c87c5fbaSopenharmony_ci return err ? 0 : 1; 371c87c5fbaSopenharmony_ci} 372c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 373c87c5fbaSopenharmony_ci 374c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 375c87c5fbaSopenharmony_ciint 376c87c5fbaSopenharmony_cicoap_socket_connect_udp(coap_socket_t *sock, 377c87c5fbaSopenharmony_ci const coap_address_t *local_if, 378c87c5fbaSopenharmony_ci const coap_address_t *server, 379c87c5fbaSopenharmony_ci int default_port, 380c87c5fbaSopenharmony_ci coap_address_t *local_addr, 381c87c5fbaSopenharmony_ci coap_address_t *remote_addr) { 382c87c5fbaSopenharmony_ci err_t err; 383c87c5fbaSopenharmony_ci struct udp_pcb *pcb; 384c87c5fbaSopenharmony_ci 385c87c5fbaSopenharmony_ci (void)local_if; 386c87c5fbaSopenharmony_ci (void)default_port; 387c87c5fbaSopenharmony_ci (void)local_addr; 388c87c5fbaSopenharmony_ci (void)remote_addr; 389c87c5fbaSopenharmony_ci 390c87c5fbaSopenharmony_ci LOCK_TCPIP_CORE(); 391c87c5fbaSopenharmony_ci 392c87c5fbaSopenharmony_ci pcb = udp_new(); 393c87c5fbaSopenharmony_ci 394c87c5fbaSopenharmony_ci if (!pcb) { 395c87c5fbaSopenharmony_ci goto err_unlock; 396c87c5fbaSopenharmony_ci } 397c87c5fbaSopenharmony_ci 398c87c5fbaSopenharmony_ci err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); 399c87c5fbaSopenharmony_ci if (err) { 400c87c5fbaSopenharmony_ci LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 401c87c5fbaSopenharmony_ci ("coap_socket_connect_udp: port bind failed\n")); 402c87c5fbaSopenharmony_ci goto err_udp_remove; 403c87c5fbaSopenharmony_ci } 404c87c5fbaSopenharmony_ci 405c87c5fbaSopenharmony_ci sock->session->addr_info.local.port = pcb->local_port; 406c87c5fbaSopenharmony_ci 407c87c5fbaSopenharmony_ci err = udp_connect(pcb, &server->addr, server->port); 408c87c5fbaSopenharmony_ci if (err) { 409c87c5fbaSopenharmony_ci goto err_udp_unbind; 410c87c5fbaSopenharmony_ci } 411c87c5fbaSopenharmony_ci 412c87c5fbaSopenharmony_ci#if LWIP_IPV6 && LWIP_IPV4 413c87c5fbaSopenharmony_ci pcb->local_ip.type = pcb->remote_ip.type; 414c87c5fbaSopenharmony_ci#endif /* LWIP_IPV6 && LWIP_IPV4 */ 415c87c5fbaSopenharmony_ci 416c87c5fbaSopenharmony_ci sock->pcb = pcb; 417c87c5fbaSopenharmony_ci 418c87c5fbaSopenharmony_ci udp_recv(sock->pcb, coap_recvc, (void *)sock->session); 419c87c5fbaSopenharmony_ci 420c87c5fbaSopenharmony_ci UNLOCK_TCPIP_CORE(); 421c87c5fbaSopenharmony_ci 422c87c5fbaSopenharmony_ci return 1; 423c87c5fbaSopenharmony_ci 424c87c5fbaSopenharmony_cierr_udp_unbind: 425c87c5fbaSopenharmony_cierr_udp_remove: 426c87c5fbaSopenharmony_ci udp_remove(pcb); 427c87c5fbaSopenharmony_cierr_unlock: 428c87c5fbaSopenharmony_ci UNLOCK_TCPIP_CORE(); 429c87c5fbaSopenharmony_ci return 0; 430c87c5fbaSopenharmony_ci} 431c87c5fbaSopenharmony_ci#endif /* ! COAP_CLIENT_SUPPORT */ 432c87c5fbaSopenharmony_ci 433c87c5fbaSopenharmony_ci#if ! COAP_DISABLE_TCP 434c87c5fbaSopenharmony_ciint 435c87c5fbaSopenharmony_cicoap_socket_connect_tcp1(coap_socket_t *sock, 436c87c5fbaSopenharmony_ci const coap_address_t *local_if, 437c87c5fbaSopenharmony_ci const coap_address_t *server, 438c87c5fbaSopenharmony_ci int default_port, 439c87c5fbaSopenharmony_ci coap_address_t *local_addr, 440c87c5fbaSopenharmony_ci coap_address_t *remote_addr) { 441c87c5fbaSopenharmony_ci (void)sock; 442c87c5fbaSopenharmony_ci (void)local_if; 443c87c5fbaSopenharmony_ci (void)server; 444c87c5fbaSopenharmony_ci (void)default_port; 445c87c5fbaSopenharmony_ci (void)local_addr; 446c87c5fbaSopenharmony_ci (void)remote_addr; 447c87c5fbaSopenharmony_ci return 0; 448c87c5fbaSopenharmony_ci} 449c87c5fbaSopenharmony_ci 450c87c5fbaSopenharmony_ciint 451c87c5fbaSopenharmony_cicoap_socket_connect_tcp2(coap_socket_t *sock, 452c87c5fbaSopenharmony_ci coap_address_t *local_addr, 453c87c5fbaSopenharmony_ci coap_address_t *remote_addr) { 454c87c5fbaSopenharmony_ci (void)sock; 455c87c5fbaSopenharmony_ci (void)local_addr; 456c87c5fbaSopenharmony_ci (void)remote_addr; 457c87c5fbaSopenharmony_ci return 0; 458c87c5fbaSopenharmony_ci} 459c87c5fbaSopenharmony_ci 460c87c5fbaSopenharmony_ciint 461c87c5fbaSopenharmony_cicoap_socket_bind_tcp(coap_socket_t *sock, 462c87c5fbaSopenharmony_ci const coap_address_t *listen_addr, 463c87c5fbaSopenharmony_ci coap_address_t *bound_addr) { 464c87c5fbaSopenharmony_ci (void)sock; 465c87c5fbaSopenharmony_ci (void)listen_addr; 466c87c5fbaSopenharmony_ci (void)bound_addr; 467c87c5fbaSopenharmony_ci return 0; 468c87c5fbaSopenharmony_ci} 469c87c5fbaSopenharmony_ci 470c87c5fbaSopenharmony_ciint 471c87c5fbaSopenharmony_cicoap_socket_accept_tcp(coap_socket_t *server, 472c87c5fbaSopenharmony_ci coap_socket_t *new_client, 473c87c5fbaSopenharmony_ci coap_address_t *local_addr, 474c87c5fbaSopenharmony_ci coap_address_t *remote_addr) { 475c87c5fbaSopenharmony_ci (void)server; 476c87c5fbaSopenharmony_ci (void)new_client; 477c87c5fbaSopenharmony_ci (void)local_addr; 478c87c5fbaSopenharmony_ci (void)remote_addr; 479c87c5fbaSopenharmony_ci return 0; 480c87c5fbaSopenharmony_ci} 481c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 482c87c5fbaSopenharmony_ci 483c87c5fbaSopenharmony_cissize_t 484c87c5fbaSopenharmony_cicoap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { 485c87c5fbaSopenharmony_ci (void)sock; 486c87c5fbaSopenharmony_ci (void)data; 487c87c5fbaSopenharmony_ci (void)data_len; 488c87c5fbaSopenharmony_ci return -1; 489c87c5fbaSopenharmony_ci} 490c87c5fbaSopenharmony_ci 491c87c5fbaSopenharmony_cissize_t 492c87c5fbaSopenharmony_cicoap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { 493c87c5fbaSopenharmony_ci (void)sock; 494c87c5fbaSopenharmony_ci (void)data; 495c87c5fbaSopenharmony_ci (void)data_len; 496c87c5fbaSopenharmony_ci return -1; 497c87c5fbaSopenharmony_ci} 498c87c5fbaSopenharmony_ci 499c87c5fbaSopenharmony_civoid 500c87c5fbaSopenharmony_cicoap_socket_close(coap_socket_t *sock) { 501c87c5fbaSopenharmony_ci if (sock->pcb) { 502c87c5fbaSopenharmony_ci LOCK_TCPIP_CORE(); 503c87c5fbaSopenharmony_ci udp_remove(sock->pcb); 504c87c5fbaSopenharmony_ci UNLOCK_TCPIP_CORE(); 505c87c5fbaSopenharmony_ci } 506c87c5fbaSopenharmony_ci sock->pcb = NULL; 507c87c5fbaSopenharmony_ci return; 508c87c5fbaSopenharmony_ci} 509