19#if ! defined(WITH_LWIP) && ! defined(WITH_CONTIKI) && ! defined (RIOT_VERSION)
29#ifdef HAVE_SYS_SELECT_H
30# include <sys/select.h>
32#ifdef HAVE_SYS_SOCKET_H
33# include <sys/socket.h>
34# define OPTVAL_T(t) (t)
35# define OPTVAL_GT(t) (t)
37#ifdef HAVE_SYS_IOCTL_H
40#ifdef HAVE_NETINET_IN_H
41# include <netinet/in.h>
45# define OPTVAL_T(t) (const char*)(t)
46# define OPTVAL_GT(t) (char*)(t)
48# define CMSG_DATA WSA_CMSG_DATA
56#ifdef COAP_EPOLL_SUPPORT
58#include <sys/timerfd.h>
65#include <sys/select.h>
66#define OPTVAL_T(t) (const void*)(t)
67#define OPTVAL_GT(t) (void*)(t)
70#ifdef IPV6_RECVPKTINFO
71#define IPV6_PKTINFO IPV6_RECVPKTINFO
73#define IPV6_PKTINFO IP_PKTINFO
75#ifndef IN6_IS_ADDR_V4MAPPED
76#define IN6_IS_ADDR_V4MAPPED(a) \
77 ((((a)->s6_addr32[0]) == 0) && (((a)->s6_addr32[1]) == 0) && \
78 (((a)->s6_addr32[2]) == htonl(0xffff)))
84#if defined(IP_PKTINFO)
85# define GEN_IP_PKTINFO IP_PKTINFO
86#elif defined(IP_RECVDSTADDR)
87# define GEN_IP_PKTINFO IP_RECVDSTADDR
89# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
93#ifdef IPV6_RECVPKTINFO
94# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
95#elif defined(IPV6_PKTINFO)
96# define GEN_IPV6_PKTINFO IPV6_PKTINFO
98# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
101#if COAP_SERVER_SUPPORT
114 sock->
fd = socket(listen_addr->
addr.
sa.sa_family, SOCK_DGRAM, 0);
129 if (setsockopt(sock->
fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
sizeof(on)) ==
COAP_SOCKET_ERROR)
130 coap_log_warn(
"coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n",
133 switch (listen_addr->
addr.
sa.sa_family) {
136 if (setsockopt(sock->
fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on),
138 coap_log_alert(
"coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n",
145 if (setsockopt(sock->
fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
147 coap_log_alert(
"coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n",
149#if !defined(ESPIDF_VERSION)
150 if (setsockopt(sock->
fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on),
152 coap_log_alert(
"coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n",
156 setsockopt(sock->
fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on),
sizeof(on));
160#if COAP_AF_UNIX_SUPPORT
164#if COAP_AF_LLC_SUPPORT
173 if (bind(sock->
fd, &listen_addr->
addr.
sa,
175 listen_addr->
addr.
sa.sa_family == AF_INET ?
176 (socklen_t)
sizeof(
struct sockaddr_in) :
184 bound_addr->
size = (socklen_t)
sizeof(*bound_addr);
185 if (getsockname(sock->
fd, &bound_addr->
addr.
sa, &bound_addr->
size) < 0) {
198#if COAP_CLIENT_SUPPORT
218 sock->
fd = socket(connect_addr.
addr.
sa.sa_family, SOCK_DGRAM, 0);
234 int keep_errno = errno;
236 coap_log_warn(
"coap_socket_connect_udp: ioctl FIONBIO: %s (%d)\n",
241 switch (connect_addr.
addr.
sa.sa_family) {
244 if (connect_addr.
addr.
sin.sin_port == 0)
245 connect_addr.
addr.
sin.sin_port = htons(default_port);
250 if (connect_addr.
addr.
sin6.sin6_port == 0)
251 connect_addr.
addr.
sin6.sin6_port = htons(default_port);
253 if (setsockopt(sock->
fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
255 if (errno != ENOSYS) {
256 coap_log_warn(
"coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
261#if COAP_AF_UNIX_SUPPORT
265#if COAP_AF_LLC_SUPPORT
270 coap_log_alert(
"coap_socket_connect_udp: unsupported sa_family %d\n",
271 connect_addr.
addr.
sa.sa_family);
275 if (local_if && local_if->
addr.
sa.sa_family) {
276 if (local_if->
addr.
sa.sa_family != connect_addr.
addr.
sa.sa_family) {
277 coap_log_warn(
"coap_socket_connect_udp: local address family != "
278 "remote address family\n");
281 if (setsockopt(sock->
fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
sizeof(on)) ==
COAP_SOCKET_ERROR)
282 coap_log_warn(
"coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
284 if (bind(sock->
fd, &local_if->
addr.
sa,
286 local_if->
addr.
sa.sa_family == AF_INET ?
287 (socklen_t)
sizeof(
struct sockaddr_in) :
294#if COAP_AF_UNIX_SUPPORT
295 }
else if (connect_addr.
addr.
sa.sa_family == AF_UNIX) {
297 coap_log_warn(
"coap_socket_connect_udp: local address required\n");
304 if (!(local_if && local_if->
addr.
sa.sa_family)) {
309 bind_addr.
addr.
sa.sa_family = connect_addr.
addr.
sa.sa_family;
310 if (bind(sock->
fd, &bind_addr.
addr.
sa,
312 bind_addr.
addr.
sa.sa_family == AF_INET ?
313 (socklen_t)
sizeof(
struct sockaddr_in) :
322 coap_log_warn(
"coap_socket_connect_udp: getsockname for multicast socket: %s\n",
329 setsockopt(sock->
fd, SOL_SOCKET, SO_BROADCAST, OPTVAL_T(&on),
331 coap_log_warn(
"coap_socket_connect_udp: setsockopt SO_BROADCAST: %s\n",
336 switch (connect_addr.
addr.
sa.sa_family) {
337#if COAP_AF_LLC_SUPPORT
342#if COAP_AF_UNIX_SUPPORT
347#if COAP_AF_UNIX_SUPPORT
348 if (connect_addr.
addr.
sa.sa_family == AF_UNIX) {
372#if COAP_AF_LLC_SUPPORT
387#if !defined(__ZEPHYR__)
388#if 0 == ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
392#if !defined(__MINGW32__)
409#define SOL_IP IPPROTO_IP
412#define COAP_SOL_IP IPPROTO_IP
414#define COAP_SOL_IP SOL_IP
419#if defined(__MINGW32__)
420static __thread LPFN_WSARECVMSG lpWSARecvMsg =
NULL;
421#if(_WIN32_WINNT >= 0x0600)
422#define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
423#define CMSG_NXTHDR WSA_CMSG_NXTHDR
424#define CMSG_LEN WSA_CMSG_LEN
425#define CMSG_SPACE WSA_CMSG_SPACE
426#if(_WIN32_WINNT < 0x0603 || _WIN32_WINNT == 0x0a00)
427#define cmsghdr _WSACMSGHDR
431static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg =
NULL;
434#define msghdr _WSAMSG
436#define msg_namelen namelen
437#define msg_iov lpBuffers
438#define msg_iovlen dwBufferCount
439#define msg_control Control.buf
440#define msg_controllen Control.len
444#define iov_len_t u_long
446#define CMSG_DATA WSA_CMSG_DATA
447#define ipi_spec_dst ipi_addr
448#if !defined(__MINGW32__)
449#pragma warning( disable : 4116 )
452#define iov_len_t size_t
455#if defined(_CYGWIN_ENV) || defined(__QNXNTO__)
456#define ipi_spec_dst ipi_addr
459#if COAP_CLIENT_SUPPORT
460static uint32_t cid_track_counter;
465 session->negotiated_cid &&
468 if ((++cid_track_counter) % session->
context->testing_cids == 0) {
483#ifdef COAP_EPOLL_SUPPORT
505 const uint8_t *data,
size_t datalen) {
506 ssize_t bytes_written = 0;
509#if COAP_CLIENT_SUPPORT
510 coap_test_cid_tuple_change(session);
517 bytes_written = (ssize_t)datalen;
521 bytes_written = send(sock->
fd, (
const char *)data, (
int)datalen, 0);
523 bytes_written = send(sock->
fd, data, datalen, 0);
527 DWORD dwNumberOfBytesSent = 0;
529#ifdef HAVE_STRUCT_CMSGHDR
538 memcpy(&iov[0].iov_base, &data,
sizeof(iov[0].iov_base));
541 memset(buf, 0,
sizeof(buf));
543 memset(&mhdr, 0,
sizeof(
struct msghdr));
544 memcpy(&mhdr.msg_name, &addr,
sizeof(mhdr.msg_name));
546 (socklen_t)
sizeof(
struct sockaddr_in) :
557 struct cmsghdr *cmsg;
561#if defined(IP_PKTINFO)
563 mhdr.msg_control = buf;
564 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
566 cmsg = CMSG_FIRSTHDR(&mhdr);
568 cmsg->cmsg_type = IP_PKTINFO;
569 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
571 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
577#elif defined(IP_SENDSRCADDR)
578 mhdr.msg_control = buf;
579 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_addr));
581 cmsg = CMSG_FIRSTHDR(&mhdr);
582 cmsg->cmsg_level = IPPROTO_IP;
583 cmsg->cmsg_type = IP_SENDSRCADDR;
584 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_addr));
586 memcpy(CMSG_DATA(cmsg),
588 sizeof(
struct in_addr));
593 mhdr.msg_control = buf;
594 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
596 cmsg = CMSG_FIRSTHDR(&mhdr);
597 cmsg->cmsg_level = IPPROTO_IPV6;
598 cmsg->cmsg_type = IPV6_PKTINFO;
599 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
619#if defined(IP_PKTINFO)
620 struct cmsghdr *cmsg;
623 mhdr.msg_control = buf;
624 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
626 cmsg = CMSG_FIRSTHDR(&mhdr);
628 cmsg->cmsg_type = IP_PKTINFO;
629 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
631 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
637#elif defined(IP_SENDSRCADDR)
638 struct cmsghdr *cmsg;
639 mhdr.msg_control = buf;
640 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_addr));
642 cmsg = CMSG_FIRSTHDR(&mhdr);
643 cmsg->cmsg_level = IPPROTO_IP;
644 cmsg->cmsg_type = IP_SENDSRCADDR;
645 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_addr));
647 memcpy(CMSG_DATA(cmsg),
649 sizeof(
struct in_addr));
654#if COAP_AF_UNIX_SUPPORT
658#if COAP_AF_LLC_SUPPORT
671 r = WSASendMsg(sock->
fd, &mhdr, 0 , &dwNumberOfBytesSent,
NULL ,
674 bytes_written = (ssize_t)dwNumberOfBytesSent;
677 coap_win_error_to_errno();
680#ifdef HAVE_STRUCT_CMSGHDR
681 bytes_written = sendmsg(sock->
fd, &mhdr, 0);
683 bytes_written = sendto(sock->
fd, (
const void *)data, datalen, 0,
690 if (bytes_written < 0)
693 return bytes_written;
696#define SIN6(A) ((struct sockaddr_in6 *)(A))
715 sock->
flags &= ~COAP_SOCKET_CAN_READ;
726 coap_win_error_to_errno();
728 if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) {
736 if (errno != EAGAIN) {
743 }
else if (len > 0) {
744 packet->
length = (size_t)len;
748 DWORD dwNumberOfBytesRecvd = 0;
751#ifdef HAVE_STRUCT_CMSGHDR
754 struct cmsghdr *cmsg;
758#if defined(__MINGW32__)
759 iov[0].iov_base = (
char *) packet->
payload;
761 iov[0].iov_base = packet->
payload;
765 memset(&mhdr, 0,
sizeof(
struct msghdr));
773 mhdr.msg_control = buf;
774 mhdr.msg_controllen =
sizeof(buf);
777 cmsg = (
struct cmsghdr *)buf;
778 cmsg->cmsg_len = CMSG_LEN(
sizeof(buf));
779 cmsg->cmsg_level = -1;
780 cmsg->cmsg_type = -1;
784 GUID wsaid = WSAID_WSARECVMSG;
785 DWORD cbBytesReturned = 0;
786 if (WSAIoctl(sock->
fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid,
sizeof(wsaid), &lpWSARecvMsg,
787 sizeof(lpWSARecvMsg), &cbBytesReturned,
NULL,
NULL) != 0) {
792 r = lpWSARecvMsg(sock->
fd, &mhdr, &dwNumberOfBytesRecvd,
NULL ,
795 len = (ssize_t)dwNumberOfBytesRecvd;
797 coap_win_error_to_errno();
799 len = recvmsg(sock->
fd, &mhdr, 0);
810 coap_win_error_to_errno();
812 if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) {
820 if (errno != EAGAIN) {
825#ifdef HAVE_STRUCT_CMSGHDR
829 packet->
length = (size_t)len;
833 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
837 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
842 u.c = CMSG_DATA(cmsg);
843 packet->
ifindex = (int)(u.p->ipi6_ifindex);
845 &u.p->ipi6_addr,
sizeof(
struct in6_addr));
853#if defined(IP_PKTINFO)
854 if (cmsg->cmsg_level ==
COAP_SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
859 u.c = CMSG_DATA(cmsg);
860 packet->
ifindex = u.p->ipi_ifindex;
867 &u.p->ipi_addr,
sizeof(
struct in_addr));
872 &u.p->ipi_addr,
sizeof(
struct in_addr));
878#if defined(IP_RECVDSTADDR)
879 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
882 CMSG_DATA(cmsg),
sizeof(
struct in_addr));
891 if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) {
892 coap_log_debug(
"cmsg_level = %d and cmsg_type = %d not supported - fix\n",
893 cmsg->cmsg_level, cmsg->cmsg_type);
907 packet->
length = (size_t)len;
927#ifdef COAP_EPOLL_SUPPORT
928#if COAP_SERVER_SUPPORT
930 sock->endpoint ? sock->endpoint->context :
NULL;
934 if (context !=
NULL) {
936 struct epoll_event event;
939 ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->
fd, &event);
940 if (ret == -1 && errno != ENOENT) {
948#if COAP_SERVER_SUPPORT
949#if COAP_AF_UNIX_SUPPORT
950 if (sock->endpoint &&
951 sock->endpoint->bind_addr.addr.sa.sa_family == AF_UNIX) {
954 _unlink(sock->endpoint->bind_addr.addr.cun.sun_path);
956 unlink(sock->endpoint->bind_addr.addr.cun.sun_path);
960 sock->endpoint =
NULL;
962#if COAP_CLIENT_SUPPORT
963#if COAP_AF_UNIX_SUPPORT
988#pragma GCC diagnostic ignored "-Wunused-function"
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.
int coap_is_af_llc(const coap_address_t *a)
Checks if given address a denotes an AF_LLC address.
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_strerror(void)
#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...
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
#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_WANT_SENDTO
socket requires a destination address for sending
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
#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.
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_socket_dgrm_close(coap_socket_t *sock)
Function interface to close off a datagram socket.
#define coap_log_debug(...)
#define coap_log_alert(...)
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_warn(...)
#define coap_log_err(...)
@ COAP_SESSION_TYPE_CLIENT
client-side
@ COAP_SESSION_STATE_ESTABLISHED
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.
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
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_addr_tuple_t addr_info
remote/local address info
coap_proto_t proto
protocol used
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
int ifindex
interface index
char sun_path[COAP_UNIX_PATH_MAX]
coap_session_t * session
Used to determine session owner.
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