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