23#ifdef HAVE_SYS_SELECT_H
24# include <sys/select.h>
26#ifdef HAVE_SYS_SOCKET_H
27# include <sys/socket.h>
28# define OPTVAL_T(t) (t)
29# define OPTVAL_GT(t) (t)
31#ifdef HAVE_SYS_IOCTL_H
34#ifdef HAVE_NETINET_IN_H
35# include <netinet/in.h>
39# define OPTVAL_T(t) (const char*)(t)
40# define OPTVAL_GT(t) (char*)(t)
42# define CMSG_DATA WSA_CMSG_DATA
53#ifdef COAP_EPOLL_SUPPORT
55#include <sys/timerfd.h>
61#include <zephyr/posix/sys/ioctl.h>
62#include <zephyr/posix/sys/select.h>
63#define OPTVAL_T(t) (const void*)(t)
64#define OPTVAL_GT(t) (void*)(t)
67#ifdef IPV6_RECVPKTINFO
68#define IPV6_PKTINFO IPV6_RECVPKTINFO
70#define IPV6_PKTINFO IP_PKTINFO
72#ifndef IN6_IS_ADDR_V4MAPPED
73#define IN6_IS_ADDR_V4MAPPED(a) \
74 ((((a)->s6_addr32[0]) == 0) && (((a)->s6_addr32[1]) == 0) && \
75 (((a)->s6_addr32[2]) == htonl(0xffff)))
80#if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) && !defined(WITH_LWIP)
82#if defined(IP_PKTINFO)
83# define GEN_IP_PKTINFO IP_PKTINFO
84#elif defined(IP_RECVDSTADDR)
85# define GEN_IP_PKTINFO IP_RECVDSTADDR
87# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
91#ifdef IPV6_RECVPKTINFO
92# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
93#elif defined(IPV6_PKTINFO)
94# define GEN_IPV6_PKTINFO IPV6_PKTINFO
96# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
100#if COAP_SERVER_SUPPORT
112#if !defined(WITH_CONTIKI) && !defined(WITH_LWIP) && !defined(RIOT_VERSION)
114#if COAP_SERVER_SUPPORT
125 struct timeval timeout = {0, 0};
131 sock->
fd = socket(listen_addr->
addr.
sa.sa_family, SOCK_DGRAM, 0);
147 if (setsockopt(sock->
fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
sizeof(on)) ==
COAP_SOCKET_ERROR)
148 coap_log_warn(
"coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n",
151 switch (listen_addr->
addr.
sa.sa_family) {
154 if (setsockopt(sock->
fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on),
156 coap_log_alert(
"coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n",
163 if (setsockopt(sock->
fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
165 coap_log_alert(
"coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n",
167#if !defined(ESPIDF_VERSION)
168 if (setsockopt(sock->
fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on),
170 coap_log_alert(
"coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n",
174 setsockopt(sock->
fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on),
sizeof(on));
178#if COAP_AF_UNIX_SUPPORT
187 if (setsockopt(sock->
fd, SOL_SOCKET, SO_RCVTIMEO, OPTVAL_T(&timeout),
189 coap_log_alert(
"coap_socket_bind_udp: setsockopt SO_RCVTIMEO: %s\n",
193 if (bind(sock->
fd, &listen_addr->
addr.
sa,
195 listen_addr->
addr.
sa.sa_family == AF_INET ?
196 (socklen_t)
sizeof(
struct sockaddr_in) :
204 bound_addr->
size = (socklen_t)
sizeof(*bound_addr);
205 if (getsockname(sock->
fd, &bound_addr->
addr.
sa, &bound_addr->
size) < 0) {
210#if defined(RIOT_VERSION) && defined(COAP_SERVER_SUPPORT)
212 bound_addr->
addr.
sa.sa_family == AF_INET6) {
213 bound_addr->
addr.
sin6.sin6_scope_id =
214 listen_addr->
addr.
sin6.sin6_scope_id;
215 bound_addr->
addr.
sin6.sin6_flowinfo = 0;
227#if COAP_CLIENT_SUPPORT
247 sock->
fd = socket(connect_addr.
addr.
sa.sa_family, SOCK_DGRAM, 0);
263 int keep_errno = errno;
265 coap_log_warn(
"coap_socket_connect_udp: ioctl FIONBIO: %s (%d)\n",
270 switch (connect_addr.
addr.
sa.sa_family) {
273 if (connect_addr.
addr.
sin.sin_port == 0)
274 connect_addr.
addr.
sin.sin_port = htons(default_port);
279 if (connect_addr.
addr.
sin6.sin6_port == 0)
280 connect_addr.
addr.
sin6.sin6_port = htons(default_port);
282 if (setsockopt(sock->
fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
284 if (errno != ENOSYS) {
285 coap_log_warn(
"coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
290#if COAP_AF_UNIX_SUPPORT
295 coap_log_alert(
"coap_socket_connect_udp: unsupported sa_family %d\n",
296 connect_addr.
addr.
sa.sa_family);
300 if (local_if && local_if->
addr.
sa.sa_family) {
301 if (local_if->
addr.
sa.sa_family != connect_addr.
addr.
sa.sa_family) {
302 coap_log_warn(
"coap_socket_connect_udp: local address family != "
303 "remote address family\n");
306 if (setsockopt(sock->
fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
sizeof(on)) ==
COAP_SOCKET_ERROR)
307 coap_log_warn(
"coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
309 if (bind(sock->
fd, &local_if->
addr.
sa,
311 local_if->
addr.
sa.sa_family == AF_INET ?
312 (socklen_t)
sizeof(
struct sockaddr_in) :
319#if COAP_AF_UNIX_SUPPORT
320 }
else if (connect_addr.
addr.
sa.sa_family == AF_UNIX) {
322 coap_log_warn(
"coap_socket_connect_udp: local address required\n");
329 if (!(local_if && local_if->
addr.
sa.sa_family)) {
334 bind_addr.
addr.
sa.sa_family = connect_addr.
addr.
sa.sa_family;
335 if (bind(sock->
fd, &bind_addr.
addr.
sa,
337 bind_addr.
addr.
sa.sa_family == AF_INET ?
338 (socklen_t)
sizeof(
struct sockaddr_in) :
347 coap_log_warn(
"coap_socket_connect_udp: getsockname for multicast socket: %s\n",
354 setsockopt(sock->
fd, SOL_SOCKET, SO_BROADCAST, OPTVAL_T(&on),
356 coap_log_warn(
"coap_socket_connect_udp: setsockopt SO_BROADCAST: %s\n",
362#if COAP_AF_UNIX_SUPPORT
363 if (connect_addr.
addr.
sa.sa_family == AF_UNIX) {
397#ifdef COAP_EPOLL_SUPPORT
398#if COAP_SERVER_SUPPORT
404 if (context != NULL) {
406 struct epoll_event event;
409 ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->
fd, &event);
410 if (ret == -1 && errno != ENOENT) {
418#if COAP_SERVER_SUPPORT
419#if COAP_AF_UNIX_SUPPORT
432#if COAP_CLIENT_SUPPORT
433#if COAP_AF_UNIX_SUPPORT
452#ifdef COAP_EPOLL_SUPPORT
458 struct epoll_event event;
461#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR
468#if COAP_SERVER_SUPPORT
478 memset(&event, 0,
sizeof(event));
479 event.events = events;
480 event.data.ptr = sock;
482 ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->
fd, &event);
495 struct epoll_event event;
498#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR
505#if COAP_SERVER_SUPPORT
514 event.events = events;
515 event.data.ptr = sock;
517 ret = epoll_ctl(context->epfd, EPOLL_CTL_MOD, sock->
fd, &event);
519#if (COAP_MAX_LOGGING_LEVEL < COAP_LOG_ERR)
534#if COAP_EPOLL_SUPPORT
535 if (context->eptimerfd != -1) {
540 struct itimerspec new_value;
544 memset(&new_value, 0,
sizeof(new_value));
546 new_value.it_value.tv_nsec = 1;
552 ret = timerfd_settime(context->eptimerfd, 0, &new_value, NULL);
555 "coap_update_io_timer",
558#ifdef COAP_DEBUG_WAKEUP_TIMES
561 new_value.it_value.tv_sec, new_value.it_value.tv_nsec);
577#if !defined(WITH_CONTIKI) && !defined(WITH_LWIP) && !defined(RIOT_VERSION)
581coap_win_error_to_errno(
void) {
582 int w_error = WSAGetLastError();
584 case WSA_NOT_ENOUGH_MEMORY:
587 case WSA_INVALID_PARAMETER:
620 case WSAECONNABORTED:
621 errno = ECONNABORTED;
632 case WSAECONNREFUSED:
633 errno = ECONNREFUSED;
635 case WSAEADDRNOTAVAIL:
636 errno = EADDRNOTAVAIL;
639 coap_log_err(
"WSAGetLastError: %d mapping to errno failed - please fix\n",
659 r = send(sock->
fd, (
const char *)data, (
int)data_len, 0);
662#define MSG_NOSIGNAL 0
668 coap_win_error_to_errno();
671#
if EAGAIN != EWOULDBLOCK
672 errno == EWOULDBLOCK ||
676#ifdef COAP_EPOLL_SUPPORT
685 if (errno == EPIPE || errno == ECONNRESET) {
694 if (r < (ssize_t)data_len) {
696#ifdef COAP_EPOLL_SUPPORT
717 r = recv(sock->
fd, (
char *)data, (
int)data_len, 0);
719 r = recv(sock->
fd, data, data_len, 0);
723 sock->
flags &= ~COAP_SOCKET_CAN_READ;
727 sock->
flags &= ~COAP_SOCKET_CAN_READ;
729 coap_win_error_to_errno();
732#
if EAGAIN != EWOULDBLOCK
733 errno == EWOULDBLOCK ||
738 if (errno != ECONNRESET) {
744 if (r < (ssize_t)data_len)
745 sock->
flags &= ~COAP_SOCKET_CAN_READ;
751#if !defined(WITH_LWIP) && !defined(__ZEPHYR__)
752#if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
756#if !defined(__MINGW32__) && !defined(RIOT_VERSION)
771#if !defined(WITH_CONTIKI) && !defined(SOL_IP)
773#define SOL_IP IPPROTO_IP
776#define COAP_SOL_IP IPPROTO_IP
778#define COAP_SOL_IP SOL_IP
783#if defined(__MINGW32__)
784static __thread LPFN_WSARECVMSG lpWSARecvMsg = NULL;
785#if(_WIN32_WINNT >= 0x0600)
786#define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
787#define CMSG_NXTHDR WSA_CMSG_NXTHDR
788#define CMSG_LEN WSA_CMSG_LEN
789#define CMSG_SPACE WSA_CMSG_SPACE
790#if(_WIN32_WINNT < 0x0603 || _WIN32_WINNT == 0x0a00)
791#define cmsghdr _WSACMSGHDR
795static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL;
798#define msghdr _WSAMSG
800#define msg_namelen namelen
801#define msg_iov lpBuffers
802#define msg_iovlen dwBufferCount
803#define msg_control Control.buf
804#define msg_controllen Control.len
808#define iov_len_t u_long
810#define CMSG_DATA WSA_CMSG_DATA
811#define ipi_spec_dst ipi_addr
812#if !defined(__MINGW32__)
813#pragma warning( disable : 4116 )
816#define iov_len_t size_t
819#if defined(_CYGWIN_ENV) || defined(__QNXNTO__)
820#define ipi_spec_dst ipi_addr
823#if !defined(RIOT_VERSION) && !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
824#if COAP_CLIENT_SUPPORT
825static uint32_t cid_track_counter;
848#ifdef COAP_EPOLL_SUPPORT
870 const uint8_t *data,
size_t datalen) {
871 ssize_t bytes_written = 0;
873#if COAP_CLIENT_SUPPORT
874 coap_test_cid_tuple_change(session);
878 bytes_written = (ssize_t)datalen;
881 bytes_written = send(sock->
fd, (
const char *)data, (
int)datalen, 0);
883 bytes_written = send(sock->
fd, data, datalen, 0);
887 DWORD dwNumberOfBytesSent = 0;
890#ifdef HAVE_STRUCT_CMSGHDR
899 memcpy(&iov[0].iov_base, &data,
sizeof(iov[0].iov_base));
902 memset(buf, 0,
sizeof(buf));
904 memset(&mhdr, 0,
sizeof(
struct msghdr));
905 memcpy(&mhdr.msg_name, &addr,
sizeof(mhdr.msg_name));
907 (socklen_t)
sizeof(
struct sockaddr_in) :
918 struct cmsghdr *cmsg;
922#if defined(IP_PKTINFO)
924 mhdr.msg_control = buf;
925 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
927 cmsg = CMSG_FIRSTHDR(&mhdr);
929 cmsg->cmsg_type = IP_PKTINFO;
930 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
932 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
938#elif defined(IP_SENDSRCADDR)
939 mhdr.msg_control = buf;
940 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_addr));
942 cmsg = CMSG_FIRSTHDR(&mhdr);
943 cmsg->cmsg_level = IPPROTO_IP;
944 cmsg->cmsg_type = IP_SENDSRCADDR;
945 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_addr));
947 memcpy(CMSG_DATA(cmsg),
949 sizeof(
struct in_addr));
954 mhdr.msg_control = buf;
955 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
957 cmsg = CMSG_FIRSTHDR(&mhdr);
958 cmsg->cmsg_level = IPPROTO_IPV6;
959 cmsg->cmsg_type = IPV6_PKTINFO;
960 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
980#if defined(IP_PKTINFO)
981 struct cmsghdr *cmsg;
984 mhdr.msg_control = buf;
985 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
987 cmsg = CMSG_FIRSTHDR(&mhdr);
989 cmsg->cmsg_type = IP_PKTINFO;
990 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
992 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
998#elif defined(IP_SENDSRCADDR)
999 struct cmsghdr *cmsg;
1000 mhdr.msg_control = buf;
1001 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_addr));
1003 cmsg = CMSG_FIRSTHDR(&mhdr);
1004 cmsg->cmsg_level = IPPROTO_IP;
1005 cmsg->cmsg_type = IP_SENDSRCADDR;
1006 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_addr));
1008 memcpy(CMSG_DATA(cmsg),
1010 sizeof(
struct in_addr));
1015#if COAP_AF_UNIX_SUPPORT
1028 r = WSASendMsg(sock->
fd, &mhdr, 0 , &dwNumberOfBytesSent, NULL ,
1031 bytes_written = (ssize_t)dwNumberOfBytesSent;
1034 coap_win_error_to_errno();
1037#ifdef HAVE_STRUCT_CMSGHDR
1038 bytes_written = sendmsg(sock->
fd, &mhdr, 0);
1040 bytes_written = sendto(sock->
fd, (
const void *)data, datalen, 0,
1047 if (bytes_written < 0)
1050 return bytes_written;
1054#define SIN6(A) ((struct sockaddr_in6 *)(A))
1059 *length = packet->
length;
1062#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
1080 sock->
flags &= ~COAP_SOCKET_CAN_READ;
1091 coap_win_error_to_errno();
1093 if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) {
1101 if (errno != EAGAIN) {
1108 }
else if (len > 0) {
1109 packet->
length = (size_t)len;
1113 DWORD dwNumberOfBytesRecvd = 0;
1116#ifdef HAVE_STRUCT_CMSGHDR
1119 struct cmsghdr *cmsg;
1121 struct iovec iov[1];
1123#if defined(__MINGW32__)
1124 iov[0].iov_base = (
char *) packet->
payload;
1126 iov[0].iov_base = packet->
payload;
1130 memset(&mhdr, 0,
sizeof(
struct msghdr));
1136 mhdr.msg_iovlen = 1;
1138 mhdr.msg_control = buf;
1139 mhdr.msg_controllen =
sizeof(buf);
1142 cmsg = (
struct cmsghdr *)buf;
1143 cmsg->cmsg_len = CMSG_LEN(
sizeof(buf));
1144 cmsg->cmsg_level = -1;
1145 cmsg->cmsg_type = -1;
1148 if (!lpWSARecvMsg) {
1149 GUID wsaid = WSAID_WSARECVMSG;
1150 DWORD cbBytesReturned = 0;
1151 if (WSAIoctl(sock->
fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid,
sizeof(wsaid), &lpWSARecvMsg,
1152 sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) {
1157 r = lpWSARecvMsg(sock->
fd, &mhdr, &dwNumberOfBytesRecvd, NULL ,
1160 len = (ssize_t)dwNumberOfBytesRecvd;
1162 coap_win_error_to_errno();
1164 len = recvmsg(sock->
fd, &mhdr, 0);
1175 coap_win_error_to_errno();
1177 if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) {
1185 if (errno != EAGAIN) {
1190#ifdef HAVE_STRUCT_CMSGHDR
1194 packet->
length = (size_t)len;
1198 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
1200#if COAP_IPV6_SUPPORT
1202 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
1207 u.c = CMSG_DATA(cmsg);
1208 packet->
ifindex = (int)(u.p->ipi6_ifindex);
1210 &u.p->ipi6_addr,
sizeof(
struct in6_addr));
1216#if COAP_IPV4_SUPPORT
1218#if defined(IP_PKTINFO)
1219 if (cmsg->cmsg_level ==
COAP_SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
1224 u.c = CMSG_DATA(cmsg);
1225 packet->
ifindex = u.p->ipi_ifindex;
1226#if COAP_IPV6_SUPPORT
1232 &u.p->ipi_addr,
sizeof(
struct in_addr));
1237 &u.p->ipi_addr,
sizeof(
struct in_addr));
1243#if defined(IP_RECVDSTADDR)
1244 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
1247 CMSG_DATA(cmsg),
sizeof(
struct in_addr));
1256 if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) {
1257 coap_log_debug(
"cmsg_level = %d and cmsg_type = %d not supported - fix\n",
1258 cmsg->cmsg_level, cmsg->cmsg_type);
1272 packet->
length = (size_t)len;
1302#ifndef COAP_EPOLL_SUPPORT
1305 coap_log_emerg(
"coap_io_prepare_epoll() requires libcoap compiled for using epoll\n");
1309 unsigned int max_sockets =
sizeof(sockets)/
sizeof(sockets[0]);
1310 unsigned int num_sockets;
1311 unsigned int timeout;
1318 if (ctx->eptimerfd != -1) {
1319 struct itimerspec new_value;
1322 memset(&new_value, 0,
sizeof(new_value));
1331#ifdef COAP_DEBUG_WAKEUP_TIMES
1333 new_value.it_value.tv_sec, new_value.it_value.tv_nsec);
1336 ret = timerfd_settime(ctx->eptimerfd, 0, &new_value, NULL);
1339 "coap_io_prepare_epoll",
1354 unsigned int max_sockets,
1355 unsigned int *num_sockets,
1372 unsigned int max_sockets,
1373 unsigned int *num_sockets,
1379#if COAP_SERVER_SUPPORT
1380 int check_dtls_timeouts = 0;
1382#if defined(COAP_EPOLL_SUPPORT) || defined(WITH_LWIP) || defined(RIOT_VERSION)
1390#if COAP_SERVER_SUPPORT
1394#if COAP_ASYNC_SUPPORT
1396 if (coap_check_async(ctx, now, &s_timeout)) {
1397 if (s_timeout < timeout)
1398 timeout = s_timeout;
1418 if (tls_timeout > 0) {
1423 if (tls_timeout - now < timeout)
1424 timeout = tls_timeout - now;
1426#if COAP_SERVER_SUPPORT
1428 check_dtls_timeouts = 1;
1432#if COAP_PROXY_SUPPORT
1433 if (coap_proxy_check_timeouts(ctx, now, &s_timeout)) {
1434 if (s_timeout < timeout)
1435 timeout = s_timeout;
1438#if COAP_SERVER_SUPPORT
1448#if !defined(COAP_EPOLL_SUPPORT) && !defined(WITH_LWIP) && !defined(RIOT_VERSION)
1450 if (*num_sockets < max_sockets)
1451 sockets[(*num_sockets)++] = &ep->
sock;
1467 s_timeout = (s->
last_rx_tx + session_timeout) - now;
1468 if (s_timeout < timeout)
1469 timeout = s_timeout;
1477 while (tls_timeout > 0 && tls_timeout <= now) {
1490 if (tls_timeout > 0 && tls_timeout - now < timeout)
1491 timeout = tls_timeout - now;
1496 if (s_timeout < timeout)
1497 timeout = s_timeout;
1503 if (s_timeout < timeout)
1504 timeout = s_timeout;
1507#if !defined(COAP_EPOLL_SUPPORT) && !defined(WITH_LWIP) && !defined(RIOT_VERSION)
1510 sockets[(*num_sockets)++] = &s->
sock;
1513#if COAP_Q_BLOCK_SUPPORT
1519 if (coap_block_check_q_block2_xmit(s, now, &s_timeout)) {
1520 if (s_timeout < timeout)
1521 timeout = s_timeout;
1553 if (s_timeout < timeout)
1554 timeout = s_timeout;
1560#if COAP_CLIENT_SUPPORT
1584 if (s_timeout < timeout)
1585 timeout = s_timeout;
1595 if (timeout == 0 || s_timeout < timeout)
1596 timeout = s_timeout;
1601 if (s_timeout < timeout)
1602 timeout = s_timeout;
1606#if !COAP_DISABLE_TCP
1618 if (s_timeout < timeout)
1619 timeout = s_timeout;
1629 while (tls_timeout > 0 && tls_timeout <= now) {
1641 if (tls_timeout > 0 && tls_timeout - now < timeout)
1642 timeout = tls_timeout - now;
1648 if (s_timeout < timeout)
1649 timeout = s_timeout;
1655 if (s_timeout < timeout)
1656 timeout = s_timeout;
1659#if COAP_Q_BLOCK_SUPPORT
1665 if (coap_block_check_q_block1_xmit(s, now, &s_timeout)) {
1666 if (s_timeout < timeout)
1667 timeout = s_timeout;
1672#if !defined(COAP_EPOLL_SUPPORT) && !defined(WITH_LWIP) && !defined(RIOT_VERSION)
1678 sockets[(*num_sockets)++] = &s->
sock;
1696 unsigned int *have_read_fds,
1697 unsigned int max_read_fds,
1699 unsigned int *have_write_fds,
1700 unsigned int max_write_fds,
1701 unsigned int *rem_timeout_ms) {
1706 have_write_fds, max_write_fds, rem_timeout_ms);
1711#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
1714 unsigned int max_this_fds) {
1715 if (*have_this_fds < max_this_fds) {
1716 this_fds[(*have_this_fds)++] = fd;
1719 coap_log_warn(
"coap_io_get_fds: Insufficient space for new fd (%u >= %u)\n", *have_this_fds,
1731 unsigned int *have_read_fds,
1732 unsigned int max_read_fds,
1734 unsigned int *have_write_fds,
1735 unsigned int max_write_fds,
1736 unsigned int *rem_timeout_ms) {
1738 *have_write_fds = 0;
1740#ifdef COAP_EPOLL_SUPPORT
1742 (void)max_write_fds;;
1744 if (!
coap_add_fd(ctx->epfd, read_fds, have_read_fds, max_read_fds))
1747 *rem_timeout_ms = 0;
1752 unsigned int timeout_ms;
1753#if COAP_SERVER_SUPPORT
1778#if COAP_CLIENT_SUPPORT
1795 *rem_timeout_ms = timeout_ms;
1809 unsigned int *have_read_fds,
1810 unsigned int max_read_fds,
1812 unsigned int *have_write_fds,
1813 unsigned int max_write_fds,
1814 unsigned int *rem_timeout_ms) {
1819 (void)max_write_fds;
1822 *have_write_fds = 0;
1823 *rem_timeout_ms = 0;
1830#if !defined(WITH_LWIP) && !defined(CONTIKI) && !defined(RIOT_VERSION)
1848 int enfds, fd_set *ereadfds, fd_set *ewritefds,
1849 fd_set *eexceptfds) {
1859#if !defined(COAP_EPOLL_SUPPORT) && COAP_THREAD_SAFE
1862 int enfds, fd_set *ereadfds, fd_set *ewritefds,
1863 fd_set *eexceptfds) {
1865 unsigned int max_sockets =
sizeof(ctx->
sockets) /
sizeof(ctx->
sockets[0]);
1870#if COAP_SERVER_SUPPORT
1886#if COAP_CLIENT_SUPPORT
1921#if !COAP_DISABLE_TCP
1936 int enfds, fd_set *ereadfds, fd_set *ewritefds,
1937 fd_set *eexceptfds) {
1940 unsigned int timeout;
1941#ifndef COAP_EPOLL_SUPPORT
1950#ifndef COAP_EPOLL_SUPPORT
1982#if !COAP_DISABLE_TCP
1996 }
else if (timeout == 0 && timeout_ms ==
COAP_IO_WAIT) {
1999 if (timeout == 0 || (timeout_ms !=
COAP_IO_WAIT && timeout_ms < timeout))
2000 timeout = timeout_ms;
2001 tv.tv_usec = (timeout % 1000) * 1000;
2002 tv.tv_sec = (long)(timeout / 1000);
2011 timeout > 0 ? &tv : NULL);
2020 coap_win_error_to_errno();
2022 if (errno != EINTR) {
2024 if (errno == EBADF) {
2036 nfds = coap_io_prepare_fds(ctx, enfds, ereadfds, ewritefds, eexceptfds);
2042 coap_win_error_to_errno();
2044 if (errno != EINTR) {
2045 if (errno == EBADF) {
2070#if !COAP_DISABLE_TCP
2109 }
else if (timeout == 0 && timeout_ms ==
COAP_IO_WAIT) {
2117 if (timeout == 0 || (timeout_ms !=
COAP_IO_WAIT && timeout_ms < timeout))
2118 etimeout = timeout_ms;
2133 if (errno != EINTR) {
2134 coap_log_err(
"epoll_wait: unexpected error: %s (%d)\n",
2146 if (errno != EINTR) {
2147 coap_log_err(
"epoll_wait: unexpected error: %s (%d)\n",
2167#if COAP_SERVER_SUPPORT
2170#if COAP_ASYNC_SUPPORT
2174 coap_check_async(ctx, now, NULL);
2177#ifndef COAP_EPOLL_SUPPORT
2195 void *main_loop_code_arg, uint32_t timeout_ms,
2196 uint32_t thread_count) {
2203 main_loop_code_arg, timeout_ms,
2212 void *main_loop_code_arg, uint32_t timeout_ms,
2213 uint32_t thread_count) {
2217 if (thread_count > 1) {
2225 if (main_loop_code) {
2246 }
else if (timeout_ms > used_ms) {
2249 unsigned int next_sec_us;
2250 unsigned int next_sec_ms;
2254 next_sec_ms = (next_sec_us + 999) / 1000;
2255 if (next_sec_ms > timeout_ms && next_sec_ms > 1000)
2256 next_sec_ms -= 1000;
2263 if (thread_count == 1) {
2271 if (timeout_ms > 0 && timeout_ms < used_ms) {
2315#if COAP_SERVER_SUPPORT
2327#if COAP_SERVER_SUPPORT
2328 LL_FOREACH(context->
endpoint, ep) {
2339#if COAP_CLIENT_SUPPORT
2354 return strerror(error);
2359 coap_win_error_to_errno();
2371#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
2386 sock->
flags = flags;
void coap_address_set_port(coap_address_t *addr, uint16_t port)
Set the port field of addr to port (in host byte order).
int coap_is_bcast(const coap_address_t *a)
Checks if given address a denotes a broadcast address.
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
uint16_t coap_address_get_port(const coap_address_t *addr)
Returns the port from addr in host byte order.
void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
COAP_STATIC_INLINE int coap_address_isany(const coap_address_t *a)
Checks if given address object a denotes the wildcard address.
int coap_debug_send_packet(void)
Check to see whether a packet should be sent or not.
#define COAP_IPV4_SUPPORT
const char * coap_socket_format_errno(int error)
ssize_t coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len)
Function interface for data stream receiving off a socket.
static int coap_add_fd(coap_fd_t fd, coap_fd_t this_fds[], unsigned int *have_this_fds, unsigned int max_this_fds)
void coap_socket_close(coap_socket_t *sock)
Function interface to close off a socket.
const char * coap_socket_strerror(void)
ssize_t coap_socket_recv(coap_socket_t *sock, coap_packet_t *packet)
Function interface for reading data.
ssize_t coap_socket_send(coap_socket_t *sock, coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for data transmission.
void coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
Given a packet, set msg and msg_len to an address and length of the packet's data in memory.
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Function interface for data stream sending off a socket.
volatile int coap_thread_quit
void coap_update_io_timer(coap_context_t *context, coap_tick_t delay)
Update when to continue with I/O processing, unless packets come in in the meantime.
#define COAP_MAX_EPOLL_EVENTS
uint16_t coap_socket_flags_t
#define COAP_RXBUFFER_SIZE
#define COAP_SOCKET_ERROR
#define COAP_INVALID_SOCKET
#define COAP_SOCKET_MULTICAST
socket is used for multicast communication
void coap_epoll_ctl_add(coap_socket_t *sock, uint32_t events, const char *func)
Epoll specific function to add the state of events that epoll is to track for the appropriate file de...
int coap_socket_connect_udp(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr)
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
#define COAP_SOCKET_CAN_WRITE
non blocking socket can now write without blocking
#define COAP_SOCKET_BOUND
the socket is bound
#define COAP_SOCKET_SLAVE
socket is a slave socket - do not close
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
#define COAP_SOCKET_CAN_ACCEPT
non blocking server socket can now accept without blocking
int coap_socket_bind_udp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
#define COAP_SOCKET_CAN_CONNECT
non blocking client socket can now connect without blocking
coap_endpoint_t * coap_malloc_endpoint(void)
void coap_epoll_ctl_mod(coap_socket_t *sock, uint32_t events, const char *func)
Epoll specific function to modify the state of events that epoll is tracking on the appropriate file ...
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
void coap_mfree_endpoint(coap_endpoint_t *ep)
#define COAP_SOCKET_CAN_READ
non blocking socket can now read without blocking
#define COAP_SOCKET_CONNECTED
the socket is connected
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Library specific build wrapper for coap_internal.h.
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
#define SESSIONS_ITER_SAFE(e, el, rtmp)
#define SESSIONS_ITER(e, el, rtmp)
#define COAP_DEFAULT_SESSION_TIMEOUT
void coap_io_do_epoll_lkd(coap_context_t *ctx, struct epoll_event *events, size_t nevents)
Process all the epoll events.
int coap_io_process_loop_lkd(coap_context_t *context, coap_io_process_thread_t main_loop_code, void *main_loop_code_arg, uint32_t timeout_ms, uint32_t thread_count)
Do the coap_io_process() across thread_count threads.
int coap_io_pending_lkd(coap_context_t *context)
Check to see if there is any i/o pending for the context.
void coap_io_do_io_lkd(coap_context_t *ctx, coap_tick_t now)
Processes any outstanding read, write, accept or connect I/O as indicated in the coap_socket_t struct...
unsigned int coap_io_get_fds_lkd(coap_context_t *ctx, coap_fd_t read_fds[], unsigned int *have_read_fds, unsigned int max_read_fds, coap_fd_t write_fds[], unsigned int *have_write_fds, unsigned int max_write_fds, unsigned int *rem_timeout_ms)
int coap_io_process_lkd(coap_context_t *ctx, uint32_t timeout_ms)
The main I/O processing function.
int coap_io_process_with_fds_lkd(coap_context_t *ctx, uint32_t timeout_ms, int enfds, fd_set *ereadfds, fd_set *ewritefds, fd_set *eexceptfds)
The main message processing loop with additional fds for internal select.
unsigned int coap_io_prepare_io_lkd(coap_context_t *ctx, coap_socket_t *sockets[], unsigned int max_sockets, unsigned int *num_sockets, coap_tick_t now)
Iterates through all the coap_socket_t structures embedded in endpoints or sessions associated with t...
unsigned int coap_io_prepare_epoll_lkd(coap_context_t *ctx, coap_tick_t now)
Any now timed out delayed packet is transmitted, along with any packets associated with requested obs...
COAP_API int coap_io_process(coap_context_t *ctx, uint32_t timeout_ms)
The main I/O processing function.
COAP_API int coap_io_pending(coap_context_t *context)
Check to see if there is any i/o pending for the context.
int coap_io_process_configure_threads(coap_context_t *context, uint32_t thread_count)
Configure a defined number of threads to do the alternate coap_io_process() work with traffic load ba...
void coap_io_process_terminate_loop(void)
Terminate all the additional threads created by coap_io_process_loop() and break out of the main thre...
void coap_io_process_remove_threads(coap_context_t *context)
Release the coap_io_process() worker threads.
COAP_API int coap_io_process_loop(coap_context_t *context, coap_io_process_thread_t main_loop_code, void *main_loop_code_arg, uint32_t timeout_ms, uint32_t thread_count)
Do the coap_io_process() across thread_count threads.
COAP_API unsigned int coap_io_get_fds(coap_context_t *ctx, coap_fd_t read_fds[], unsigned int *have_read_fds, unsigned int max_read_fds, coap_fd_t write_fds[], unsigned int *have_write_fds, unsigned int max_write_fds, unsigned int *rem_timeout_ms)
COAP_API unsigned int coap_io_prepare_io(coap_context_t *ctx, coap_socket_t *sockets[], unsigned int max_sockets, unsigned int *num_sockets, coap_tick_t now)
Iterates through all the coap_socket_t structures embedded in endpoints or sessions associated with t...
COAP_API void coap_socket_set_flags(coap_socket_t *sock, coap_socket_flags_t flags)
Set the libcoap internal flags for a socket.
COAP_API unsigned int coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now)
Any now timed out delayed packet is transmitted, along with any packets associated with requested obs...
COAP_API coap_fd_t coap_socket_get_fd(coap_socket_t *sock)
Get the libcoap internal file descriptor for a socket.
COAP_API int coap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms, int enfds, fd_set *ereadfds, fd_set *ewritefds, fd_set *eexceptfds)
The main message processing loop with additional fds for internal select.
void(* coap_io_process_thread_t)(void *arg)
Main thread coap_io_process_loop activity.
COAP_API coap_socket_flags_t coap_socket_get_flags(coap_socket_t *sock)
Get the libcoap internal flags for a socket.
int coap_block_check_lg_crcv_timeouts(coap_session_t *session, coap_tick_t now, coap_tick_t *tim_rem)
int coap_block_check_lg_srcv_timeouts(coap_session_t *session, coap_tick_t now, coap_tick_t *tim_rem)
int coap_block_check_lg_xmit_timeouts(coap_session_t *session, coap_tick_t now, coap_tick_t *tim_rem)
void coap_expire_cache_entries(coap_context_t *context)
Expire coap_cache_entry_t entries.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
#define COAP_MAX_DELAY_TICKS
uint64_t coap_ticks_to_rt_us(coap_tick_t t)
Helper function that converts coap ticks to POSIX wallclock time in us.
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
coap_queue_t * coap_peek_next(coap_context_t *context)
Returns the next pdu to send without removing from sendqeue.
coap_queue_t * coap_pop_next(coap_context_t *context)
Returns the next pdu to send and removes it from the sendqeue.
coap_mid_t coap_retransmit(coap_context_t *context, coap_queue_t *node)
Handles retransmissions of confirmable messages.
void coap_send_recv_terminate(void)
Terminate any active coap_send_recv() sessions.
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
@ COAP_EVENT_SERVER_SESSION_DEL
Called in the CoAP IO loop if a server session is deleted (e.g., due to inactivity or because the max...
@ COAP_EVENT_KEEPALIVE_FAILURE
Triggered when no response to a keep alive (ping) packet.
#define coap_lock_unlock()
Dummy for no thread-safe code.
#define coap_lock_check_locked()
Dummy for no thread-safe code.
#define coap_lock_callback_release(func, failed)
Dummy for no thread-safe code.
#define coap_lock_lock(failed)
Dummy for no thread-safe code.
#define coap_log_debug(...)
#define coap_log_alert(...)
#define coap_log_emerg(...)
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
#define coap_log_warn(...)
#define coap_log_err(...)
#define coap_log_crit(...)
int coap_mid_t
coap_mid_t is used to store the CoAP Message ID of a CoAP PDU.
#define COAP_INVALID_MID
Indicates an invalid message id.
int coap_session_reconnect(coap_session_t *session)
Close the current session (if not already closed) and reconnect to server (client session only).
void coap_session_server_keepalive_failed(coap_session_t *session)
Clear down a session following a keepalive failure.
void coap_session_failed(coap_session_t *session)
Session has failed due to a socket error.
coap_mid_t coap_session_send_ping_lkd(coap_session_t *session)
Send a ping message for the session.
void coap_session_free(coap_session_t *session)
void coap_session_release_lkd(coap_session_t *session)
Decrement reference counter on a session.
coap_session_t * coap_session_reference_lkd(coap_session_t *session)
Increment reference counter on a session.
#define COAP_PROTO_RELIABLE(p)
@ COAP_SESSION_TYPE_SERVER
server-side
@ COAP_SESSION_TYPE_CLIENT
client-side
@ COAP_SESSION_STATE_HANDSHAKE
@ COAP_SESSION_STATE_ESTABLISHED
@ COAP_SESSION_STATE_NONE
void coap_check_notify_lkd(coap_context_t *context)
Checks all known resources to see if they are dirty and then notifies subscribed observers.
coap_address_t remote
remote address and port
coap_address_t local
local address and port
Multi-purpose address abstraction.
socklen_t size
size of addr
struct coap_sockaddr_un cun
union coap_address_t::@0 addr
The CoAP stack's global state is stored in a coap_context_t object.
coap_tick_t sendqueue_basetime
The time stamp in the first element of the sendqeue is relative to sendqueue_basetime.
coap_socket_t * sockets[64]
Track different socket information in coap_io_process_with_fds_lkd()
unsigned int reconnect_time
Time to wait before reconnecting a failed client session.
unsigned int num_sockets
Number of sockets being tracked.
coap_session_t * sessions
client sessions
fd_set exceptfds
Used for select call in coap_io_process_with_fds_lkd()
unsigned int ping_timeout
Minimum inactivity time before sending a ping message.
uint8_t testing_cids
Change client's source port every testing_cids.
coap_endpoint_t * endpoint
the endpoints used for listening
uint32_t csm_timeout_ms
Timeout for waiting for a CSM from the remote side.
coap_tick_t next_timeout
When the next timeout is to occur.
unsigned int session_timeout
Number of seconds of inactivity after which an unused session will be closed.
Abstraction of virtual endpoint that can be attached to coap_context_t.
coap_context_t * context
endpoint's context
coap_session_t * sessions
hash table or list of active sessions
coap_address_t bind_addr
local interface address
coap_socket_t sock
socket object for the interface, if any
size_t length
length of payload
coap_addr_tuple_t addr_info
local and remote addresses
unsigned char * payload
payload
int ifindex
the interface index
coap_tick_t t
when to send PDU for the next time
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_lg_xmit_t * lg_xmit
list of large transmissions
unsigned ref_subscriptions
reference count of current subscriptions
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
unsigned ref_proxy_subs
reference count of current proxy subscriptions
coap_addr_tuple_t addr_info
remote/local address info
coap_proto_t proto
protocol used
unsigned ref
reference count from queues
uint8_t negotiated_cid
Set for a client if CID negotiated.
void * tls
security parameters
uint8_t con_active
Active CON request sent.
coap_queue_t * delayqueue
list of delayed messages waiting to be sent
coap_mid_t last_ping_mid
the last keepalive message id that was used in this session
coap_lg_srcv_t * lg_srcv
Server list of expected large receives.
coap_lg_crcv_t * lg_crcv
Client list of expected large receives.
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
uint8_t session_failed
Set if session failed and can try re-connect.
int ifindex
interface index
char sun_path[COAP_UNIX_PATH_MAX]
coap_session_t * session
Used to determine session owner.
coap_endpoint_t * endpoint
Used by the epoll logic for a listening endpoint.
coap_address_t mcast_addr
remote address and port (multicast track)
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values
struct in6_addr ipi6_addr
unsigned int ipi6_ifindex
struct in_addr ipi_spec_dst