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