libcoap 4.3.5-develop-5a5330d
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) {
168 coap_session_t *s, *stmp;
169 unsigned int max_sockets = sizeof(ctx->sockets) / sizeof(ctx->sockets[0]);
170 coap_fd_t nfds = 0;
171 unsigned int i;
172
173 ctx->num_sockets = 0;
174#if COAP_SERVER_SUPPORT
175 coap_endpoint_t *ep;
176
177 LL_FOREACH(ctx->endpoint, ep) {
179 if (ctx->num_sockets < max_sockets)
180 ctx->sockets[ctx->num_sockets++] = &ep->sock;
181 }
182 SESSIONS_ITER(ep->sessions, s, stmp) {
184 if (ctx->num_sockets < max_sockets)
185 ctx->sockets[ctx->num_sockets++] = &s->sock;
186 }
187 }
188 }
189#endif /* COAP_SERVER_SUPPORT */
190#if COAP_CLIENT_SUPPORT
191 SESSIONS_ITER(ctx->sessions, s, stmp) {
195 if (ctx->num_sockets < max_sockets)
196 ctx->sockets[ctx->num_sockets++] = &s->sock;
197 }
198 }
199#endif /* COAP_CLIENT_SUPPORT */
200 if (ereadfds) {
201 ctx->readfds = *ereadfds;
202 nfds = enfds;
203 } else {
204 FD_ZERO(&ctx->readfds);
205 }
206 if (ewritefds) {
207 ctx->writefds = *ewritefds;
208 nfds = enfds;
209 } else {
210 FD_ZERO(&ctx->writefds);
211 }
212 if (eexceptfds) {
213 ctx->exceptfds = *eexceptfds;
214 nfds = enfds;
215 } else {
216 FD_ZERO(&ctx->exceptfds);
217 }
218 for (i = 0; i < ctx->num_sockets; i++) {
219 if (ctx->sockets[i]->fd + 1 > nfds)
220 nfds = ctx->sockets[i]->fd + 1;
221 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ)
222 FD_SET(ctx->sockets[i]->fd, &ctx->readfds);
223 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
224 FD_SET(ctx->sockets[i]->fd, &ctx->writefds);
225#if !COAP_DISABLE_TCP
227 FD_SET(ctx->sockets[i]->fd, &ctx->readfds);
228 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
229 FD_SET(ctx->sockets[i]->fd, &ctx->writefds);
230 FD_SET(ctx->sockets[i]->fd, &ctx->exceptfds);
231 }
232#endif /* !COAP_DISABLE_TCP */
233 }
234 return nfds;
235}
236#endif /* ! COAP_EPOLL_SUPPORT && COAP_THREAD_SAFE */
237
238int
240 int enfds, fd_set *ereadfds, fd_set *ewritefds,
241 fd_set *eexceptfds) {
242 coap_fd_t nfds = 0;
243 coap_tick_t before, now;
244 unsigned int timeout;
245#if ! COAP_EPOLL_SUPPORT
246 struct timeval tv;
247 int result;
248 unsigned int i;
249#endif /* ! COAP_EPOLL_SUPPORT */
250
252 coap_ticks(&before);
253
254#if ! COAP_EPOLL_SUPPORT
255
256 timeout = coap_io_prepare_io_lkd(ctx, ctx->sockets,
257 (sizeof(ctx->sockets) / sizeof(ctx->sockets[0])),
258 &ctx->num_sockets, before);
259 ctx->next_timeout = timeout ? timeout + before : 0;
260
261 if (ereadfds) {
262 ctx->readfds = *ereadfds;
263 nfds = enfds;
264 } else {
265 FD_ZERO(&ctx->readfds);
266 }
267 if (ewritefds) {
268 ctx->writefds = *ewritefds;
269 nfds = enfds;
270 } else {
271 FD_ZERO(&ctx->writefds);
272 }
273 if (eexceptfds) {
274 ctx->exceptfds = *eexceptfds;
275 nfds = enfds;
276 } else {
277 FD_ZERO(&ctx->exceptfds);
278 }
279 for (i = 0; i < ctx->num_sockets; i++) {
280 if (ctx->sockets[i]->fd + 1 > nfds)
281 nfds = ctx->sockets[i]->fd + 1;
282 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ)
283 FD_SET(ctx->sockets[i]->fd, &ctx->readfds);
284 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
285 FD_SET(ctx->sockets[i]->fd, &ctx->writefds);
286#if !COAP_DISABLE_TCP
288 FD_SET(ctx->sockets[i]->fd, &ctx->readfds);
289 if (ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
290 FD_SET(ctx->sockets[i]->fd, &ctx->writefds);
291 FD_SET(ctx->sockets[i]->fd, &ctx->exceptfds);
292 }
293#endif /* !COAP_DISABLE_TCP */
294 }
295
296 if (timeout_ms == COAP_IO_NO_WAIT) {
297 tv.tv_usec = 0;
298 tv.tv_sec = 0;
299 timeout = 1;
300 } else if (timeout == 0 && timeout_ms == COAP_IO_WAIT) {
301 ;
302 } else {
303 if (timeout == 0 || (timeout_ms != COAP_IO_WAIT && timeout_ms < timeout))
304 timeout = timeout_ms;
305 tv.tv_usec = (timeout % 1000) * 1000;
306 tv.tv_sec = (long)(timeout / 1000);
307 }
308
309 /* on Windows select will return an error if called without FDs */
310#ifdef _WIN32
311 if (nfds > 0) {
312#endif /* _WIN32 */
313 /* Unlock so that other threads can lock/update ctx */
315
316 result = select((int)nfds, &ctx->readfds, &ctx->writefds, &ctx->exceptfds,
317 timeout > 0 ? &tv : NULL);
318
319 coap_lock_lock(return -1);
320#ifdef _WIN32
321 } else {
322 if (timeout > 0) {
323 DWORD milliseconds = tv.tv_sec * 1000 + tv.tv_usec / 1000;
324
325 if (milliseconds > 2000) {
326 /* Wait at most 2 seconds */
327 milliseconds = 2000;
328 }
329 if (milliseconds) {
330 Sleep(milliseconds);
331 }
332 }
333 goto all_over;
334 }
335#endif /* _WIN32 */
336
337 if (result < 0) { /* error */
338#ifdef _WIN32
339 coap_win_error_to_errno();
340#endif
341 if (errno != EINTR) {
342#if COAP_THREAD_SAFE
343 if (errno == EBADF) {
344 coap_log_debug("select: %s\n", coap_socket_strerror());
345 goto all_over;
346 }
347#endif /* COAP_THREAD_SAFE */
348 coap_log_err("select: %s\n", coap_socket_strerror());
349 return -1;
350 }
351 goto all_over;
352 }
353#if COAP_THREAD_SAFE
354 /* Need to refresh what is available to read / write etc. */
355 nfds = coap_io_prepare_fds(ctx, enfds, ereadfds, ewritefds, eexceptfds);
356 tv.tv_usec = 0;
357 tv.tv_sec = 0;
358 result = select((int)nfds, &ctx->readfds, &ctx->writefds, &ctx->exceptfds, &tv);
359 if (result < 0) { /* error */
360#ifdef _WIN32
361 coap_win_error_to_errno();
362#endif
363 if (errno != EINTR) {
364 if (errno == EBADF) {
365 coap_log_debug("select: %s\n", coap_socket_strerror());
366 goto all_over;
367 }
368 coap_log_err("select: %s\n", coap_socket_strerror());
369 return -1;
370 }
371 goto all_over;
372 }
373#endif /* COAP_THREAD_SAFE */
374 if (ereadfds) {
375 *ereadfds = ctx->readfds;
376 }
377 if (ewritefds) {
378 *ewritefds = ctx->writefds;
379 }
380 if (eexceptfds) {
381 *eexceptfds = ctx->exceptfds;
382 }
383
384 if (result > 0) {
385 for (i = 0; i < ctx->num_sockets; i++) {
386 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ) &&
387 FD_ISSET(ctx->sockets[i]->fd, &ctx->readfds))
389#if !COAP_DISABLE_TCP
390 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) &&
391 FD_ISSET(ctx->sockets[i]->fd, &ctx->readfds))
393 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE) &&
394 FD_ISSET(ctx->sockets[i]->fd, &ctx->writefds))
396 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) &&
397 (FD_ISSET(ctx->sockets[i]->fd, &ctx->writefds) ||
398 FD_ISSET(ctx->sockets[i]->fd, &ctx->exceptfds)))
400#endif /* !COAP_DISABLE_TCP */
401 }
402 }
403
404 coap_ticks(&now);
405 coap_io_do_io_lkd(ctx, now);
406 coap_ticks(&now);
407 timeout = coap_io_prepare_io_lkd(ctx, ctx->sockets,
408 (sizeof(ctx->sockets) / sizeof(ctx->sockets[0])),
409 &ctx->num_sockets, now);
410 ctx->next_timeout = timeout ? timeout + now : 0;
411
412#else /* COAP_EPOLL_SUPPORT */
413 (void)ereadfds;
414 (void)ewritefds;
415 (void)eexceptfds;
416 (void)enfds;
417
418 timeout = coap_io_prepare_epoll_lkd(ctx, before);
419
420 do {
421 struct epoll_event events[COAP_MAX_EPOLL_EVENTS];
422 int etimeout;
423
424 /* Potentially adjust based on what the caller wants */
425 if (timeout_ms == COAP_IO_NO_WAIT) {
426 /* Need to return immediately from epoll_wait() */
427 etimeout = 0;
428 } else if (timeout == 0 && timeout_ms == COAP_IO_WAIT) {
429 /*
430 * Nothing found in coap_io_prepare_epoll_lkd() and COAP_IO_WAIT set,
431 * so wait forever in epoll_wait().
432 */
433 etimeout = -1;
434 } else {
435 etimeout = timeout;
436 if (timeout == 0 || (timeout_ms != COAP_IO_WAIT && timeout_ms < timeout))
437 etimeout = timeout_ms;
438 if (etimeout < 0) {
439 /*
440 * If timeout > INT_MAX, epoll_wait() cannot wait longer than this as
441 * it has int timeout parameter
442 */
443 etimeout = INT_MAX;
444 }
445 }
446
447 /* Unlock so that other threads can lock/update ctx */
449
450 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout);
451 if (nfds < 0) {
452 if (errno != EINTR) {
453 coap_log_err("epoll_wait: unexpected error: %s (%d)\n",
454 coap_socket_strerror(), nfds);
455 }
456 coap_lock_lock(return -1);
457 break;
458 }
459
460 coap_lock_lock(return -1);
461#if COAP_THREAD_SAFE
462 /* Need to refresh what is available to read / write etc. */
463 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, 0);
464 if (nfds < 0) {
465 if (errno != EINTR) {
466 coap_log_err("epoll_wait: unexpected error: %s (%d)\n",
467 coap_socket_strerror(), nfds);
468 }
469 break;
470 }
471#endif /* COAP_THREAD_SAFE */
472
473 coap_io_do_epoll_lkd(ctx, events, nfds);
474
475 /*
476 * reset to COAP_IO_NO_WAIT (which causes etimeout to become 0)
477 * incase we have to do another iteration
478 * (COAP_MAX_EPOLL_EVENTS insufficient)
479 */
480 timeout_ms = COAP_IO_NO_WAIT;
481
482 /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */
483 } while (nfds == COAP_MAX_EPOLL_EVENTS);
484
485#endif /* COAP_EPOLL_SUPPORT */
486#if COAP_SERVER_SUPPORT
488#endif /* COAP_SERVER_SUPPORT */
489#if COAP_ASYNC_SUPPORT
490 /* Check to see if we need to send off any Async requests as delay might
491 have been updated */
492 coap_ticks(&now);
493 coap_check_async(ctx, now, NULL);
494#endif /* COAP_ASYNC_SUPPORT */
495
496#if ! COAP_EPOLL_SUPPORT
497all_over:
498#endif /* COAP_EPOLL_SUPPORT */
499 coap_ticks(&now);
500 return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
501}
502
503volatile int coap_thread_quit = 0;
504
505void
510
511COAP_API int
513 coap_io_process_thread_t main_loop_code,
514 void *main_loop_code_arg, uint32_t timeout_ms,
515 uint32_t thread_count) {
516 int ret;
517
518 if (!context)
519 return 0;
520 coap_lock_lock(return 0);
521 ret = coap_io_process_loop_lkd(context, main_loop_code,
522 main_loop_code_arg, timeout_ms,
523 thread_count);
525 return ret;
526}
527
528int
530 coap_io_process_thread_t main_loop_code,
531 void *main_loop_code_arg, uint32_t timeout_ms,
532 uint32_t thread_count) {
533 int ret = 0;;
534
535#if COAP_THREAD_SAFE
536 if (thread_count > 1) {
537 if (!coap_io_process_configure_threads(context, thread_count - 1))
538 return 0;
539 }
540#else /* COAP_THREAD_SAFE */
541 thread_count = 1;
542#endif /* COAP_THREAD_SAFE */
543 while (!coap_thread_quit) {
544 if (main_loop_code) {
545 coap_tick_t begin, end;
546 uint32_t used_ms;
547
548 coap_ticks(&begin);
549 /*
550 * main_loop_codecode should not be blocking for any time, and not calling
551 * coap_io_process().
552 */
553 coap_lock_callback_release(main_loop_code(main_loop_code_arg),
554 /* On re-lock failure */
555 ret = 0; break);
556 /*
557 * Need to delay for the remainder of timeout_ms. In case main_loop_code()
558 * is time sensitive (e.g Observe subscription to /time), delay to the
559 * start of the a second boundary
560 */
561 coap_ticks(&end);
562 used_ms = (uint32_t)(end - begin) * 1000 / COAP_TICKS_PER_SECOND;
563 if (timeout_ms == COAP_IO_NO_WAIT || timeout_ms == COAP_IO_WAIT) {
564 ret = coap_io_process_lkd(context, timeout_ms);
565 } else if (timeout_ms > used_ms) {
566 /* Wait for remaining time rounded up to next second start */
567 coap_tick_t next_time = end + (timeout_ms - used_ms) * COAP_TICKS_PER_SECOND / 1000;
568 unsigned int next_sec_us;
569 unsigned int next_sec_ms;
570
571 next_sec_us = (timeout_ms - used_ms) * 1000000 / COAP_TICKS_PER_SECOND + 1000000 -
572 (coap_ticks_to_rt_us(next_time) % 1000000);
573 next_sec_ms = (next_sec_us + 999) / 1000;
574 if (next_sec_ms > timeout_ms && next_sec_ms > 1000)
575 next_sec_ms -= 1000;
576 ret = coap_io_process_lkd(context, next_sec_ms ? next_sec_ms : 1);
577 } else {
578 /* timeout_ms has expired */
579 ret = coap_io_process_lkd(context, COAP_IO_NO_WAIT);
580 }
581
582 if (thread_count == 1) {
583 /*
584 * Need to delay if only one thread until the remainder of
585 * timeout_ms is used up. Otherwise, another thread will be
586 * waiting on coap_io_process() to do any input / timeout work.
587 */
588 coap_ticks(&end);
589 used_ms = (uint32_t)(end - begin) * 1000 / COAP_TICKS_PER_SECOND;
590 if (timeout_ms > 0 && timeout_ms < used_ms) {
591 ret = coap_io_process_lkd(context, used_ms - timeout_ms);
592 } else {
593 ret = coap_io_process_lkd(context, COAP_IO_NO_WAIT);
594 }
595 }
596 } else {
597 ret = coap_io_process_lkd(context, timeout_ms);
598 }
599 /* coap_io_process_lkd() can return 0 */
600 if (ret >= 0)
601 ret = 1;
602
603 if (ret < 0) {
604 ret = 0;
605 break;
606 }
607 }
608#if COAP_THREAD_SAFE
610#endif /* COAP_THREAD_SAFE */
612 return ret;
613}
614
615#else /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
616
617#ifdef __clang__
618/* Make compilers happy that do not like empty modules. As this function is
619 * never used, we ignore -Wunused-function at the end of compiling this file
620 */
621#pragma GCC diagnostic ignored "-Wunused-function"
622#endif
623static inline void
624dummy(void) {
625}
626
627#endif /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
static void dummy(void)
const char * coap_socket_strerror(void)
Definition coap_io.c:847
#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_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
volatile int coap_thread_quit
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:2806
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:2736
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:314
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:2115
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
fd_set exceptfds
Used for select call in coap_io_process_with_fds_lkd()
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