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