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