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