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
169 if (bind(sock->
fd, &listen_addr->
addr.
sa,
171 listen_addr->
addr.
sa.sa_family == AF_INET ?
172 (socklen_t)
sizeof(
struct sockaddr_in) :
180 bound_addr->
size = (socklen_t)
sizeof(*bound_addr);
181 if (getsockname(sock->
fd, &bound_addr->
addr.
sa, &bound_addr->
size) < 0) {
194#if COAP_CLIENT_SUPPORT
214 sock->
fd = socket(connect_addr.
addr.
sa.sa_family, SOCK_DGRAM, 0);
230 int keep_errno = errno;
232 coap_log_warn(
"coap_socket_connect_udp: ioctl FIONBIO: %s (%d)\n",
237 switch (connect_addr.
addr.
sa.sa_family) {
240 if (connect_addr.
addr.
sin.sin_port == 0)
241 connect_addr.
addr.
sin.sin_port = htons(default_port);
246 if (connect_addr.
addr.
sin6.sin6_port == 0)
247 connect_addr.
addr.
sin6.sin6_port = htons(default_port);
249 if (setsockopt(sock->
fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off),
251 if (errno != ENOSYS) {
252 coap_log_warn(
"coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
257#if COAP_AF_UNIX_SUPPORT
262 coap_log_alert(
"coap_socket_connect_udp: unsupported sa_family %d\n",
263 connect_addr.
addr.
sa.sa_family);
267 if (local_if && local_if->
addr.
sa.sa_family) {
268 if (local_if->
addr.
sa.sa_family != connect_addr.
addr.
sa.sa_family) {
269 coap_log_warn(
"coap_socket_connect_udp: local address family != "
270 "remote address family\n");
273 if (setsockopt(sock->
fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
sizeof(on)) ==
COAP_SOCKET_ERROR)
274 coap_log_warn(
"coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
276 if (bind(sock->
fd, &local_if->
addr.
sa,
278 local_if->
addr.
sa.sa_family == AF_INET ?
279 (socklen_t)
sizeof(
struct sockaddr_in) :
286#if COAP_AF_UNIX_SUPPORT
287 }
else if (connect_addr.
addr.
sa.sa_family == AF_UNIX) {
289 coap_log_warn(
"coap_socket_connect_udp: local address required\n");
296 if (!(local_if && local_if->
addr.
sa.sa_family)) {
301 bind_addr.
addr.
sa.sa_family = connect_addr.
addr.
sa.sa_family;
302 if (bind(sock->
fd, &bind_addr.
addr.
sa,
304 bind_addr.
addr.
sa.sa_family == AF_INET ?
305 (socklen_t)
sizeof(
struct sockaddr_in) :
314 coap_log_warn(
"coap_socket_connect_udp: getsockname for multicast socket: %s\n",
321 setsockopt(sock->
fd, SOL_SOCKET, SO_BROADCAST, OPTVAL_T(&on),
323 coap_log_warn(
"coap_socket_connect_udp: setsockopt SO_BROADCAST: %s\n",
329#if COAP_AF_UNIX_SUPPORT
330 if (connect_addr.
addr.
sa.sa_family == AF_UNIX) {
361#if !defined(__ZEPHYR__)
362#if 0 == ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
366#if !defined(__MINGW32__)
383#define SOL_IP IPPROTO_IP
386#define COAP_SOL_IP IPPROTO_IP
388#define COAP_SOL_IP SOL_IP
393#if defined(__MINGW32__)
394static __thread LPFN_WSARECVMSG lpWSARecvMsg = NULL;
395#if(_WIN32_WINNT >= 0x0600)
396#define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
397#define CMSG_NXTHDR WSA_CMSG_NXTHDR
398#define CMSG_LEN WSA_CMSG_LEN
399#define CMSG_SPACE WSA_CMSG_SPACE
400#if(_WIN32_WINNT < 0x0603 || _WIN32_WINNT == 0x0a00)
401#define cmsghdr _WSACMSGHDR
405static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL;
408#define msghdr _WSAMSG
410#define msg_namelen namelen
411#define msg_iov lpBuffers
412#define msg_iovlen dwBufferCount
413#define msg_control Control.buf
414#define msg_controllen Control.len
418#define iov_len_t u_long
420#define CMSG_DATA WSA_CMSG_DATA
421#define ipi_spec_dst ipi_addr
422#if !defined(__MINGW32__)
423#pragma warning( disable : 4116 )
426#define iov_len_t size_t
429#if defined(_CYGWIN_ENV) || defined(__QNXNTO__)
430#define ipi_spec_dst ipi_addr
433#if COAP_CLIENT_SUPPORT
434static uint32_t cid_track_counter;
457#ifdef COAP_EPOLL_SUPPORT
479 const uint8_t *data,
size_t datalen) {
480 ssize_t bytes_written = 0;
482#if COAP_CLIENT_SUPPORT
483 coap_test_cid_tuple_change(session);
487 bytes_written = (ssize_t)datalen;
490 bytes_written = send(sock->
fd, (
const char *)data, (
int)datalen, 0);
492 bytes_written = send(sock->
fd, data, datalen, 0);
496 DWORD dwNumberOfBytesSent = 0;
499#ifdef HAVE_STRUCT_CMSGHDR
508 memcpy(&iov[0].iov_base, &data,
sizeof(iov[0].iov_base));
511 memset(buf, 0,
sizeof(buf));
513 memset(&mhdr, 0,
sizeof(
struct msghdr));
514 memcpy(&mhdr.msg_name, &addr,
sizeof(mhdr.msg_name));
516 (socklen_t)
sizeof(
struct sockaddr_in) :
527 struct cmsghdr *cmsg;
531#if defined(IP_PKTINFO)
533 mhdr.msg_control = buf;
534 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
536 cmsg = CMSG_FIRSTHDR(&mhdr);
538 cmsg->cmsg_type = IP_PKTINFO;
539 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
541 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
547#elif defined(IP_SENDSRCADDR)
548 mhdr.msg_control = buf;
549 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_addr));
551 cmsg = CMSG_FIRSTHDR(&mhdr);
552 cmsg->cmsg_level = IPPROTO_IP;
553 cmsg->cmsg_type = IP_SENDSRCADDR;
554 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_addr));
556 memcpy(CMSG_DATA(cmsg),
558 sizeof(
struct in_addr));
563 mhdr.msg_control = buf;
564 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
566 cmsg = CMSG_FIRSTHDR(&mhdr);
567 cmsg->cmsg_level = IPPROTO_IPV6;
568 cmsg->cmsg_type = IPV6_PKTINFO;
569 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
589#if defined(IP_PKTINFO)
590 struct cmsghdr *cmsg;
593 mhdr.msg_control = buf;
594 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
596 cmsg = CMSG_FIRSTHDR(&mhdr);
598 cmsg->cmsg_type = IP_PKTINFO;
599 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
601 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
607#elif defined(IP_SENDSRCADDR)
608 struct cmsghdr *cmsg;
609 mhdr.msg_control = buf;
610 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_addr));
612 cmsg = CMSG_FIRSTHDR(&mhdr);
613 cmsg->cmsg_level = IPPROTO_IP;
614 cmsg->cmsg_type = IP_SENDSRCADDR;
615 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_addr));
617 memcpy(CMSG_DATA(cmsg),
619 sizeof(
struct in_addr));
624#if COAP_AF_UNIX_SUPPORT
637 r = WSASendMsg(sock->
fd, &mhdr, 0 , &dwNumberOfBytesSent, NULL ,
640 bytes_written = (ssize_t)dwNumberOfBytesSent;
643 coap_win_error_to_errno();
646#ifdef HAVE_STRUCT_CMSGHDR
647 bytes_written = sendmsg(sock->
fd, &mhdr, 0);
649 bytes_written = sendto(sock->
fd, (
const void *)data, datalen, 0,
656 if (bytes_written < 0)
659 return bytes_written;
662#define SIN6(A) ((struct sockaddr_in6 *)(A))
681 sock->
flags &= ~COAP_SOCKET_CAN_READ;
692 coap_win_error_to_errno();
694 if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) {
702 if (errno != EAGAIN) {
709 }
else if (len > 0) {
710 packet->
length = (size_t)len;
714 DWORD dwNumberOfBytesRecvd = 0;
717#ifdef HAVE_STRUCT_CMSGHDR
720 struct cmsghdr *cmsg;
724#if defined(__MINGW32__)
725 iov[0].iov_base = (
char *) packet->
payload;
727 iov[0].iov_base = packet->
payload;
731 memset(&mhdr, 0,
sizeof(
struct msghdr));
739 mhdr.msg_control = buf;
740 mhdr.msg_controllen =
sizeof(buf);
743 cmsg = (
struct cmsghdr *)buf;
744 cmsg->cmsg_len = CMSG_LEN(
sizeof(buf));
745 cmsg->cmsg_level = -1;
746 cmsg->cmsg_type = -1;
750 GUID wsaid = WSAID_WSARECVMSG;
751 DWORD cbBytesReturned = 0;
752 if (WSAIoctl(sock->
fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid,
sizeof(wsaid), &lpWSARecvMsg,
753 sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) {
758 r = lpWSARecvMsg(sock->
fd, &mhdr, &dwNumberOfBytesRecvd, NULL ,
761 len = (ssize_t)dwNumberOfBytesRecvd;
763 coap_win_error_to_errno();
765 len = recvmsg(sock->
fd, &mhdr, 0);
776 coap_win_error_to_errno();
778 if (errno == ECONNREFUSED || errno == EHOSTUNREACH || errno == ECONNRESET) {
786 if (errno != EAGAIN) {
791#ifdef HAVE_STRUCT_CMSGHDR
795 packet->
length = (size_t)len;
799 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
803 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
808 u.c = CMSG_DATA(cmsg);
809 packet->
ifindex = (int)(u.p->ipi6_ifindex);
811 &u.p->ipi6_addr,
sizeof(
struct in6_addr));
819#if defined(IP_PKTINFO)
820 if (cmsg->cmsg_level ==
COAP_SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
825 u.c = CMSG_DATA(cmsg);
826 packet->
ifindex = u.p->ipi_ifindex;
833 &u.p->ipi_addr,
sizeof(
struct in_addr));
838 &u.p->ipi_addr,
sizeof(
struct in_addr));
844#if defined(IP_RECVDSTADDR)
845 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
848 CMSG_DATA(cmsg),
sizeof(
struct in_addr));
857 if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) {
858 coap_log_debug(
"cmsg_level = %d and cmsg_type = %d not supported - fix\n",
859 cmsg->cmsg_level, cmsg->cmsg_type);
873 packet->
length = (size_t)len;
893#ifdef COAP_EPOLL_SUPPORT
894#if COAP_SERVER_SUPPORT
900 if (context != NULL) {
902 struct epoll_event event;
905 ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->
fd, &event);
906 if (ret == -1 && errno != ENOENT) {
914#if COAP_SERVER_SUPPORT
915#if COAP_AF_UNIX_SUPPORT
928#if COAP_CLIENT_SUPPORT
929#if COAP_AF_UNIX_SUPPORT
954#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.
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_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.
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)
Create a new UDP socket and 'connect' it to the address tuple.
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.
int coap_socket_bind_udp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Create a new UDP socket and then listen for new incoming UDP sessions to the specified IP address and...
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(...)
#define coap_log_crit(...)
@ 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.
uint8_t testing_cids
Change client's source port every testing_cids.
coap_context_t * context
endpoint's context
coap_address_t bind_addr
local interface address
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
uint8_t negotiated_cid
Set for a client if CID negotiated.
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_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