libcoap  4.2.0
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_config.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 
44 #ifdef WITH_CONTIKI
45 # include "uip.h"
46 #endif
47 
48 #include "libcoap.h"
49 #include "coap_debug.h"
50 #include "mem.h"
51 #include "net.h"
52 #include "coap_io.h"
53 #include "pdu.h"
54 #include "utlist.h"
55 #include "resource.h"
56 
57 #if !defined(WITH_CONTIKI)
58  /* define generic PKTINFO for IPv4 */
59 #if defined(IP_PKTINFO)
60 # define GEN_IP_PKTINFO IP_PKTINFO
61 #elif defined(IP_RECVDSTADDR)
62 # define GEN_IP_PKTINFO IP_RECVDSTADDR
63 #else
64 # error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
65 #endif /* IP_PKTINFO */
66 
67 /* define generic KTINFO for IPv6 */
68 #ifdef IPV6_RECVPKTINFO
69 # define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
70 #elif defined(IPV6_PKTINFO)
71 # define GEN_IPV6_PKTINFO IPV6_PKTINFO
72 #else
73 # error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
74 #endif /* IPV6_RECVPKTINFO */
75 #endif
76 
78 
79 #ifdef WITH_CONTIKI
80 static int ep_initialized = 0;
81 
82 struct coap_endpoint_t *
84  static struct coap_endpoint_t ep;
85 
86  if (ep_initialized) {
87  return NULL;
88  } else {
89  ep_initialized = 1;
90  return &ep;
91  }
92 }
93 
94 void
96  ep_initialized = 0;
98 }
99 
100 int
102  const coap_address_t *listen_addr,
103  coap_address_t *bound_addr) {
104  sock->conn = udp_new(NULL, 0, NULL);
105 
106  if (!sock->conn) {
107  coap_log(LOG_WARNING, "coap_socket_bind_udp");
108  return 0;
109  }
110 
111  coap_address_init(bound_addr);
112  uip_ipaddr_copy(&bound_addr->addr, &listen_addr->addr);
113  bound_addr->port = listen_addr->port;
114  udp_bind((struct uip_udp_conn *)sock->conn, bound_addr->port);
115  return 1;
116 }
117 
118 int
120  const coap_address_t *local_if,
121  const coap_address_t *server,
122  int default_port,
123  coap_address_t *local_addr,
124  coap_address_t *remote_addr) {
125  return 0;
126 }
127 
128 int
130  const coap_address_t *local_if,
131  const coap_address_t *server,
132  int default_port,
133  coap_address_t *local_addr,
134  coap_address_t *remote_addr) {
135  return 0;
136 }
137 
138 int
140  coap_address_t *local_addr,
141  coap_address_t *remote_addr) {
142  return 0;
143 }
144 
145 int
147  const coap_address_t *listen_addr,
148  coap_address_t *bound_addr) {
149  return 0;
150 }
151 
152 int
154  coap_socket_t *new_client,
155  coap_address_t *local_addr,
156  coap_address_t *remote_addr) {
157  return 0;
158 }
159 
160 ssize_t
161 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
162  return -1;
163 }
164 
165 ssize_t
166 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
167  return -1;
168 }
169 
170 void coap_socket_close(coap_socket_t *sock) {
171  if (sock->conn)
172  uip_udp_remove((struct uip_udp_conn *)sock->conn);
173  sock->flags = COAP_SOCKET_EMPTY;
174 }
175 
176 #else
177 
178 static const char *coap_socket_format_errno( int error );
179 
180 struct coap_endpoint_t *
182  return (struct coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(struct coap_endpoint_t));
183 }
184 
185 void
189 }
190 
191 int
193  const coap_address_t *listen_addr,
194  coap_address_t *bound_addr) {
195  int on = 1, off = 0;
196 #ifdef _WIN32
197  u_long u_on = 1;
198 #endif
199 
200  sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0);
201 
202  if (sock->fd == COAP_INVALID_SOCKET) {
204  "coap_socket_bind_udp: socket: %s\n", coap_socket_strerror());
205  goto error;
206  }
207 
208 #ifdef _WIN32
209  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
210 #else
211  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
212 #endif
214  "coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror());
215  }
216 
217  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
219  "coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n",
221 
222  switch (listen_addr->addr.sa.sa_family) {
223  case AF_INET:
224  if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
226  "coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n",
228  break;
229  case AF_INET6:
230  /* Configure the socket as dual-stacked */
231  if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
233  "coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n",
235  if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
237  "coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n",
239  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 */
240  break;
241  default:
242  coap_log(LOG_ALERT, "coap_socket_bind_udp: unsupported sa_family\n");
243  break;
244  }
245 
246  if (bind(sock->fd, &listen_addr->addr.sa, listen_addr->size) == COAP_SOCKET_ERROR) {
247  coap_log(LOG_WARNING, "coap_socket_bind_udp: bind: %s\n",
249  goto error;
250  }
251 
252  bound_addr->size = (socklen_t)sizeof(*bound_addr);
253  if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
255  "coap_socket_bind_udp: getsockname: %s\n",
257  goto error;
258  }
259 
260  return 1;
261 
262 error:
263  coap_socket_close(sock);
264  return 0;
265 }
266 
267 int
269  const coap_address_t *local_if,
270  const coap_address_t *server,
271  int default_port,
272  coap_address_t *local_addr,
273  coap_address_t *remote_addr) {
274  int on = 1, off = 0;
275 #ifdef _WIN32
276  u_long u_on = 1;
277 #endif
278  coap_address_t connect_addr;
279  coap_address_copy( &connect_addr, server );
280 
281  sock->flags &= ~COAP_SOCKET_CONNECTED;
282  sock->fd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0);
283 
284  if (sock->fd == COAP_INVALID_SOCKET) {
286  "coap_socket_connect_tcp1: socket: %s\n",
288  goto error;
289  }
290 
291 #ifdef _WIN32
292  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
293 #else
294  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
295 #endif
297  "coap_socket_connect_tcp1: ioctl FIONBIO: %s\n",
299  }
300 
301  switch (server->addr.sa.sa_family) {
302  case AF_INET:
303  if (connect_addr.addr.sin.sin_port == 0)
304  connect_addr.addr.sin.sin_port = htons(default_port);
305  break;
306  case AF_INET6:
307  if (connect_addr.addr.sin6.sin6_port == 0)
308  connect_addr.addr.sin6.sin6_port = htons(default_port);
309  /* Configure the socket as dual-stacked */
310  if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
312  "coap_socket_connect_tcp1: setsockopt IPV6_V6ONLY: %s\n",
314  break;
315  default:
316  coap_log(LOG_ALERT, "coap_socket_connect_tcp1: unsupported sa_family\n");
317  break;
318  }
319 
320  if (local_if && local_if->addr.sa.sa_family) {
321  coap_address_copy(local_addr, local_if);
322  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
324  "coap_socket_connect_tcp1: setsockopt SO_REUSEADDR: %s\n",
326  if (bind(sock->fd, &local_if->addr.sa, local_if->size) == COAP_SOCKET_ERROR) {
327  coap_log(LOG_WARNING, "coap_socket_connect_tcp1: bind: %s\n",
329  goto error;
330  }
331  } else {
332  local_addr->addr.sa.sa_family = server->addr.sa.sa_family;
333  }
334 
335  if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
336 #ifdef _WIN32
337  if (WSAGetLastError() == WSAEWOULDBLOCK) {
338 #else
339  if (errno == EINPROGRESS) {
340 #endif
341  /*
342  * COAP_SOCKET_CONNECTED needs to be set here as there will be reads/writes
343  * by underlying TLS libraries during connect() and we do not want to
344  * assert() in coap_read_session() or coap_write_session() when called by coap_read()
345  */
347  return 1;
348  }
349  coap_log(LOG_WARNING, "coap_socket_connect_tcp1: connect: %s\n",
351  goto error;
352  }
353 
354  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
355  coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getsockname: %s\n",
357  }
358 
359  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
360  coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getpeername: %s\n",
362  }
363 
364  sock->flags |= COAP_SOCKET_CONNECTED;
365  return 1;
366 
367 error:
368  coap_socket_close(sock);
369  return 0;
370 }
371 
372 int
374  coap_address_t *local_addr,
375  coap_address_t *remote_addr) {
376  int error = 0;
377 #ifdef _WIN32
378  int optlen = (int)sizeof( error );
379 #else
380  socklen_t optlen = (socklen_t)sizeof( error );
381 #endif
382 
384 
385  if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error),
386  &optlen) == COAP_SOCKET_ERROR) {
387  coap_log(LOG_WARNING, "coap_socket_finish_connect_tcp: getsockopt: %s\n",
389  }
390 
391  if (error) {
393  "coap_socket_finish_connect_tcp: connect failed: %s\n",
394  coap_socket_format_errno(error));
395  coap_socket_close(sock);
396  return 0;
397  }
398 
399  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
400  coap_log(LOG_WARNING, "coap_socket_connect_tcp: getsockname: %s\n",
402  }
403 
404  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
405  coap_log(LOG_WARNING, "coap_socket_connect_tcp: getpeername: %s\n",
407  }
408 
409  return 1;
410 }
411 
412 int
414  const coap_address_t *listen_addr,
415  coap_address_t *bound_addr) {
416  int on = 1, off = 0;
417 #ifdef _WIN32
418  u_long u_on = 1;
419 #endif
420 
421  sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_STREAM, 0);
422 
423  if (sock->fd == COAP_INVALID_SOCKET) {
424  coap_log(LOG_WARNING, "coap_socket_bind_tcp: socket: %s\n",
426  goto error;
427  }
428 
429 #ifdef _WIN32
430  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
431 #else
432  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
433 #endif
434  coap_log(LOG_WARNING, "coap_socket_bind_tcp: ioctl FIONBIO: %s\n",
436  }
437  if (setsockopt (sock->fd, SOL_SOCKET, SO_KEEPALIVE, OPTVAL_T(&on),
438  sizeof (on)) == COAP_SOCKET_ERROR)
440  "coap_socket_bind_tcp: setsockopt SO_KEEPALIVE: %s\n",
442 
443  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
444  sizeof(on)) == COAP_SOCKET_ERROR)
446  "coap_socket_bind_tcp: setsockopt SO_REUSEADDR: %s\n",
448 
449  switch (listen_addr->addr.sa.sa_family) {
450  case AF_INET:
451  break;
452  case AF_INET6:
453  /* Configure the socket as dual-stacked */
454  if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
456  "coap_socket_bind_tcp: setsockopt IPV6_V6ONLY: %s\n",
458  break;
459  default:
460  coap_log(LOG_ALERT, "coap_socket_bind_tcp: unsupported sa_family\n");
461  }
462 
463  if (bind(sock->fd, &listen_addr->addr.sa, listen_addr->size) == COAP_SOCKET_ERROR) {
464  coap_log(LOG_ALERT, "coap_socket_bind_tcp: bind: %s\n",
466  goto error;
467  }
468 
469  bound_addr->size = (socklen_t)sizeof(*bound_addr);
470  if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
471  coap_log(LOG_WARNING, "coap_socket_bind_tcp: getsockname: %s\n",
473  goto error;
474  }
475 
476  if (listen(sock->fd, 5) == COAP_SOCKET_ERROR) {
477  coap_log(LOG_ALERT, "coap_socket_bind_tcp: listen: %s\n",
479  goto error;
480  }
481 
482  return 1;
483 
484 error:
485  coap_socket_close(sock);
486  return 0;
487 }
488 
489 int
491  coap_socket_t *new_client,
492  coap_address_t *local_addr,
493  coap_address_t *remote_addr) {
494 #ifdef _WIN32
495  u_long u_on = 1;
496 #else
497  int on = 1;
498 #endif
499 
500  server->flags &= ~COAP_SOCKET_CAN_ACCEPT;
501 
502  new_client->fd = accept(server->fd, &remote_addr->addr.sa,
503  &remote_addr->size);
504  if (new_client->fd == COAP_INVALID_SOCKET) {
505  coap_log(LOG_WARNING, "coap_socket_accept_tcp: accept: %s\n",
507  return 0;
508  }
509 
510  if (getsockname( new_client->fd, &local_addr->addr.sa, &local_addr->size) < 0)
511  coap_log(LOG_WARNING, "coap_socket_accept_tcp: getsockname: %s\n",
513 
514  #ifdef _WIN32
515  if (ioctlsocket(new_client->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
516 #else
517  if (ioctl(new_client->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
518 #endif
519  coap_log(LOG_WARNING, "coap_socket_accept_tcp: ioctl FIONBIO: %s\n",
521  }
522 
523  return 1;
524 }
525 
526 int
528  const coap_address_t *local_if,
529  const coap_address_t *server,
530  int default_port,
531  coap_address_t *local_addr,
532  coap_address_t *remote_addr) {
533  int on = 1, off = 0;
534 #ifdef _WIN32
535  u_long u_on = 1;
536 #endif
537  coap_address_t connect_addr;
538  int is_mcast = coap_is_mcast(server);
539  coap_address_copy(&connect_addr, server);
540 
542  sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0);
543 
544  if (sock->fd == COAP_INVALID_SOCKET) {
545  coap_log(LOG_WARNING, "coap_socket_connect_udp: socket: %s\n",
547  goto error;
548  }
549 
550 #ifdef _WIN32
551  if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
552 #else
553  if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
554 #endif
555  coap_log(LOG_WARNING, "coap_socket_connect_udp: ioctl FIONBIO: %s\n",
557  }
558 
559  switch (connect_addr.addr.sa.sa_family) {
560  case AF_INET:
561  if (connect_addr.addr.sin.sin_port == 0)
562  connect_addr.addr.sin.sin_port = htons(default_port);
563  break;
564  case AF_INET6:
565  if (connect_addr.addr.sin6.sin6_port == 0)
566  connect_addr.addr.sin6.sin6_port = htons(default_port);
567  /* Configure the socket as dual-stacked */
568  if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
570  "coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
572  break;
573  default:
574  coap_log(LOG_ALERT, "coap_socket_connect_udp: unsupported sa_family\n");
575  break;
576  }
577 
578  if (local_if && local_if->addr.sa.sa_family) {
579  if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
581  "coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
583  if (bind(sock->fd, &local_if->addr.sa, local_if->size) == COAP_SOCKET_ERROR) {
584  coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n",
586  goto error;
587  }
588  }
589 
590  /* special treatment for sockets that are used for multicast communication */
591  if (is_mcast) {
592  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
594  "coap_socket_connect_udp: getsockname for multicast socket: %s\n",
596  }
597  coap_address_copy(remote_addr, &connect_addr);
598  sock->flags |= COAP_SOCKET_MULTICAST;
599  return 1;
600  }
601 
602  if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
603  coap_log(LOG_WARNING, "coap_socket_connect_udp: connect: %s\n",
605  goto error;
606  }
607 
608  if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
609  coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname: %s\n",
611  }
612 
613  if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
614  coap_log(LOG_WARNING, "coap_socket_connect_udp: getpeername: %s\n",
616  }
617 
618  sock->flags |= COAP_SOCKET_CONNECTED;
619  return 1;
620 
621 error:
622  coap_socket_close(sock);
623  return 0;
624 }
625 
627  if (sock->fd != COAP_INVALID_SOCKET) {
628  coap_closesocket(sock->fd);
629  sock->fd = COAP_INVALID_SOCKET;
630  }
631  sock->flags = COAP_SOCKET_EMPTY;
632 }
633 
634 ssize_t
635 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
636  ssize_t r;
637 
639 #ifdef _WIN32
640  r = send(sock->fd, (const char *)data, (int)data_len, 0);
641 #else
642  r = send(sock->fd, data, data_len, 0);
643 #endif
644  if (r == COAP_SOCKET_ERROR) {
645 #ifdef _WIN32
646  if (WSAGetLastError() == WSAEWOULDBLOCK) {
647 #elif EAGAIN != EWOULDBLOCK
648  if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
649 #else
650  if (errno==EAGAIN || errno == EINTR) {
651 #endif
652  sock->flags |= COAP_SOCKET_WANT_WRITE;
653  return 0;
654  }
655  coap_log(LOG_WARNING, "coap_socket_write: send: %s\n",
657  return -1;
658  }
659  if (r < (ssize_t)data_len)
660  sock->flags |= COAP_SOCKET_WANT_WRITE;
661  return r;
662 }
663 
664 ssize_t
665 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
666  ssize_t r;
667 #ifdef _WIN32
668  int error;
669 #endif
670 
671 #ifdef _WIN32
672  r = recv(sock->fd, (char *)data, (int)data_len, 0);
673 #else
674  r = recv(sock->fd, data, data_len, 0);
675 #endif
676  if (r == 0) {
677  /* graceful shutdown */
678  sock->flags &= ~COAP_SOCKET_CAN_READ;
679  return -1;
680  } else if (r == COAP_SOCKET_ERROR) {
681  sock->flags &= ~COAP_SOCKET_CAN_READ;
682 #ifdef _WIN32
683  error = WSAGetLastError();
684  if (error == WSAEWOULDBLOCK) {
685 #elif EAGAIN != EWOULDBLOCK
686  if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
687 #else
688  if (errno==EAGAIN || errno == EINTR) {
689 #endif
690  return 0;
691  }
692 #ifdef _WIN32
693  if (error != WSAECONNRESET)
694 #else
695  if (errno != ECONNRESET)
696 #endif
697  coap_log(LOG_WARNING, "coap_socket_read: recv: %s\n",
699  return -1;
700  }
701  if (r < (ssize_t)data_len)
702  sock->flags &= ~COAP_SOCKET_CAN_READ;
703  return r;
704 }
705 
706 #endif /* WITH_CONTIKI */
707 
708 #if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
709 /* define struct in6_pktinfo and struct in_pktinfo if not available
710  FIXME: check with configure
711 */
712 struct in6_pktinfo {
713  struct in6_addr ipi6_addr; /* src/dst IPv6 address */
714  unsigned int ipi6_ifindex; /* send/recv interface index */
715 };
716 
717 struct in_pktinfo {
719  struct in_addr ipi_spec_dst;
720  struct in_addr ipi_addr;
721 };
722 #endif
723 
724 #if !defined(WITH_CONTIKI) && !defined(SOL_IP)
725 /* Solaris expects level IPPROTO_IP for ancillary data. */
726 #define SOL_IP IPPROTO_IP
727 #endif
728 
729 #ifdef __GNUC__
730 #define UNUSED_PARAM __attribute__ ((unused))
731 #else /* not a GCC */
732 #define UNUSED_PARAM
733 #endif /* GCC */
734 
735 #if defined(_WIN32)
736 #include <mswsock.h>
737 static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL;
738 /* Map struct WSABUF fields to their posix counterpart */
739 #define msghdr _WSAMSG
740 #define msg_name name
741 #define msg_namelen namelen
742 #define msg_iov lpBuffers
743 #define msg_iovlen dwBufferCount
744 #define msg_control Control.buf
745 #define msg_controllen Control.len
746 #define iovec _WSABUF
747 #define iov_base buf
748 #define iov_len len
749 #define iov_len_t u_long
750 #undef CMSG_DATA
751 #define CMSG_DATA WSA_CMSG_DATA
752 #define ipi_spec_dst ipi_addr
753 #else
754 #define iov_len_t size_t
755 #endif
756 
757 ssize_t
758 coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen) {
759  ssize_t bytes_written = 0;
760 
761  if (!coap_debug_send_packet()) {
762  bytes_written = (ssize_t)datalen;
763 #ifndef WITH_CONTIKI
764  } else if (sock->flags & COAP_SOCKET_CONNECTED) {
765 #ifdef _WIN32
766  bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0);
767 #else
768  bytes_written = send(sock->fd, data, datalen, 0);
769 #endif
770 #endif
771  } else {
772 #ifndef WITH_CONTIKI
773  /* a buffer large enough to hold all packet info types, ipv6 is the largest */
774  char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
775 #ifdef _WIN32
776  DWORD dwNumberOfBytesSent = 0;
777  int r;
778 #endif
779  struct msghdr mhdr;
780  struct iovec iov[1];
781  const void *addr = &session->remote_addr.addr;
782 
783  assert(session);
784 
785  memcpy (&iov[0].iov_base, &data, sizeof (iov[0].iov_base));
786  iov[0].iov_len = (iov_len_t)datalen;
787 
788  memset( buf, 0, sizeof(buf));
789 
790  memset(&mhdr, 0, sizeof(struct msghdr));
791  memcpy (&mhdr.msg_name, &addr, sizeof (mhdr.msg_name));
792  mhdr.msg_namelen = session->remote_addr.size;
793 
794  mhdr.msg_iov = iov;
795  mhdr.msg_iovlen = 1;
796 
797  if (!coap_address_isany(&session->local_addr) && !coap_is_mcast(&session->local_addr)) switch (session->local_addr.addr.sa.sa_family) {
798  case AF_INET6:
799  {
800  struct cmsghdr *cmsg;
801 
802  if (IN6_IS_ADDR_V4MAPPED(&session->local_addr.addr.sin6.sin6_addr)) {
803 #if defined(IP_PKTINFO)
804  struct in_pktinfo *pktinfo;
805  mhdr.msg_control = buf;
806  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
807 
808  cmsg = CMSG_FIRSTHDR(&mhdr);
809  cmsg->cmsg_level = SOL_IP;
810  cmsg->cmsg_type = IP_PKTINFO;
811  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
812 
813  pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
814 
815  pktinfo->ipi_ifindex = session->ifindex;
816  memcpy(&pktinfo->ipi_spec_dst, session->local_addr.addr.sin6.sin6_addr.s6_addr + 12, sizeof(pktinfo->ipi_spec_dst));
817 #elif defined(IP_SENDSRCADDR)
818  mhdr.msg_control = buf;
819  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
820 
821  cmsg = CMSG_FIRSTHDR(&mhdr);
822  cmsg->cmsg_level = IPPROTO_IP;
823  cmsg->cmsg_type = IP_SENDSRCADDR;
824  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
825 
826  memcpy(CMSG_DATA(cmsg), session->local_addr.addr.sin6.sin6_addr.s6_addr + 12, sizeof(struct in_addr));
827 #endif /* IP_PKTINFO */
828  } else {
829  struct in6_pktinfo *pktinfo;
830  mhdr.msg_control = buf;
831  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
832 
833  cmsg = CMSG_FIRSTHDR(&mhdr);
834  cmsg->cmsg_level = IPPROTO_IPV6;
835  cmsg->cmsg_type = IPV6_PKTINFO;
836  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
837 
838  pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
839 
840  pktinfo->ipi6_ifindex = session->ifindex;
841  memcpy(&pktinfo->ipi6_addr, &session->local_addr.addr.sin6.sin6_addr, sizeof(pktinfo->ipi6_addr));
842  }
843  break;
844  }
845  case AF_INET:
846  {
847 #if defined(IP_PKTINFO)
848  struct cmsghdr *cmsg;
849  struct in_pktinfo *pktinfo;
850 
851  mhdr.msg_control = buf;
852  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
853 
854  cmsg = CMSG_FIRSTHDR(&mhdr);
855  cmsg->cmsg_level = SOL_IP;
856  cmsg->cmsg_type = IP_PKTINFO;
857  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
858 
859  pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
860 
861  pktinfo->ipi_ifindex = session->ifindex;
862  memcpy(&pktinfo->ipi_spec_dst, &session->local_addr.addr.sin.sin_addr, sizeof(pktinfo->ipi_spec_dst));
863 #elif defined(IP_SENDSRCADDR)
864  struct cmsghdr *cmsg;
865  mhdr.msg_control = buf;
866  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
867 
868  cmsg = CMSG_FIRSTHDR(&mhdr);
869  cmsg->cmsg_level = IPPROTO_IP;
870  cmsg->cmsg_type = IP_SENDSRCADDR;
871  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
872 
873  memcpy(CMSG_DATA(cmsg), &session->local_addr.addr.sin.sin_addr, sizeof(struct in_addr));
874 #endif /* IP_PKTINFO */
875  break;
876  }
877  default:
878  /* error */
879  coap_log(LOG_WARNING, "protocol not supported\n");
880  bytes_written = -1;
881  }
882 
883 #ifdef _WIN32
884  r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, NULL /*lpCompletionRoutine*/);
885  if (r == 0)
886  bytes_written = (ssize_t)dwNumberOfBytesSent;
887  else
888  bytes_written = -1;
889 #else
890  bytes_written = sendmsg(sock->fd, &mhdr, 0);
891 #endif
892 #else /* WITH_CONTIKI */
893  /* FIXME: untested */
894  /* FIXME: is there a way to check if send was successful? */
895  (void)datalen;
896  (void)data;
897  uip_udp_packet_sendto((struct uip_udp_conn *)sock->conn, data, datalen,
898  &session->remote_addr.addr, session->remote_addr.port);
899  bytes_written = datalen;
900 #endif /* WITH_CONTIKI */
901  }
902 
903  if (bytes_written < 0)
904  coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror());
905 
906  return bytes_written;
907 }
908 
909 #define SIN6(A) ((struct sockaddr_in6 *)(A))
910 
911 void
912 coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) {
913  *address = packet->payload;
914  *length = packet->length;
915 }
916 
917 void coap_packet_set_addr(coap_packet_t *packet, const coap_address_t *src, const coap_address_t *dst) {
918  coap_address_copy(&packet->src, src);
919  coap_address_copy(&packet->dst, dst);
920 }
921 
922 ssize_t
924  ssize_t len = -1;
925 
926  assert(sock);
927  assert(packet);
928 
929  if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) {
930  return -1;
931  } else {
932  /* clear has-data flag */
933  sock->flags &= ~COAP_SOCKET_CAN_READ;
934  }
935 
936 #ifndef WITH_CONTIKI
937  if (sock->flags & COAP_SOCKET_CONNECTED) {
938 #ifdef _WIN32
939  len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0);
940 #else
941  len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0);
942 #endif
943  if (len < 0) {
944 #ifdef _WIN32
945  if (WSAGetLastError() == WSAECONNRESET) {
946 #else
947  if (errno == ECONNREFUSED) {
948 #endif
949  /* client-side ICMP destination unreachable, ignore it */
950  coap_log(LOG_WARNING, "coap_network_read: unreachable\n");
951  return -2;
952  }
953  coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
954  goto error;
955  } else if (len > 0) {
956  packet->length = (size_t)len;
957  }
958  } else {
959 #endif /* WITH_CONTIKI */
960 #if defined(_WIN32)
961  DWORD dwNumberOfBytesRecvd = 0;
962  int r;
963 #endif
964 #if !defined(WITH_CONTIKI)
965  /* a buffer large enough to hold all packet info types, ipv6 is the largest */
966  char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
967  struct msghdr mhdr;
968  struct iovec iov[1];
969 
970  iov[0].iov_base = packet->payload;
971  iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE;
972 
973  memset(&mhdr, 0, sizeof(struct msghdr));
974 
975  mhdr.msg_name = (struct sockaddr*)&packet->src.addr;
976  mhdr.msg_namelen = sizeof(packet->src.addr);
977 
978  mhdr.msg_iov = iov;
979  mhdr.msg_iovlen = 1;
980 
981  mhdr.msg_control = buf;
982  mhdr.msg_controllen = sizeof(buf);
983 
984 #if defined(_WIN32)
985  if (!lpWSARecvMsg) {
986  GUID wsaid = WSAID_WSARECVMSG;
987  DWORD cbBytesReturned = 0;
988  if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) {
989  coap_log(LOG_WARNING, "coap_network_read: no WSARecvMsg\n");
990  return -1;
991  }
992  }
993  r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */);
994  if (r == 0)
995  len = (ssize_t)dwNumberOfBytesRecvd;
996 #else
997  len = recvmsg(sock->fd, &mhdr, 0);
998 #endif
999 
1000  if (len < 0) {
1001 #ifdef _WIN32
1002  if (WSAGetLastError() == WSAECONNRESET) {
1003 #else
1004  if (errno == ECONNREFUSED) {
1005 #endif
1006  /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */
1007  return 0;
1008  }
1009  coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
1010  goto error;
1011  } else {
1012  struct cmsghdr *cmsg;
1013 
1014  packet->src.size = mhdr.msg_namelen;
1015  packet->length = (size_t)len;
1016 
1017  /* Walk through ancillary data records until the local interface
1018  * is found where the data was received. */
1019  for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
1020 
1021  /* get the local interface for IPv6 */
1022  if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
1023  union {
1024  uint8_t *c;
1025  struct in6_pktinfo *p;
1026  } u;
1027  u.c = CMSG_DATA(cmsg);
1028  packet->ifindex = (int)(u.p->ipi6_ifindex);
1029  memcpy(&packet->dst.addr.sin6.sin6_addr, &u.p->ipi6_addr, sizeof(struct in6_addr));
1030  break;
1031  }
1032 
1033  /* local interface for IPv4 */
1034 #if defined(IP_PKTINFO)
1035  if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
1036  union {
1037  uint8_t *c;
1038  struct in_pktinfo *p;
1039  } u;
1040  u.c = CMSG_DATA(cmsg);
1041  packet->ifindex = u.p->ipi_ifindex;
1042  if (packet->dst.addr.sa.sa_family == AF_INET6) {
1043  memset(packet->dst.addr.sin6.sin6_addr.s6_addr, 0, 10);
1044  packet->dst.addr.sin6.sin6_addr.s6_addr[10] = 0xff;
1045  packet->dst.addr.sin6.sin6_addr.s6_addr[11] = 0xff;
1046  memcpy(packet->dst.addr.sin6.sin6_addr.s6_addr + 12, &u.p->ipi_addr, sizeof(struct in_addr));
1047  } else {
1048  memcpy(&packet->dst.addr.sin.sin_addr, &u.p->ipi_addr, sizeof(struct in_addr));
1049  }
1050  break;
1051  }
1052 #elif defined(IP_RECVDSTADDR)
1053  if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
1054  packet->ifindex = 0;
1055  memcpy(&packet->dst.addr.sin.sin_addr, CMSG_DATA(cmsg), sizeof(struct in_addr));
1056  break;
1057  }
1058 #endif /* IP_PKTINFO */
1059  }
1060  }
1061 #endif /* !defined(WITH_CONTIKI) */
1062 #ifdef WITH_CONTIKI
1063  /* FIXME: untested, make this work */
1064 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
1065 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
1066 
1067  if (uip_newdata()) {
1068  uip_ipaddr_copy(&packet->src.addr, &UIP_IP_BUF->srcipaddr);
1069  packet->src.port = UIP_UDP_BUF->srcport;
1070  uip_ipaddr_copy(&(packet)->dst.addr, &UIP_IP_BUF->destipaddr);
1071  packet->dst.port = UIP_UDP_BUF->destport;
1072 
1073  len = uip_datalen();
1074 
1075  if (len > COAP_RXBUFFER_SIZE) {
1076  /* FIXME: we might want to send back a response */
1077  coap_log(LOG_WARNING, "discarded oversized packet\n");
1078  return -1;
1079  }
1080 
1081  ((char *)uip_appdata)[len] = 0;
1082 #ifndef NDEBUG
1083  if (LOG_DEBUG <= coap_get_log_level()) {
1084 #ifndef INET6_ADDRSTRLEN
1085 #define INET6_ADDRSTRLEN 40
1086 #endif
1087  unsigned char addr_str[INET6_ADDRSTRLEN + 8];
1088 
1089  if (coap_print_addr(&packet->src, addr_str, INET6_ADDRSTRLEN + 8)) {
1090  coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str);
1091  }
1092  }
1093 #endif /* NDEBUG */
1094 
1095  packet->length = len;
1096  memcpy(&packet->payload, uip_appdata, len);
1097  }
1098 
1099 #undef UIP_IP_BUF
1100 #undef UIP_UDP_BUF
1101 #endif /* WITH_CONTIKI */
1102 #ifndef WITH_CONTIKI
1103  }
1104 #endif /* WITH_CONTIKI */
1105 
1106  if (len >= 0)
1107  return len;
1108 #if !defined(WITH_CONTIKI)
1109 error:
1110 #endif
1111  return -1;
1112 }
1113 
1114 #if !defined(WITH_CONTIKI)
1115 
1116 unsigned int
1118  coap_socket_t *sockets[],
1119  unsigned int max_sockets,
1120  unsigned int *num_sockets,
1121  coap_tick_t now)
1122 {
1123  coap_queue_t *nextpdu;
1124  coap_endpoint_t *ep;
1125  coap_session_t *s;
1126  coap_tick_t session_timeout;
1127  coap_tick_t timeout = 0;
1128  coap_session_t *tmp;
1129 
1130  *num_sockets = 0;
1131 
1132  /* Check to see if we need to send off any Observe requests */
1133  coap_check_notify(ctx);
1134 
1135  if (ctx->session_timeout > 0)
1136  session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND;
1137  else
1139 
1140  LL_FOREACH(ctx->endpoint, ep) {
1142  if (*num_sockets < max_sockets)
1143  sockets[(*num_sockets)++] = &ep->sock;
1144  }
1145  LL_FOREACH_SAFE(ep->sessions, s, tmp) {
1146  if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 &&
1147  s->delayqueue == NULL &&
1148  (s->last_rx_tx + session_timeout <= now ||
1149  s->state == COAP_SESSION_STATE_NONE)) {
1150  coap_session_free(s);
1151  } else {
1152  if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && s->delayqueue == NULL) {
1153  coap_tick_t s_timeout = (s->last_rx_tx + session_timeout) - now;
1154  if (timeout == 0 || s_timeout < timeout)
1155  timeout = s_timeout;
1156  }
1158  if (*num_sockets < max_sockets)
1159  sockets[(*num_sockets)++] = &s->sock;
1160  }
1161  }
1162  }
1163  }
1164  LL_FOREACH_SAFE(ctx->sessions, s, tmp) {
1165  if (
1167  && COAP_PROTO_RELIABLE(s->proto)
1169  && ctx->ping_timeout > 0
1170  ) {
1171  coap_tick_t s_timeout;
1172  if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) {
1173  if ((s->last_ping > 0 && s->last_pong < s->last_ping)
1175  {
1176  /* Make sure the session object is not deleted in the callback */
1180  continue;
1181  }
1182  s->last_rx_tx = now;
1183  s->last_ping = now;
1184  }
1185  s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now;
1186  if (timeout == 0 || s_timeout < timeout)
1187  timeout = s_timeout;
1188  }
1189 
1190  if (
1192  && COAP_PROTO_RELIABLE(s->proto)
1193  && s->state == COAP_SESSION_STATE_CSM
1194  && ctx->csm_timeout > 0
1195  ) {
1196  coap_tick_t s_timeout;
1197  if (s->csm_tx == 0) {
1198  s->csm_tx = now;
1199  } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) {
1200  /* Make sure the session object is not deleted in the callback */
1204  continue;
1205  }
1206  s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now;
1207  if (timeout == 0 || s_timeout < timeout)
1208  timeout = s_timeout;
1209  }
1210 
1212  if (*num_sockets < max_sockets)
1213  sockets[(*num_sockets)++] = &s->sock;
1214  }
1215  }
1216 
1217  nextpdu = coap_peek_next(ctx);
1218 
1219  while (nextpdu && now >= ctx->sendqueue_basetime && nextpdu->t <= now - ctx->sendqueue_basetime) {
1220  coap_retransmit(ctx, coap_pop_next(ctx));
1221  nextpdu = coap_peek_next(ctx);
1222  }
1223 
1224  if (nextpdu && (timeout == 0 || nextpdu->t - ( now - ctx->sendqueue_basetime ) < timeout))
1225  timeout = nextpdu->t - (now - ctx->sendqueue_basetime);
1226 
1227  if (ctx->dtls_context) {
1230  if (tls_timeout > 0) {
1231  if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10)
1232  tls_timeout = now + COAP_TICKS_PER_SECOND / 10;
1233  coap_log(LOG_DEBUG, "** DTLS global timeout set to %dms\n",
1234  (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND));
1235  if (timeout == 0 || tls_timeout - now < timeout)
1236  timeout = tls_timeout - now;
1237  }
1238  } else {
1239  LL_FOREACH(ctx->endpoint, ep) {
1240  if (ep->proto == COAP_PROTO_DTLS) {
1241  LL_FOREACH(ep->sessions, s) {
1242  if (s->proto == COAP_PROTO_DTLS && s->tls) {
1243  coap_tick_t tls_timeout = coap_dtls_get_timeout(s);
1244  while (tls_timeout > 0 && tls_timeout <= now) {
1245  coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n",
1246  coap_session_str(s));
1248  if (s->tls)
1249  tls_timeout = coap_dtls_get_timeout(s);
1250  else {
1251  tls_timeout = 0;
1252  timeout = 1;
1253  }
1254  }
1255  if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
1256  timeout = tls_timeout - now;
1257  }
1258  }
1259  }
1260  }
1261  LL_FOREACH(ctx->sessions, s) {
1262  if (s->proto == COAP_PROTO_DTLS && s->tls) {
1263  coap_tick_t tls_timeout = coap_dtls_get_timeout(s);
1264  while (tls_timeout > 0 && tls_timeout <= now) {
1265  coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", coap_session_str(s));
1267  if (s->tls)
1268  tls_timeout = coap_dtls_get_timeout(s);
1269  else {
1270  tls_timeout = 0;
1271  timeout = 1;
1272  }
1273  }
1274  if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
1275  timeout = tls_timeout - now;
1276  }
1277  }
1278  }
1279  }
1280 
1281  return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND);
1282 }
1283 
1284 int
1285 coap_run_once(coap_context_t *ctx, unsigned timeout_ms) {
1286  fd_set readfds, writefds, exceptfds;
1287  coap_fd_t nfds = 0;
1288  struct timeval tv;
1289  coap_tick_t before, now;
1290  int result;
1291  coap_socket_t *sockets[64];
1292  unsigned int num_sockets = 0, i, timeout;
1293 
1294  coap_ticks(&before);
1295 
1296  timeout = coap_write(ctx, sockets, (unsigned int)(sizeof(sockets) / sizeof(sockets[0])), &num_sockets, before);
1297  if (timeout == 0 || timeout_ms < timeout)
1298  timeout = timeout_ms;
1299 
1300  FD_ZERO(&readfds);
1301  FD_ZERO(&writefds);
1302  FD_ZERO(&exceptfds);
1303  for (i = 0; i < num_sockets; i++) {
1304  if (sockets[i]->fd + 1 > nfds)
1305  nfds = sockets[i]->fd + 1;
1306  if (sockets[i]->flags & COAP_SOCKET_WANT_READ)
1307  FD_SET(sockets[i]->fd, &readfds);
1308  if (sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
1309  FD_SET(sockets[i]->fd, &writefds);
1310  if (sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT)
1311  FD_SET(sockets[i]->fd, &readfds);
1312  if (sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
1313  FD_SET(sockets[i]->fd, &writefds);
1314  FD_SET(sockets[i]->fd, &exceptfds);
1315  }
1316  }
1317 
1318  if ( timeout > 0 ) {
1319  tv.tv_usec = (timeout % 1000) * 1000;
1320  tv.tv_sec = (long)(timeout / 1000);
1321  }
1322 
1323  result = select(nfds, &readfds, &writefds, &exceptfds, timeout > 0 ? &tv : NULL);
1324 
1325  if (result < 0) { /* error */
1326 #ifdef _WIN32
1327  if (WSAGetLastError() != WSAEINVAL) { /* May happen because of ICMP */
1328 #else
1329  if (errno != EINTR) {
1330 #endif
1332  return -1;
1333  }
1334  }
1335 
1336  if (result > 0) {
1337  for (i = 0; i < num_sockets; i++) {
1338  if ((sockets[i]->flags & COAP_SOCKET_WANT_READ) && FD_ISSET(sockets[i]->fd, &readfds))
1339  sockets[i]->flags |= COAP_SOCKET_CAN_READ;
1340  if ((sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && FD_ISSET(sockets[i]->fd, &readfds))
1341  sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT;
1342  if ((sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && FD_ISSET(sockets[i]->fd, &writefds))
1343  sockets[i]->flags |= COAP_SOCKET_CAN_WRITE;
1344  if ((sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && (FD_ISSET(sockets[i]->fd, &writefds) || FD_ISSET(sockets[i]->fd, &exceptfds)))
1345  sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT;
1346  }
1347  }
1348 
1349  coap_ticks(&now);
1350  coap_read(ctx, now);
1351 
1352  return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
1353 }
1354 
1355 #else
1356 int coap_run_once(coap_context_t *ctx, unsigned int timeout_ms) {
1357  return -1;
1358 }
1359 
1360 unsigned int
1362  coap_socket_t *sockets[],
1363  unsigned int max_sockets,
1364  unsigned int *num_sockets,
1365  coap_tick_t now)
1366 {
1367  *num_sockets = 0;
1368  return 0;
1369 }
1370 #endif
1371 
1372 #ifdef _WIN32
1373 static const char *coap_socket_format_errno(int error) {
1374  static char szError[256];
1375  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)
1376  strcpy(szError, "Unknown error");
1377  return szError;
1378 }
1379 
1380 const char *coap_socket_strerror(void) {
1381  return coap_socket_format_errno(WSAGetLastError());
1382 }
1383 #else
1384 #ifndef WITH_CONTIKI
1385 static const char *coap_socket_format_errno(int error) {
1386  return strerror(error);
1387 }
1388 #endif /* WITH_CONTIKI */
1389 
1390 const char *coap_socket_strerror(void) {
1391  return strerror(errno);
1392 }
1393 #endif
1394 
1395 ssize_t
1397  const uint8_t *data, size_t data_len) {
1398  return session->context->network_send(sock, session, data, data_len);
1399 }
1400 
1401 #undef SIN6
#define LL_FOREACH(head, el)
Definition: utlist.h:413
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Definition: coap_io.h:54
#define COAP_RXBUFFER_SIZE
Definition: coap_io.h:19
coap_tick_t last_rx_tx
Definition: coap_session.h:79
void coap_check_notify(coap_context_t *context)
Checks for all known resources, if they are dirty and notifies subscribed observers.
Definition: resource.c:869
#define COAP_SESSION_TYPE_CLIENT
coap_session_type_t values
Definition: coap_session.h:42
void coap_socket_close(coap_socket_t *sock)
Definition: coap_io.c:626
struct coap_context_t * context
session&#39;s context
Definition: coap_session.h:70
struct sockaddr_in6 sin6
Definition: address.h:67
struct sockaddr_in sin
Definition: address.h:66
void * tls
security parameters
Definition: coap_session.h:71
#define coap_closesocket
Definition: coap_io.h:29
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:912
coap_session_t * sessions
list of active sessions
Definition: coap_session.h:308
coap_endpoint_t * endpoint
the endpoints used for listening
Definition: net.h:166
#define COAP_SOCKET_CONNECTED
the socket is connected
Definition: coap_io.h:57
multi-purpose address abstraction
Definition: address.h:62
coap_fd_t fd
Definition: coap_io.h:46
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:1396
#define COAP_SOCKET_MULTICAST
socket is used for multicast communication
Definition: coap_io.h:66
unsigned ref
reference count from queues
Definition: coap_session.h:61
void coap_free_endpoint(coap_endpoint_t *ep)
Definition: coap_session.c:901
coap_tid_t coap_session_send_ping(coap_session_t *session)
Send a ping message for the session.
Definition: coap_session.c:316
int ifindex
the interface index
Definition: coap_io.h:199
#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:490
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:171
COAP_STATIC_INLINE void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.h:104
#define COAP_SOCKET_ERROR
Definition: coap_io.h:30
struct in_addr ipi_spec_dst
Definition: coap_io.c:719
static const char * coap_socket_format_errno(int error)
Definition: coap_io.c:1385
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:268
ssize_t coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len)
Definition: coap_io.c:665
#define COAP_SOCKET_CAN_READ
non blocking socket can now read without blocking
Definition: coap_io.h:62
Debug.
Definition: coap_debug.h:49
#define COAP_INVALID_SOCKET
Definition: coap_io.h:31
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
Definition: coap_io.h:60
unsigned char payload[COAP_RXBUFFER_SIZE]
payload
Definition: coap_io.h:201
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:758
#define COAP_SOCKET_CAN_ACCEPT
non blocking server socket can now accept without blocking
Definition: coap_io.h:64
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
Definition: coap_session.c:71
#define iov_len_t
Definition: coap_io.c:754
coap_queue_t * coap_peek_next(coap_context_t *context)
Returns the next pdu to send without removing from sendqeue.
Definition: net.c:270
Abstraction of virtual endpoint that can be attached to coap_context_t.
Definition: coap_session.h:301
const char * coap_session_str(const coap_session_t *session)
Get session description.
Definition: coap_session.c:943
coap_address_t local_addr
local address and port
Definition: coap_session.h:66
const char * coap_socket_strerror(void)
Definition: coap_io.c:1390
#define COAP_SESSION_STATE_ESTABLISHED
Definition: coap_session.h:54
coap_tick_t sendqueue_basetime
The time stamp in the first element of the sendqeue is relative to sendqueue_basetime.
Definition: net.h:164
int coap_run_once(coap_context_t *ctx, unsigned timeout_ms)
Definition: coap_io.c:1285
struct coap_endpoint_t * coap_malloc_endpoint(void)
Definition: coap_io.c:181
coap_tick_t csm_tx
Definition: coap_session.h:83
int coap_fd_t
Definition: coap_io.h:28
coap_tick_t t
when to send PDU for the next time
Definition: net.h:41
int coap_debug_send_packet(void)
Check to see whether a packet should be sent or not.
Definition: coap_debug.c:833
struct in6_addr ipi6_addr
Definition: coap_io.c:713
void coap_session_mfree(coap_session_t *session)
Definition: coap_session.c:147
unsigned int ping_timeout
Minimum inactivity time before sending a ping message.
Definition: net.h:216
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition: coap_time.h:100
#define COAP_INVALID_TID
Indicates an invalid transaction id.
Definition: pdu.h:241
coap_tick_t last_ping
Definition: coap_session.h:81
coap_address_t remote_addr
remote address and port
Definition: coap_session.h:65
coap_address_t src
the packet&#39;s source address
Definition: coap_io.h:197
ssize_t(* network_send)(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen)
Definition: net.h:199
struct coap_queue_t * delayqueue
list of delayed messages waiting to be sent
Definition: coap_session.h:74
coap_proto_t proto
protocol used
Definition: coap_session.h:58
Warning.
Definition: coap_debug.h:46
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:85
#define assert(...)
Definition: mem.c:18
void coap_packet_set_addr(coap_packet_t *packet, const coap_address_t *src, const coap_address_t *dst)
Definition: coap_io.c:917
coap_session_t hello
special session of DTLS hello messages
Definition: coap_session.h:309
int coap_socket_connect_tcp2(coap_socket_t *sock, coap_address_t *local_addr, coap_address_t *remote_addr)
Definition: coap_io.c:373
void coap_session_free(coap_session_t *session)
Definition: coap_session.c:170
coap_socket_t sock
socket object for the session, if any
Definition: coap_session.h:68
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Definition: coap_io.c:635
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
#define INET6_ADDRSTRLEN
coap_proto_t proto
protocol used on this interface
Definition: coap_session.h:304
Generic resource handling.
coap_session_type_t type
client or server side socket
Definition: coap_session.h:59
void * dtls_context
Definition: net.h:207
coap_session_state_t state
current state of relationaship with peer
Definition: coap_session.h:60
#define COAP_SESSION_TYPE_SERVER
server-side
Definition: coap_session.h:43
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:77
#define COAP_DEFAULT_SESSION_TIMEOUT
Definition: coap_session.h:31
int ifindex
interface index
Definition: coap_session.h:67
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:154
Pre-defined constants that reflect defaults for CoAP.
coap_address_t dst
the packet&#39;s destination address
Definition: coap_io.h:198
COAP_STATIC_INLINE void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
Definition: address.h:116
size_t length
length of payload
Definition: coap_io.h:200
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
Definition: coap_io.h:58
#define LL_FOREACH_SAFE(head, el, tmp)
Definition: utlist.h:419
#define COAP_PROTO_RELIABLE(p)
Definition: coap_session.h:36
#define SOL_IP
Definition: coap_io.c:726
unsigned int csm_timeout
Timeout for waiting for a CSM from the remote side.
Definition: net.h:217
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:1319
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
Definition: coap_io.h:61
coap_tick_t coap_dtls_get_timeout(coap_session_t *session UNUSED)
Definition: coap_notls.c:124
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:128
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:71
int ipi_ifindex
Definition: coap_io.c:718
coap_socket_flags_t flags
Definition: coap_io.h:48
#define COAP_SOCKET_CAN_WRITE
non blocking socket can now write without blocking
Definition: coap_io.h:63
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:383
coap_session_t * sessions
client sessions
Definition: net.h:167
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:122
union coap_address_t::@0 addr
coap_socket_t sock
socket object for the interface, if any
Definition: coap_session.h:306
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:1117
unsigned int ipi6_ifindex
Definition: coap_io.c:714
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:527
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:923
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:59
coap_tick_t last_pong
Definition: coap_session.h:82
#define COAP_SOCKET_CAN_CONNECT
non blocking client socket can now connect without blocking
Definition: coap_io.h:65
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED)
Definition: coap_notls.c:120
Critical.
Definition: coap_debug.h:44
int coap_socket_bind_udp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Definition: coap_io.c:192
#define COAP_SESSION_STATE_NONE
coap_session_state_t values
Definition: coap_session.h:50
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node)
Handles retransmissions of confirmable messages.
Definition: net.c:931
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:278
int coap_socket_bind_tcp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Definition: coap_io.c:413
void coap_mfree_endpoint(struct coap_endpoint_t *ep)
Definition: coap_io.c:186
Queue entry.
Definition: net.h:39
Alert.
Definition: coap_debug.h:43
The CoAP stack&#39;s global state is stored in a coap_context_t object.
Definition: net.h:148
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition: coap_notls.c:116
struct sockaddr sa
Definition: address.h:65
#define COAP_SESSION_STATE_CSM
Definition: coap_session.h:53
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
Definition: coap_io.h:59
unsigned int session_timeout
Number of seconds of inactivity after which an unused session will be closed.
Definition: net.h:213