libcoap 4.3.5-develop-3c685a2
Loading...
Searching...
No Matches
coap_io_posix.c
Go to the documentation of this file.
1/* coap_io_posix.c -- Network I/O functions for libcoap using Posix
2 *
3 * Copyright (C) 2012,2014,2016-2025 Olaf Bergmann <bergmann@tzi.org> and others
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10
17
18#if ! defined(WITH_LWIP) && ! defined(WITH_CONTIKI) && ! defined (RIOT_VERSION)
19
20#ifdef HAVE_STDIO_H
21# include <stdio.h>
22#endif
23#ifdef HAVE_UNISTD_H
24# include <unistd.h>
25#endif
26
27#ifndef __ZEPHYR__
28#ifdef HAVE_SYS_SELECT_H
29# include <sys/select.h>
30#endif
31#ifdef HAVE_SYS_SOCKET_H
32# include <sys/socket.h>
33#endif
34#ifdef HAVE_SYS_IOCTL_H
35#include <sys/ioctl.h>
36#endif
37#ifdef HAVE_NETINET_IN_H
38# include <netinet/in.h>
39#endif
40#ifdef HAVE_SYS_UIO_H
41# include <sys/uio.h>
42#endif
43#ifdef _WIN32
44#include <stdio.h>
45#endif /* _WIN32 */
46#if COAP_EPOLL_SUPPORT
47#include <sys/epoll.h>
48#include <sys/timerfd.h>
49#ifdef HAVE_LIMITS_H
50#include <limits.h>
51#endif
52#endif /* COAP_EPOLL_SUPPORT */
53#else /* __ZEPHYR__ */
54#include <sys/ioctl.h>
55#include <sys/select.h>
56#endif /* __ZEPHYR__ */
57
58#if COAP_EPOLL_SUPPORT
59void
61 uint32_t events,
62 const char *func) {
63 int ret;
64 struct epoll_event event;
65 coap_context_t *context;
66
67#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR
68 (void)func;
69#endif
70
71 if (sock == NULL)
72 return;
73
74#if COAP_SERVER_SUPPORT
75 context = sock->session ? sock->session->context :
76 sock->endpoint ? sock->endpoint->context : NULL;
77#else /* ! COAP_SERVER_SUPPORT */
78 context = sock->session ? sock->session->context : NULL;
79#endif /* ! COAP_SERVER_SUPPORT */
80 if (context == NULL)
81 return;
82
83 /* Needed if running 32bit as ptr is only 32bit */
84 memset(&event, 0, sizeof(event));
85 event.events = events;
86 event.data.ptr = sock;
87
88 ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->fd, &event);
89 if (ret == -1) {
90 coap_log_err("%s: epoll_ctl ADD failed: %s (%d)\n",
91 func,
92 coap_socket_strerror(), errno);
93 }
94}
95
96void
98 uint32_t events,
99 const char *func) {
100 int ret;
101 struct epoll_event event;
102 coap_context_t *context;
103
104#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_ERR
105 (void)func;
106#endif
107
108 if (sock == NULL)
109 return;
110
111#if COAP_SERVER_SUPPORT
112 context = sock->session ? sock->session->context :
113 sock->endpoint ? sock->endpoint->context : NULL;
114#else /* COAP_SERVER_SUPPORT */
115 context = sock->session ? sock->session->context : NULL;
116#endif /* COAP_SERVER_SUPPORT */
117 if (context == NULL)
118 return;
119
120 event.events = events;
121 event.data.ptr = sock;
122
123 ret = epoll_ctl(context->epfd, EPOLL_CTL_MOD, sock->fd, &event);
124 if (ret == -1) {
125#if (COAP_MAX_LOGGING_LEVEL < COAP_LOG_ERR)
126 (void)func;
127#endif
128 coap_log_err("%s: epoll_ctl MOD failed: %s (%d)\n",
129 func,
130 coap_socket_strerror(), errno);
131 }
132}
133#endif /* COAP_EPOLL_SUPPORT */
134
135COAP_API int
136coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) {
137 int ret;
138
139 coap_lock_lock(return 0);
140 ret = coap_io_process_lkd(ctx, timeout_ms);
142 return ret;
143}
144
145int
146coap_io_process_lkd(coap_context_t *ctx, uint32_t timeout_ms) {
147 return coap_io_process_with_fds_lkd(ctx, timeout_ms, 0, NULL, NULL, NULL);
148}
149
150COAP_API int
151coap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms,
152 int enfds, fd_set *ereadfds, fd_set *ewritefds,
153 fd_set *eexceptfds) {
154 int ret;
155
156 coap_lock_lock(return 0);
157 ret = coap_io_process_with_fds_lkd(ctx, timeout_ms, enfds, ereadfds, ewritefds,
158 eexceptfds);
160 return ret;
161}
162
163#if ! COAP_EPOLL_SUPPORT && COAP_THREAD_SAFE
164static unsigned int
165coap_io_prepare_fds(coap_context_t *ctx,
166 int enfds, fd_set *ereadfds, fd_set *ewritefds,
167 fd_set *eexceptfds, fd_set *readfds, fd_set *writefds,
168 fd_set *exceptfds
169 ) {
170 coap_session_t *s, *stmp;
171 unsigned int max_sockets = sizeof(ctx->sockets) / sizeof(ctx->sockets[0]);
172 coap_fd_t nfds = 0;
173 unsigned int i;
174
175 ctx->num_sockets = 0;
176#if COAP_SERVER_SUPPORT
177 coap_endpoint_t *ep;
178
179 LL_FOREACH(ctx->endpoint, ep) {
181 if (ctx->num_sockets < max_sockets)
182 ctx->sockets[ctx->num_sockets++] = &ep->sock;
183 }
184 SESSIONS_ITER(ep->sessions, s, stmp) {
186 if (ctx->num_sockets < max_sockets && !(s->sock.flags & COAP_SOCKET_SLAVE))
187 ctx->sockets[ctx->num_sockets++] = &s->sock;
188 }
189 }
190 }
191#endif /* COAP_SERVER_SUPPORT */
192#if COAP_CLIENT_SUPPORT
193 SESSIONS_ITER(ctx->sessions, s, stmp) {
197 if (ctx->num_sockets < max_sockets && !(s->sock.flags & COAP_SOCKET_SLAVE))
198 ctx->sockets[ctx->num_sockets++] = &s->sock;
199 }
200 }
201#endif /* COAP_CLIENT_SUPPORT */
202 if (ereadfds) {
203 *readfds = *ereadfds;
204 nfds = enfds;
205 } else {
206 FD_ZERO(readfds);
207 }
208 if (ewritefds) {
209 *writefds = *ewritefds;
210 nfds = enfds;
211 } else {
212 FD_ZERO(writefds);
213 }
214 if (eexceptfds) {
215 *exceptfds = *eexceptfds;
216 nfds = enfds;
217 } else {
218 FD_ZERO(exceptfds);
219 }
220 for (i = 0; i < ctx->num_sockets; i++) {
221 if (ctx->sockets[i]->fd + 1 > nfds)
222 nfds = ctx->sockets[i]->fd + 1;
223 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ)
224 FD_SET(ctx->sockets[i]->fd, readfds);
225 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
226 FD_SET(ctx->sockets[i]->fd, writefds);
227#if !COAP_DISABLE_TCP
229 FD_SET(ctx->sockets[i]->fd, readfds);
230 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
231 FD_SET(ctx->sockets[i]->fd, writefds);
232 FD_SET(ctx->sockets[i]->fd, exceptfds);
233 }
234#endif /* !COAP_DISABLE_TCP */
235 }
236 return nfds;
237}
238#endif /* ! COAP_EPOLL_SUPPORT && COAP_THREAD_SAFE */
239
240int
242 int enfds, fd_set *ereadfds, fd_set *ewritefds,
243 fd_set *eexceptfds) {
244 coap_fd_t nfds = 0;
245 coap_tick_t before, now;
246 unsigned int timeout;
247#if ! COAP_EPOLL_SUPPORT
248 struct timeval tv;
249 int result;
250 unsigned int i;
251#if ! COAP_CONSTRAINED_STACK
252 fd_set readfds, writefds, exceptfds;
253#define COAP_READFDS readfds
254#define COAP_WRITEFDS writefds
255#define COAP_EXCEPTFDS exceptfds
256#else
257#define COAP_READFDS (ctx->readfds)
258#define COAP_WRITEFDS (ctx->writefds)
259#define COAP_EXCEPTFDS (ctx->exceptfds)
260#endif /* ! COAP_CONSTRAINED_STACK */
261#endif /* ! COAP_EPOLL_SUPPORT */
262
264 coap_ticks(&before);
265
266#if ! COAP_EPOLL_SUPPORT
267
268 timeout = coap_io_prepare_io_lkd(ctx, ctx->sockets,
269 (sizeof(ctx->sockets) / sizeof(ctx->sockets[0])),
270 &ctx->num_sockets, before);
271 ctx->next_timeout = timeout ? timeout + before : 0;
272
273 if (ereadfds) {
274 COAP_READFDS = *ereadfds;
275 nfds = enfds;
276 } else {
277 FD_ZERO(&COAP_READFDS);
278 }
279 if (ewritefds) {
280 COAP_WRITEFDS = *ewritefds;
281 nfds = enfds;
282 } else {
283 FD_ZERO(&COAP_WRITEFDS);
284 }
285 if (eexceptfds) {
286 COAP_EXCEPTFDS = *eexceptfds;
287 nfds = enfds;
288 } else {
289 FD_ZERO(&COAP_EXCEPTFDS);
290 }
291 for (i = 0; i < ctx->num_sockets; i++) {
292 if (ctx->sockets[i]->fd + 1 > nfds)
293 nfds = ctx->sockets[i]->fd + 1;
294 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ)
295 FD_SET(ctx->sockets[i]->fd, &COAP_READFDS);
296 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
297 FD_SET(ctx->sockets[i]->fd, &COAP_WRITEFDS);
298#if !COAP_DISABLE_TCP
300 FD_SET(ctx->sockets[i]->fd, &COAP_READFDS);
301 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
302 FD_SET(ctx->sockets[i]->fd, &COAP_WRITEFDS);
303 FD_SET(ctx->sockets[i]->fd, &COAP_EXCEPTFDS);
304 }
305#endif /* !COAP_DISABLE_TCP */
306 }
307
308 if (timeout_ms == COAP_IO_NO_WAIT) {
309 tv.tv_usec = 0;
310 tv.tv_sec = 0;
311 timeout = 1;
312 } else if (timeout == 0 && timeout_ms == COAP_IO_WAIT) {
313 ;
314 } else {
315 if (timeout == 0 || (timeout_ms != COAP_IO_WAIT && timeout_ms < timeout))
316 timeout = timeout_ms;
317 tv.tv_usec = (timeout % 1000) * 1000;
318 tv.tv_sec = (long)(timeout / 1000);
319 }
320
321 /* on Windows select will return an error if called without FDs */
322#ifdef _WIN32
323 if (nfds > 0) {
324#endif /* _WIN32 */
325 /* Unlock so that other threads can lock/update ctx */
327
328 result = select((int)nfds, &COAP_READFDS, &COAP_WRITEFDS, &COAP_EXCEPTFDS,
329 timeout > 0 ? &tv : NULL);
330
331 coap_lock_lock(return -1);
332#ifdef _WIN32
333 } else {
334 if (timeout > 0) {
335 DWORD milliseconds = tv.tv_sec * 1000 + tv.tv_usec / 1000;
336
337 if (milliseconds > 2000) {
338 /* Wait at most 2 seconds */
339 milliseconds = 2000;
340 }
341 if (milliseconds) {
343 Sleep(milliseconds);
344 coap_lock_lock(return -1);
345 }
346 }
347 result = 0;
348 }
349#endif /* _WIN32 */
350
351 if (result < 0) { /* error */
352#ifdef _WIN32
353 coap_win_error_to_errno();
354#endif /* _WIN32 */
355 if (errno != EINTR) {
356#if COAP_THREAD_SAFE
357 if (errno == EBADF) {
358 coap_log_debug("select: %s\n", coap_socket_strerror());
359 goto all_over;
360 }
361#endif /* COAP_THREAD_SAFE */
362 coap_log_err("select: %s\n", coap_socket_strerror());
363 return -1;
364 }
365 goto all_over;
366 }
367#if COAP_THREAD_SAFE
368 /* Need to refresh what is available to read / write etc. */
369 nfds = coap_io_prepare_fds(ctx, enfds, ereadfds, ewritefds, eexceptfds,
371#ifdef _WIN32
372 if (nfds > 0) {
373#endif /* _WIN32 */
374 tv.tv_usec = 0;
375 tv.tv_sec = 0;
376 result = select((int)nfds, &COAP_READFDS, &COAP_WRITEFDS, &COAP_EXCEPTFDS, &tv);
377 if (result < 0) { /* error */
378#ifdef _WIN32
379 coap_win_error_to_errno();
380#endif /* _WIN32 */
381 if (errno != EINTR) {
382 if (errno == EBADF) {
383 coap_log_debug("select: %s\n", coap_socket_strerror());
384 goto all_over;
385 }
386 coap_log_err("select: %s\n", coap_socket_strerror());
387 return -1;
388 }
389 goto all_over;
390 }
391#ifdef _WIN32
392 }
393#endif /* _WIN32 */
394#endif /* COAP_THREAD_SAFE */
395 if (ereadfds) {
396 *ereadfds = COAP_READFDS;
397 }
398 if (ewritefds) {
399 *ewritefds = COAP_WRITEFDS;
400 }
401 if (eexceptfds) {
402 *eexceptfds = COAP_EXCEPTFDS;
403 }
404
405 if (result > 0) {
406 for (i = 0; i < ctx->num_sockets; i++) {
407 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ) &&
408 FD_ISSET(ctx->sockets[i]->fd, &COAP_READFDS))
410#if !COAP_DISABLE_TCP
411 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) &&
412 FD_ISSET(ctx->sockets[i]->fd, &COAP_READFDS))
414 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE) &&
415 FD_ISSET(ctx->sockets[i]->fd, &COAP_WRITEFDS))
417 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) &&
418 (FD_ISSET(ctx->sockets[i]->fd, &COAP_WRITEFDS) ||
419 FD_ISSET(ctx->sockets[i]->fd, &COAP_EXCEPTFDS)))
421#endif /* !COAP_DISABLE_TCP */
422 }
423 }
424
425 coap_ticks(&now);
426 coap_io_do_io_lkd(ctx, now);
427 coap_ticks(&now);
428 timeout = coap_io_prepare_io_lkd(ctx, ctx->sockets,
429 (sizeof(ctx->sockets) / sizeof(ctx->sockets[0])),
430 &ctx->num_sockets, now);
431 ctx->next_timeout = timeout ? timeout + now : 0;
432
433#else /* COAP_EPOLL_SUPPORT */
434 (void)ereadfds;
435 (void)ewritefds;
436 (void)eexceptfds;
437 (void)enfds;
438
439 timeout = coap_io_prepare_epoll_lkd(ctx, before);
440
441 do {
442 struct epoll_event events[COAP_MAX_EPOLL_EVENTS];
443 int etimeout;
444
445 /* Potentially adjust based on what the caller wants */
446 if (timeout_ms == COAP_IO_NO_WAIT) {
447 /* Need to return immediately from epoll_wait() */
448 etimeout = 0;
449 } else if (timeout == 0 && timeout_ms == COAP_IO_WAIT) {
450 /*
451 * Nothing found in coap_io_prepare_epoll_lkd() and COAP_IO_WAIT set,
452 * so wait forever in epoll_wait().
453 */
454 etimeout = -1;
455 } else {
456 etimeout = timeout;
457 if (timeout == 0 || (timeout_ms != COAP_IO_WAIT && timeout_ms < timeout))
458 etimeout = timeout_ms;
459 if (etimeout < 0) {
460 /*
461 * If timeout > INT_MAX, epoll_wait() cannot wait longer than this as
462 * it has int timeout parameter
463 */
464 etimeout = INT_MAX;
465 }
466 }
467
468 /* Unlock so that other threads can lock/update ctx */
470
471 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout);
472 if (nfds < 0) {
473 if (errno != EINTR) {
474 coap_log_err("epoll_wait: unexpected error: %s (%d)\n",
475 coap_socket_strerror(), nfds);
476 }
477 coap_lock_lock(return -1);
478 break;
479 }
480
481 coap_lock_lock(return -1);
482#if COAP_THREAD_SAFE
483 /* Need to refresh what is available to read / write etc. */
484 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, 0);
485 if (nfds < 0) {
486 if (errno != EINTR) {
487 coap_log_err("epoll_wait: unexpected error: %s (%d)\n",
488 coap_socket_strerror(), nfds);
489 }
490 break;
491 }
492#endif /* COAP_THREAD_SAFE */
493
494 coap_io_do_epoll_lkd(ctx, events, nfds);
495
496 /*
497 * reset to COAP_IO_NO_WAIT (which causes etimeout to become 0)
498 * incase we have to do another iteration
499 * (COAP_MAX_EPOLL_EVENTS insufficient)
500 */
501 timeout_ms = COAP_IO_NO_WAIT;
502
503 /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */
504 } while (nfds == COAP_MAX_EPOLL_EVENTS);
505
506#endif /* COAP_EPOLL_SUPPORT */
507#if COAP_SERVER_SUPPORT
509#endif /* COAP_SERVER_SUPPORT */
510#if COAP_ASYNC_SUPPORT
511 /* Check to see if we need to send off any Async requests as delay might
512 have been updated */
513 coap_ticks(&now);
514 coap_check_async(ctx, now, NULL);
515#endif /* COAP_ASYNC_SUPPORT */
516
517#if ! COAP_EPOLL_SUPPORT
518all_over:
519#endif /* COAP_EPOLL_SUPPORT */
520 coap_ticks(&now);
521 return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
522}
523
524volatile int coap_thread_quit = 0;
525
526void
531
532COAP_API int
534 coap_io_process_thread_t main_loop_code,
535 void *main_loop_code_arg, uint32_t timeout_ms,
536 uint32_t thread_count) {
537 int ret;
538
539 if (!context)
540 return 0;
541 coap_lock_lock(return 0);
542 ret = coap_io_process_loop_lkd(context, main_loop_code,
543 main_loop_code_arg, timeout_ms,
544 thread_count);
546 return ret;
547}
548
549int
551 coap_io_process_thread_t main_loop_code,
552 void *main_loop_code_arg, uint32_t timeout_ms,
553 uint32_t thread_count) {
554 int ret = 0;;
555
556#if COAP_THREAD_SAFE
557 if (thread_count > 1) {
558 if (!coap_io_process_configure_threads(context, thread_count - 1))
559 return 0;
560 }
561#else /* COAP_THREAD_SAFE */
562 thread_count = 1;
563#endif /* COAP_THREAD_SAFE */
564 while (!coap_thread_quit) {
565 if (main_loop_code) {
566 coap_tick_t begin, end;
567 uint32_t used_ms;
568
569 coap_ticks(&begin);
570 /*
571 * main_loop_codecode should not be blocking for any time, and not calling
572 * coap_io_process().
573 */
574 coap_lock_callback_release(main_loop_code(main_loop_code_arg),
575 /* On re-lock failure */
576 ret = 0; break);
577 /*
578 * Need to delay for the remainder of timeout_ms. In case main_loop_code()
579 * is time sensitive (e.g Observe subscription to /time), delay to the
580 * start of the a second boundary
581 */
582 coap_ticks(&end);
583 used_ms = (uint32_t)(end - begin) * 1000 / COAP_TICKS_PER_SECOND;
584 if (timeout_ms == COAP_IO_NO_WAIT || timeout_ms == COAP_IO_WAIT) {
585 ret = coap_io_process_lkd(context, timeout_ms);
586 } else if (timeout_ms > used_ms) {
587 /* Wait for remaining time rounded up to next second start */
588 coap_tick_t next_time = end + (timeout_ms - used_ms) * COAP_TICKS_PER_SECOND / 1000;
589 unsigned int next_sec_us;
590 unsigned int next_sec_ms;
591
592 next_sec_us = (timeout_ms - used_ms) * 1000000 / COAP_TICKS_PER_SECOND + 1000000 -
593 (coap_ticks_to_rt_us(next_time) % 1000000);
594 next_sec_ms = (next_sec_us + 999) / 1000;
595 if (next_sec_ms > timeout_ms && next_sec_ms > 1000)
596 next_sec_ms -= 1000;
597 ret = coap_io_process_lkd(context, next_sec_ms ? next_sec_ms : 1);
598 } else {
599 /* timeout_ms has expired */
600 ret = coap_io_process_lkd(context, COAP_IO_NO_WAIT);
601 }
602
603 if (thread_count == 1) {
604 /*
605 * Need to delay if only one thread until the remainder of
606 * timeout_ms is used up. Otherwise, another thread will be
607 * waiting on coap_io_process() to do any input / timeout work.
608 */
609 coap_ticks(&end);
610 used_ms = (uint32_t)(end - begin) * 1000 / COAP_TICKS_PER_SECOND;
611 if (timeout_ms > 0 && timeout_ms < used_ms) {
612 ret = coap_io_process_lkd(context, used_ms - timeout_ms);
613 } else {
614 ret = coap_io_process_lkd(context, COAP_IO_NO_WAIT);
615 }
616 }
617 } else {
618 ret = coap_io_process_lkd(context, timeout_ms);
619 }
620 /* coap_io_process_lkd() can return 0 */
621 if (ret >= 0)
622 ret = 1;
623
624 if (ret < 0) {
625 ret = 0;
626 break;
627 }
628 }
629#if COAP_THREAD_SAFE
631#endif /* COAP_THREAD_SAFE */
633 return ret;
634}
635
636#else /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
637
638#ifdef __clang__
639/* Make compilers happy that do not like empty modules. As this function is
640 * never used, we ignore -Wunused-function at the end of compiling this file
641 */
642#pragma GCC diagnostic ignored "-Wunused-function"
643#endif
644static inline void
645dummy(void) {
646}
647
648#endif /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
static void dummy(void)
const char * coap_socket_strerror(void)
Definition coap_io.c:935
#define COAP_MAX_EPOLL_EVENTS
Definition coap_io.h:42
int coap_fd_t
Definition coap_io.h:51
void coap_epoll_ctl_add(coap_socket_t *sock, uint32_t events, const char *func)
Epoll specific function to add the state of events that epoll is to track for the appropriate file de...
#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_SLAVE
socket is a slave socket - do not close
#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)
Epoll specific function to modify the state of events that epoll is tracking on the appropriate file ...
#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_READFDS
volatile int coap_thread_quit
#define COAP_WRITEFDS
#define COAP_EXCEPTFDS
Library specific build wrapper for coap_internal.h.
#define COAP_API
#define SESSIONS_ITER(e, el, rtmp)
void coap_io_do_epoll_lkd(coap_context_t *ctx, struct epoll_event *events, size_t nevents)
Process all the epoll events.
Definition coap_net.c:2829
int coap_io_process_loop_lkd(coap_context_t *context, coap_io_process_thread_t main_loop_code, void *main_loop_code_arg, uint32_t timeout_ms, uint32_t thread_count)
Do the coap_io_process() across thread_count threads.
void coap_io_do_io_lkd(coap_context_t *ctx, coap_tick_t now)
Processes any outstanding read, write, accept or connect I/O as indicated in the coap_socket_t struct...
Definition coap_net.c:2759
int coap_io_process_lkd(coap_context_t *ctx, uint32_t timeout_ms)
The main I/O processing function.
int coap_io_process_with_fds_lkd(coap_context_t *ctx, uint32_t timeout_ms, int enfds, fd_set *ereadfds, fd_set *ewritefds, fd_set *eexceptfds)
The main message processing loop with additional fds for internal select.
unsigned int coap_io_prepare_io_lkd(coap_context_t *ctx, coap_socket_t *sockets[], unsigned int max_sockets, unsigned int *num_sockets, coap_tick_t now)
Iterates through all the coap_socket_t structures embedded in endpoints or sessions associated with t...
Definition coap_io.c:331
unsigned int coap_io_prepare_epoll_lkd(coap_context_t *ctx, coap_tick_t now)
Any now timed out delayed packet is transmitted, along with any packets associated with requested obs...
Definition coap_io.c:219
COAP_API int coap_io_process(coap_context_t *ctx, uint32_t timeout_ms)
The main I/O processing function.
int coap_io_process_configure_threads(coap_context_t *context, uint32_t thread_count)
Configure a defined number of threads to do the alternate coap_io_process() work with traffic load ba...
void coap_io_process_terminate_loop(void)
Terminate all the additional threads created by coap_io_process_loop() and break out of the main thre...
void coap_io_process_remove_threads(coap_context_t *context)
Release the coap_io_process() worker threads.
COAP_API int coap_io_process_loop(coap_context_t *context, coap_io_process_thread_t main_loop_code, void *main_loop_code_arg, uint32_t timeout_ms, uint32_t thread_count)
Do the coap_io_process() across thread_count threads.
#define COAP_IO_NO_WAIT
Definition coap_net.h:826
COAP_API int coap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms, int enfds, fd_set *ereadfds, fd_set *ewritefds, fd_set *eexceptfds)
The main message processing loop with additional fds for internal select.
#define COAP_IO_WAIT
Definition coap_net.h:825
void(* coap_io_process_thread_t)(void *arg)
Main thread coap_io_process_loop activity.
Definition coap_net.h:1007
void coap_expire_cache_entries(coap_context_t *context)
Expire coap_cache_entry_t entries.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:151
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:166
uint64_t coap_ticks_to_rt_us(coap_tick_t t)
Helper function that converts coap ticks to POSIX wallclock time in us.
Definition coap_time.c:128
void coap_send_recv_terminate(void)
Terminate any active coap_send_recv() sessions.
Definition coap_net.c:2138
void coap_ticks(coap_tick_t *t)
Returns the current value of an internal tick counter.
Definition coap_time.c:90
#define coap_lock_unlock()
Dummy for no thread-safe code.
#define coap_lock_check_locked()
Dummy for no thread-safe code.
#define coap_lock_callback_release(func, failed)
Dummy for no thread-safe code.
#define coap_lock_lock(failed)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:126
#define coap_log_err(...)
Definition coap_debug.h:102
The CoAP stack's global state is stored in a coap_context_t object.
coap_socket_t * sockets[64]
Track different socket information in coap_io_process_with_fds_lkd()
unsigned int num_sockets
Number of sockets being tracked.
coap_session_t * sessions
client sessions
coap_endpoint_t * endpoint
the endpoints used for listening
coap_tick_t next_timeout
When the next timeout is to occur.
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
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_context_t * context
session's context
coap_session_t * session
Used to determine session owner.
coap_endpoint_t * endpoint
Used by the epoll logic for a listening endpoint.
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values