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