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