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