1 /* coap_io.c -- Default network I/O functions for libcoap
2  *
3  * Copyright (C) 2012,2014,2016-2019 Olaf Bergmann <bergmann@tzi.org> and others
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  *
7  * This file is part of the CoAP library libcoap. Please see
8  * README for terms of use.
9  */
10 
11 #include "coap3/coap_internal.h"
12 
13 #ifdef HAVE_STDIO_H
14 #  include <stdio.h>
15 #endif
16 
17 #ifdef HAVE_SYS_SELECT_H
18 # include <sys/select.h>
19 #endif
20 #ifdef HAVE_SYS_SOCKET_H
21 # include <sys/socket.h>
22 # define OPTVAL_T(t)         (t)
23 # define OPTVAL_GT(t)        (t)
24 #endif
25 #ifdef HAVE_SYS_IOCTL_H
26  #include <sys/ioctl.h>
27 #endif
28 #ifdef HAVE_NETINET_IN_H
29 # include <netinet/in.h>
30 #endif
31 #ifdef HAVE_WS2TCPIP_H
32 #include <ws2tcpip.h>
33 # define OPTVAL_T(t)         (const char*)(t)
34 # define OPTVAL_GT(t)        (char*)(t)
35 # undef CMSG_DATA
36 # define CMSG_DATA WSA_CMSG_DATA
37 #endif
38 #ifdef HAVE_SYS_UIO_H
39 # include <sys/uio.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #include <errno.h>
45 #ifdef COAP_EPOLL_SUPPORT
46 #include <sys/epoll.h>
47 #include <sys/timerfd.h>
48 #ifdef HAVE_LIMITS_H
49 #include <limits.h>
50 #endif
51 #endif /* COAP_EPOLL_SUPPORT */
52 
53 #ifdef WITH_CONTIKI
54 # include "uip.h"
55 #endif
56 
57 #if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
58  /* define generic PKTINFO for IPv4 */
59 #if defined(IP_PKTINFO)
60 #  define GEN_IP_PKTINFO IP_PKTINFO
61 #elif defined(IP_RECVDSTADDR)
62 #  define GEN_IP_PKTINFO IP_RECVDSTADDR
63 #else
64 #  error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
65 #endif /* IP_PKTINFO */
66 
67 /* define generic KTINFO for IPv6 */
68 #ifdef IPV6_RECVPKTINFO
69 #  define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
70 #elif defined(IPV6_PKTINFO)
71 #  define GEN_IPV6_PKTINFO IPV6_PKTINFO
72 #else
73 #  error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
74 #endif /* IPV6_RECVPKTINFO */
75 #endif /* !(WITH_CONTIKI || RIOT_VERSION) */
76 
77 #ifdef WITH_CONTIKI
78 static int ep_initialized = 0;
79 
80 coap_endpoint_t *
coap_malloc_endpoint()81   coap_malloc_endpoint() {
82   static coap_endpoint_t ep;
83 
84   if (ep_initialized) {
85     return NULL;
86   } else {
87     ep_initialized = 1;
88     return &ep;
89   }
90 }
91 
92 void
coap_mfree_endpoint(coap_endpoint_t * ep)93 coap_mfree_endpoint(coap_endpoint_t *ep) {
94   ep_initialized = 0;
95 }
96 
97 int
coap_socket_bind_udp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)98 coap_socket_bind_udp(coap_socket_t *sock,
99   const coap_address_t *listen_addr,
100   coap_address_t *bound_addr) {
101   sock->conn = udp_new(NULL, 0, NULL);
102 
103   if (!sock->conn) {
104     coap_log(LOG_WARNING, "coap_socket_bind_udp");
105     return 0;
106   }
107 
108   coap_address_init(bound_addr);
109   uip_ipaddr_copy(&bound_addr->addr, &listen_addr->addr);
110   bound_addr->port = listen_addr->port;
111   udp_bind((struct uip_udp_conn *)sock->conn, bound_addr->port);
112   return 1;
113 }
114 
115 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)116 coap_socket_connect_udp(coap_socket_t *sock,
117   const coap_address_t *local_if,
118   const coap_address_t *server,
119   int default_port,
120   coap_address_t *local_addr,
121   coap_address_t *remote_addr) {
122   return 0;
123 }
124 
125 ssize_t
coap_socket_write(coap_socket_t * sock,const uint8_t * data,size_t data_len)126 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
127   return -1;
128 }
129 
130 ssize_t
coap_socket_read(coap_socket_t * sock,uint8_t * data,size_t data_len)131 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
132   return -1;
133 }
134 
coap_socket_close(coap_socket_t * sock)135 void coap_socket_close(coap_socket_t *sock) {
136   if (sock->conn)
137     uip_udp_remove((struct uip_udp_conn *)sock->conn);
138   sock->flags = COAP_SOCKET_EMPTY;
139 }
140 
141 #else
142 
143 coap_endpoint_t *
coap_malloc_endpoint(void)144   coap_malloc_endpoint(void) {
145   return (coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(coap_endpoint_t));
146 }
147 
148 void
coap_mfree_endpoint(coap_endpoint_t * ep)149 coap_mfree_endpoint(coap_endpoint_t *ep) {
150   coap_free_type(COAP_ENDPOINT, ep);
151 }
152 
153 int
coap_socket_bind_udp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)154 coap_socket_bind_udp(coap_socket_t *sock,
155   const coap_address_t *listen_addr,
156   coap_address_t *bound_addr) {
157 #ifndef RIOT_VERSION
158   int on = 1, off = 0;
159 #endif /* RIOT_VERSION */
160 #ifdef _WIN32
161   u_long u_on = 1;
162 #endif
163 
164   sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0);
165 
166   if (sock->fd == COAP_INVALID_SOCKET) {
167     coap_log(LOG_WARNING,
168              "coap_socket_bind_udp: socket: %s\n", coap_socket_strerror());
169     goto error;
170   }
171 #ifndef RIOT_VERSION
172 #ifdef _WIN32
173   if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
174 #else
175   if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
176 #endif
177     coap_log(LOG_WARNING,
178          "coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror());
179   }
180 
181 #ifndef RIOT_VERSION
182   if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
183     coap_log(LOG_WARNING,
184              "coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n",
185               coap_socket_strerror());
186 #endif /* RIOT_VERSION */
187 
188   switch (listen_addr->addr.sa.sa_family) {
189   case AF_INET:
190     if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
191       coap_log(LOG_ALERT,
192                "coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n",
193                 coap_socket_strerror());
194     break;
195   case AF_INET6:
196     /* Configure the socket as dual-stacked */
197     if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
198       coap_log(LOG_ALERT,
199                "coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n",
200                 coap_socket_strerror());
201 #if !defined(ESPIDF_VERSION)
202     if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
203       coap_log(LOG_ALERT,
204                "coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n",
205                 coap_socket_strerror());
206 #endif /* !defined(ESPIDF_VERSION) */
207     setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on));
208     /* ignore error, because likely cause is that IPv4 is disabled at the os
209        level */
210     break;
211   default:
212     coap_log(LOG_ALERT, "coap_socket_bind_udp: unsupported sa_family\n");
213     break;
214   }
215 #endif /* RIOT_VERSION */
216 
217   if (bind(sock->fd, &listen_addr->addr.sa,
218            listen_addr->addr.sa.sa_family == AF_INET ?
219             (socklen_t)sizeof(struct sockaddr_in) :
220             (socklen_t)listen_addr->size) == COAP_SOCKET_ERROR) {
221     coap_log(LOG_WARNING, "coap_socket_bind_udp: bind: %s\n",
222              coap_socket_strerror());
223     goto error;
224   }
225 
226   bound_addr->size = (socklen_t)sizeof(*bound_addr);
227   if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
228     coap_log(LOG_WARNING,
229              "coap_socket_bind_udp: getsockname: %s\n",
230               coap_socket_strerror());
231     goto error;
232   }
233 
234   return 1;
235 
236 error:
237   coap_socket_close(sock);
238   return 0;
239 }
240 
241 int
242 coap_socket_connect_udp(coap_socket_t *sock,
243   const coap_address_t *local_if,
244   const coap_address_t *server,
245   int default_port,
246   coap_address_t *local_addr,
247   coap_address_t *remote_addr) {
248 #ifndef RIOT_VERSION
249   int on = 1;
250   int off = 0;
251 #endif /* RIOT_VERSION */
252 #ifdef _WIN32
253   u_long u_on = 1;
254 #endif
255   coap_address_t connect_addr;
256   int is_mcast = coap_is_mcast(server);
257   coap_address_copy(&connect_addr, server);
258 
259   sock->flags &= ~(COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST);
260   sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0);
261 
262   if (sock->fd == COAP_INVALID_SOCKET) {
263     coap_log(LOG_WARNING, "coap_socket_connect_udp: socket: %s\n",
264              coap_socket_strerror());
265     goto error;
266   }
267 
268 #ifndef RIOT_VERSION
269 #ifdef _WIN32
270   if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
271 #else
272   if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
273 #endif
274     coap_log(LOG_WARNING, "coap_socket_connect_udp: ioctl FIONBIO: %s\n",
275              coap_socket_strerror());
276   }
277 #endif /* RIOT_VERSION */
278 
279   switch (connect_addr.addr.sa.sa_family) {
280   case AF_INET:
281     if (connect_addr.addr.sin.sin_port == 0)
282       connect_addr.addr.sin.sin_port = htons(default_port);
283     break;
284   case AF_INET6:
285     if (connect_addr.addr.sin6.sin6_port == 0)
286       connect_addr.addr.sin6.sin6_port = htons(default_port);
287 #ifndef RIOT_VERSION
288     /* Configure the socket as dual-stacked */
289     if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
290       coap_log(LOG_WARNING,
291                "coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
292                coap_socket_strerror());
293 #endif /* RIOT_VERSION */
294     break;
295   default:
296     coap_log(LOG_ALERT, "coap_socket_connect_udp: unsupported sa_family\n");
297     break;
298   }
299 
300   if (local_if && local_if->addr.sa.sa_family) {
301 #ifndef RIOT_VERSION
302     if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
303       coap_log(LOG_WARNING,
304                "coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
305                coap_socket_strerror());
306 #endif /* RIOT_VERSION */
307     if (bind(sock->fd, &local_if->addr.sa,
308              local_if->addr.sa.sa_family == AF_INET ?
309               (socklen_t)sizeof(struct sockaddr_in) :
310               (socklen_t)local_if->size) == COAP_SOCKET_ERROR) {
311       coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n",
312                coap_socket_strerror());
313       goto error;
314     }
315   }
316 
317   /* special treatment for sockets that are used for multicast communication */
318   if (is_mcast) {
319     if (!(local_if && local_if->addr.sa.sa_family)) {
320       /* Bind to a (unused) port to simplify logging */
321       coap_address_t bind_addr;
322 
323       coap_address_init(&bind_addr);
324       bind_addr.addr.sa.sa_family = connect_addr.addr.sa.sa_family;
325       if (bind(sock->fd, &bind_addr.addr.sa,
326                bind_addr.addr.sa.sa_family == AF_INET ?
327                 (socklen_t)sizeof(struct sockaddr_in) :
328                 (socklen_t)bind_addr.size) == COAP_SOCKET_ERROR) {
329         coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n",
330                  coap_socket_strerror());
331         goto error;
332       }
333     }
334     if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
335       coap_log(LOG_WARNING,
336               "coap_socket_connect_udp: getsockname for multicast socket: %s\n",
337               coap_socket_strerror());
338     }
339     coap_address_copy(remote_addr, &connect_addr);
340     sock->flags |= COAP_SOCKET_MULTICAST;
341     return 1;
342   }
343 
344   if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
345     coap_log(LOG_WARNING, "coap_socket_connect_udp: connect: %s\n",
346              coap_socket_strerror());
347     goto error;
348   }
349 
350   if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
351     coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname: %s\n",
352              coap_socket_strerror());
353   }
354 
355   if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
356     coap_log(LOG_WARNING, "coap_socket_connect_udp: getpeername: %s\n",
357              coap_socket_strerror());
358   }
359 
360   sock->flags |= COAP_SOCKET_CONNECTED;
361   return 1;
362 
363 error:
364   coap_socket_close(sock);
365   return 0;
366 }
367 
368 void coap_socket_close(coap_socket_t *sock) {
369   if (sock->fd != COAP_INVALID_SOCKET) {
370 #ifdef COAP_EPOLL_SUPPORT
371     coap_context_t *context = sock->session ? sock->session->context :
372                               sock->endpoint ? sock->endpoint->context : NULL;
373     if (context != NULL) {
374       int ret;
375       struct epoll_event event;
376 
377       /* Kernels prior to 2.6.9 expect non NULL event parameter */
378       ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->fd, &event);
379       if (ret == -1) {
380          coap_log(LOG_ERR,
381                   "%s: epoll_ctl DEL failed: %s (%d)\n",
382                   "coap_socket_close",
383                   coap_socket_strerror(), errno);
384       }
385     }
386     sock->endpoint = NULL;
387     sock->session = NULL;
388 #endif /* COAP_EPOLL_SUPPORT */
389     coap_closesocket(sock->fd);
390     sock->fd = COAP_INVALID_SOCKET;
391   }
392   sock->flags = COAP_SOCKET_EMPTY;
393 }
394 
395 #ifdef COAP_EPOLL_SUPPORT
396 void
397 coap_epoll_ctl_mod(coap_socket_t *sock,
398                    uint32_t events,
399                    const char *func
400 ) {
401   int ret;
402   struct epoll_event event;
403   coap_context_t *context;
404 
405   if (sock == NULL)
406     return;
407 
408   context = sock->session ? sock->session->context :
409                             sock->endpoint ? sock->endpoint->context : NULL;
410   if (context == NULL)
411     return;
412 
413   event.events = events;
414   event.data.ptr = sock;
415 
416   ret = epoll_ctl(context->epfd, EPOLL_CTL_MOD, sock->fd, &event);
417   if (ret == -1) {
418      coap_log(LOG_ERR,
419               "%s: epoll_ctl MOD failed: %s (%d)\n",
420               func,
421               coap_socket_strerror(), errno);
422   }
423 }
424 #endif /* COAP_EPOLL_SUPPORT */
425 
426 ssize_t
427 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
428   ssize_t r;
429 
430   sock->flags &= ~(COAP_SOCKET_WANT_WRITE | COAP_SOCKET_CAN_WRITE);
431 #ifdef _WIN32
432   r = send(sock->fd, (const char *)data, (int)data_len, 0);
433 #else
434   r = send(sock->fd, data, data_len, 0);
435 #endif
436   if (r == COAP_SOCKET_ERROR) {
437 #ifdef _WIN32
438     if (WSAGetLastError() == WSAEWOULDBLOCK) {
439 #elif EAGAIN != EWOULDBLOCK
440     if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
441 #else
442     if (errno==EAGAIN || errno == EINTR) {
443 #endif
444       sock->flags |= COAP_SOCKET_WANT_WRITE;
445 #ifdef COAP_EPOLL_SUPPORT
446       coap_epoll_ctl_mod(sock,
447                          EPOLLOUT |
448                           ((sock->flags & COAP_SOCKET_WANT_READ) ?
449                            EPOLLIN : 0),
450                          __func__);
451 #endif /* COAP_EPOLL_SUPPORT */
452       return 0;
453     }
454     if (errno == EPIPE || errno == ECONNRESET) {
455       coap_log(LOG_INFO, "coap_socket_write: send: %s\n",
456                coap_socket_strerror());
457     }
458     else {
459       coap_log(LOG_WARNING, "coap_socket_write: send: %s\n",
460                coap_socket_strerror());
461     }
462     return -1;
463   }
464   if (r < (ssize_t)data_len) {
465     sock->flags |= COAP_SOCKET_WANT_WRITE;
466 #ifdef COAP_EPOLL_SUPPORT
467       coap_epoll_ctl_mod(sock,
468                          EPOLLOUT |
469                           ((sock->flags & COAP_SOCKET_WANT_READ) ?
470                            EPOLLIN : 0),
471                          __func__);
472 #endif /* COAP_EPOLL_SUPPORT */
473   }
474   return r;
475 }
476 
477 ssize_t
478 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
479   ssize_t r;
480 #ifdef _WIN32
481   int error;
482 #endif
483 
484 #ifdef _WIN32
485   r = recv(sock->fd, (char *)data, (int)data_len, 0);
486 #else
487   r = recv(sock->fd, data, data_len, 0);
488 #endif
489   if (r == 0) {
490     /* graceful shutdown */
491     sock->flags &= ~COAP_SOCKET_CAN_READ;
492     return -1;
493   } else if (r == COAP_SOCKET_ERROR) {
494     sock->flags &= ~COAP_SOCKET_CAN_READ;
495 #ifdef _WIN32
496     error = WSAGetLastError();
497     if (error == WSAEWOULDBLOCK) {
498 #elif EAGAIN != EWOULDBLOCK
499     if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
500 #else
501     if (errno==EAGAIN || errno == EINTR) {
502 #endif
503       return 0;
504     }
505 #ifdef _WIN32
506     if (error != WSAECONNRESET)
507 #else
508     if (errno != ECONNRESET)
509 #endif
510       coap_log(LOG_WARNING, "coap_socket_read: recv: %s\n",
511                coap_socket_strerror());
512     return -1;
513   }
514   if (r < (ssize_t)data_len)
515     sock->flags &= ~COAP_SOCKET_CAN_READ;
516   return r;
517 }
518 
519 #endif  /* WITH_CONTIKI */
520 
521 #if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
522 /* define struct in6_pktinfo and struct in_pktinfo if not available
523    FIXME: check with configure
524 */
525 struct in6_pktinfo {
526   struct in6_addr ipi6_addr;        /* src/dst IPv6 address */
527   unsigned int ipi6_ifindex;        /* send/recv interface index */
528 };
529 
530 struct in_pktinfo {
531   int ipi_ifindex;
532   struct in_addr ipi_spec_dst;
533   struct in_addr ipi_addr;
534 };
535 #endif
536 
537 #if !defined(WITH_CONTIKI) && !defined(SOL_IP)
538 /* Solaris expects level IPPROTO_IP for ancillary data. */
539 #define SOL_IP IPPROTO_IP
540 #endif
541 
542 #if defined(_WIN32)
543 #include <mswsock.h>
544 static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL;
545 /* Map struct WSABUF fields to their posix counterpart */
546 #define msghdr _WSAMSG
547 #define msg_name name
548 #define msg_namelen namelen
549 #define msg_iov lpBuffers
550 #define msg_iovlen dwBufferCount
551 #define msg_control Control.buf
552 #define msg_controllen Control.len
553 #define iovec _WSABUF
554 #define iov_base buf
555 #define iov_len len
556 #define iov_len_t u_long
557 #undef CMSG_DATA
558 #define CMSG_DATA WSA_CMSG_DATA
559 #define ipi_spec_dst ipi_addr
560 #pragma warning( disable : 4116 )
561 #else
562 #define iov_len_t size_t
563 #endif
564 
565 #if defined(_CYGWIN_ENV)
566 #define ipi_spec_dst ipi_addr
567 #endif
568 
569 #ifndef RIOT_VERSION
570 ssize_t
571 coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen) {
572   ssize_t bytes_written = 0;
573 
574   if (!coap_debug_send_packet()) {
575     bytes_written = (ssize_t)datalen;
576 #ifndef WITH_CONTIKI
577   } else if (sock->flags & COAP_SOCKET_CONNECTED) {
578 #ifdef _WIN32
579     bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0);
580 #else
581     bytes_written = send(sock->fd, data, datalen, 0);
582 #endif
583 #endif
584   } else {
585 #ifdef _WIN32
586     DWORD dwNumberOfBytesSent = 0;
587     int r;
588 #endif
589 #ifdef HAVE_STRUCT_CMSGHDR
590     /* a buffer large enough to hold all packet info types, ipv6 is the largest */
591     char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
592     struct msghdr mhdr;
593     struct iovec iov[1];
594     const void *addr = &session->addr_info.remote.addr;
595 
596     assert(session);
597 
598     memcpy (&iov[0].iov_base, &data, sizeof (iov[0].iov_base));
599     iov[0].iov_len = (iov_len_t)datalen;
600 
601     memset(buf, 0, sizeof (buf));
602 
603     memset(&mhdr, 0, sizeof(struct msghdr));
604     memcpy (&mhdr.msg_name, &addr, sizeof (mhdr.msg_name));
605     mhdr.msg_namelen = session->addr_info.remote.size;
606 
607     mhdr.msg_iov = iov;
608     mhdr.msg_iovlen = 1;
609 
610     if (!coap_address_isany(&session->addr_info.local) &&
611         !coap_is_mcast(&session->addr_info.local))
612     switch (session->addr_info.local.addr.sa.sa_family) {
613     case AF_INET6:
614     {
615       struct cmsghdr *cmsg;
616 
617       if (IN6_IS_ADDR_V4MAPPED(&session->addr_info.local.addr.sin6.sin6_addr)) {
618 #if defined(IP_PKTINFO)
619         struct in_pktinfo *pktinfo;
620         mhdr.msg_control = buf;
621         mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
622 
623         cmsg = CMSG_FIRSTHDR(&mhdr);
624         cmsg->cmsg_level = SOL_IP;
625         cmsg->cmsg_type = IP_PKTINFO;
626         cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
627 
628         pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
629 
630         pktinfo->ipi_ifindex = session->ifindex;
631         memcpy(&pktinfo->ipi_spec_dst,
632                session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12,
633                sizeof(pktinfo->ipi_spec_dst));
634 #elif defined(IP_SENDSRCADDR)
635         mhdr.msg_control = buf;
636         mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
637 
638         cmsg = CMSG_FIRSTHDR(&mhdr);
639         cmsg->cmsg_level = IPPROTO_IP;
640         cmsg->cmsg_type = IP_SENDSRCADDR;
641         cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
642 
643         memcpy(CMSG_DATA(cmsg),
644                session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12,
645                sizeof(struct in_addr));
646 #endif /* IP_PKTINFO */
647       } else {
648         struct in6_pktinfo *pktinfo;
649         mhdr.msg_control = buf;
650         mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
651 
652         cmsg = CMSG_FIRSTHDR(&mhdr);
653         cmsg->cmsg_level = IPPROTO_IPV6;
654         cmsg->cmsg_type = IPV6_PKTINFO;
655         cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
656 
657         pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
658 
659         pktinfo->ipi6_ifindex = session->ifindex;
660         memcpy(&pktinfo->ipi6_addr,
661                &session->addr_info.local.addr.sin6.sin6_addr,
662                sizeof(pktinfo->ipi6_addr));
663       }
664       break;
665     }
666     case AF_INET:
667     {
668 #if defined(IP_PKTINFO)
669       struct cmsghdr *cmsg;
670       struct in_pktinfo *pktinfo;
671 
672       mhdr.msg_control = buf;
673       mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
674 
675       cmsg = CMSG_FIRSTHDR(&mhdr);
676       cmsg->cmsg_level = SOL_IP;
677       cmsg->cmsg_type = IP_PKTINFO;
678       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
679 
680       pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
681 
682       pktinfo->ipi_ifindex = session->ifindex;
683       memcpy(&pktinfo->ipi_spec_dst,
684              &session->addr_info.local.addr.sin.sin_addr,
685              sizeof(pktinfo->ipi_spec_dst));
686 #elif defined(IP_SENDSRCADDR)
687       struct cmsghdr *cmsg;
688       mhdr.msg_control = buf;
689       mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
690 
691       cmsg = CMSG_FIRSTHDR(&mhdr);
692       cmsg->cmsg_level = IPPROTO_IP;
693       cmsg->cmsg_type = IP_SENDSRCADDR;
694       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
695 
696       memcpy(CMSG_DATA(cmsg),
697              &session->addr_info.local.addr.sin.sin_addr,
698              sizeof(struct in_addr));
699 #endif /* IP_PKTINFO */
700       break;
701     }
702     default:
703       /* error */
704       coap_log(LOG_WARNING, "protocol not supported\n");
705       bytes_written = -1;
706     }
707 #endif /* HAVE_STRUCT_CMSGHDR */
708 
709 #ifdef _WIN32
710     r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, NULL /*lpCompletionRoutine*/);
711     if (r == 0)
712       bytes_written = (ssize_t)dwNumberOfBytesSent;
713     else
714       bytes_written = -1;
715 #else
716 #ifdef HAVE_STRUCT_CMSGHDR
717     bytes_written = sendmsg(sock->fd, &mhdr, 0);
718 #elif !defined(CONTIKI) /* ! HAVE_STRUCT_CMSGHDR */
719     bytes_written = sendto(sock->fd, data, datalen, 0,
720                            &session->addr_info.remote.addr.sa,
721                            session->addr_info.remote.size);
722 #endif /* ! HAVE_STRUCT_CMSGHDR */
723 #endif
724 #if defined(WITH_CONTIKI)
725     /* FIXME: untested */
726     /* FIXME: is there a way to check if send was successful? */
727     (void)datalen;
728     (void)data;
729     uip_udp_packet_sendto((struct uip_udp_conn *)sock->conn, data, datalen,
730       &session->addr_info.remote.addr, session->addr_info.remote.port);
731     bytes_written = datalen;
732 #endif /* WITH_CONTIKI */
733   }
734 
735   if (bytes_written < 0)
736     coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror());
737 
738   return bytes_written;
739 }
740 #endif /* RIOT_VERSION */
741 
742 #define SIN6(A) ((struct sockaddr_in6 *)(A))
743 
744 void
745 coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) {
746   *address = packet->payload;
747   *length = packet->length;
748 }
749 
750 #ifndef RIOT_VERSION
751 ssize_t
752 coap_network_read(coap_socket_t *sock, coap_packet_t *packet) {
753   ssize_t len = -1;
754 
755   assert(sock);
756   assert(packet);
757 
758   if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) {
759     return -1;
760   } else {
761     /* clear has-data flag */
762     sock->flags &= ~COAP_SOCKET_CAN_READ;
763   }
764 
765 #if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
766   if (sock->flags & COAP_SOCKET_CONNECTED) {
767 #ifdef _WIN32
768     len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0);
769 #else
770     len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0);
771 #endif
772     if (len < 0) {
773 #ifdef _WIN32
774       if (WSAGetLastError() == WSAECONNRESET) {
775 #else
776       if (errno == ECONNREFUSED) {
777 #endif
778         /* client-side ICMP destination unreachable, ignore it */
779         coap_log(LOG_WARNING, "coap_network_read: unreachable\n");
780         return -2;
781       }
782       coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
783       goto error;
784     } else if (len > 0) {
785       packet->length = (size_t)len;
786     }
787   } else {
788 #endif /* !(WITH_CONTIKI || RIOT_VERSION) */
789 #if defined(_WIN32)
790     DWORD dwNumberOfBytesRecvd = 0;
791     int r;
792 #endif
793 #if !defined(WITH_CONTIKI)
794 #ifdef HAVE_STRUCT_CMSGHDR
795     /* a buffer large enough to hold all packet info types, ipv6 is the largest */
796     char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
797     struct cmsghdr *cmsg;
798     struct msghdr mhdr;
799     struct iovec iov[1];
800 
801     iov[0].iov_base = packet->payload;
802     iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE;
803 
804     memset(&mhdr, 0, sizeof(struct msghdr));
805 
806     mhdr.msg_name = (struct sockaddr*)&packet->addr_info.remote.addr;
807     mhdr.msg_namelen = sizeof(packet->addr_info.remote.addr);
808 
809     mhdr.msg_iov = iov;
810     mhdr.msg_iovlen = 1;
811 
812     mhdr.msg_control = buf;
813     mhdr.msg_controllen = sizeof(buf);
814     /* set a big first length incase recvmsg() does not implement updating
815        msg_control as well as preset the first cmsg with bad data */
816     cmsg = (struct cmsghdr *)buf;
817     cmsg->cmsg_len = CMSG_LEN(sizeof(buf));
818     cmsg->cmsg_level = -1;
819     cmsg->cmsg_type = -1;
820 
821 #if defined(_WIN32)
822     if (!lpWSARecvMsg) {
823       GUID wsaid = WSAID_WSARECVMSG;
824       DWORD cbBytesReturned = 0;
825       if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) {
826         coap_log(LOG_WARNING, "coap_network_read: no WSARecvMsg\n");
827         return -1;
828       }
829     }
830     r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */);
831     if (r == 0)
832       len = (ssize_t)dwNumberOfBytesRecvd;
833 #else
834     len = recvmsg(sock->fd, &mhdr, 0);
835 #endif
836 
837 #else /* ! HAVE_STRUCT_CMSGHDR */
838     len = recvfrom(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0,
839                    &packet->addr_info.remote.addr.sa,
840                    &packet->addr_info.remote.size);
841 #endif /* ! HAVE_STRUCT_CMSGHDR */
842 
843     if (len < 0) {
844 #ifdef _WIN32
845       if (WSAGetLastError() == WSAECONNRESET) {
846 #else
847       if (errno == ECONNREFUSED) {
848 #endif
849         /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */
850         return 0;
851       }
852       coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
853       goto error;
854     } else {
855 #ifdef HAVE_STRUCT_CMSGHDR
856       int dst_found = 0;
857 
858       packet->addr_info.remote.size = mhdr.msg_namelen;
859       packet->length = (size_t)len;
860 
861       /* Walk through ancillary data records until the local interface
862        * is found where the data was received. */
863       for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
864 
865         /* get the local interface for IPv6 */
866         if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
867           union {
868             uint8_t *c;
869             struct in6_pktinfo *p;
870           } u;
871           u.c = CMSG_DATA(cmsg);
872           packet->ifindex = (int)(u.p->ipi6_ifindex);
873           memcpy(&packet->addr_info.local.addr.sin6.sin6_addr,
874                  &u.p->ipi6_addr, sizeof(struct in6_addr));
875           dst_found = 1;
876           break;
877         }
878 
879         /* local interface for IPv4 */
880 #if defined(IP_PKTINFO)
881         if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
882           union {
883             uint8_t *c;
884             struct in_pktinfo *p;
885           } u;
886           u.c = CMSG_DATA(cmsg);
887           packet->ifindex = u.p->ipi_ifindex;
888           if (packet->addr_info.local.addr.sa.sa_family == AF_INET6) {
889             memset(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr, 0, 10);
890             packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[10] = 0xff;
891             packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[11] = 0xff;
892             memcpy(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12,
893                    &u.p->ipi_addr, sizeof(struct in_addr));
894           } else {
895             memcpy(&packet->addr_info.local.addr.sin.sin_addr,
896                    &u.p->ipi_addr, sizeof(struct in_addr));
897           }
898           dst_found = 1;
899           break;
900         }
901 #elif defined(IP_RECVDSTADDR)
902         if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
903           packet->ifindex = sock->fd;
904           memcpy(&packet->addr_info.local.addr.sin.sin_addr,
905                  CMSG_DATA(cmsg), sizeof(struct in_addr));
906           dst_found = 1;
907           break;
908         }
909 #endif /* IP_PKTINFO */
910         if (!dst_found) {
911           /* cmsg_level / cmsg_type combination we do not understand
912              (ignore preset case for bad recvmsg() not updating cmsg) */
913           if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) {
914             coap_log(LOG_DEBUG,
915                      "cmsg_level = %d and cmsg_type = %d not supported - fix\n",
916                      cmsg->cmsg_level, cmsg->cmsg_type);
917           }
918         }
919       }
920       if (!dst_found) {
921         /* Not expected, but cmsg_level and cmsg_type don't match above and
922            may need a new case */
923         packet->ifindex = (int)sock->fd;
924         if (getsockname(sock->fd, &packet->addr_info.local.addr.sa,
925             &packet->addr_info.local.size) < 0) {
926           coap_log(LOG_DEBUG, "Cannot determine local port\n");
927         }
928       }
929 #else /* ! HAVE_STRUCT_CMSGHDR */
930       packet->length = (size_t)len;
931       packet->ifindex = 0;
932       if (getsockname(sock->fd, &packet->addr_info.local.addr.sa,
933                       &packet->addr_info.local.size) < 0) {
934          coap_log(LOG_DEBUG, "Cannot determine local port\n");
935          goto error;
936       }
937 #endif /* ! HAVE_STRUCT_CMSGHDR */
938     }
939 #endif /* !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) */
940 #ifdef WITH_CONTIKI
941     /* FIXME: untested, make this work */
942 #define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
943 #define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
944 
945     if (uip_newdata()) {
946       uip_ipaddr_copy(&packet->addr_info.remote.addr, &UIP_IP_BUF->srcipaddr);
947       packet->addr_info.remote.port = UIP_UDP_BUF->srcport;
948       uip_ipaddr_copy(&(packet)->addr_info.local.addr, &UIP_IP_BUF->destipaddr);
949       packet->addr_info.local.port = UIP_UDP_BUF->destport;
950 
951       len = uip_datalen();
952 
953       if (len > COAP_RXBUFFER_SIZE) {
954         /* FIXME: we might want to send back a response */
955         coap_log(LOG_WARNING, "discarded oversized packet\n");
956         return -1;
957       }
958 
959       ((char *)uip_appdata)[len] = 0;
960       if (LOG_DEBUG <= coap_get_log_level()) {
961 #ifndef INET6_ADDRSTRLEN
962 #define INET6_ADDRSTRLEN 40
963 #endif
964         unsigned char addr_str[INET6_ADDRSTRLEN + 8];
965 
966         if (coap_print_addr(&packet->addr_info.remote, addr_str,
967                             INET6_ADDRSTRLEN + 8)) {
968           coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str);
969         }
970       }
971 
972       packet->length = len;
973       memcpy(&packet->payload, uip_appdata, len);
974     }
975 
976 #undef UIP_IP_BUF
977 #undef UIP_UDP_BUF
978 #endif /* WITH_CONTIKI */
979 #ifdef RIOT_VERSION
980     packet->src.size = sizeof(packet->src.addr);
981     len = recvfrom (sock->fd, packet->payload, COAP_RXBUFFER_SIZE,
982                     0, &packet->src.addr.sa, &packet->src.size);
983     if (LOG_DEBUG <= coap_get_log_level()) {
984       unsigned char addr_str[INET6_ADDRSTRLEN + 8];
985 
986       if (coap_print_addr(&packet->src, addr_str, INET6_ADDRSTRLEN + 8)) {
987         coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str);
988       }
989     }
990 #endif /* RIOT_VERSION */
991 #if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
992   }
993 #endif /* !(WITH_CONTIKI || RIOT_VERSION) */
994 
995   if (len >= 0)
996     return len;
997 #if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
998 error:
999 #endif
1000   return -1;
1001 }
1002 #endif /* RIOT_VERSION */
1003 
1004 #if !defined(WITH_CONTIKI)
1005 
1006 unsigned int
1007 coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) {
1008 #ifndef COAP_EPOLL_SUPPORT
1009   (void)ctx;
1010   (void)now;
1011    coap_log(LOG_EMERG,
1012             "coap_io_prepare_epoll() requires libcoap compiled for using epoll\n");
1013   return 0;
1014 #else /* COAP_EPOLL_SUPPORT */
1015   coap_socket_t *sockets[1];
1016   unsigned int max_sockets = sizeof(sockets)/sizeof(sockets[0]);
1017   unsigned int num_sockets;
1018   unsigned int timeout;
1019 
1020   /* Use the common logic */
1021   timeout = coap_io_prepare_io(ctx, sockets, max_sockets, &num_sockets, now);
1022   /* Save when the next expected I/O is to take place */
1023   ctx->next_timeout = timeout ? now + timeout : 0;
1024   if (ctx->eptimerfd != -1) {
1025     struct itimerspec new_value;
1026     int ret;
1027 
1028     memset(&new_value, 0, sizeof(new_value));
1029     coap_ticks(&now);
1030     if (ctx->next_timeout != 0 && ctx->next_timeout > now) {
1031       coap_tick_t rem_timeout = ctx->next_timeout - now;
1032       /* Need to trigger an event on ctx->epfd in the future */
1033       new_value.it_value.tv_sec = rem_timeout / COAP_TICKS_PER_SECOND;
1034       new_value.it_value.tv_nsec = (rem_timeout % COAP_TICKS_PER_SECOND) *
1035                                    1000000;
1036     }
1037 #ifdef COAP_DEBUG_WAKEUP_TIMES
1038     coap_log(LOG_INFO, "****** Next wakeup time %ld.%09ld\n",
1039              new_value.it_value.tv_sec, new_value.it_value.tv_nsec);
1040 #endif /* COAP_DEBUG_WAKEUP_TIMES */
1041     /* reset, or specify a future time for eptimerfd to trigger */
1042     ret = timerfd_settime(ctx->eptimerfd, 0, &new_value, NULL);
1043     if (ret == -1) {
1044       coap_log(LOG_ERR,
1045                 "%s: timerfd_settime failed: %s (%d)\n",
1046                 "coap_io_prepare_epoll",
1047                 coap_socket_strerror(), errno);
1048     }
1049   }
1050   return timeout;
1051 #endif /* COAP_EPOLL_SUPPORT */
1052 }
1053 
1054 /*
1055  * return  0 No i/o pending
1056  *       +ve millisecs to next i/o activity
1057  */
1058 unsigned int
1059 coap_io_prepare_io(coap_context_t *ctx,
1060            coap_socket_t *sockets[],
1061            unsigned int max_sockets,
1062            unsigned int *num_sockets,
1063            coap_tick_t now)
1064 {
1065   coap_queue_t *nextpdu;
1066   coap_endpoint_t *ep;
1067   coap_session_t *s, *rtmp;
1068   coap_tick_t session_timeout;
1069   coap_tick_t timeout = 0;
1070   coap_tick_t s_timeout;
1071 #ifdef COAP_EPOLL_SUPPORT
1072   (void)sockets;
1073   (void)max_sockets;
1074 #endif /* COAP_EPOLL_SUPPORT */
1075 
1076   *num_sockets = 0;
1077 
1078   /* Check to see if we need to send off any Observe requests */
1079   coap_check_notify(ctx);
1080 
1081   if (ctx->session_timeout > 0)
1082     session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND;
1083   else
1084     session_timeout = COAP_DEFAULT_SESSION_TIMEOUT * COAP_TICKS_PER_SECOND;
1085 
1086 #ifndef WITHOUT_ASYNC
1087   /* Check to see if we need to send off any Async requests */
1088   timeout = coap_check_async(ctx, now);
1089 #endif /* WITHOUT_ASYNC */
1090 
1091   LL_FOREACH(ctx->endpoint, ep) {
1092 #ifndef COAP_EPOLL_SUPPORT
1093     if (ep->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_ACCEPT)) {
1094       if (*num_sockets < max_sockets)
1095         sockets[(*num_sockets)++] = &ep->sock;
1096     }
1097 #endif /* ! COAP_EPOLL_SUPPORT */
1098     SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) {
1099       if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 &&
1100           s->delayqueue == NULL &&
1101           (s->last_rx_tx + session_timeout <= now ||
1102            s->state == COAP_SESSION_STATE_NONE)) {
1103         coap_session_free(s);
1104       } else {
1105         if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && s->delayqueue == NULL) {
1106           s_timeout = (s->last_rx_tx + session_timeout) - now;
1107           if (timeout == 0 || s_timeout < timeout)
1108             timeout = s_timeout;
1109         }
1110         /* Check if any server large receives have timed out */
1111         if (s->lg_srcv) {
1112           s_timeout = coap_block_check_lg_srcv_timeouts(s, now);
1113           if (timeout == 0 || s_timeout < timeout)
1114             timeout = s_timeout;
1115         }
1116 #ifndef COAP_EPOLL_SUPPORT
1117         if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE)) {
1118           if (*num_sockets < max_sockets)
1119             sockets[(*num_sockets)++] = &s->sock;
1120         }
1121 #endif /* ! COAP_EPOLL_SUPPORT */
1122       }
1123     }
1124   }
1125   SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) {
1126     if (!COAP_DISABLE_TCP
1127      && s->type == COAP_SESSION_TYPE_CLIENT
1128      && s->state == COAP_SESSION_STATE_ESTABLISHED
1129      && ctx->ping_timeout > 0
1130     ) {
1131       if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) {
1132         if ((s->last_ping > 0 && s->last_pong < s->last_ping)
1133           || ((s->last_ping_mid = coap_session_send_ping(s)) == COAP_INVALID_MID))
1134         {
1135           /* Make sure the session object is not deleted in the callback */
1136           coap_session_reference(s);
1137           coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE);
1138           coap_session_release(s);
1139           continue;
1140         }
1141         s->last_rx_tx = now;
1142         s->last_ping = now;
1143       }
1144       s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now;
1145       if (timeout == 0 || s_timeout < timeout)
1146         timeout = s_timeout;
1147     }
1148 
1149     if (!COAP_DISABLE_TCP
1150      && s->type == COAP_SESSION_TYPE_CLIENT
1151      && COAP_PROTO_RELIABLE(s->proto)
1152      && s->state == COAP_SESSION_STATE_CSM
1153      && ctx->csm_timeout > 0
1154     ) {
1155       if (s->csm_tx == 0) {
1156         s->csm_tx = now;
1157       } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) {
1158         /* Make sure the session object is not deleted in the callback */
1159         coap_session_reference(s);
1160         coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE);
1161         coap_session_release(s);
1162         continue;
1163       }
1164       s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now;
1165       if (timeout == 0 || s_timeout < timeout)
1166         timeout = s_timeout;
1167     }
1168 
1169     /* Check if any client large receives have timed out */
1170     if (s->lg_crcv) {
1171       s_timeout = coap_block_check_lg_crcv_timeouts(s, now);
1172       if (timeout == 0 || s_timeout < timeout)
1173         timeout = s_timeout;
1174     }
1175 
1176 #ifndef COAP_EPOLL_SUPPORT
1177     if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_CONNECT)) {
1178       if (*num_sockets < max_sockets)
1179         sockets[(*num_sockets)++] = &s->sock;
1180     }
1181 #endif /* ! COAP_EPOLL_SUPPORT */
1182   }
1183 
1184   nextpdu = coap_peek_next(ctx);
1185 
1186   while (nextpdu && now >= ctx->sendqueue_basetime && nextpdu->t <= now - ctx->sendqueue_basetime) {
1187     coap_retransmit(ctx, coap_pop_next(ctx));
1188     nextpdu = coap_peek_next(ctx);
1189   }
1190 
1191   if (nextpdu && (timeout == 0 || nextpdu->t - ( now - ctx->sendqueue_basetime ) < timeout))
1192     timeout = nextpdu->t - (now - ctx->sendqueue_basetime);
1193 
1194   if (ctx->dtls_context) {
1195     if (coap_dtls_is_context_timeout()) {
1196       coap_tick_t tls_timeout = coap_dtls_get_context_timeout(ctx->dtls_context);
1197       if (tls_timeout > 0) {
1198         if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10)
1199           tls_timeout = now + COAP_TICKS_PER_SECOND / 10;
1200         coap_log(LOG_DEBUG, "** DTLS global timeout set to %dms\n",
1201                  (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND));
1202         if (timeout == 0 || tls_timeout - now < timeout)
1203           timeout = tls_timeout - now;
1204       }
1205     } else {
1206       LL_FOREACH(ctx->endpoint, ep) {
1207         if (ep->proto == COAP_PROTO_DTLS) {
1208           SESSIONS_ITER(ep->sessions, s, rtmp) {
1209             if (s->state == COAP_SESSION_STATE_HANDSHAKE &&
1210                 s->proto == COAP_PROTO_DTLS && s->tls) {
1211               coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now);
1212               while (tls_timeout > 0 && tls_timeout <= now) {
1213                 coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n",
1214                          coap_session_str(s));
1215                 /* Make sure the session object is not deleted in any callbacks */
1216                 coap_session_reference(s);
1217                 coap_dtls_handle_timeout(s);
1218                 if (s->tls)
1219                   tls_timeout = coap_dtls_get_timeout(s, now);
1220                 else {
1221                   tls_timeout = 0;
1222                   timeout = 1;
1223                 }
1224                 coap_session_release(s);
1225               }
1226               if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
1227                 timeout = tls_timeout - now;
1228             }
1229           }
1230         }
1231       }
1232       SESSIONS_ITER(ctx->sessions, s, rtmp) {
1233         if (s->state == COAP_SESSION_STATE_HANDSHAKE &&
1234             s->proto == COAP_PROTO_DTLS && s->tls) {
1235           coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now);
1236           while (tls_timeout > 0 && tls_timeout <= now) {
1237             coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", coap_session_str(s));
1238             /* Make sure the session object is not deleted in any callbacks */
1239             coap_session_reference(s);
1240             coap_dtls_handle_timeout(s);
1241             if (s->tls)
1242               tls_timeout = coap_dtls_get_timeout(s, now);
1243             else {
1244               tls_timeout = 0;
1245               timeout = 1;
1246             }
1247             coap_session_release(s);
1248           }
1249           if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
1250             timeout = tls_timeout - now;
1251         }
1252       }
1253     }
1254   }
1255 
1256   return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND);
1257 }
1258 
1259 #ifndef RIOT_VERSION
1260 int
1261 coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) {
1262   return coap_io_process_with_fds(ctx, timeout_ms, 0, NULL, NULL, NULL);
1263 }
1264 
1265 int
1266 coap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms,
1267                          int enfds, fd_set *ereadfds, fd_set *ewritefds,
1268                          fd_set *eexceptfds) {
1269 #if COAP_CONSTRAINED_STACK
1270   static coap_mutex_t static_mutex = COAP_MUTEX_INITIALIZER;
1271 # ifndef COAP_EPOLL_SUPPORT
1272   static fd_set readfds, writefds, exceptfds;
1273   static coap_socket_t *sockets[64];
1274   unsigned int num_sockets = 0;
1275 # endif /* ! COAP_EPOLL_SUPPORT */
1276 #else /* ! COAP_CONSTRAINED_STACK */
1277 # ifndef COAP_EPOLL_SUPPORT
1278   fd_set readfds, writefds, exceptfds;
1279   coap_socket_t *sockets[64];
1280   unsigned int num_sockets = 0;
1281 # endif /* ! COAP_EPOLL_SUPPORT */
1282 #endif /* ! COAP_CONSTRAINED_STACK */
1283   coap_fd_t nfds = 0;
1284   coap_tick_t before, now;
1285   unsigned int timeout;
1286 #ifndef COAP_EPOLL_SUPPORT
1287   struct timeval tv;
1288   int result;
1289   unsigned int i;
1290 #endif /* ! COAP_EPOLL_SUPPORT */
1291 
1292 #if COAP_CONSTRAINED_STACK
1293   coap_mutex_lock(&static_mutex);
1294 #endif /* COAP_CONSTRAINED_STACK */
1295 
1296   coap_ticks(&before);
1297 
1298 #ifndef COAP_EPOLL_SUPPORT
1299   timeout = coap_io_prepare_io(ctx, sockets,
1300                             (sizeof(sockets) / sizeof(sockets[0])),
1301                             &num_sockets, before);
1302   if (timeout == 0 || timeout_ms < timeout)
1303     timeout = timeout_ms;
1304 
1305   if (ereadfds) {
1306     readfds = *ereadfds;
1307     nfds = enfds;
1308   }
1309   else {
1310     FD_ZERO(&readfds);
1311   }
1312   if (ewritefds) {
1313     writefds = *ewritefds;
1314     nfds = enfds;
1315   }
1316   else {
1317     FD_ZERO(&writefds);
1318   }
1319   if (eexceptfds) {
1320     exceptfds = *eexceptfds;
1321     nfds = enfds;
1322   }
1323   else {
1324     FD_ZERO(&exceptfds);
1325   }
1326   for (i = 0; i < num_sockets; i++) {
1327     if (sockets[i]->fd + 1 > nfds)
1328       nfds = sockets[i]->fd + 1;
1329     if (sockets[i]->flags & COAP_SOCKET_WANT_READ)
1330       FD_SET(sockets[i]->fd, &readfds);
1331     if (sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
1332       FD_SET(sockets[i]->fd, &writefds);
1333 #if !COAP_DISABLE_TCP
1334     if (sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT)
1335       FD_SET(sockets[i]->fd, &readfds);
1336     if (sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
1337       FD_SET(sockets[i]->fd, &writefds);
1338       FD_SET(sockets[i]->fd, &exceptfds);
1339     }
1340 #endif /* !COAP_DISABLE_TCP */
1341   }
1342 
1343   if (timeout_ms == COAP_IO_NO_WAIT) {
1344     tv.tv_usec = 0;
1345     tv.tv_sec = 0;
1346     timeout = 1;
1347   }
1348   else if (timeout > 0) {
1349     tv.tv_usec = (timeout % 1000) * 1000;
1350     tv.tv_sec = (long)(timeout / 1000);
1351   }
1352 
1353   result = select((int)nfds, &readfds, &writefds, &exceptfds, timeout > 0 ? &tv : NULL);
1354 
1355   if (result < 0) {   /* error */
1356 #ifdef _WIN32
1357     if (WSAGetLastError() != WSAEINVAL) { /* May happen because of ICMP */
1358 #else
1359     if (errno != EINTR) {
1360 #endif
1361       coap_log(LOG_DEBUG, "%s", coap_socket_strerror());
1362 #if COAP_CONSTRAINED_STACK
1363       coap_mutex_unlock(&static_mutex);
1364 #endif /* COAP_CONSTRAINED_STACK */
1365       return -1;
1366     }
1367   }
1368 
1369   if (result > 0) {
1370     for (i = 0; i < num_sockets; i++) {
1371       if ((sockets[i]->flags & COAP_SOCKET_WANT_READ) && FD_ISSET(sockets[i]->fd, &readfds))
1372         sockets[i]->flags |= COAP_SOCKET_CAN_READ;
1373 #if !COAP_DISABLE_TCP
1374       if ((sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && FD_ISSET(sockets[i]->fd, &readfds))
1375         sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT;
1376       if ((sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && FD_ISSET(sockets[i]->fd, &writefds))
1377         sockets[i]->flags |= COAP_SOCKET_CAN_WRITE;
1378       if ((sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && (FD_ISSET(sockets[i]->fd, &writefds) || FD_ISSET(sockets[i]->fd, &exceptfds)))
1379         sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT;
1380 #endif /* !COAP_DISABLE_TCP */
1381     }
1382   }
1383 
1384   coap_ticks(&now);
1385   coap_io_do_io(ctx, now);
1386   if (ereadfds) {
1387     *ereadfds = readfds;
1388   }
1389   if (ewritefds) {
1390     *ewritefds = writefds;
1391   }
1392   if (eexceptfds) {
1393     *eexceptfds = exceptfds;
1394   }
1395 
1396 #else /* COAP_EPOLL_SUPPORT */
1397   (void)ereadfds;
1398   (void)ewritefds;
1399   (void)eexceptfds;
1400   (void)enfds;
1401 
1402   timeout = coap_io_prepare_epoll(ctx, before);
1403 
1404   if (timeout == 0 || timeout_ms < timeout)
1405     timeout = timeout_ms;
1406 
1407   do {
1408     struct epoll_event events[COAP_MAX_EPOLL_EVENTS];
1409     int etimeout = timeout;
1410 
1411     /* Potentially adjust based on what the caller wants */
1412     if (timeout_ms == COAP_IO_NO_WAIT) {
1413       etimeout = 0;
1414     }
1415     else if (timeout == COAP_IO_WAIT) {
1416       /* coap_io_prepare_epoll() returned 0 and timeout_ms COAP_IO_WAIT (0) */
1417       etimeout = -1;
1418     }
1419     else if (etimeout < 0) {
1420      /* epoll_wait cannot wait longer than this as int timeout parameter */
1421       etimeout = INT_MAX;
1422     }
1423 
1424     nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout);
1425     if (nfds < 0) {
1426       if (errno != EINTR) {
1427         coap_log (LOG_ERR, "epoll_wait: unexpected error: %s (%d)\n",
1428                             coap_socket_strerror(), nfds);
1429       }
1430       break;
1431     }
1432 
1433     coap_io_do_epoll(ctx, events, nfds);
1434 
1435     /*
1436      * reset to COAP_IO_NO_WAIT (which causes etimeout to become 0)
1437      * incase we have to do another iteration
1438      * (COAP_MAX_EPOLL_EVENTS insufficient)
1439      */
1440     timeout_ms = COAP_IO_NO_WAIT;
1441 
1442     /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */
1443   } while (nfds == COAP_MAX_EPOLL_EVENTS);
1444 
1445 #endif /* COAP_EPOLL_SUPPORT */
1446   coap_expire_cache_entries(ctx);
1447   coap_ticks(&now);
1448 #ifndef WITHOUT_ASYNC
1449   /* Check to see if we need to send off any Async requests as delay might
1450      have been updated */
1451   coap_check_async(ctx, now);
1452   coap_ticks(&now);
1453 #endif /* WITHOUT_ASYNC */
1454 
1455 #if COAP_CONSTRAINED_STACK
1456   coap_mutex_unlock(&static_mutex);
1457 #endif /* COAP_CONSTRAINED_STACK */
1458 
1459   return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
1460 }
1461 #endif /* RIOT_VERSION */
1462 
1463 #else /* WITH_CONTIKI */
1464 int coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) {
1465   coap_tick_t now;
1466 
1467   coap_ticks(&now);
1468   /* There is something to read on the endpoint */
1469   ctx->endpoint->sock.flags |= COAP_SOCKET_CAN_READ;
1470   /* read in, and send off any responses */
1471   coap_io_do_io(ctx, now);  /* read received data */
1472   return -1;
1473 }
1474 
1475 unsigned int
1476 coap_io_prepare(coap_context_t *ctx,
1477                 coap_socket_t *sockets[],
1478                 unsigned int max_sockets,
1479                 unsigned int *num_sockets,
1480                 coap_tick_t now)
1481 {
1482   *num_sockets = 0;
1483   return 0;
1484 }
1485 #endif /* WITH_CONTIKI */
1486 
1487 #ifdef _WIN32
1488 const char *coap_socket_format_errno(int error) {
1489   static char szError[256];
1490   if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)szError, (DWORD)sizeof(szError), NULL) == 0)
1491     strcpy(szError, "Unknown error");
1492   return szError;
1493 }
1494 
1495 const char *coap_socket_strerror(void) {
1496   return coap_socket_format_errno(WSAGetLastError());
1497 }
1498 #else /* _WIN32 */
1499 const char *coap_socket_format_errno(int error) {
1500   return strerror(error);
1501 }
1502 const char *coap_socket_strerror(void) {
1503   return coap_socket_format_errno(errno);
1504 }
1505 #endif /* _WIN32 */
1506 
1507 ssize_t
1508 coap_socket_send(coap_socket_t *sock, coap_session_t *session,
1509   const uint8_t *data, size_t data_len) {
1510   return session->context->network_send(sock, session, data, data_len);
1511 }
1512 
1513 #undef SIN6
1514