1c87c5fbaSopenharmony_ci/* coap_io.c -- Default network I/O functions for libcoap 2c87c5fbaSopenharmony_ci * 3c87c5fbaSopenharmony_ci * Copyright (C) 2012,2014,2016-2023 Olaf Bergmann <bergmann@tzi.org> and others 4c87c5fbaSopenharmony_ci * 5c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 6c87c5fbaSopenharmony_ci * 7c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see 8c87c5fbaSopenharmony_ci * README for terms of use. 9c87c5fbaSopenharmony_ci */ 10c87c5fbaSopenharmony_ci 11c87c5fbaSopenharmony_ci/** 12c87c5fbaSopenharmony_ci * @file coap_io.c 13c87c5fbaSopenharmony_ci * @brief Network I/O functions 14c87c5fbaSopenharmony_ci */ 15c87c5fbaSopenharmony_ci 16c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h" 17c87c5fbaSopenharmony_ci 18c87c5fbaSopenharmony_ci#ifdef HAVE_STDIO_H 19c87c5fbaSopenharmony_ci# include <stdio.h> 20c87c5fbaSopenharmony_ci#endif 21c87c5fbaSopenharmony_ci 22c87c5fbaSopenharmony_ci#ifdef HAVE_SYS_SELECT_H 23c87c5fbaSopenharmony_ci# include <sys/select.h> 24c87c5fbaSopenharmony_ci#endif 25c87c5fbaSopenharmony_ci#ifdef HAVE_SYS_SOCKET_H 26c87c5fbaSopenharmony_ci# include <sys/socket.h> 27c87c5fbaSopenharmony_ci# define OPTVAL_T(t) (t) 28c87c5fbaSopenharmony_ci# define OPTVAL_GT(t) (t) 29c87c5fbaSopenharmony_ci#endif 30c87c5fbaSopenharmony_ci#ifdef HAVE_SYS_IOCTL_H 31c87c5fbaSopenharmony_ci#include <sys/ioctl.h> 32c87c5fbaSopenharmony_ci#endif 33c87c5fbaSopenharmony_ci#ifdef HAVE_NETINET_IN_H 34c87c5fbaSopenharmony_ci# include <netinet/in.h> 35c87c5fbaSopenharmony_ci#endif 36c87c5fbaSopenharmony_ci#ifdef HAVE_WS2TCPIP_H 37c87c5fbaSopenharmony_ci#include <ws2tcpip.h> 38c87c5fbaSopenharmony_ci# define OPTVAL_T(t) (const char*)(t) 39c87c5fbaSopenharmony_ci# define OPTVAL_GT(t) (char*)(t) 40c87c5fbaSopenharmony_ci# undef CMSG_DATA 41c87c5fbaSopenharmony_ci# define CMSG_DATA WSA_CMSG_DATA 42c87c5fbaSopenharmony_ci#endif 43c87c5fbaSopenharmony_ci#ifdef HAVE_SYS_UIO_H 44c87c5fbaSopenharmony_ci# include <sys/uio.h> 45c87c5fbaSopenharmony_ci#endif 46c87c5fbaSopenharmony_ci#ifdef HAVE_UNISTD_H 47c87c5fbaSopenharmony_ci# include <unistd.h> 48c87c5fbaSopenharmony_ci#endif 49c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 50c87c5fbaSopenharmony_ci#include <sys/epoll.h> 51c87c5fbaSopenharmony_ci#include <sys/timerfd.h> 52c87c5fbaSopenharmony_ci#ifdef HAVE_LIMITS_H 53c87c5fbaSopenharmony_ci#include <limits.h> 54c87c5fbaSopenharmony_ci#endif 55c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 56c87c5fbaSopenharmony_ci 57c87c5fbaSopenharmony_ci#if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) && !(WITH_LWIP) 58c87c5fbaSopenharmony_ci/* define generic PKTINFO for IPv4 */ 59c87c5fbaSopenharmony_ci#if defined(IP_PKTINFO) 60c87c5fbaSopenharmony_ci# define GEN_IP_PKTINFO IP_PKTINFO 61c87c5fbaSopenharmony_ci#elif defined(IP_RECVDSTADDR) 62c87c5fbaSopenharmony_ci# define GEN_IP_PKTINFO IP_RECVDSTADDR 63c87c5fbaSopenharmony_ci#else 64c87c5fbaSopenharmony_ci# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS." 65c87c5fbaSopenharmony_ci#endif /* IP_PKTINFO */ 66c87c5fbaSopenharmony_ci 67c87c5fbaSopenharmony_ci/* define generic PKTINFO for IPv6 */ 68c87c5fbaSopenharmony_ci#ifdef IPV6_RECVPKTINFO 69c87c5fbaSopenharmony_ci# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO 70c87c5fbaSopenharmony_ci#elif defined(IPV6_PKTINFO) 71c87c5fbaSopenharmony_ci# define GEN_IPV6_PKTINFO IPV6_PKTINFO 72c87c5fbaSopenharmony_ci#else 73c87c5fbaSopenharmony_ci# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS." 74c87c5fbaSopenharmony_ci#endif /* IPV6_RECVPKTINFO */ 75c87c5fbaSopenharmony_ci#endif /* !(WITH_CONTIKI || RIOT_VERSION) */ 76c87c5fbaSopenharmony_ci 77c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 78c87c5fbaSopenharmony_ci#include <coap3/coap_address.h> 79c87c5fbaSopenharmony_ci#ifndef _WIN32 80c87c5fbaSopenharmony_ci#include <arpa/inet.h> 81c87c5fbaSopenharmony_ci#include <net/if.h> 82c87c5fbaSopenharmony_ci 83c87c5fbaSopenharmony_cistatic int 84c87c5fbaSopenharmony_cibind_to_device(int sockfd, const struct sockaddr_in *local_addr) { 85c87c5fbaSopenharmony_ci struct ifreq buf[COAP_INTERFACE_MAX]; 86c87c5fbaSopenharmony_ci struct ifconf ifc; 87c87c5fbaSopenharmony_ci (void)memset_s(buf, COAP_INTERFACE_MAX * sizeof(struct ifreq), 0x00, COAP_INTERFACE_MAX * sizeof(struct ifreq)); 88c87c5fbaSopenharmony_ci (void)memset_s(&ifc, sizeof(struct ifconf), 0x00, sizeof(struct ifconf)); 89c87c5fbaSopenharmony_ci ifc.ifc_len = sizeof(buf); 90c87c5fbaSopenharmony_ci ifc.ifc_buf = (char *)buf; 91c87c5fbaSopenharmony_ci 92c87c5fbaSopenharmony_ci if(ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0) { 93c87c5fbaSopenharmony_ci coap_log_err("bind_to_device: ioctl SIOCGIFCONF fail, err: %s\n", coap_socket_strerror()); 94c87c5fbaSopenharmony_ci return -1; 95c87c5fbaSopenharmony_ci } 96c87c5fbaSopenharmony_ci int interface_num = ifc.ifc_len / sizeof(struct ifreq); 97c87c5fbaSopenharmony_ci for (int i = 0; i < interface_num && i < COAP_INTERFACE_MAX; i++) { 98c87c5fbaSopenharmony_ci coap_log_debug("bind_to_device: nic name: %s\n", buf[i].ifr_name); 99c87c5fbaSopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, (char *)(&buf[i])) < 0) { 100c87c5fbaSopenharmony_ci coap_log_err("bind_to_device: ioctl SIOCGIFFLAGS fail, err: %s\n", coap_socket_strerror()); 101c87c5fbaSopenharmony_ci return -1; 102c87c5fbaSopenharmony_ci } 103c87c5fbaSopenharmony_ci if (!((uint16_t)buf[i].ifr_flags & IFF_UP)) { 104c87c5fbaSopenharmony_ci coap_log_warn("bind_to_device: nic is not up\n"); 105c87c5fbaSopenharmony_ci continue; 106c87c5fbaSopenharmony_ci } 107c87c5fbaSopenharmony_ci if (ioctl(sockfd, SIOCGIFADDR, (char *)&buf[i]) < 0) { 108c87c5fbaSopenharmony_ci coap_log_err("bind_to_device: ioctl SIOCGIFADDR fail, err: %s\n", coap_socket_strerror()); 109c87c5fbaSopenharmony_ci return -1; 110c87c5fbaSopenharmony_ci } 111c87c5fbaSopenharmony_ci /* find the target nic by ip, begin to bind */ 112c87c5fbaSopenharmony_ci if (local_addr->sin_addr.s_addr == ((struct sockaddr_in *)&(buf[i].ifr_addr))->sin_addr.s_addr) { 113c87c5fbaSopenharmony_ci struct ifreq ifr; 114c87c5fbaSopenharmony_ci (void)memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); 115c87c5fbaSopenharmony_ci (void)strcpy_s(ifr.ifr_ifrn.ifrn_name, sizeof(ifr.ifr_ifrn.ifrn_name), 116c87c5fbaSopenharmony_ci buf[i].ifr_name); 117c87c5fbaSopenharmony_ci if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr)) < 0) { 118c87c5fbaSopenharmony_ci coap_log_err("bind_to_device: setsockopt SO_BINDTODEVICE fail, err: %s\n", coap_socket_strerror()); 119c87c5fbaSopenharmony_ci return -1; 120c87c5fbaSopenharmony_ci } 121c87c5fbaSopenharmony_ci coap_log_debug("bind_to_device: bind nic %s success\n", buf[i].ifr_name); 122c87c5fbaSopenharmony_ci break; 123c87c5fbaSopenharmony_ci } 124c87c5fbaSopenharmony_ci } 125c87c5fbaSopenharmony_ci return 0; 126c87c5fbaSopenharmony_ci} 127c87c5fbaSopenharmony_ci 128c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 129c87c5fbaSopenharmony_ci#endif /* COAP_SUPPORT_SOCKET_BROADCAST */ 130c87c5fbaSopenharmony_ci 131c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 132c87c5fbaSopenharmony_cicoap_endpoint_t * 133c87c5fbaSopenharmony_cicoap_malloc_endpoint(void) { 134c87c5fbaSopenharmony_ci return (coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(coap_endpoint_t)); 135c87c5fbaSopenharmony_ci} 136c87c5fbaSopenharmony_ci 137c87c5fbaSopenharmony_civoid 138c87c5fbaSopenharmony_cicoap_mfree_endpoint(coap_endpoint_t *ep) { 139c87c5fbaSopenharmony_ci coap_free_type(COAP_ENDPOINT, ep); 140c87c5fbaSopenharmony_ci} 141c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 142c87c5fbaSopenharmony_ci 143c87c5fbaSopenharmony_ci#if !defined(WITH_CONTIKI) && !defined(WITH_LWIP) 144c87c5fbaSopenharmony_ci 145c87c5fbaSopenharmony_ciint 146c87c5fbaSopenharmony_cicoap_socket_bind_udp(coap_socket_t *sock, 147c87c5fbaSopenharmony_ci const coap_address_t *listen_addr, 148c87c5fbaSopenharmony_ci coap_address_t *bound_addr) { 149c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION 150c87c5fbaSopenharmony_ci int on = 1; 151c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 152c87c5fbaSopenharmony_ci int off = 0; 153c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 154c87c5fbaSopenharmony_ci#else /* ! RIOT_VERSION */ 155c87c5fbaSopenharmony_ci struct timeval timeout = {0, 0}; 156c87c5fbaSopenharmony_ci#endif /* ! RIOT_VERSION */ 157c87c5fbaSopenharmony_ci#ifdef _WIN32 158c87c5fbaSopenharmony_ci u_long u_on = 1; 159c87c5fbaSopenharmony_ci#endif 160c87c5fbaSopenharmony_ci 161c87c5fbaSopenharmony_ci sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0); 162c87c5fbaSopenharmony_ci 163c87c5fbaSopenharmony_ci if (sock->fd == COAP_INVALID_SOCKET) { 164c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_bind_udp: socket: %s\n", coap_socket_strerror()); 165c87c5fbaSopenharmony_ci goto error; 166c87c5fbaSopenharmony_ci } 167c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION 168c87c5fbaSopenharmony_ci#ifdef _WIN32 169c87c5fbaSopenharmony_ci if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { 170c87c5fbaSopenharmony_ci#else 171c87c5fbaSopenharmony_ci if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { 172c87c5fbaSopenharmony_ci#endif 173c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror()); 174c87c5fbaSopenharmony_ci } 175c87c5fbaSopenharmony_ci 176c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) 177c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n", 178c87c5fbaSopenharmony_ci coap_socket_strerror()); 179c87c5fbaSopenharmony_ci 180c87c5fbaSopenharmony_ci switch (listen_addr->addr.sa.sa_family) { 181c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 182c87c5fbaSopenharmony_ci case AF_INET: 183c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), 184c87c5fbaSopenharmony_ci sizeof(on)) == COAP_SOCKET_ERROR) 185c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n", 186c87c5fbaSopenharmony_ci coap_socket_strerror()); 187c87c5fbaSopenharmony_ci break; 188c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 189c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 190c87c5fbaSopenharmony_ci case AF_INET6: 191c87c5fbaSopenharmony_ci /* Configure the socket as dual-stacked */ 192c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), 193c87c5fbaSopenharmony_ci sizeof(off)) == COAP_SOCKET_ERROR) 194c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n", 195c87c5fbaSopenharmony_ci coap_socket_strerror()); 196c87c5fbaSopenharmony_ci#if !defined(ESPIDF_VERSION) 197c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), 198c87c5fbaSopenharmony_ci sizeof(on)) == COAP_SOCKET_ERROR) 199c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n", 200c87c5fbaSopenharmony_ci coap_socket_strerror()); 201c87c5fbaSopenharmony_ci#endif /* !defined(ESPIDF_VERSION) */ 202c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 203c87c5fbaSopenharmony_ci setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)); 204c87c5fbaSopenharmony_ci /* ignore error, because likely cause is that IPv4 is disabled at the os 205c87c5fbaSopenharmony_ci level */ 206c87c5fbaSopenharmony_ci break; 207c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 208c87c5fbaSopenharmony_ci case AF_UNIX: 209c87c5fbaSopenharmony_ci break; 210c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 211c87c5fbaSopenharmony_ci default: 212c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_bind_udp: unsupported sa_family\n"); 213c87c5fbaSopenharmony_ci break; 214c87c5fbaSopenharmony_ci } 215c87c5fbaSopenharmony_ci#else /* ! RIOT_VERSION */ 216c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, OPTVAL_T(&timeout), 217c87c5fbaSopenharmony_ci (socklen_t)sizeof(timeout)) == COAP_SOCKET_ERROR) 218c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_bind_udp: setsockopt SO_RCVTIMEO: %s\n", 219c87c5fbaSopenharmony_ci coap_socket_strerror()); 220c87c5fbaSopenharmony_ci#endif /* ! RIOT_VERSION */ 221c87c5fbaSopenharmony_ci 222c87c5fbaSopenharmony_ci if (bind(sock->fd, &listen_addr->addr.sa, 223c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 224c87c5fbaSopenharmony_ci listen_addr->addr.sa.sa_family == AF_INET ? 225c87c5fbaSopenharmony_ci (socklen_t)sizeof(struct sockaddr_in) : 226c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 227c87c5fbaSopenharmony_ci (socklen_t)listen_addr->size) == COAP_SOCKET_ERROR) { 228c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_bind_udp: bind: %s\n", 229c87c5fbaSopenharmony_ci coap_socket_strerror()); 230c87c5fbaSopenharmony_ci goto error; 231c87c5fbaSopenharmony_ci } 232c87c5fbaSopenharmony_ci 233c87c5fbaSopenharmony_ci bound_addr->size = (socklen_t)sizeof(*bound_addr); 234c87c5fbaSopenharmony_ci if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) { 235c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_bind_udp: getsockname: %s\n", 236c87c5fbaSopenharmony_ci coap_socket_strerror()); 237c87c5fbaSopenharmony_ci goto error; 238c87c5fbaSopenharmony_ci } 239c87c5fbaSopenharmony_ci#if defined(RIOT_VERSION) && defined(COAP_SERVER_SUPPORT) 240c87c5fbaSopenharmony_ci if (sock->endpoint && 241c87c5fbaSopenharmony_ci bound_addr->addr.sa.sa_family == AF_INET6) { 242c87c5fbaSopenharmony_ci bound_addr->addr.sin6.sin6_scope_id = 243c87c5fbaSopenharmony_ci listen_addr->addr.sin6.sin6_scope_id; 244c87c5fbaSopenharmony_ci bound_addr->addr.sin6.sin6_flowinfo = 0; 245c87c5fbaSopenharmony_ci } 246c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION && COAP_SERVER_SUPPORT */ 247c87c5fbaSopenharmony_ci 248c87c5fbaSopenharmony_ci return 1; 249c87c5fbaSopenharmony_ci 250c87c5fbaSopenharmony_cierror: 251c87c5fbaSopenharmony_ci coap_socket_close(sock); 252c87c5fbaSopenharmony_ci return 0; 253c87c5fbaSopenharmony_ci} 254c87c5fbaSopenharmony_ci 255c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 256c87c5fbaSopenharmony_ciint 257c87c5fbaSopenharmony_cicoap_socket_connect_udp(coap_socket_t *sock, 258c87c5fbaSopenharmony_ci const coap_address_t *local_if, 259c87c5fbaSopenharmony_ci const coap_address_t *server, 260c87c5fbaSopenharmony_ci int default_port, 261c87c5fbaSopenharmony_ci coap_address_t *local_addr, 262c87c5fbaSopenharmony_ci coap_address_t *remote_addr) { 263c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION 264c87c5fbaSopenharmony_ci int on = 1; 265c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 266c87c5fbaSopenharmony_ci int off = 0; 267c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 268c87c5fbaSopenharmony_ci#else /* ! RIOT_VERSION */ 269c87c5fbaSopenharmony_ci struct timeval timeout = {0, 0}; 270c87c5fbaSopenharmony_ci#endif /* ! RIOT_VERSION */ 271c87c5fbaSopenharmony_ci#ifdef _WIN32 272c87c5fbaSopenharmony_ci u_long u_on = 1; 273c87c5fbaSopenharmony_ci#endif 274c87c5fbaSopenharmony_ci coap_address_t connect_addr; 275c87c5fbaSopenharmony_ci#if !defined(RIOT_VERSION) 276c87c5fbaSopenharmony_ci int is_mcast = coap_is_mcast(server); 277c87c5fbaSopenharmony_ci#endif /* !defined(RIOT_VERSION) */ 278c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 279c87c5fbaSopenharmony_ci int is_bcast = coap_is_bcast(server); 280c87c5fbaSopenharmony_ci#endif 281c87c5fbaSopenharmony_ci coap_address_copy(&connect_addr, server); 282c87c5fbaSopenharmony_ci 283c87c5fbaSopenharmony_ci sock->flags &= ~(COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST); 284c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 285c87c5fbaSopenharmony_ci sock->flags &= ~(COAP_SOCKET_BROADCAST); 286c87c5fbaSopenharmony_ci#endif 287c87c5fbaSopenharmony_ci sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0); 288c87c5fbaSopenharmony_ci 289c87c5fbaSopenharmony_ci if (sock->fd == COAP_INVALID_SOCKET) { 290c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: socket: %s\n", 291c87c5fbaSopenharmony_ci coap_socket_strerror()); 292c87c5fbaSopenharmony_ci goto error; 293c87c5fbaSopenharmony_ci } 294c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 295c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(int)) < 0) { 296c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: setsockopt SO_BROADCAST fail, err: %s\n", 297c87c5fbaSopenharmony_ci coap_socket_strerror()); 298c87c5fbaSopenharmony_ci goto error; 299c87c5fbaSopenharmony_ci } 300c87c5fbaSopenharmony_ci#endif 301c87c5fbaSopenharmony_ci 302c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION 303c87c5fbaSopenharmony_ci#ifdef _WIN32 304c87c5fbaSopenharmony_ci if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) 305c87c5fbaSopenharmony_ci#else 306c87c5fbaSopenharmony_ci if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) 307c87c5fbaSopenharmony_ci#endif 308c87c5fbaSopenharmony_ci { 309c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: ioctl FIONBIO: %s\n", 310c87c5fbaSopenharmony_ci coap_socket_strerror()); 311c87c5fbaSopenharmony_ci } 312c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */ 313c87c5fbaSopenharmony_ci 314c87c5fbaSopenharmony_ci switch (connect_addr.addr.sa.sa_family) { 315c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 316c87c5fbaSopenharmony_ci case AF_INET: 317c87c5fbaSopenharmony_ci if (connect_addr.addr.sin.sin_port == 0) 318c87c5fbaSopenharmony_ci connect_addr.addr.sin.sin_port = htons(default_port); 319c87c5fbaSopenharmony_ci break; 320c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 321c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 322c87c5fbaSopenharmony_ci case AF_INET6: 323c87c5fbaSopenharmony_ci if (connect_addr.addr.sin6.sin6_port == 0) 324c87c5fbaSopenharmony_ci connect_addr.addr.sin6.sin6_port = htons(default_port); 325c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION 326c87c5fbaSopenharmony_ci /* Configure the socket as dual-stacked */ 327c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), 328c87c5fbaSopenharmony_ci sizeof(off)) == COAP_SOCKET_ERROR) 329c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n", 330c87c5fbaSopenharmony_ci coap_socket_strerror()); 331c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */ 332c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 333c87c5fbaSopenharmony_ci break; 334c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 335c87c5fbaSopenharmony_ci case AF_UNIX: 336c87c5fbaSopenharmony_ci break; 337c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 338c87c5fbaSopenharmony_ci default: 339c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_connect_udp: unsupported sa_family %d\n", 340c87c5fbaSopenharmony_ci connect_addr.addr.sa.sa_family); 341c87c5fbaSopenharmony_ci goto error;; 342c87c5fbaSopenharmony_ci } 343c87c5fbaSopenharmony_ci 344c87c5fbaSopenharmony_ci if (local_if && local_if->addr.sa.sa_family) { 345c87c5fbaSopenharmony_ci if (local_if->addr.sa.sa_family != connect_addr.addr.sa.sa_family) { 346c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: local address family != " 347c87c5fbaSopenharmony_ci "remote address family\n"); 348c87c5fbaSopenharmony_ci goto error; 349c87c5fbaSopenharmony_ci } 350c87c5fbaSopenharmony_ci#ifndef RIOT_VERSION 351c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) 352c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n", 353c87c5fbaSopenharmony_ci coap_socket_strerror()); 354c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION */ 355c87c5fbaSopenharmony_ci if (bind(sock->fd, &local_if->addr.sa, 356c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 357c87c5fbaSopenharmony_ci local_if->addr.sa.sa_family == AF_INET ? 358c87c5fbaSopenharmony_ci (socklen_t)sizeof(struct sockaddr_in) : 359c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 360c87c5fbaSopenharmony_ci (socklen_t)local_if->size) == COAP_SOCKET_ERROR) { 361c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: bind: %s\n", 362c87c5fbaSopenharmony_ci coap_socket_strerror()); 363c87c5fbaSopenharmony_ci goto error; 364c87c5fbaSopenharmony_ci } 365c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 366c87c5fbaSopenharmony_ci#ifndef _WIN32 367c87c5fbaSopenharmony_ci int ret = bind_to_device(sock->fd, (struct sockaddr_in *)(&local_if->addr.sa)); 368c87c5fbaSopenharmony_ci if (ret == -1) 369c87c5fbaSopenharmony_ci goto error; 370c87c5fbaSopenharmony_ci#endif 371c87c5fbaSopenharmony_ci#endif 372c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 373c87c5fbaSopenharmony_ci } else if (connect_addr.addr.sa.sa_family == AF_UNIX) { 374c87c5fbaSopenharmony_ci /* Need to bind to a local address for clarity over endpoints */ 375c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: local address required\n"); 376c87c5fbaSopenharmony_ci goto error; 377c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 378c87c5fbaSopenharmony_ci } 379c87c5fbaSopenharmony_ci 380c87c5fbaSopenharmony_ci /* special treatment for sockets that are used for multicast communication */ 381c87c5fbaSopenharmony_ci#if !defined(RIOT_VERSION) 382c87c5fbaSopenharmony_ci if (is_mcast) { 383c87c5fbaSopenharmony_ci if (!(local_if && local_if->addr.sa.sa_family)) { 384c87c5fbaSopenharmony_ci /* Bind to a (unused) port to simplify logging */ 385c87c5fbaSopenharmony_ci coap_address_t bind_addr; 386c87c5fbaSopenharmony_ci 387c87c5fbaSopenharmony_ci coap_address_init(&bind_addr); 388c87c5fbaSopenharmony_ci bind_addr.addr.sa.sa_family = connect_addr.addr.sa.sa_family; 389c87c5fbaSopenharmony_ci if (bind(sock->fd, &bind_addr.addr.sa, 390c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 391c87c5fbaSopenharmony_ci bind_addr.addr.sa.sa_family == AF_INET ? 392c87c5fbaSopenharmony_ci (socklen_t)sizeof(struct sockaddr_in) : 393c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 394c87c5fbaSopenharmony_ci (socklen_t)bind_addr.size) == COAP_SOCKET_ERROR) { 395c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: bind: %s\n", 396c87c5fbaSopenharmony_ci coap_socket_strerror()); 397c87c5fbaSopenharmony_ci goto error; 398c87c5fbaSopenharmony_ci } 399c87c5fbaSopenharmony_ci } 400c87c5fbaSopenharmony_ci if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { 401c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: getsockname for multicast socket: %s\n", 402c87c5fbaSopenharmony_ci coap_socket_strerror()); 403c87c5fbaSopenharmony_ci } 404c87c5fbaSopenharmony_ci coap_address_copy(remote_addr, &connect_addr); 405c87c5fbaSopenharmony_ci coap_address_copy(&sock->mcast_addr, &connect_addr); 406c87c5fbaSopenharmony_ci sock->flags |= COAP_SOCKET_MULTICAST; 407c87c5fbaSopenharmony_ci if (coap_is_bcast(server) && 408c87c5fbaSopenharmony_ci setsockopt(sock->fd, SOL_SOCKET, SO_BROADCAST, OPTVAL_T(&on), 409c87c5fbaSopenharmony_ci sizeof(on)) == COAP_SOCKET_ERROR) 410c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: setsockopt SO_BROADCAST: %s\n", 411c87c5fbaSopenharmony_ci coap_socket_strerror()); 412c87c5fbaSopenharmony_ci return 1; 413c87c5fbaSopenharmony_ci } 414c87c5fbaSopenharmony_ci 415c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 416c87c5fbaSopenharmony_ci if (is_bcast) { 417c87c5fbaSopenharmony_ci if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { 418c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: getsockname for broadcast socket: %s\n", 419c87c5fbaSopenharmony_ci coap_socket_strerror()); 420c87c5fbaSopenharmony_ci } 421c87c5fbaSopenharmony_ci sock->flags |= COAP_SOCKET_BROADCAST; 422c87c5fbaSopenharmony_ci return 1; 423c87c5fbaSopenharmony_ci } 424c87c5fbaSopenharmony_ci#endif 425c87c5fbaSopenharmony_ci#else /* defined(RIOT_VERSION) */ 426c87c5fbaSopenharmony_ci if (!(local_if && local_if->addr.sa.sa_family)) { 427c87c5fbaSopenharmony_ci /* Bind to a (unused) port to simplify logging */ 428c87c5fbaSopenharmony_ci coap_address_t bind_addr; 429c87c5fbaSopenharmony_ci 430c87c5fbaSopenharmony_ci coap_address_init(&bind_addr); 431c87c5fbaSopenharmony_ci bind_addr.addr.sa.sa_family = connect_addr.addr.sa.sa_family; 432c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 433c87c5fbaSopenharmony_ci if (bind_addr.addr.sa.sa_family == AF_INET6) 434c87c5fbaSopenharmony_ci bind_addr.addr.sin6.sin6_scope_id = connect_addr.addr.sin6.sin6_scope_id; 435c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 436c87c5fbaSopenharmony_ci if (bind(sock->fd, &bind_addr.addr.sa, 437c87c5fbaSopenharmony_ci bind_addr.addr.sa.sa_family == AF_INET ? 438c87c5fbaSopenharmony_ci (socklen_t)sizeof(struct sockaddr_in) : 439c87c5fbaSopenharmony_ci (socklen_t)bind_addr.size) == COAP_SOCKET_ERROR) { 440c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: bind: %s\n", 441c87c5fbaSopenharmony_ci coap_socket_strerror()); 442c87c5fbaSopenharmony_ci goto error; 443c87c5fbaSopenharmony_ci } 444c87c5fbaSopenharmony_ci } 445c87c5fbaSopenharmony_ci if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, OPTVAL_T(&timeout), 446c87c5fbaSopenharmony_ci (socklen_t)sizeof(timeout)) == COAP_SOCKET_ERROR) 447c87c5fbaSopenharmony_ci coap_log_alert("coap_socket_bind_udp: setsockopt SO_RCVTIMEO: %s\n", 448c87c5fbaSopenharmony_ci coap_socket_strerror()); 449c87c5fbaSopenharmony_ci#endif /* defined(RIOT_VERSION) */ 450c87c5fbaSopenharmony_ci 451c87c5fbaSopenharmony_ci if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) { 452c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 453c87c5fbaSopenharmony_ci if (connect_addr.addr.sa.sa_family == AF_UNIX) { 454c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: connect: %s: %s\n", 455c87c5fbaSopenharmony_ci connect_addr.addr.cun.sun_path, coap_socket_strerror()); 456c87c5fbaSopenharmony_ci } else 457c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 458c87c5fbaSopenharmony_ci { 459c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: connect: %s (%d)\n", 460c87c5fbaSopenharmony_ci coap_socket_strerror(), connect_addr.addr.sa.sa_family); 461c87c5fbaSopenharmony_ci } 462c87c5fbaSopenharmony_ci goto error; 463c87c5fbaSopenharmony_ci } 464c87c5fbaSopenharmony_ci 465c87c5fbaSopenharmony_ci if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { 466c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: getsockname: %s\n", 467c87c5fbaSopenharmony_ci coap_socket_strerror()); 468c87c5fbaSopenharmony_ci } 469c87c5fbaSopenharmony_ci 470c87c5fbaSopenharmony_ci if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { 471c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_connect_udp: getpeername: %s\n", 472c87c5fbaSopenharmony_ci coap_socket_strerror()); 473c87c5fbaSopenharmony_ci } 474c87c5fbaSopenharmony_ci 475c87c5fbaSopenharmony_ci sock->flags |= COAP_SOCKET_CONNECTED; 476c87c5fbaSopenharmony_ci return 1; 477c87c5fbaSopenharmony_ci 478c87c5fbaSopenharmony_cierror: 479c87c5fbaSopenharmony_ci coap_socket_close(sock); 480c87c5fbaSopenharmony_ci return 0; 481c87c5fbaSopenharmony_ci} 482c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 483c87c5fbaSopenharmony_ci 484c87c5fbaSopenharmony_civoid 485c87c5fbaSopenharmony_cicoap_socket_close(coap_socket_t *sock) { 486c87c5fbaSopenharmony_ci if (sock->fd != COAP_INVALID_SOCKET) { 487c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 488c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 489c87c5fbaSopenharmony_ci coap_context_t *context = sock->session ? sock->session->context : 490c87c5fbaSopenharmony_ci sock->endpoint ? sock->endpoint->context : NULL; 491c87c5fbaSopenharmony_ci#else /* COAP_SERVER_SUPPORT */ 492c87c5fbaSopenharmony_ci coap_context_t *context = sock->session ? sock->session->context : NULL; 493c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 494c87c5fbaSopenharmony_ci if (context != NULL) { 495c87c5fbaSopenharmony_ci int ret; 496c87c5fbaSopenharmony_ci struct epoll_event event; 497c87c5fbaSopenharmony_ci 498c87c5fbaSopenharmony_ci /* Kernels prior to 2.6.9 expect non NULL event parameter */ 499c87c5fbaSopenharmony_ci ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->fd, &event); 500c87c5fbaSopenharmony_ci if (ret == -1 && errno != ENOENT) { 501c87c5fbaSopenharmony_ci coap_log_err("%s: epoll_ctl DEL failed: %s (%d)\n", 502c87c5fbaSopenharmony_ci "coap_socket_close", 503c87c5fbaSopenharmony_ci coap_socket_strerror(), errno); 504c87c5fbaSopenharmony_ci } 505c87c5fbaSopenharmony_ci } 506c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 507c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 508c87c5fbaSopenharmony_ci if (sock->endpoint && 509c87c5fbaSopenharmony_ci sock->endpoint->bind_addr.addr.sa.sa_family == AF_UNIX) { 510c87c5fbaSopenharmony_ci /* Clean up Unix endpoint */ 511c87c5fbaSopenharmony_ci unlink(sock->endpoint->bind_addr.addr.cun.sun_path); 512c87c5fbaSopenharmony_ci } 513c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 514c87c5fbaSopenharmony_ci sock->endpoint = NULL; 515c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 516c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 517c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 518c87c5fbaSopenharmony_ci if (sock->session && sock->session->type == COAP_SESSION_TYPE_CLIENT && 519c87c5fbaSopenharmony_ci sock->session->addr_info.local.addr.sa.sa_family == AF_UNIX) { 520c87c5fbaSopenharmony_ci /* Clean up Unix endpoint */ 521c87c5fbaSopenharmony_ci unlink(sock->session->addr_info.local.addr.cun.sun_path); 522c87c5fbaSopenharmony_ci } 523c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 524c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 525c87c5fbaSopenharmony_ci sock->session = NULL; 526c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 527c87c5fbaSopenharmony_ci coap_closesocket(sock->fd); 528c87c5fbaSopenharmony_ci sock->fd = COAP_INVALID_SOCKET; 529c87c5fbaSopenharmony_ci } 530c87c5fbaSopenharmony_ci sock->flags = COAP_SOCKET_EMPTY; 531c87c5fbaSopenharmony_ci} 532c87c5fbaSopenharmony_ci 533c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 534c87c5fbaSopenharmony_civoid 535c87c5fbaSopenharmony_cicoap_epoll_ctl_add(coap_socket_t *sock, 536c87c5fbaSopenharmony_ci uint32_t events, 537c87c5fbaSopenharmony_ci const char *func) { 538c87c5fbaSopenharmony_ci int ret; 539c87c5fbaSopenharmony_ci struct epoll_event event; 540c87c5fbaSopenharmony_ci coap_context_t *context; 541c87c5fbaSopenharmony_ci 542c87c5fbaSopenharmony_ci#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR 543c87c5fbaSopenharmony_ci (void)func; 544c87c5fbaSopenharmony_ci#endif 545c87c5fbaSopenharmony_ci 546c87c5fbaSopenharmony_ci if (sock == NULL) 547c87c5fbaSopenharmony_ci return; 548c87c5fbaSopenharmony_ci 549c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 550c87c5fbaSopenharmony_ci context = sock->session ? sock->session->context : 551c87c5fbaSopenharmony_ci sock->endpoint ? sock->endpoint->context : NULL; 552c87c5fbaSopenharmony_ci#else /* ! COAP_SERVER_SUPPORT */ 553c87c5fbaSopenharmony_ci context = sock->session ? sock->session->context : NULL; 554c87c5fbaSopenharmony_ci#endif /* ! COAP_SERVER_SUPPORT */ 555c87c5fbaSopenharmony_ci if (context == NULL) 556c87c5fbaSopenharmony_ci return; 557c87c5fbaSopenharmony_ci 558c87c5fbaSopenharmony_ci /* Needed if running 32bit as ptr is only 32bit */ 559c87c5fbaSopenharmony_ci memset(&event, 0, sizeof(event)); 560c87c5fbaSopenharmony_ci event.events = events; 561c87c5fbaSopenharmony_ci event.data.ptr = sock; 562c87c5fbaSopenharmony_ci 563c87c5fbaSopenharmony_ci ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->fd, &event); 564c87c5fbaSopenharmony_ci if (ret == -1) { 565c87c5fbaSopenharmony_ci coap_log_err("%s: epoll_ctl ADD failed: %s (%d)\n", 566c87c5fbaSopenharmony_ci func, 567c87c5fbaSopenharmony_ci coap_socket_strerror(), errno); 568c87c5fbaSopenharmony_ci } 569c87c5fbaSopenharmony_ci} 570c87c5fbaSopenharmony_ci 571c87c5fbaSopenharmony_civoid 572c87c5fbaSopenharmony_cicoap_epoll_ctl_mod(coap_socket_t *sock, 573c87c5fbaSopenharmony_ci uint32_t events, 574c87c5fbaSopenharmony_ci const char *func) { 575c87c5fbaSopenharmony_ci int ret; 576c87c5fbaSopenharmony_ci struct epoll_event event; 577c87c5fbaSopenharmony_ci coap_context_t *context; 578c87c5fbaSopenharmony_ci 579c87c5fbaSopenharmony_ci#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR 580c87c5fbaSopenharmony_ci (void)func; 581c87c5fbaSopenharmony_ci#endif 582c87c5fbaSopenharmony_ci 583c87c5fbaSopenharmony_ci if (sock == NULL) 584c87c5fbaSopenharmony_ci return; 585c87c5fbaSopenharmony_ci 586c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 587c87c5fbaSopenharmony_ci context = sock->session ? sock->session->context : 588c87c5fbaSopenharmony_ci sock->endpoint ? sock->endpoint->context : NULL; 589c87c5fbaSopenharmony_ci#else /* COAP_SERVER_SUPPORT */ 590c87c5fbaSopenharmony_ci context = sock->session ? sock->session->context : NULL; 591c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 592c87c5fbaSopenharmony_ci if (context == NULL) 593c87c5fbaSopenharmony_ci return; 594c87c5fbaSopenharmony_ci 595c87c5fbaSopenharmony_ci event.events = events; 596c87c5fbaSopenharmony_ci event.data.ptr = sock; 597c87c5fbaSopenharmony_ci 598c87c5fbaSopenharmony_ci ret = epoll_ctl(context->epfd, EPOLL_CTL_MOD, sock->fd, &event); 599c87c5fbaSopenharmony_ci if (ret == -1) { 600c87c5fbaSopenharmony_ci#if (COAP_MAX_LOGGING_LEVEL < COAP_LOG_ERR) 601c87c5fbaSopenharmony_ci (void)func; 602c87c5fbaSopenharmony_ci#endif 603c87c5fbaSopenharmony_ci coap_log_err("%s: epoll_ctl MOD failed: %s (%d)\n", 604c87c5fbaSopenharmony_ci func, 605c87c5fbaSopenharmony_ci coap_socket_strerror(), errno); 606c87c5fbaSopenharmony_ci } 607c87c5fbaSopenharmony_ci} 608c87c5fbaSopenharmony_ci 609c87c5fbaSopenharmony_civoid 610c87c5fbaSopenharmony_cicoap_update_epoll_timer(coap_context_t *context, coap_tick_t delay) { 611c87c5fbaSopenharmony_ci if (context->eptimerfd != -1) { 612c87c5fbaSopenharmony_ci coap_tick_t now; 613c87c5fbaSopenharmony_ci 614c87c5fbaSopenharmony_ci coap_ticks(&now); 615c87c5fbaSopenharmony_ci if (context->next_timeout == 0 || context->next_timeout > now + delay) { 616c87c5fbaSopenharmony_ci struct itimerspec new_value; 617c87c5fbaSopenharmony_ci int ret; 618c87c5fbaSopenharmony_ci 619c87c5fbaSopenharmony_ci context->next_timeout = now + delay; 620c87c5fbaSopenharmony_ci memset(&new_value, 0, sizeof(new_value)); 621c87c5fbaSopenharmony_ci if (delay == 0) { 622c87c5fbaSopenharmony_ci new_value.it_value.tv_nsec = 1; /* small but not zero */ 623c87c5fbaSopenharmony_ci } else { 624c87c5fbaSopenharmony_ci new_value.it_value.tv_sec = delay / COAP_TICKS_PER_SECOND; 625c87c5fbaSopenharmony_ci new_value.it_value.tv_nsec = (delay % COAP_TICKS_PER_SECOND) * 626c87c5fbaSopenharmony_ci 1000000; 627c87c5fbaSopenharmony_ci } 628c87c5fbaSopenharmony_ci ret = timerfd_settime(context->eptimerfd, 0, &new_value, NULL); 629c87c5fbaSopenharmony_ci if (ret == -1) { 630c87c5fbaSopenharmony_ci coap_log_err("%s: timerfd_settime failed: %s (%d)\n", 631c87c5fbaSopenharmony_ci "coap_resource_notify_observers", 632c87c5fbaSopenharmony_ci coap_socket_strerror(), errno); 633c87c5fbaSopenharmony_ci } 634c87c5fbaSopenharmony_ci#ifdef COAP_DEBUG_WAKEUP_TIMES 635c87c5fbaSopenharmony_ci else { 636c87c5fbaSopenharmony_ci coap_log_debug("****** Next wakeup time %3ld.%09ld\n", 637c87c5fbaSopenharmony_ci new_value.it_value.tv_sec, new_value.it_value.tv_nsec); 638c87c5fbaSopenharmony_ci } 639c87c5fbaSopenharmony_ci#endif /* COAP_DEBUG_WAKEUP_TIMES */ 640c87c5fbaSopenharmony_ci } 641c87c5fbaSopenharmony_ci } 642c87c5fbaSopenharmony_ci} 643c87c5fbaSopenharmony_ci 644c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 645c87c5fbaSopenharmony_ci 646c87c5fbaSopenharmony_ci#ifdef _WIN32 647c87c5fbaSopenharmony_cistatic void 648c87c5fbaSopenharmony_cicoap_win_error_to_errno(void) { 649c87c5fbaSopenharmony_ci int w_error = WSAGetLastError(); 650c87c5fbaSopenharmony_ci switch (w_error) { 651c87c5fbaSopenharmony_ci case WSA_NOT_ENOUGH_MEMORY: 652c87c5fbaSopenharmony_ci errno = ENOMEM; 653c87c5fbaSopenharmony_ci break; 654c87c5fbaSopenharmony_ci case WSA_INVALID_PARAMETER: 655c87c5fbaSopenharmony_ci errno = EINVAL; 656c87c5fbaSopenharmony_ci break; 657c87c5fbaSopenharmony_ci case WSAEINTR: 658c87c5fbaSopenharmony_ci errno = EINTR; 659c87c5fbaSopenharmony_ci break; 660c87c5fbaSopenharmony_ci case WSAEBADF: 661c87c5fbaSopenharmony_ci errno = EBADF; 662c87c5fbaSopenharmony_ci break; 663c87c5fbaSopenharmony_ci case WSAEACCES: 664c87c5fbaSopenharmony_ci errno = EACCES; 665c87c5fbaSopenharmony_ci break; 666c87c5fbaSopenharmony_ci case WSAEFAULT: 667c87c5fbaSopenharmony_ci errno = EFAULT; 668c87c5fbaSopenharmony_ci break; 669c87c5fbaSopenharmony_ci case WSAEINVAL: 670c87c5fbaSopenharmony_ci errno = EINVAL; 671c87c5fbaSopenharmony_ci break; 672c87c5fbaSopenharmony_ci case WSAEMFILE: 673c87c5fbaSopenharmony_ci errno = EMFILE; 674c87c5fbaSopenharmony_ci break; 675c87c5fbaSopenharmony_ci case WSAEWOULDBLOCK: 676c87c5fbaSopenharmony_ci errno = EWOULDBLOCK; 677c87c5fbaSopenharmony_ci break; 678c87c5fbaSopenharmony_ci case WSAENETDOWN: 679c87c5fbaSopenharmony_ci errno = ENETDOWN; 680c87c5fbaSopenharmony_ci break; 681c87c5fbaSopenharmony_ci case WSAENETUNREACH: 682c87c5fbaSopenharmony_ci errno = ENETUNREACH; 683c87c5fbaSopenharmony_ci break; 684c87c5fbaSopenharmony_ci case WSAENETRESET: 685c87c5fbaSopenharmony_ci errno = ENETRESET; 686c87c5fbaSopenharmony_ci break; 687c87c5fbaSopenharmony_ci case WSAECONNABORTED: 688c87c5fbaSopenharmony_ci errno = ECONNABORTED; 689c87c5fbaSopenharmony_ci break; 690c87c5fbaSopenharmony_ci case WSAECONNRESET: 691c87c5fbaSopenharmony_ci errno = ECONNRESET; 692c87c5fbaSopenharmony_ci break; 693c87c5fbaSopenharmony_ci case WSAENOBUFS: 694c87c5fbaSopenharmony_ci errno = ENOBUFS; 695c87c5fbaSopenharmony_ci break; 696c87c5fbaSopenharmony_ci case WSAETIMEDOUT: 697c87c5fbaSopenharmony_ci errno = ETIMEDOUT; 698c87c5fbaSopenharmony_ci break; 699c87c5fbaSopenharmony_ci case WSAECONNREFUSED: 700c87c5fbaSopenharmony_ci errno = ECONNREFUSED; 701c87c5fbaSopenharmony_ci break; 702c87c5fbaSopenharmony_ci default: 703c87c5fbaSopenharmony_ci coap_log_err("WSAGetLastError: %d mapping to errno failed - please fix\n", 704c87c5fbaSopenharmony_ci w_error); 705c87c5fbaSopenharmony_ci errno = EPERM; 706c87c5fbaSopenharmony_ci break; 707c87c5fbaSopenharmony_ci } 708c87c5fbaSopenharmony_ci} 709c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 710c87c5fbaSopenharmony_ci 711c87c5fbaSopenharmony_ci/* 712c87c5fbaSopenharmony_ci * strm 713c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 714c87c5fbaSopenharmony_ci * 0 No data written. 715c87c5fbaSopenharmony_ci * -1 Error (error in errno). 716c87c5fbaSopenharmony_ci */ 717c87c5fbaSopenharmony_cissize_t 718c87c5fbaSopenharmony_cicoap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { 719c87c5fbaSopenharmony_ci ssize_t r; 720c87c5fbaSopenharmony_ci 721c87c5fbaSopenharmony_ci sock->flags &= ~(COAP_SOCKET_WANT_WRITE | COAP_SOCKET_CAN_WRITE); 722c87c5fbaSopenharmony_ci#ifdef _WIN32 723c87c5fbaSopenharmony_ci r = send(sock->fd, (const char *)data, (int)data_len, 0); 724c87c5fbaSopenharmony_ci#else 725c87c5fbaSopenharmony_ci#ifndef MSG_NOSIGNAL 726c87c5fbaSopenharmony_ci#define MSG_NOSIGNAL 0 727c87c5fbaSopenharmony_ci#endif /* MSG_NOSIGNAL */ 728c87c5fbaSopenharmony_ci r = send(sock->fd, data, data_len, MSG_NOSIGNAL); 729c87c5fbaSopenharmony_ci#endif 730c87c5fbaSopenharmony_ci if (r == COAP_SOCKET_ERROR) { 731c87c5fbaSopenharmony_ci#ifdef _WIN32 732c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 733c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 734c87c5fbaSopenharmony_ci if (errno==EAGAIN || 735c87c5fbaSopenharmony_ci#if EAGAIN != EWOULDBLOCK 736c87c5fbaSopenharmony_ci errno == EWOULDBLOCK || 737c87c5fbaSopenharmony_ci#endif 738c87c5fbaSopenharmony_ci errno == EINTR) { 739c87c5fbaSopenharmony_ci sock->flags |= COAP_SOCKET_WANT_WRITE; 740c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 741c87c5fbaSopenharmony_ci coap_epoll_ctl_mod(sock, 742c87c5fbaSopenharmony_ci EPOLLOUT | 743c87c5fbaSopenharmony_ci ((sock->flags & COAP_SOCKET_WANT_READ) ? 744c87c5fbaSopenharmony_ci EPOLLIN : 0), 745c87c5fbaSopenharmony_ci __func__); 746c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 747c87c5fbaSopenharmony_ci return 0; 748c87c5fbaSopenharmony_ci } 749c87c5fbaSopenharmony_ci if (errno == EPIPE || errno == ECONNRESET) { 750c87c5fbaSopenharmony_ci coap_log_info("coap_socket_write: send: %s\n", 751c87c5fbaSopenharmony_ci coap_socket_strerror()); 752c87c5fbaSopenharmony_ci } else { 753c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_write: send: %s\n", 754c87c5fbaSopenharmony_ci coap_socket_strerror()); 755c87c5fbaSopenharmony_ci } 756c87c5fbaSopenharmony_ci return -1; 757c87c5fbaSopenharmony_ci } 758c87c5fbaSopenharmony_ci if (r < (ssize_t)data_len) { 759c87c5fbaSopenharmony_ci sock->flags |= COAP_SOCKET_WANT_WRITE; 760c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 761c87c5fbaSopenharmony_ci coap_epoll_ctl_mod(sock, 762c87c5fbaSopenharmony_ci EPOLLOUT | 763c87c5fbaSopenharmony_ci ((sock->flags & COAP_SOCKET_WANT_READ) ? 764c87c5fbaSopenharmony_ci EPOLLIN : 0), 765c87c5fbaSopenharmony_ci __func__); 766c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 767c87c5fbaSopenharmony_ci } 768c87c5fbaSopenharmony_ci return r; 769c87c5fbaSopenharmony_ci} 770c87c5fbaSopenharmony_ci 771c87c5fbaSopenharmony_ci/* 772c87c5fbaSopenharmony_ci * strm 773c87c5fbaSopenharmony_ci * return >=0 Number of bytes read. 774c87c5fbaSopenharmony_ci * -1 Error (error in errno). 775c87c5fbaSopenharmony_ci */ 776c87c5fbaSopenharmony_cissize_t 777c87c5fbaSopenharmony_cicoap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { 778c87c5fbaSopenharmony_ci ssize_t r; 779c87c5fbaSopenharmony_ci 780c87c5fbaSopenharmony_ci#ifdef _WIN32 781c87c5fbaSopenharmony_ci r = recv(sock->fd, (char *)data, (int)data_len, 0); 782c87c5fbaSopenharmony_ci#else 783c87c5fbaSopenharmony_ci r = recv(sock->fd, data, data_len, 0); 784c87c5fbaSopenharmony_ci#endif 785c87c5fbaSopenharmony_ci if (r == 0) { 786c87c5fbaSopenharmony_ci /* graceful shutdown */ 787c87c5fbaSopenharmony_ci sock->flags &= ~COAP_SOCKET_CAN_READ; 788c87c5fbaSopenharmony_ci errno = ECONNRESET; 789c87c5fbaSopenharmony_ci return -1; 790c87c5fbaSopenharmony_ci } else if (r == COAP_SOCKET_ERROR) { 791c87c5fbaSopenharmony_ci sock->flags &= ~COAP_SOCKET_CAN_READ; 792c87c5fbaSopenharmony_ci#ifdef _WIN32 793c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 794c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 795c87c5fbaSopenharmony_ci if (errno==EAGAIN || 796c87c5fbaSopenharmony_ci#if EAGAIN != EWOULDBLOCK 797c87c5fbaSopenharmony_ci errno == EWOULDBLOCK || 798c87c5fbaSopenharmony_ci#endif 799c87c5fbaSopenharmony_ci errno == EINTR) { 800c87c5fbaSopenharmony_ci return 0; 801c87c5fbaSopenharmony_ci } 802c87c5fbaSopenharmony_ci if (errno != ECONNRESET) { 803c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_read: recv: %s\n", 804c87c5fbaSopenharmony_ci coap_socket_strerror()); 805c87c5fbaSopenharmony_ci } 806c87c5fbaSopenharmony_ci return -1; 807c87c5fbaSopenharmony_ci } 808c87c5fbaSopenharmony_ci if (r < (ssize_t)data_len) 809c87c5fbaSopenharmony_ci sock->flags &= ~COAP_SOCKET_CAN_READ; 810c87c5fbaSopenharmony_ci return r; 811c87c5fbaSopenharmony_ci} 812c87c5fbaSopenharmony_ci 813c87c5fbaSopenharmony_ci#endif /* ! WITH_CONTIKI && ! WITH_LWIP */ 814c87c5fbaSopenharmony_ci 815c87c5fbaSopenharmony_ci#if !defined(WITH_LWIP) 816c87c5fbaSopenharmony_ci#if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) ) 817c87c5fbaSopenharmony_ci/* define struct in6_pktinfo and struct in_pktinfo if not available 818c87c5fbaSopenharmony_ci FIXME: check with configure 819c87c5fbaSopenharmony_ci*/ 820c87c5fbaSopenharmony_ci#if !defined(__MINGW32__) 821c87c5fbaSopenharmony_cistruct in6_pktinfo { 822c87c5fbaSopenharmony_ci struct in6_addr ipi6_addr; /* src/dst IPv6 address */ 823c87c5fbaSopenharmony_ci unsigned int ipi6_ifindex; /* send/recv interface index */ 824c87c5fbaSopenharmony_ci}; 825c87c5fbaSopenharmony_ci 826c87c5fbaSopenharmony_cistruct in_pktinfo { 827c87c5fbaSopenharmony_ci int ipi_ifindex; 828c87c5fbaSopenharmony_ci struct in_addr ipi_spec_dst; 829c87c5fbaSopenharmony_ci struct in_addr ipi_addr; 830c87c5fbaSopenharmony_ci}; 831c87c5fbaSopenharmony_ci#endif /* ! __MINGW32__ */ 832c87c5fbaSopenharmony_ci#endif 833c87c5fbaSopenharmony_ci#endif /* ! WITH_LWIP */ 834c87c5fbaSopenharmony_ci 835c87c5fbaSopenharmony_ci#if !defined(WITH_CONTIKI) && !defined(SOL_IP) 836c87c5fbaSopenharmony_ci/* Solaris expects level IPPROTO_IP for ancillary data. */ 837c87c5fbaSopenharmony_ci#define SOL_IP IPPROTO_IP 838c87c5fbaSopenharmony_ci#endif 839c87c5fbaSopenharmony_ci#ifdef _WIN32 840c87c5fbaSopenharmony_ci#define COAP_SOL_IP IPPROTO_IP 841c87c5fbaSopenharmony_ci#else /* ! _WIN32 */ 842c87c5fbaSopenharmony_ci#define COAP_SOL_IP SOL_IP 843c87c5fbaSopenharmony_ci#endif /* ! _WIN32 */ 844c87c5fbaSopenharmony_ci 845c87c5fbaSopenharmony_ci#if defined(_WIN32) 846c87c5fbaSopenharmony_ci#include <mswsock.h> 847c87c5fbaSopenharmony_ci#if !defined(__MINGW32__) 848c87c5fbaSopenharmony_cistatic __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL; 849c87c5fbaSopenharmony_ci#endif /* ! __MINGW32__ */ 850c87c5fbaSopenharmony_ci/* Map struct WSABUF fields to their posix counterpart */ 851c87c5fbaSopenharmony_ci#define msghdr _WSAMSG 852c87c5fbaSopenharmony_ci#define msg_name name 853c87c5fbaSopenharmony_ci#define msg_namelen namelen 854c87c5fbaSopenharmony_ci#define msg_iov lpBuffers 855c87c5fbaSopenharmony_ci#define msg_iovlen dwBufferCount 856c87c5fbaSopenharmony_ci#define msg_control Control.buf 857c87c5fbaSopenharmony_ci#define msg_controllen Control.len 858c87c5fbaSopenharmony_ci#define iovec _WSABUF 859c87c5fbaSopenharmony_ci#define iov_base buf 860c87c5fbaSopenharmony_ci#define iov_len len 861c87c5fbaSopenharmony_ci#define iov_len_t u_long 862c87c5fbaSopenharmony_ci#undef CMSG_DATA 863c87c5fbaSopenharmony_ci#define CMSG_DATA WSA_CMSG_DATA 864c87c5fbaSopenharmony_ci#define ipi_spec_dst ipi_addr 865c87c5fbaSopenharmony_ci#if !defined(__MINGW32__) 866c87c5fbaSopenharmony_ci#pragma warning( disable : 4116 ) 867c87c5fbaSopenharmony_ci#endif /* ! __MINGW32__ */ 868c87c5fbaSopenharmony_ci#else 869c87c5fbaSopenharmony_ci#define iov_len_t size_t 870c87c5fbaSopenharmony_ci#endif 871c87c5fbaSopenharmony_ci 872c87c5fbaSopenharmony_ci#if defined(_CYGWIN_ENV) 873c87c5fbaSopenharmony_ci#define ipi_spec_dst ipi_addr 874c87c5fbaSopenharmony_ci#endif 875c87c5fbaSopenharmony_ci 876c87c5fbaSopenharmony_ci#if !defined(RIOT_VERSION) && !defined(WITH_LWIP) && !defined(WITH_CONTIKI) 877c87c5fbaSopenharmony_ci/* 878c87c5fbaSopenharmony_ci * dgram 879c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 880c87c5fbaSopenharmony_ci * -1 Error error in errno). 881c87c5fbaSopenharmony_ci */ 882c87c5fbaSopenharmony_cissize_t 883c87c5fbaSopenharmony_cicoap_socket_send(coap_socket_t *sock, const coap_session_t *session, 884c87c5fbaSopenharmony_ci const uint8_t *data, size_t datalen) { 885c87c5fbaSopenharmony_ci ssize_t bytes_written = 0; 886c87c5fbaSopenharmony_ci 887c87c5fbaSopenharmony_ci if (!coap_debug_send_packet()) { 888c87c5fbaSopenharmony_ci bytes_written = (ssize_t)datalen; 889c87c5fbaSopenharmony_ci } else if (sock->flags & COAP_SOCKET_CONNECTED) { 890c87c5fbaSopenharmony_ci#ifdef _WIN32 891c87c5fbaSopenharmony_ci bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0); 892c87c5fbaSopenharmony_ci#else 893c87c5fbaSopenharmony_ci bytes_written = send(sock->fd, data, datalen, 0); 894c87c5fbaSopenharmony_ci#endif 895c87c5fbaSopenharmony_ci } else { 896c87c5fbaSopenharmony_ci#if defined(_WIN32) && !defined(__MINGW32__) 897c87c5fbaSopenharmony_ci DWORD dwNumberOfBytesSent = 0; 898c87c5fbaSopenharmony_ci int r; 899c87c5fbaSopenharmony_ci#endif /* _WIN32 && !__MINGW32__ */ 900c87c5fbaSopenharmony_ci#ifdef HAVE_STRUCT_CMSGHDR 901c87c5fbaSopenharmony_ci /* a buffer large enough to hold all packet info types, ipv6 is the largest */ 902c87c5fbaSopenharmony_ci char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 903c87c5fbaSopenharmony_ci struct msghdr mhdr; 904c87c5fbaSopenharmony_ci struct iovec iov[1]; 905c87c5fbaSopenharmony_ci const void *addr = &session->addr_info.remote.addr; 906c87c5fbaSopenharmony_ci 907c87c5fbaSopenharmony_ci assert(session); 908c87c5fbaSopenharmony_ci 909c87c5fbaSopenharmony_ci memcpy(&iov[0].iov_base, &data, sizeof(iov[0].iov_base)); 910c87c5fbaSopenharmony_ci iov[0].iov_len = (iov_len_t)datalen; 911c87c5fbaSopenharmony_ci 912c87c5fbaSopenharmony_ci memset(buf, 0, sizeof(buf)); 913c87c5fbaSopenharmony_ci 914c87c5fbaSopenharmony_ci memset(&mhdr, 0, sizeof(struct msghdr)); 915c87c5fbaSopenharmony_ci memcpy(&mhdr.msg_name, &addr, sizeof(mhdr.msg_name)); 916c87c5fbaSopenharmony_ci mhdr.msg_namelen = session->addr_info.remote.addr.sa.sa_family == AF_INET ? 917c87c5fbaSopenharmony_ci (socklen_t)sizeof(struct sockaddr_in) : 918c87c5fbaSopenharmony_ci session->addr_info.remote.size; 919c87c5fbaSopenharmony_ci 920c87c5fbaSopenharmony_ci mhdr.msg_iov = iov; 921c87c5fbaSopenharmony_ci mhdr.msg_iovlen = 1; 922c87c5fbaSopenharmony_ci 923c87c5fbaSopenharmony_ci if (!coap_address_isany(&session->addr_info.local) && 924c87c5fbaSopenharmony_ci !coap_is_mcast(&session->addr_info.local)) { 925c87c5fbaSopenharmony_ci switch (session->addr_info.local.addr.sa.sa_family) { 926c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 927c87c5fbaSopenharmony_ci case AF_INET6: { 928c87c5fbaSopenharmony_ci struct cmsghdr *cmsg; 929c87c5fbaSopenharmony_ci 930c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 931c87c5fbaSopenharmony_ci if (IN6_IS_ADDR_V4MAPPED(&session->addr_info.local.addr.sin6.sin6_addr)) { 932c87c5fbaSopenharmony_ci#if defined(IP_PKTINFO) 933c87c5fbaSopenharmony_ci struct in_pktinfo *pktinfo; 934c87c5fbaSopenharmony_ci mhdr.msg_control = buf; 935c87c5fbaSopenharmony_ci mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); 936c87c5fbaSopenharmony_ci 937c87c5fbaSopenharmony_ci cmsg = CMSG_FIRSTHDR(&mhdr); 938c87c5fbaSopenharmony_ci cmsg->cmsg_level = COAP_SOL_IP; 939c87c5fbaSopenharmony_ci cmsg->cmsg_type = IP_PKTINFO; 940c87c5fbaSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 941c87c5fbaSopenharmony_ci 942c87c5fbaSopenharmony_ci pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); 943c87c5fbaSopenharmony_ci 944c87c5fbaSopenharmony_ci pktinfo->ipi_ifindex = session->ifindex; 945c87c5fbaSopenharmony_ci memcpy(&pktinfo->ipi_spec_dst, 946c87c5fbaSopenharmony_ci session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12, 947c87c5fbaSopenharmony_ci sizeof(pktinfo->ipi_spec_dst)); 948c87c5fbaSopenharmony_ci#elif defined(IP_SENDSRCADDR) 949c87c5fbaSopenharmony_ci mhdr.msg_control = buf; 950c87c5fbaSopenharmony_ci mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); 951c87c5fbaSopenharmony_ci 952c87c5fbaSopenharmony_ci cmsg = CMSG_FIRSTHDR(&mhdr); 953c87c5fbaSopenharmony_ci cmsg->cmsg_level = IPPROTO_IP; 954c87c5fbaSopenharmony_ci cmsg->cmsg_type = IP_SENDSRCADDR; 955c87c5fbaSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); 956c87c5fbaSopenharmony_ci 957c87c5fbaSopenharmony_ci memcpy(CMSG_DATA(cmsg), 958c87c5fbaSopenharmony_ci session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12, 959c87c5fbaSopenharmony_ci sizeof(struct in_addr)); 960c87c5fbaSopenharmony_ci#endif /* IP_PKTINFO */ 961c87c5fbaSopenharmony_ci } else { 962c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 963c87c5fbaSopenharmony_ci struct in6_pktinfo *pktinfo; 964c87c5fbaSopenharmony_ci mhdr.msg_control = buf; 965c87c5fbaSopenharmony_ci mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 966c87c5fbaSopenharmony_ci 967c87c5fbaSopenharmony_ci cmsg = CMSG_FIRSTHDR(&mhdr); 968c87c5fbaSopenharmony_ci cmsg->cmsg_level = IPPROTO_IPV6; 969c87c5fbaSopenharmony_ci cmsg->cmsg_type = IPV6_PKTINFO; 970c87c5fbaSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 971c87c5fbaSopenharmony_ci 972c87c5fbaSopenharmony_ci pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg); 973c87c5fbaSopenharmony_ci 974c87c5fbaSopenharmony_ci pktinfo->ipi6_ifindex = session->ifindex; 975c87c5fbaSopenharmony_ci memcpy(&pktinfo->ipi6_addr, 976c87c5fbaSopenharmony_ci &session->addr_info.local.addr.sin6.sin6_addr, 977c87c5fbaSopenharmony_ci sizeof(pktinfo->ipi6_addr)); 978c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 979c87c5fbaSopenharmony_ci } 980c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 981c87c5fbaSopenharmony_ci break; 982c87c5fbaSopenharmony_ci } 983c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 984c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 985c87c5fbaSopenharmony_ci case AF_INET: { 986c87c5fbaSopenharmony_ci#if defined(IP_PKTINFO) 987c87c5fbaSopenharmony_ci struct cmsghdr *cmsg; 988c87c5fbaSopenharmony_ci struct in_pktinfo *pktinfo; 989c87c5fbaSopenharmony_ci 990c87c5fbaSopenharmony_ci mhdr.msg_control = buf; 991c87c5fbaSopenharmony_ci mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); 992c87c5fbaSopenharmony_ci 993c87c5fbaSopenharmony_ci cmsg = CMSG_FIRSTHDR(&mhdr); 994c87c5fbaSopenharmony_ci cmsg->cmsg_level = COAP_SOL_IP; 995c87c5fbaSopenharmony_ci cmsg->cmsg_type = IP_PKTINFO; 996c87c5fbaSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 997c87c5fbaSopenharmony_ci 998c87c5fbaSopenharmony_ci pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); 999c87c5fbaSopenharmony_ci 1000c87c5fbaSopenharmony_ci pktinfo->ipi_ifindex = session->ifindex; 1001c87c5fbaSopenharmony_ci memcpy(&pktinfo->ipi_spec_dst, 1002c87c5fbaSopenharmony_ci &session->addr_info.local.addr.sin.sin_addr, 1003c87c5fbaSopenharmony_ci sizeof(pktinfo->ipi_spec_dst)); 1004c87c5fbaSopenharmony_ci#elif defined(IP_SENDSRCADDR) 1005c87c5fbaSopenharmony_ci struct cmsghdr *cmsg; 1006c87c5fbaSopenharmony_ci mhdr.msg_control = buf; 1007c87c5fbaSopenharmony_ci mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); 1008c87c5fbaSopenharmony_ci 1009c87c5fbaSopenharmony_ci cmsg = CMSG_FIRSTHDR(&mhdr); 1010c87c5fbaSopenharmony_ci cmsg->cmsg_level = IPPROTO_IP; 1011c87c5fbaSopenharmony_ci cmsg->cmsg_type = IP_SENDSRCADDR; 1012c87c5fbaSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); 1013c87c5fbaSopenharmony_ci 1014c87c5fbaSopenharmony_ci memcpy(CMSG_DATA(cmsg), 1015c87c5fbaSopenharmony_ci &session->addr_info.local.addr.sin.sin_addr, 1016c87c5fbaSopenharmony_ci sizeof(struct in_addr)); 1017c87c5fbaSopenharmony_ci#endif /* IP_PKTINFO */ 1018c87c5fbaSopenharmony_ci break; 1019c87c5fbaSopenharmony_ci } 1020c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 1021c87c5fbaSopenharmony_ci#if COAP_AF_UNIX_SUPPORT 1022c87c5fbaSopenharmony_ci case AF_UNIX: 1023c87c5fbaSopenharmony_ci break; 1024c87c5fbaSopenharmony_ci#endif /* COAP_AF_UNIX_SUPPORT */ 1025c87c5fbaSopenharmony_ci default: 1026c87c5fbaSopenharmony_ci /* error */ 1027c87c5fbaSopenharmony_ci coap_log_warn("protocol not supported\n"); 1028c87c5fbaSopenharmony_ci return -1; 1029c87c5fbaSopenharmony_ci } 1030c87c5fbaSopenharmony_ci } 1031c87c5fbaSopenharmony_ci#endif /* HAVE_STRUCT_CMSGHDR */ 1032c87c5fbaSopenharmony_ci 1033c87c5fbaSopenharmony_ci#if defined(_WIN32) && !defined(__MINGW32__) 1034c87c5fbaSopenharmony_ci r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, 1035c87c5fbaSopenharmony_ci NULL /*lpCompletionRoutine*/); 1036c87c5fbaSopenharmony_ci if (r == 0) 1037c87c5fbaSopenharmony_ci bytes_written = (ssize_t)dwNumberOfBytesSent; 1038c87c5fbaSopenharmony_ci else { 1039c87c5fbaSopenharmony_ci bytes_written = -1; 1040c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 1041c87c5fbaSopenharmony_ci } 1042c87c5fbaSopenharmony_ci#else /* !_WIN32 || __MINGW32__ */ 1043c87c5fbaSopenharmony_ci#ifdef HAVE_STRUCT_CMSGHDR 1044c87c5fbaSopenharmony_ci bytes_written = sendmsg(sock->fd, &mhdr, 0); 1045c87c5fbaSopenharmony_ci#else /* ! HAVE_STRUCT_CMSGHDR */ 1046c87c5fbaSopenharmony_ci bytes_written = sendto(sock->fd, (const void *)data, datalen, 0, 1047c87c5fbaSopenharmony_ci &session->addr_info.remote.addr.sa, 1048c87c5fbaSopenharmony_ci session->addr_info.remote.size); 1049c87c5fbaSopenharmony_ci#endif /* ! HAVE_STRUCT_CMSGHDR */ 1050c87c5fbaSopenharmony_ci#endif /* !_WIN32 || __MINGW32__ */ 1051c87c5fbaSopenharmony_ci } 1052c87c5fbaSopenharmony_ci 1053c87c5fbaSopenharmony_ci if (bytes_written < 0) 1054c87c5fbaSopenharmony_ci coap_log_crit("coap_socket_send: %s\n", coap_socket_strerror()); 1055c87c5fbaSopenharmony_ci 1056c87c5fbaSopenharmony_ci return bytes_written; 1057c87c5fbaSopenharmony_ci} 1058c87c5fbaSopenharmony_ci#endif /* ! RIOT_VERSION && ! WITH_LWIP && ! WITH_CONTIKI */ 1059c87c5fbaSopenharmony_ci 1060c87c5fbaSopenharmony_ci#define SIN6(A) ((struct sockaddr_in6 *)(A)) 1061c87c5fbaSopenharmony_ci 1062c87c5fbaSopenharmony_civoid 1063c87c5fbaSopenharmony_cicoap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) { 1064c87c5fbaSopenharmony_ci *address = packet->payload; 1065c87c5fbaSopenharmony_ci *length = packet->length; 1066c87c5fbaSopenharmony_ci} 1067c87c5fbaSopenharmony_ci 1068c87c5fbaSopenharmony_ci#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) 1069c87c5fbaSopenharmony_ci/* 1070c87c5fbaSopenharmony_ci * dgram 1071c87c5fbaSopenharmony_ci * return +ve Number of bytes written. 1072c87c5fbaSopenharmony_ci * -1 Error error in errno). 1073c87c5fbaSopenharmony_ci * -2 ICMP error response 1074c87c5fbaSopenharmony_ci */ 1075c87c5fbaSopenharmony_cissize_t 1076c87c5fbaSopenharmony_cicoap_socket_recv(coap_socket_t *sock, coap_packet_t *packet) { 1077c87c5fbaSopenharmony_ci ssize_t len = -1; 1078c87c5fbaSopenharmony_ci 1079c87c5fbaSopenharmony_ci assert(sock); 1080c87c5fbaSopenharmony_ci assert(packet); 1081c87c5fbaSopenharmony_ci 1082c87c5fbaSopenharmony_ci if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) { 1083c87c5fbaSopenharmony_ci return -1; 1084c87c5fbaSopenharmony_ci } else { 1085c87c5fbaSopenharmony_ci /* clear has-data flag */ 1086c87c5fbaSopenharmony_ci sock->flags &= ~COAP_SOCKET_CAN_READ; 1087c87c5fbaSopenharmony_ci } 1088c87c5fbaSopenharmony_ci 1089c87c5fbaSopenharmony_ci if (sock->flags & COAP_SOCKET_CONNECTED) { 1090c87c5fbaSopenharmony_ci#ifdef _WIN32 1091c87c5fbaSopenharmony_ci len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0); 1092c87c5fbaSopenharmony_ci#else 1093c87c5fbaSopenharmony_ci len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0); 1094c87c5fbaSopenharmony_ci#endif 1095c87c5fbaSopenharmony_ci if (len < 0) { 1096c87c5fbaSopenharmony_ci#ifdef _WIN32 1097c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 1098c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 1099c87c5fbaSopenharmony_ci if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) { 1100c87c5fbaSopenharmony_ci /* client-side ICMP destination unreachable, ignore it */ 1101c87c5fbaSopenharmony_ci coap_log_warn("** %s: coap_socket_recv: ICMP: %s\n", 1102c87c5fbaSopenharmony_ci sock->session ? 1103c87c5fbaSopenharmony_ci coap_session_str(sock->session) : "", 1104c87c5fbaSopenharmony_ci coap_socket_strerror()); 1105c87c5fbaSopenharmony_ci return -2; 1106c87c5fbaSopenharmony_ci } 1107c87c5fbaSopenharmony_ci coap_log_warn("** %s: coap_socket_recv: %s\n", 1108c87c5fbaSopenharmony_ci sock->session ? 1109c87c5fbaSopenharmony_ci coap_session_str(sock->session) : "", 1110c87c5fbaSopenharmony_ci coap_socket_strerror()); 1111c87c5fbaSopenharmony_ci goto error; 1112c87c5fbaSopenharmony_ci } else if (len > 0) { 1113c87c5fbaSopenharmony_ci packet->length = (size_t)len; 1114c87c5fbaSopenharmony_ci } 1115c87c5fbaSopenharmony_ci } else { 1116c87c5fbaSopenharmony_ci#if defined(_WIN32) && !defined(__MINGW32__) 1117c87c5fbaSopenharmony_ci DWORD dwNumberOfBytesRecvd = 0; 1118c87c5fbaSopenharmony_ci int r; 1119c87c5fbaSopenharmony_ci#endif /* _WIN32 && !__MINGW32__ */ 1120c87c5fbaSopenharmony_ci#ifdef HAVE_STRUCT_CMSGHDR 1121c87c5fbaSopenharmony_ci /* a buffer large enough to hold all packet info types, ipv6 is the largest */ 1122c87c5fbaSopenharmony_ci char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 1123c87c5fbaSopenharmony_ci struct cmsghdr *cmsg; 1124c87c5fbaSopenharmony_ci struct msghdr mhdr; 1125c87c5fbaSopenharmony_ci struct iovec iov[1]; 1126c87c5fbaSopenharmony_ci 1127c87c5fbaSopenharmony_ci iov[0].iov_base = packet->payload; 1128c87c5fbaSopenharmony_ci iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE; 1129c87c5fbaSopenharmony_ci 1130c87c5fbaSopenharmony_ci memset(&mhdr, 0, sizeof(struct msghdr)); 1131c87c5fbaSopenharmony_ci 1132c87c5fbaSopenharmony_ci mhdr.msg_name = (struct sockaddr *)&packet->addr_info.remote.addr; 1133c87c5fbaSopenharmony_ci mhdr.msg_namelen = sizeof(packet->addr_info.remote.addr); 1134c87c5fbaSopenharmony_ci 1135c87c5fbaSopenharmony_ci mhdr.msg_iov = iov; 1136c87c5fbaSopenharmony_ci mhdr.msg_iovlen = 1; 1137c87c5fbaSopenharmony_ci 1138c87c5fbaSopenharmony_ci mhdr.msg_control = buf; 1139c87c5fbaSopenharmony_ci mhdr.msg_controllen = sizeof(buf); 1140c87c5fbaSopenharmony_ci /* set a big first length incase recvmsg() does not implement updating 1141c87c5fbaSopenharmony_ci msg_control as well as preset the first cmsg with bad data */ 1142c87c5fbaSopenharmony_ci cmsg = (struct cmsghdr *)buf; 1143c87c5fbaSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(buf)); 1144c87c5fbaSopenharmony_ci cmsg->cmsg_level = -1; 1145c87c5fbaSopenharmony_ci cmsg->cmsg_type = -1; 1146c87c5fbaSopenharmony_ci 1147c87c5fbaSopenharmony_ci#if defined(_WIN32) 1148c87c5fbaSopenharmony_ci if (!lpWSARecvMsg) { 1149c87c5fbaSopenharmony_ci GUID wsaid = WSAID_WSARECVMSG; 1150c87c5fbaSopenharmony_ci DWORD cbBytesReturned = 0; 1151c87c5fbaSopenharmony_ci if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, 1152c87c5fbaSopenharmony_ci sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) { 1153c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_recv: no WSARecvMsg\n"); 1154c87c5fbaSopenharmony_ci return -1; 1155c87c5fbaSopenharmony_ci } 1156c87c5fbaSopenharmony_ci } 1157c87c5fbaSopenharmony_ci r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, 1158c87c5fbaSopenharmony_ci NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */); 1159c87c5fbaSopenharmony_ci if (r == 0) 1160c87c5fbaSopenharmony_ci len = (ssize_t)dwNumberOfBytesRecvd; 1161c87c5fbaSopenharmony_ci else if (r == COAP_SOCKET_ERROR) 1162c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 1163c87c5fbaSopenharmony_ci#else 1164c87c5fbaSopenharmony_ci len = recvmsg(sock->fd, &mhdr, 0); 1165c87c5fbaSopenharmony_ci#endif 1166c87c5fbaSopenharmony_ci 1167c87c5fbaSopenharmony_ci#else /* ! HAVE_STRUCT_CMSGHDR */ 1168c87c5fbaSopenharmony_ci len = recvfrom(sock->fd, (void *)packet->payload, COAP_RXBUFFER_SIZE, 0, 1169c87c5fbaSopenharmony_ci &packet->addr_info.remote.addr.sa, 1170c87c5fbaSopenharmony_ci &packet->addr_info.remote.size); 1171c87c5fbaSopenharmony_ci#if defined(RIOT_VERSION) && defined(COAP_SERVER_SUPPORT) && COAP_IPV6_SUPPORT 1172c87c5fbaSopenharmony_ci if (sock->endpoint && 1173c87c5fbaSopenharmony_ci packet->addr_info.remote.addr.sa.sa_family == AF_INET6) { 1174c87c5fbaSopenharmony_ci packet->addr_info.remote.addr.sin6.sin6_scope_id = 1175c87c5fbaSopenharmony_ci sock->endpoint->bind_addr.addr.sin6.sin6_scope_id; 1176c87c5fbaSopenharmony_ci packet->addr_info.remote.addr.sin6.sin6_flowinfo = 0; 1177c87c5fbaSopenharmony_ci } 1178c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION && COAP_SERVER_SUPPORT && COAP_IPV6_SUPPORT */ 1179c87c5fbaSopenharmony_ci#endif /* ! HAVE_STRUCT_CMSGHDR */ 1180c87c5fbaSopenharmony_ci 1181c87c5fbaSopenharmony_ci if (len < 0) { 1182c87c5fbaSopenharmony_ci#ifdef _WIN32 1183c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 1184c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 1185c87c5fbaSopenharmony_ci if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) { 1186c87c5fbaSopenharmony_ci /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */ 1187c87c5fbaSopenharmony_ci coap_log_warn("** %s: coap_socket_recv: ICMP: %s\n", 1188c87c5fbaSopenharmony_ci sock->session ? 1189c87c5fbaSopenharmony_ci coap_session_str(sock->session) : "", 1190c87c5fbaSopenharmony_ci coap_socket_strerror()); 1191c87c5fbaSopenharmony_ci return 0; 1192c87c5fbaSopenharmony_ci } 1193c87c5fbaSopenharmony_ci coap_log_warn("coap_socket_recv: %s\n", coap_socket_strerror()); 1194c87c5fbaSopenharmony_ci goto error; 1195c87c5fbaSopenharmony_ci } else { 1196c87c5fbaSopenharmony_ci#ifdef HAVE_STRUCT_CMSGHDR 1197c87c5fbaSopenharmony_ci int dst_found = 0; 1198c87c5fbaSopenharmony_ci 1199c87c5fbaSopenharmony_ci packet->addr_info.remote.size = mhdr.msg_namelen; 1200c87c5fbaSopenharmony_ci packet->length = (size_t)len; 1201c87c5fbaSopenharmony_ci 1202c87c5fbaSopenharmony_ci /* Walk through ancillary data records until the local interface 1203c87c5fbaSopenharmony_ci * is found where the data was received. */ 1204c87c5fbaSopenharmony_ci for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) { 1205c87c5fbaSopenharmony_ci 1206c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 1207c87c5fbaSopenharmony_ci /* get the local interface for IPv6 */ 1208c87c5fbaSopenharmony_ci if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { 1209c87c5fbaSopenharmony_ci union { 1210c87c5fbaSopenharmony_ci uint8_t *c; 1211c87c5fbaSopenharmony_ci struct in6_pktinfo *p; 1212c87c5fbaSopenharmony_ci } u; 1213c87c5fbaSopenharmony_ci u.c = CMSG_DATA(cmsg); 1214c87c5fbaSopenharmony_ci packet->ifindex = (int)(u.p->ipi6_ifindex); 1215c87c5fbaSopenharmony_ci memcpy(&packet->addr_info.local.addr.sin6.sin6_addr, 1216c87c5fbaSopenharmony_ci &u.p->ipi6_addr, sizeof(struct in6_addr)); 1217c87c5fbaSopenharmony_ci dst_found = 1; 1218c87c5fbaSopenharmony_ci break; 1219c87c5fbaSopenharmony_ci } 1220c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 1221c87c5fbaSopenharmony_ci 1222c87c5fbaSopenharmony_ci#if COAP_IPV4_SUPPORT 1223c87c5fbaSopenharmony_ci /* local interface for IPv4 */ 1224c87c5fbaSopenharmony_ci#if defined(IP_PKTINFO) 1225c87c5fbaSopenharmony_ci if (cmsg->cmsg_level == COAP_SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { 1226c87c5fbaSopenharmony_ci union { 1227c87c5fbaSopenharmony_ci uint8_t *c; 1228c87c5fbaSopenharmony_ci struct in_pktinfo *p; 1229c87c5fbaSopenharmony_ci } u; 1230c87c5fbaSopenharmony_ci u.c = CMSG_DATA(cmsg); 1231c87c5fbaSopenharmony_ci packet->ifindex = u.p->ipi_ifindex; 1232c87c5fbaSopenharmony_ci#if COAP_IPV6_SUPPORT 1233c87c5fbaSopenharmony_ci if (packet->addr_info.local.addr.sa.sa_family == AF_INET6) { 1234c87c5fbaSopenharmony_ci memset(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr, 0, 10); 1235c87c5fbaSopenharmony_ci packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[10] = 0xff; 1236c87c5fbaSopenharmony_ci packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[11] = 0xff; 1237c87c5fbaSopenharmony_ci memcpy(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12, 1238c87c5fbaSopenharmony_ci &u.p->ipi_addr, sizeof(struct in_addr)); 1239c87c5fbaSopenharmony_ci } else 1240c87c5fbaSopenharmony_ci#endif /* COAP_IPV6_SUPPORT */ 1241c87c5fbaSopenharmony_ci { 1242c87c5fbaSopenharmony_ci memcpy(&packet->addr_info.local.addr.sin.sin_addr, 1243c87c5fbaSopenharmony_ci &u.p->ipi_addr, sizeof(struct in_addr)); 1244c87c5fbaSopenharmony_ci } 1245c87c5fbaSopenharmony_ci dst_found = 1; 1246c87c5fbaSopenharmony_ci break; 1247c87c5fbaSopenharmony_ci } 1248c87c5fbaSopenharmony_ci#endif /* IP_PKTINFO */ 1249c87c5fbaSopenharmony_ci#if defined(IP_RECVDSTADDR) 1250c87c5fbaSopenharmony_ci if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { 1251c87c5fbaSopenharmony_ci packet->ifindex = (int)sock->fd; 1252c87c5fbaSopenharmony_ci memcpy(&packet->addr_info.local.addr.sin.sin_addr, 1253c87c5fbaSopenharmony_ci CMSG_DATA(cmsg), sizeof(struct in_addr)); 1254c87c5fbaSopenharmony_ci dst_found = 1; 1255c87c5fbaSopenharmony_ci break; 1256c87c5fbaSopenharmony_ci } 1257c87c5fbaSopenharmony_ci#endif /* IP_RECVDSTADDR */ 1258c87c5fbaSopenharmony_ci#endif /* COAP_IPV4_SUPPORT */ 1259c87c5fbaSopenharmony_ci if (!dst_found) { 1260c87c5fbaSopenharmony_ci /* cmsg_level / cmsg_type combination we do not understand 1261c87c5fbaSopenharmony_ci (ignore preset case for bad recvmsg() not updating cmsg) */ 1262c87c5fbaSopenharmony_ci if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) { 1263c87c5fbaSopenharmony_ci coap_log_debug("cmsg_level = %d and cmsg_type = %d not supported - fix\n", 1264c87c5fbaSopenharmony_ci cmsg->cmsg_level, cmsg->cmsg_type); 1265c87c5fbaSopenharmony_ci } 1266c87c5fbaSopenharmony_ci } 1267c87c5fbaSopenharmony_ci } 1268c87c5fbaSopenharmony_ci if (!dst_found) { 1269c87c5fbaSopenharmony_ci /* Not expected, but cmsg_level and cmsg_type don't match above and 1270c87c5fbaSopenharmony_ci may need a new case */ 1271c87c5fbaSopenharmony_ci packet->ifindex = (int)sock->fd; 1272c87c5fbaSopenharmony_ci if (getsockname(sock->fd, &packet->addr_info.local.addr.sa, 1273c87c5fbaSopenharmony_ci &packet->addr_info.local.size) < 0) { 1274c87c5fbaSopenharmony_ci coap_log_debug("Cannot determine local port\n"); 1275c87c5fbaSopenharmony_ci } 1276c87c5fbaSopenharmony_ci } 1277c87c5fbaSopenharmony_ci#else /* ! HAVE_STRUCT_CMSGHDR */ 1278c87c5fbaSopenharmony_ci packet->length = (size_t)len; 1279c87c5fbaSopenharmony_ci packet->ifindex = 0; 1280c87c5fbaSopenharmony_ci if (getsockname(sock->fd, &packet->addr_info.local.addr.sa, 1281c87c5fbaSopenharmony_ci &packet->addr_info.local.size) < 0) { 1282c87c5fbaSopenharmony_ci coap_log_debug("Cannot determine local port\n"); 1283c87c5fbaSopenharmony_ci goto error; 1284c87c5fbaSopenharmony_ci } 1285c87c5fbaSopenharmony_ci#if defined(RIOT_VERSION) && defined(COAP_SERVER_SUPPORT) && COAP_IPV6_SUPPORT 1286c87c5fbaSopenharmony_ci if (sock->endpoint && 1287c87c5fbaSopenharmony_ci packet->addr_info.local.addr.sa.sa_family == AF_INET6) { 1288c87c5fbaSopenharmony_ci packet->addr_info.local.addr.sin6.sin6_scope_id = 1289c87c5fbaSopenharmony_ci sock->endpoint->bind_addr.addr.sin6.sin6_scope_id; 1290c87c5fbaSopenharmony_ci packet->addr_info.local.addr.sin6.sin6_flowinfo = 0; 1291c87c5fbaSopenharmony_ci } 1292c87c5fbaSopenharmony_ci#endif /* RIOT_VERSION && COAP_SERVER_SUPPORT && COAP_IPV6_SUPPORT */ 1293c87c5fbaSopenharmony_ci#endif /* ! HAVE_STRUCT_CMSGHDR */ 1294c87c5fbaSopenharmony_ci } 1295c87c5fbaSopenharmony_ci } 1296c87c5fbaSopenharmony_ci 1297c87c5fbaSopenharmony_ci if (len >= 0) 1298c87c5fbaSopenharmony_ci return len; 1299c87c5fbaSopenharmony_cierror: 1300c87c5fbaSopenharmony_ci return -1; 1301c87c5fbaSopenharmony_ci} 1302c87c5fbaSopenharmony_ci#endif /* ! WITH_LWIP && ! WITH_CONTIKI */ 1303c87c5fbaSopenharmony_ci 1304c87c5fbaSopenharmony_ciunsigned int 1305c87c5fbaSopenharmony_cicoap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) { 1306c87c5fbaSopenharmony_ci#ifndef COAP_EPOLL_SUPPORT 1307c87c5fbaSopenharmony_ci (void)ctx; 1308c87c5fbaSopenharmony_ci (void)now; 1309c87c5fbaSopenharmony_ci coap_log_emerg("coap_io_prepare_epoll() requires libcoap compiled for using epoll\n"); 1310c87c5fbaSopenharmony_ci return 0; 1311c87c5fbaSopenharmony_ci#else /* COAP_EPOLL_SUPPORT */ 1312c87c5fbaSopenharmony_ci coap_socket_t *sockets[1]; 1313c87c5fbaSopenharmony_ci unsigned int max_sockets = sizeof(sockets)/sizeof(sockets[0]); 1314c87c5fbaSopenharmony_ci unsigned int num_sockets; 1315c87c5fbaSopenharmony_ci unsigned int timeout; 1316c87c5fbaSopenharmony_ci 1317c87c5fbaSopenharmony_ci /* Use the common logic */ 1318c87c5fbaSopenharmony_ci timeout = coap_io_prepare_io(ctx, sockets, max_sockets, &num_sockets, now); 1319c87c5fbaSopenharmony_ci /* Save when the next expected I/O is to take place */ 1320c87c5fbaSopenharmony_ci ctx->next_timeout = timeout ? now + timeout : 0; 1321c87c5fbaSopenharmony_ci if (ctx->eptimerfd != -1) { 1322c87c5fbaSopenharmony_ci struct itimerspec new_value; 1323c87c5fbaSopenharmony_ci int ret; 1324c87c5fbaSopenharmony_ci 1325c87c5fbaSopenharmony_ci memset(&new_value, 0, sizeof(new_value)); 1326c87c5fbaSopenharmony_ci coap_ticks(&now); 1327c87c5fbaSopenharmony_ci if (ctx->next_timeout != 0 && ctx->next_timeout > now) { 1328c87c5fbaSopenharmony_ci coap_tick_t rem_timeout = ctx->next_timeout - now; 1329c87c5fbaSopenharmony_ci /* Need to trigger an event on ctx->eptimerfd in the future */ 1330c87c5fbaSopenharmony_ci new_value.it_value.tv_sec = rem_timeout / COAP_TICKS_PER_SECOND; 1331c87c5fbaSopenharmony_ci new_value.it_value.tv_nsec = (rem_timeout % COAP_TICKS_PER_SECOND) * 1332c87c5fbaSopenharmony_ci 1000000; 1333c87c5fbaSopenharmony_ci } 1334c87c5fbaSopenharmony_ci#ifdef COAP_DEBUG_WAKEUP_TIMES 1335c87c5fbaSopenharmony_ci coap_log_debug("****** Next wakeup time %3ld.%09ld\n", 1336c87c5fbaSopenharmony_ci new_value.it_value.tv_sec, new_value.it_value.tv_nsec); 1337c87c5fbaSopenharmony_ci#endif /* COAP_DEBUG_WAKEUP_TIMES */ 1338c87c5fbaSopenharmony_ci /* reset, or specify a future time for eptimerfd to trigger */ 1339c87c5fbaSopenharmony_ci ret = timerfd_settime(ctx->eptimerfd, 0, &new_value, NULL); 1340c87c5fbaSopenharmony_ci if (ret == -1) { 1341c87c5fbaSopenharmony_ci coap_log_err("%s: timerfd_settime failed: %s (%d)\n", 1342c87c5fbaSopenharmony_ci "coap_io_prepare_epoll", 1343c87c5fbaSopenharmony_ci coap_socket_strerror(), errno); 1344c87c5fbaSopenharmony_ci } 1345c87c5fbaSopenharmony_ci } 1346c87c5fbaSopenharmony_ci return timeout; 1347c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 1348c87c5fbaSopenharmony_ci} 1349c87c5fbaSopenharmony_ci 1350c87c5fbaSopenharmony_ci/* 1351c87c5fbaSopenharmony_ci * return 0 No i/o pending 1352c87c5fbaSopenharmony_ci * +ve millisecs to next i/o activity 1353c87c5fbaSopenharmony_ci */ 1354c87c5fbaSopenharmony_ciunsigned int 1355c87c5fbaSopenharmony_cicoap_io_prepare_io(coap_context_t *ctx, 1356c87c5fbaSopenharmony_ci coap_socket_t *sockets[], 1357c87c5fbaSopenharmony_ci unsigned int max_sockets, 1358c87c5fbaSopenharmony_ci unsigned int *num_sockets, 1359c87c5fbaSopenharmony_ci coap_tick_t now) { 1360c87c5fbaSopenharmony_ci coap_queue_t *nextpdu; 1361c87c5fbaSopenharmony_ci coap_session_t *s, *rtmp; 1362c87c5fbaSopenharmony_ci coap_tick_t timeout = 0; 1363c87c5fbaSopenharmony_ci coap_tick_t s_timeout; 1364c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1365c87c5fbaSopenharmony_ci int check_dtls_timeouts = 0; 1366c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1367c87c5fbaSopenharmony_ci#if defined(COAP_EPOLL_SUPPORT) || defined(WITH_LWIP) 1368c87c5fbaSopenharmony_ci (void)sockets; 1369c87c5fbaSopenharmony_ci (void)max_sockets; 1370c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT || WITH_LWIP */ 1371c87c5fbaSopenharmony_ci 1372c87c5fbaSopenharmony_ci *num_sockets = 0; 1373c87c5fbaSopenharmony_ci 1374c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1375c87c5fbaSopenharmony_ci /* Check to see if we need to send off any Observe requests */ 1376c87c5fbaSopenharmony_ci coap_check_notify(ctx); 1377c87c5fbaSopenharmony_ci 1378c87c5fbaSopenharmony_ci#if COAP_ASYNC_SUPPORT 1379c87c5fbaSopenharmony_ci /* Check to see if we need to send off any Async requests */ 1380c87c5fbaSopenharmony_ci timeout = coap_check_async(ctx, now); 1381c87c5fbaSopenharmony_ci#endif /* COAP_ASYNC_SUPPORT */ 1382c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1383c87c5fbaSopenharmony_ci 1384c87c5fbaSopenharmony_ci /* Check to see if we need to send off any retransmit request */ 1385c87c5fbaSopenharmony_ci nextpdu = coap_peek_next(ctx); 1386c87c5fbaSopenharmony_ci while (nextpdu && now >= ctx->sendqueue_basetime && 1387c87c5fbaSopenharmony_ci nextpdu->t <= now - ctx->sendqueue_basetime) { 1388c87c5fbaSopenharmony_ci coap_retransmit(ctx, coap_pop_next(ctx)); 1389c87c5fbaSopenharmony_ci nextpdu = coap_peek_next(ctx); 1390c87c5fbaSopenharmony_ci } 1391c87c5fbaSopenharmony_ci if (nextpdu && (timeout == 0 || 1392c87c5fbaSopenharmony_ci nextpdu->t - (now - ctx->sendqueue_basetime) < timeout)) 1393c87c5fbaSopenharmony_ci timeout = nextpdu->t - (now - ctx->sendqueue_basetime); 1394c87c5fbaSopenharmony_ci 1395c87c5fbaSopenharmony_ci /* Check for DTLS timeouts */ 1396c87c5fbaSopenharmony_ci if (ctx->dtls_context) { 1397c87c5fbaSopenharmony_ci if (coap_dtls_is_context_timeout()) { 1398c87c5fbaSopenharmony_ci coap_tick_t tls_timeout = coap_dtls_get_context_timeout(ctx->dtls_context); 1399c87c5fbaSopenharmony_ci if (tls_timeout > 0) { 1400c87c5fbaSopenharmony_ci if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10) 1401c87c5fbaSopenharmony_ci tls_timeout = now + COAP_TICKS_PER_SECOND / 10; 1402c87c5fbaSopenharmony_ci coap_log_debug("** DTLS global timeout set to %dms\n", 1403c87c5fbaSopenharmony_ci (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND)); 1404c87c5fbaSopenharmony_ci if (timeout == 0 || tls_timeout - now < timeout) 1405c87c5fbaSopenharmony_ci timeout = tls_timeout - now; 1406c87c5fbaSopenharmony_ci } 1407c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1408c87c5fbaSopenharmony_ci } else { 1409c87c5fbaSopenharmony_ci check_dtls_timeouts = 1; 1410c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1411c87c5fbaSopenharmony_ci } 1412c87c5fbaSopenharmony_ci } 1413c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1414c87c5fbaSopenharmony_ci coap_endpoint_t *ep; 1415c87c5fbaSopenharmony_ci coap_tick_t session_timeout; 1416c87c5fbaSopenharmony_ci 1417c87c5fbaSopenharmony_ci if (ctx->session_timeout > 0) 1418c87c5fbaSopenharmony_ci session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND; 1419c87c5fbaSopenharmony_ci else 1420c87c5fbaSopenharmony_ci session_timeout = COAP_DEFAULT_SESSION_TIMEOUT * COAP_TICKS_PER_SECOND; 1421c87c5fbaSopenharmony_ci 1422c87c5fbaSopenharmony_ci LL_FOREACH(ctx->endpoint, ep) { 1423c87c5fbaSopenharmony_ci#if !defined(COAP_EPOLL_SUPPORT) && !defined(WITH_LWIP) 1424c87c5fbaSopenharmony_ci if (ep->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_ACCEPT)) { 1425c87c5fbaSopenharmony_ci if (*num_sockets < max_sockets) 1426c87c5fbaSopenharmony_ci sockets[(*num_sockets)++] = &ep->sock; 1427c87c5fbaSopenharmony_ci } 1428c87c5fbaSopenharmony_ci#endif /* ! COAP_EPOLL_SUPPORT i && ! WITH_LWIP */ 1429c87c5fbaSopenharmony_ci SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) { 1430c87c5fbaSopenharmony_ci /* Check whether any idle server sessions should be released */ 1431c87c5fbaSopenharmony_ci if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && 1432c87c5fbaSopenharmony_ci s->delayqueue == NULL && 1433c87c5fbaSopenharmony_ci (s->last_rx_tx + session_timeout <= now || 1434c87c5fbaSopenharmony_ci s->state == COAP_SESSION_STATE_NONE)) { 1435c87c5fbaSopenharmony_ci coap_handle_event(ctx, COAP_EVENT_SERVER_SESSION_DEL, s); 1436c87c5fbaSopenharmony_ci coap_session_free(s); 1437c87c5fbaSopenharmony_ci } else { 1438c87c5fbaSopenharmony_ci if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && 1439c87c5fbaSopenharmony_ci s->delayqueue == NULL) { 1440c87c5fbaSopenharmony_ci s_timeout = (s->last_rx_tx + session_timeout) - now; 1441c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1442c87c5fbaSopenharmony_ci timeout = s_timeout; 1443c87c5fbaSopenharmony_ci } 1444c87c5fbaSopenharmony_ci /* Make sure the session object is not deleted in any callbacks */ 1445c87c5fbaSopenharmony_ci coap_session_reference(s); 1446c87c5fbaSopenharmony_ci /* Check any DTLS timeouts and expire if appropriate */ 1447c87c5fbaSopenharmony_ci if (check_dtls_timeouts && s->state == COAP_SESSION_STATE_HANDSHAKE && 1448c87c5fbaSopenharmony_ci s->proto == COAP_PROTO_DTLS && s->tls) { 1449c87c5fbaSopenharmony_ci coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now); 1450c87c5fbaSopenharmony_ci while (tls_timeout > 0 && tls_timeout <= now) { 1451c87c5fbaSopenharmony_ci coap_log_debug("** %s: DTLS retransmit timeout\n", 1452c87c5fbaSopenharmony_ci coap_session_str(s)); 1453c87c5fbaSopenharmony_ci if (coap_dtls_handle_timeout(s)) 1454c87c5fbaSopenharmony_ci goto release_1; 1455c87c5fbaSopenharmony_ci 1456c87c5fbaSopenharmony_ci if (s->tls) 1457c87c5fbaSopenharmony_ci tls_timeout = coap_dtls_get_timeout(s, now); 1458c87c5fbaSopenharmony_ci else { 1459c87c5fbaSopenharmony_ci tls_timeout = 0; 1460c87c5fbaSopenharmony_ci timeout = 1; 1461c87c5fbaSopenharmony_ci } 1462c87c5fbaSopenharmony_ci } 1463c87c5fbaSopenharmony_ci if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout)) 1464c87c5fbaSopenharmony_ci timeout = tls_timeout - now; 1465c87c5fbaSopenharmony_ci } 1466c87c5fbaSopenharmony_ci /* Check if any server large receives are missing blocks */ 1467c87c5fbaSopenharmony_ci if (s->lg_srcv) { 1468c87c5fbaSopenharmony_ci if (coap_block_check_lg_srcv_timeouts(s, now, &s_timeout)) { 1469c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1470c87c5fbaSopenharmony_ci timeout = s_timeout; 1471c87c5fbaSopenharmony_ci } 1472c87c5fbaSopenharmony_ci } 1473c87c5fbaSopenharmony_ci /* Check if any server large sending have timed out */ 1474c87c5fbaSopenharmony_ci if (s->lg_xmit) { 1475c87c5fbaSopenharmony_ci if (coap_block_check_lg_xmit_timeouts(s, now, &s_timeout)) { 1476c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1477c87c5fbaSopenharmony_ci timeout = s_timeout; 1478c87c5fbaSopenharmony_ci } 1479c87c5fbaSopenharmony_ci } 1480c87c5fbaSopenharmony_ci#if !defined(COAP_EPOLL_SUPPORT) && !defined(WITH_LWIP) 1481c87c5fbaSopenharmony_ci if (s->sock.flags & (COAP_SOCKET_WANT_READ|COAP_SOCKET_WANT_WRITE)) { 1482c87c5fbaSopenharmony_ci if (*num_sockets < max_sockets) 1483c87c5fbaSopenharmony_ci sockets[(*num_sockets)++] = &s->sock; 1484c87c5fbaSopenharmony_ci } 1485c87c5fbaSopenharmony_ci#endif /* ! COAP_EPOLL_SUPPORT && ! WITH_LWIP */ 1486c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 1487c87c5fbaSopenharmony_ci /* 1488c87c5fbaSopenharmony_ci * Check if any server large transmits have hit MAX_PAYLOAD and need 1489c87c5fbaSopenharmony_ci * restarting 1490c87c5fbaSopenharmony_ci */ 1491c87c5fbaSopenharmony_ci if (s->lg_xmit) { 1492c87c5fbaSopenharmony_ci s_timeout = coap_block_check_q_block2_xmit(s, now); 1493c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1494c87c5fbaSopenharmony_ci timeout = s_timeout; 1495c87c5fbaSopenharmony_ci } 1496c87c5fbaSopenharmony_ci#endif /* COAP_Q_BLOCK_SUPPORT */ 1497c87c5fbaSopenharmony_cirelease_1: 1498c87c5fbaSopenharmony_ci coap_session_release(s); 1499c87c5fbaSopenharmony_ci } 1500c87c5fbaSopenharmony_ci } 1501c87c5fbaSopenharmony_ci } 1502c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1503c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1504c87c5fbaSopenharmony_ci SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) { 1505c87c5fbaSopenharmony_ci if (s->type == COAP_SESSION_TYPE_CLIENT && 1506c87c5fbaSopenharmony_ci s->state == COAP_SESSION_STATE_ESTABLISHED && 1507c87c5fbaSopenharmony_ci ctx->ping_timeout > 0) { 1508c87c5fbaSopenharmony_ci if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) { 1509c87c5fbaSopenharmony_ci /* Time to send a ping */ 1510c87c5fbaSopenharmony_ci if ((s->last_ping_mid = coap_session_send_ping(s)) == COAP_INVALID_MID) 1511c87c5fbaSopenharmony_ci /* Some issue - not safe to continue processing */ 1512c87c5fbaSopenharmony_ci continue; 1513c87c5fbaSopenharmony_ci if (s->last_ping > 0 && s->last_pong < s->last_ping) { 1514c87c5fbaSopenharmony_ci coap_handle_event(s->context, COAP_EVENT_KEEPALIVE_FAILURE, s); 1515c87c5fbaSopenharmony_ci } 1516c87c5fbaSopenharmony_ci s->last_rx_tx = now; 1517c87c5fbaSopenharmony_ci s->last_ping = now; 1518c87c5fbaSopenharmony_ci } 1519c87c5fbaSopenharmony_ci s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now; 1520c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1521c87c5fbaSopenharmony_ci timeout = s_timeout; 1522c87c5fbaSopenharmony_ci } 1523c87c5fbaSopenharmony_ci 1524c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1525c87c5fbaSopenharmony_ci if (s->type == COAP_SESSION_TYPE_CLIENT && COAP_PROTO_RELIABLE(s->proto) && 1526c87c5fbaSopenharmony_ci s->state == COAP_SESSION_STATE_CSM && ctx->csm_timeout > 0) { 1527c87c5fbaSopenharmony_ci if (s->csm_tx == 0) { 1528c87c5fbaSopenharmony_ci s->csm_tx = now; 1529c87c5fbaSopenharmony_ci } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) { 1530c87c5fbaSopenharmony_ci /* Make sure the session object is not deleted in the callback */ 1531c87c5fbaSopenharmony_ci coap_session_reference(s); 1532c87c5fbaSopenharmony_ci coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE); 1533c87c5fbaSopenharmony_ci coap_session_release(s); 1534c87c5fbaSopenharmony_ci continue; 1535c87c5fbaSopenharmony_ci } 1536c87c5fbaSopenharmony_ci s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now; 1537c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1538c87c5fbaSopenharmony_ci timeout = s_timeout; 1539c87c5fbaSopenharmony_ci } 1540c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1541c87c5fbaSopenharmony_ci 1542c87c5fbaSopenharmony_ci /* Make sure the session object is not deleted in any callbacks */ 1543c87c5fbaSopenharmony_ci coap_session_reference(s); 1544c87c5fbaSopenharmony_ci /* Check any DTLS timeouts and expire if appropriate */ 1545c87c5fbaSopenharmony_ci if (s->state == COAP_SESSION_STATE_HANDSHAKE && 1546c87c5fbaSopenharmony_ci s->proto == COAP_PROTO_DTLS && s->tls) { 1547c87c5fbaSopenharmony_ci coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now); 1548c87c5fbaSopenharmony_ci while (tls_timeout > 0 && tls_timeout <= now) { 1549c87c5fbaSopenharmony_ci coap_log_debug("** %s: DTLS retransmit timeout\n", coap_session_str(s)); 1550c87c5fbaSopenharmony_ci if (coap_dtls_handle_timeout(s)) 1551c87c5fbaSopenharmony_ci goto release_2; 1552c87c5fbaSopenharmony_ci 1553c87c5fbaSopenharmony_ci if (s->tls) 1554c87c5fbaSopenharmony_ci tls_timeout = coap_dtls_get_timeout(s, now); 1555c87c5fbaSopenharmony_ci else { 1556c87c5fbaSopenharmony_ci tls_timeout = 0; 1557c87c5fbaSopenharmony_ci timeout = 1; 1558c87c5fbaSopenharmony_ci } 1559c87c5fbaSopenharmony_ci } 1560c87c5fbaSopenharmony_ci if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout)) 1561c87c5fbaSopenharmony_ci timeout = tls_timeout - now; 1562c87c5fbaSopenharmony_ci } 1563c87c5fbaSopenharmony_ci 1564c87c5fbaSopenharmony_ci /* Check if any client large receives are missing blocks */ 1565c87c5fbaSopenharmony_ci if (s->lg_crcv) { 1566c87c5fbaSopenharmony_ci if (coap_block_check_lg_crcv_timeouts(s, now, &s_timeout)) { 1567c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1568c87c5fbaSopenharmony_ci timeout = s_timeout; 1569c87c5fbaSopenharmony_ci } 1570c87c5fbaSopenharmony_ci } 1571c87c5fbaSopenharmony_ci /* Check if any client large sending have timed out */ 1572c87c5fbaSopenharmony_ci if (s->lg_xmit) { 1573c87c5fbaSopenharmony_ci if (coap_block_check_lg_xmit_timeouts(s, now, &s_timeout)) { 1574c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1575c87c5fbaSopenharmony_ci timeout = s_timeout; 1576c87c5fbaSopenharmony_ci } 1577c87c5fbaSopenharmony_ci } 1578c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 1579c87c5fbaSopenharmony_ci /* 1580c87c5fbaSopenharmony_ci * Check if any client large transmits have hit MAX_PAYLOAD and need 1581c87c5fbaSopenharmony_ci * restarting 1582c87c5fbaSopenharmony_ci */ 1583c87c5fbaSopenharmony_ci if (s->lg_xmit) { 1584c87c5fbaSopenharmony_ci s_timeout = coap_block_check_q_block1_xmit(s, now); 1585c87c5fbaSopenharmony_ci if (timeout == 0 || s_timeout < timeout) 1586c87c5fbaSopenharmony_ci timeout = s_timeout; 1587c87c5fbaSopenharmony_ci } 1588c87c5fbaSopenharmony_ci#endif /* COAP_Q_BLOCK_SUPPORT */ 1589c87c5fbaSopenharmony_ci 1590c87c5fbaSopenharmony_ci#if !defined(COAP_EPOLL_SUPPORT) && !defined(WITHLWIP) 1591c87c5fbaSopenharmony_ci assert(s->ref > 1); 1592c87c5fbaSopenharmony_ci if (s->sock.flags & (COAP_SOCKET_WANT_READ | 1593c87c5fbaSopenharmony_ci COAP_SOCKET_WANT_WRITE | 1594c87c5fbaSopenharmony_ci COAP_SOCKET_WANT_CONNECT)) { 1595c87c5fbaSopenharmony_ci if (*num_sockets < max_sockets) 1596c87c5fbaSopenharmony_ci sockets[(*num_sockets)++] = &s->sock; 1597c87c5fbaSopenharmony_ci } 1598c87c5fbaSopenharmony_ci#endif /* ! COAP_EPOLL_SUPPORT && ! WITH_LWIP */ 1599c87c5fbaSopenharmony_cirelease_2: 1600c87c5fbaSopenharmony_ci coap_session_release(s); 1601c87c5fbaSopenharmony_ci } 1602c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1603c87c5fbaSopenharmony_ci 1604c87c5fbaSopenharmony_ci return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND); 1605c87c5fbaSopenharmony_ci} 1606c87c5fbaSopenharmony_ci 1607c87c5fbaSopenharmony_ci#if !defined(WITH_LWIP) && !defined(CONTIKI) 1608c87c5fbaSopenharmony_ciint 1609c87c5fbaSopenharmony_cicoap_io_process(coap_context_t *ctx, uint32_t timeout_ms) { 1610c87c5fbaSopenharmony_ci return coap_io_process_with_fds(ctx, timeout_ms, 0, NULL, NULL, NULL); 1611c87c5fbaSopenharmony_ci} 1612c87c5fbaSopenharmony_ci 1613c87c5fbaSopenharmony_ciint 1614c87c5fbaSopenharmony_cicoap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms, 1615c87c5fbaSopenharmony_ci int enfds, fd_set *ereadfds, fd_set *ewritefds, 1616c87c5fbaSopenharmony_ci fd_set *eexceptfds) { 1617c87c5fbaSopenharmony_ci coap_fd_t nfds = 0; 1618c87c5fbaSopenharmony_ci coap_tick_t before, now; 1619c87c5fbaSopenharmony_ci unsigned int timeout; 1620c87c5fbaSopenharmony_ci#ifndef COAP_EPOLL_SUPPORT 1621c87c5fbaSopenharmony_ci struct timeval tv; 1622c87c5fbaSopenharmony_ci int result; 1623c87c5fbaSopenharmony_ci unsigned int i; 1624c87c5fbaSopenharmony_ci#endif /* ! COAP_EPOLL_SUPPORT */ 1625c87c5fbaSopenharmony_ci 1626c87c5fbaSopenharmony_ci coap_ticks(&before); 1627c87c5fbaSopenharmony_ci 1628c87c5fbaSopenharmony_ci#ifndef COAP_EPOLL_SUPPORT 1629c87c5fbaSopenharmony_ci 1630c87c5fbaSopenharmony_ci timeout = coap_io_prepare_io(ctx, ctx->sockets, 1631c87c5fbaSopenharmony_ci (sizeof(ctx->sockets) / sizeof(ctx->sockets[0])), 1632c87c5fbaSopenharmony_ci &ctx->num_sockets, before); 1633c87c5fbaSopenharmony_ci if (timeout == 0 || timeout_ms < timeout) 1634c87c5fbaSopenharmony_ci timeout = timeout_ms; 1635c87c5fbaSopenharmony_ci 1636c87c5fbaSopenharmony_ci if (ereadfds) { 1637c87c5fbaSopenharmony_ci ctx->readfds = *ereadfds; 1638c87c5fbaSopenharmony_ci nfds = enfds; 1639c87c5fbaSopenharmony_ci } else { 1640c87c5fbaSopenharmony_ci FD_ZERO(&ctx->readfds); 1641c87c5fbaSopenharmony_ci } 1642c87c5fbaSopenharmony_ci if (ewritefds) { 1643c87c5fbaSopenharmony_ci ctx->writefds = *ewritefds; 1644c87c5fbaSopenharmony_ci nfds = enfds; 1645c87c5fbaSopenharmony_ci } else { 1646c87c5fbaSopenharmony_ci FD_ZERO(&ctx->writefds); 1647c87c5fbaSopenharmony_ci } 1648c87c5fbaSopenharmony_ci if (eexceptfds) { 1649c87c5fbaSopenharmony_ci ctx->exceptfds = *eexceptfds; 1650c87c5fbaSopenharmony_ci nfds = enfds; 1651c87c5fbaSopenharmony_ci } else { 1652c87c5fbaSopenharmony_ci FD_ZERO(&ctx->exceptfds); 1653c87c5fbaSopenharmony_ci } 1654c87c5fbaSopenharmony_ci for (i = 0; i < ctx->num_sockets; i++) { 1655c87c5fbaSopenharmony_ci if (ctx->sockets[i]->fd + 1 > nfds) 1656c87c5fbaSopenharmony_ci nfds = ctx->sockets[i]->fd + 1; 1657c87c5fbaSopenharmony_ci if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ) 1658c87c5fbaSopenharmony_ci FD_SET(ctx->sockets[i]->fd, &ctx->readfds); 1659c87c5fbaSopenharmony_ci if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE) 1660c87c5fbaSopenharmony_ci FD_SET(ctx->sockets[i]->fd, &ctx->writefds); 1661c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1662c87c5fbaSopenharmony_ci if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) 1663c87c5fbaSopenharmony_ci FD_SET(ctx->sockets[i]->fd, &ctx->readfds); 1664c87c5fbaSopenharmony_ci if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) { 1665c87c5fbaSopenharmony_ci FD_SET(ctx->sockets[i]->fd, &ctx->writefds); 1666c87c5fbaSopenharmony_ci FD_SET(ctx->sockets[i]->fd, &ctx->exceptfds); 1667c87c5fbaSopenharmony_ci } 1668c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1669c87c5fbaSopenharmony_ci } 1670c87c5fbaSopenharmony_ci 1671c87c5fbaSopenharmony_ci if (timeout_ms == COAP_IO_NO_WAIT) { 1672c87c5fbaSopenharmony_ci tv.tv_usec = 0; 1673c87c5fbaSopenharmony_ci tv.tv_sec = 0; 1674c87c5fbaSopenharmony_ci timeout = 1; 1675c87c5fbaSopenharmony_ci } else if (timeout > 0) { 1676c87c5fbaSopenharmony_ci tv.tv_usec = (timeout % 1000) * 1000; 1677c87c5fbaSopenharmony_ci tv.tv_sec = (long)(timeout / 1000); 1678c87c5fbaSopenharmony_ci } 1679c87c5fbaSopenharmony_ci 1680c87c5fbaSopenharmony_ci result = select((int)nfds, &ctx->readfds, &ctx->writefds, &ctx->exceptfds, 1681c87c5fbaSopenharmony_ci timeout > 0 ? &tv : NULL); 1682c87c5fbaSopenharmony_ci 1683c87c5fbaSopenharmony_ci if (result < 0) { /* error */ 1684c87c5fbaSopenharmony_ci#ifdef _WIN32 1685c87c5fbaSopenharmony_ci coap_win_error_to_errno(); 1686c87c5fbaSopenharmony_ci#endif 1687c87c5fbaSopenharmony_ci if (errno != EINTR) { 1688c87c5fbaSopenharmony_ci coap_log_debug("%s", coap_socket_strerror()); 1689c87c5fbaSopenharmony_ci return -1; 1690c87c5fbaSopenharmony_ci } 1691c87c5fbaSopenharmony_ci } 1692c87c5fbaSopenharmony_ci if (ereadfds) { 1693c87c5fbaSopenharmony_ci *ereadfds = ctx->readfds; 1694c87c5fbaSopenharmony_ci } 1695c87c5fbaSopenharmony_ci if (ewritefds) { 1696c87c5fbaSopenharmony_ci *ewritefds = ctx->writefds; 1697c87c5fbaSopenharmony_ci } 1698c87c5fbaSopenharmony_ci if (eexceptfds) { 1699c87c5fbaSopenharmony_ci *eexceptfds = ctx->exceptfds; 1700c87c5fbaSopenharmony_ci } 1701c87c5fbaSopenharmony_ci 1702c87c5fbaSopenharmony_ci if (result > 0) { 1703c87c5fbaSopenharmony_ci for (i = 0; i < ctx->num_sockets; i++) { 1704c87c5fbaSopenharmony_ci if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ) && 1705c87c5fbaSopenharmony_ci FD_ISSET(ctx->sockets[i]->fd, &ctx->readfds)) 1706c87c5fbaSopenharmony_ci ctx->sockets[i]->flags |= COAP_SOCKET_CAN_READ; 1707c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1708c87c5fbaSopenharmony_ci if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && 1709c87c5fbaSopenharmony_ci FD_ISSET(ctx->sockets[i]->fd, &ctx->readfds)) 1710c87c5fbaSopenharmony_ci ctx->sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT; 1711c87c5fbaSopenharmony_ci if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && 1712c87c5fbaSopenharmony_ci FD_ISSET(ctx->sockets[i]->fd, &ctx->writefds)) 1713c87c5fbaSopenharmony_ci ctx->sockets[i]->flags |= COAP_SOCKET_CAN_WRITE; 1714c87c5fbaSopenharmony_ci if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && 1715c87c5fbaSopenharmony_ci (FD_ISSET(ctx->sockets[i]->fd, &ctx->writefds) || 1716c87c5fbaSopenharmony_ci FD_ISSET(ctx->sockets[i]->fd, &ctx->exceptfds))) 1717c87c5fbaSopenharmony_ci ctx->sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT; 1718c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1719c87c5fbaSopenharmony_ci } 1720c87c5fbaSopenharmony_ci } 1721c87c5fbaSopenharmony_ci 1722c87c5fbaSopenharmony_ci coap_ticks(&now); 1723c87c5fbaSopenharmony_ci coap_io_do_io(ctx, now); 1724c87c5fbaSopenharmony_ci 1725c87c5fbaSopenharmony_ci#else /* COAP_EPOLL_SUPPORT */ 1726c87c5fbaSopenharmony_ci (void)ereadfds; 1727c87c5fbaSopenharmony_ci (void)ewritefds; 1728c87c5fbaSopenharmony_ci (void)eexceptfds; 1729c87c5fbaSopenharmony_ci (void)enfds; 1730c87c5fbaSopenharmony_ci 1731c87c5fbaSopenharmony_ci timeout = coap_io_prepare_epoll(ctx, before); 1732c87c5fbaSopenharmony_ci 1733c87c5fbaSopenharmony_ci if (timeout == 0 || timeout_ms < timeout) 1734c87c5fbaSopenharmony_ci timeout = timeout_ms; 1735c87c5fbaSopenharmony_ci 1736c87c5fbaSopenharmony_ci do { 1737c87c5fbaSopenharmony_ci struct epoll_event events[COAP_MAX_EPOLL_EVENTS]; 1738c87c5fbaSopenharmony_ci int etimeout = timeout; 1739c87c5fbaSopenharmony_ci 1740c87c5fbaSopenharmony_ci /* Potentially adjust based on what the caller wants */ 1741c87c5fbaSopenharmony_ci if (timeout_ms == COAP_IO_NO_WAIT) { 1742c87c5fbaSopenharmony_ci etimeout = 0; 1743c87c5fbaSopenharmony_ci } else if (timeout == COAP_IO_WAIT) { 1744c87c5fbaSopenharmony_ci /* coap_io_prepare_epoll() returned 0 and timeout_ms COAP_IO_WAIT (0) */ 1745c87c5fbaSopenharmony_ci etimeout = -1; 1746c87c5fbaSopenharmony_ci } else if (etimeout < 0) { 1747c87c5fbaSopenharmony_ci /* epoll_wait cannot wait longer than this as int timeout parameter */ 1748c87c5fbaSopenharmony_ci etimeout = INT_MAX; 1749c87c5fbaSopenharmony_ci } 1750c87c5fbaSopenharmony_ci 1751c87c5fbaSopenharmony_ci nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout); 1752c87c5fbaSopenharmony_ci if (nfds < 0) { 1753c87c5fbaSopenharmony_ci if (errno != EINTR) { 1754c87c5fbaSopenharmony_ci coap_log_err("epoll_wait: unexpected error: %s (%d)\n", 1755c87c5fbaSopenharmony_ci coap_socket_strerror(), nfds); 1756c87c5fbaSopenharmony_ci } 1757c87c5fbaSopenharmony_ci break; 1758c87c5fbaSopenharmony_ci } 1759c87c5fbaSopenharmony_ci 1760c87c5fbaSopenharmony_ci coap_io_do_epoll(ctx, events, nfds); 1761c87c5fbaSopenharmony_ci 1762c87c5fbaSopenharmony_ci /* 1763c87c5fbaSopenharmony_ci * reset to COAP_IO_NO_WAIT (which causes etimeout to become 0) 1764c87c5fbaSopenharmony_ci * incase we have to do another iteration 1765c87c5fbaSopenharmony_ci * (COAP_MAX_EPOLL_EVENTS insufficient) 1766c87c5fbaSopenharmony_ci */ 1767c87c5fbaSopenharmony_ci timeout_ms = COAP_IO_NO_WAIT; 1768c87c5fbaSopenharmony_ci 1769c87c5fbaSopenharmony_ci /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */ 1770c87c5fbaSopenharmony_ci } while (nfds == COAP_MAX_EPOLL_EVENTS); 1771c87c5fbaSopenharmony_ci 1772c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 1773c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1774c87c5fbaSopenharmony_ci coap_expire_cache_entries(ctx); 1775c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1776c87c5fbaSopenharmony_ci coap_ticks(&now); 1777c87c5fbaSopenharmony_ci#if COAP_ASYNC_SUPPORT 1778c87c5fbaSopenharmony_ci /* Check to see if we need to send off any Async requests as delay might 1779c87c5fbaSopenharmony_ci have been updated */ 1780c87c5fbaSopenharmony_ci coap_check_async(ctx, now); 1781c87c5fbaSopenharmony_ci coap_ticks(&now); 1782c87c5fbaSopenharmony_ci#endif /* COAP_ASYNC_SUPPORT */ 1783c87c5fbaSopenharmony_ci 1784c87c5fbaSopenharmony_ci return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND); 1785c87c5fbaSopenharmony_ci} 1786c87c5fbaSopenharmony_ci#endif /* ! WITH_LWIP && ! WITH_CONTIKI */ 1787c87c5fbaSopenharmony_ci 1788c87c5fbaSopenharmony_ci/* 1789c87c5fbaSopenharmony_ci * return 1 I/O pending 1790c87c5fbaSopenharmony_ci * 0 No I/O pending 1791c87c5fbaSopenharmony_ci */ 1792c87c5fbaSopenharmony_ciint 1793c87c5fbaSopenharmony_cicoap_io_pending(coap_context_t *context) { 1794c87c5fbaSopenharmony_ci coap_session_t *s, *rtmp; 1795c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1796c87c5fbaSopenharmony_ci coap_endpoint_t *ep; 1797c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1798c87c5fbaSopenharmony_ci 1799c87c5fbaSopenharmony_ci if (!context) 1800c87c5fbaSopenharmony_ci return 0; 1801c87c5fbaSopenharmony_ci if (coap_io_process(context, COAP_IO_NO_WAIT) < 0) 1802c87c5fbaSopenharmony_ci return 0; 1803c87c5fbaSopenharmony_ci 1804c87c5fbaSopenharmony_ci if (context->sendqueue) 1805c87c5fbaSopenharmony_ci return 1; 1806c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1807c87c5fbaSopenharmony_ci LL_FOREACH(context->endpoint, ep) { 1808c87c5fbaSopenharmony_ci SESSIONS_ITER(ep->sessions, s, rtmp) { 1809c87c5fbaSopenharmony_ci if (s->delayqueue) 1810c87c5fbaSopenharmony_ci return 1; 1811c87c5fbaSopenharmony_ci if (s->lg_xmit) 1812c87c5fbaSopenharmony_ci return 1; 1813c87c5fbaSopenharmony_ci if (s->lg_srcv) 1814c87c5fbaSopenharmony_ci return 1; 1815c87c5fbaSopenharmony_ci } 1816c87c5fbaSopenharmony_ci } 1817c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1818c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1819c87c5fbaSopenharmony_ci SESSIONS_ITER(context->sessions, s, rtmp) { 1820c87c5fbaSopenharmony_ci if (s->delayqueue) 1821c87c5fbaSopenharmony_ci return 1; 1822c87c5fbaSopenharmony_ci if (s->lg_xmit) 1823c87c5fbaSopenharmony_ci return 1; 1824c87c5fbaSopenharmony_ci if (s->lg_crcv) 1825c87c5fbaSopenharmony_ci return 1; 1826c87c5fbaSopenharmony_ci } 1827c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1828c87c5fbaSopenharmony_ci return 0; 1829c87c5fbaSopenharmony_ci} 1830c87c5fbaSopenharmony_ci 1831c87c5fbaSopenharmony_ci#ifdef _WIN32 1832c87c5fbaSopenharmony_ciconst char * 1833c87c5fbaSopenharmony_cicoap_socket_format_errno(int error) { 1834c87c5fbaSopenharmony_ci static char szError[256]; 1835c87c5fbaSopenharmony_ci if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 1836c87c5fbaSopenharmony_ci NULL, (DWORD)error, MAKELANGID(LANG_NEUTRAL, 1837c87c5fbaSopenharmony_ci SUBLANG_DEFAULT), (LPSTR)szError, (DWORD)sizeof(szError), 1838c87c5fbaSopenharmony_ci NULL) == 0) 1839c87c5fbaSopenharmony_ci strcpy(szError, "Unknown error"); 1840c87c5fbaSopenharmony_ci return szError; 1841c87c5fbaSopenharmony_ci} 1842c87c5fbaSopenharmony_ci 1843c87c5fbaSopenharmony_ciconst char * 1844c87c5fbaSopenharmony_cicoap_socket_strerror(void) { 1845c87c5fbaSopenharmony_ci return coap_socket_format_errno(WSAGetLastError()); 1846c87c5fbaSopenharmony_ci} 1847c87c5fbaSopenharmony_ci#else /* _WIN32 */ 1848c87c5fbaSopenharmony_ciconst char * 1849c87c5fbaSopenharmony_cicoap_socket_format_errno(int error) { 1850c87c5fbaSopenharmony_ci return strerror(error); 1851c87c5fbaSopenharmony_ci} 1852c87c5fbaSopenharmony_ciconst char * 1853c87c5fbaSopenharmony_cicoap_socket_strerror(void) { 1854c87c5fbaSopenharmony_ci return coap_socket_format_errno(errno); 1855c87c5fbaSopenharmony_ci} 1856c87c5fbaSopenharmony_ci#endif /* _WIN32 */ 1857c87c5fbaSopenharmony_ci 1858c87c5fbaSopenharmony_ci#undef SIN6 1859