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