libcoap 4.3.5-develop-490e4e0
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 if (nfds > 0) {
311 /* Unlock so that other threads can lock/update ctx */
313
314 result = select((int)nfds, &ctx->readfds, &ctx->writefds, &ctx->exceptfds,
315 timeout > 0 ? &tv : NULL);
316
317 coap_lock_lock(return -1);
318 } else {
319 goto all_over;
320 }
321
322 if (result < 0) { /* error */
323#ifdef _WIN32
324 coap_win_error_to_errno();
325#endif
326 if (errno != EINTR) {
327#if COAP_THREAD_SAFE
328 if (errno == EBADF) {
329 coap_log_debug("select: %s\n", coap_socket_strerror());
330 goto all_over;
331 }
332#endif /* COAP_THREAD_SAFE */
333 coap_log_err("select: %s\n", coap_socket_strerror());
334 return -1;
335 }
336 goto all_over;
337 }
338#if COAP_THREAD_SAFE
339 /* Need to refresh what is available to read / write etc. */
340 nfds = coap_io_prepare_fds(ctx, enfds, ereadfds, ewritefds, eexceptfds);
341 tv.tv_usec = 0;
342 tv.tv_sec = 0;
343 result = select((int)nfds, &ctx->readfds, &ctx->writefds, &ctx->exceptfds, &tv);
344 if (result < 0) { /* error */
345#ifdef _WIN32
346 coap_win_error_to_errno();
347#endif
348 if (errno != EINTR) {
349 if (errno == EBADF) {
350 coap_log_debug("select: %s\n", coap_socket_strerror());
351 goto all_over;
352 }
353 coap_log_err("select: %s\n", coap_socket_strerror());
354 return -1;
355 }
356 goto all_over;
357 }
358#endif /* COAP_THREAD_SAFE */
359 if (ereadfds) {
360 *ereadfds = ctx->readfds;
361 }
362 if (ewritefds) {
363 *ewritefds = ctx->writefds;
364 }
365 if (eexceptfds) {
366 *eexceptfds = ctx->exceptfds;
367 }
368
369 if (result > 0) {
370 for (i = 0; i < ctx->num_sockets; i++) {
371 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_READ) &&
372 FD_ISSET(ctx->sockets[i]->fd, &ctx->readfds))
374#if !COAP_DISABLE_TCP
375 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) &&
376 FD_ISSET(ctx->sockets[i]->fd, &ctx->readfds))
378 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_WRITE) &&
379 FD_ISSET(ctx->sockets[i]->fd, &ctx->writefds))
381 if ((ctx->sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) &&
382 (FD_ISSET(ctx->sockets[i]->fd, &ctx->writefds) ||
383 FD_ISSET(ctx->sockets[i]->fd, &ctx->exceptfds)))
385#endif /* !COAP_DISABLE_TCP */
386 }
387 }
388
389 coap_ticks(&now);
390 coap_io_do_io_lkd(ctx, now);
391 coap_ticks(&now);
392 timeout = coap_io_prepare_io_lkd(ctx, ctx->sockets,
393 (sizeof(ctx->sockets) / sizeof(ctx->sockets[0])),
394 &ctx->num_sockets, now);
395 ctx->next_timeout = timeout ? timeout + now : 0;
396
397#else /* COAP_EPOLL_SUPPORT */
398 (void)ereadfds;
399 (void)ewritefds;
400 (void)eexceptfds;
401 (void)enfds;
402
403 timeout = coap_io_prepare_epoll_lkd(ctx, before);
404
405 do {
406 struct epoll_event events[COAP_MAX_EPOLL_EVENTS];
407 int etimeout;
408
409 /* Potentially adjust based on what the caller wants */
410 if (timeout_ms == COAP_IO_NO_WAIT) {
411 /* Need to return immediately from epoll_wait() */
412 etimeout = 0;
413 } else if (timeout == 0 && timeout_ms == COAP_IO_WAIT) {
414 /*
415 * Nothing found in coap_io_prepare_epoll_lkd() and COAP_IO_WAIT set,
416 * so wait forever in epoll_wait().
417 */
418 etimeout = -1;
419 } else {
420 etimeout = timeout;
421 if (timeout == 0 || (timeout_ms != COAP_IO_WAIT && timeout_ms < timeout))
422 etimeout = timeout_ms;
423 if (etimeout < 0) {
424 /*
425 * If timeout > INT_MAX, epoll_wait() cannot wait longer than this as
426 * it has int timeout parameter
427 */
428 etimeout = INT_MAX;
429 }
430 }
431
432 /* Unlock so that other threads can lock/update ctx */
434
435 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout);
436 if (nfds < 0) {
437 if (errno != EINTR) {
438 coap_log_err("epoll_wait: unexpected error: %s (%d)\n",
439 coap_socket_strerror(), nfds);
440 }
441 coap_lock_lock(return -1);
442 break;
443 }
444
445 coap_lock_lock(return -1);
446#if COAP_THREAD_SAFE
447 /* Need to refresh what is available to read / write etc. */
448 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, 0);
449 if (nfds < 0) {
450 if (errno != EINTR) {
451 coap_log_err("epoll_wait: unexpected error: %s (%d)\n",
452 coap_socket_strerror(), nfds);
453 }
454 break;
455 }
456#endif /* COAP_THREAD_SAFE */
457
458 coap_io_do_epoll_lkd(ctx, events, nfds);
459
460 /*
461 * reset to COAP_IO_NO_WAIT (which causes etimeout to become 0)
462 * incase we have to do another iteration
463 * (COAP_MAX_EPOLL_EVENTS insufficient)
464 */
465 timeout_ms = COAP_IO_NO_WAIT;
466
467 /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */
468 } while (nfds == COAP_MAX_EPOLL_EVENTS);
469
470#endif /* COAP_EPOLL_SUPPORT */
471#if COAP_SERVER_SUPPORT
473#endif /* COAP_SERVER_SUPPORT */
474#if COAP_ASYNC_SUPPORT
475 /* Check to see if we need to send off any Async requests as delay might
476 have been updated */
477 coap_ticks(&now);
478 coap_check_async(ctx, now, NULL);
479#endif /* COAP_ASYNC_SUPPORT */
480
481#if ! COAP_EPOLL_SUPPORT
482all_over:
483#endif /* COAP_EPOLL_SUPPORT */
484 coap_ticks(&now);
485 return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
486}
487
488volatile int coap_thread_quit = 0;
489
490void
495
496COAP_API int
498 coap_io_process_thread_t main_loop_code,
499 void *main_loop_code_arg, uint32_t timeout_ms,
500 uint32_t thread_count) {
501 int ret;
502
503 if (!context)
504 return 0;
505 coap_lock_lock(return 0);
506 ret = coap_io_process_loop_lkd(context, main_loop_code,
507 main_loop_code_arg, timeout_ms,
508 thread_count);
510 return ret;
511}
512
513int
515 coap_io_process_thread_t main_loop_code,
516 void *main_loop_code_arg, uint32_t timeout_ms,
517 uint32_t thread_count) {
518 int ret = 0;;
519
520#if COAP_THREAD_SAFE
521 if (thread_count > 1) {
522 if (!coap_io_process_configure_threads(context, thread_count - 1))
523 return 0;
524 }
525#else /* COAP_THREAD_SAFE */
526 thread_count = 1;
527#endif /* COAP_THREAD_SAFE */
528 while (!coap_thread_quit) {
529 if (main_loop_code) {
530 coap_tick_t begin, end;
531 uint32_t used_ms;
532
533 coap_ticks(&begin);
534 /*
535 * main_loop_codecode should not be blocking for any time, and not calling
536 * coap_io_process().
537 */
538 coap_lock_callback_release(main_loop_code(main_loop_code_arg),
539 /* On re-lock failure */
540 ret = 0; break);
541 /*
542 * Need to delay for the remainder of timeout_ms. In case main_loop_code()
543 * is time sensitive (e.g Observe subscription to /time), delay to the
544 * start of the a second boundary
545 */
546 coap_ticks(&end);
547 used_ms = (uint32_t)(end - begin) * 1000 / COAP_TICKS_PER_SECOND;
548 if (timeout_ms == COAP_IO_NO_WAIT || timeout_ms == COAP_IO_WAIT) {
549 ret = coap_io_process_lkd(context, timeout_ms);
550 } else if (timeout_ms > used_ms) {
551 /* Wait for remaining time rounded up to next second start */
552 coap_tick_t next_time = end + (timeout_ms - used_ms) * COAP_TICKS_PER_SECOND / 1000;
553 unsigned int next_sec_us;
554 unsigned int next_sec_ms;
555
556 next_sec_us = (timeout_ms - used_ms) * 1000000 / COAP_TICKS_PER_SECOND + 1000000 -
557 (coap_ticks_to_rt_us(next_time) % 1000000);
558 next_sec_ms = (next_sec_us + 999) / 1000;
559 if (next_sec_ms > timeout_ms && next_sec_ms > 1000)
560 next_sec_ms -= 1000;
561 ret = coap_io_process_lkd(context, next_sec_ms ? next_sec_ms : 1);
562 } else {
563 /* timeout_ms has expired */
564 ret = coap_io_process_lkd(context, COAP_IO_NO_WAIT);
565 }
566
567 if (thread_count == 1) {
568 /*
569 * Need to delay if only one thread until the remainder of
570 * timeout_ms is used up. Otherwise, another thread will be
571 * waiting on coap_io_process() to do any input / timeout work.
572 */
573 coap_ticks(&end);
574 used_ms = (uint32_t)(end - begin) * 1000 / COAP_TICKS_PER_SECOND;
575 if (timeout_ms > 0 && timeout_ms < used_ms) {
576 ret = coap_io_process_lkd(context, used_ms - timeout_ms);
577 } else {
578 ret = coap_io_process_lkd(context, COAP_IO_NO_WAIT);
579 }
580 }
581 } else {
582 ret = coap_io_process_lkd(context, timeout_ms);
583 }
584 /* coap_io_process_lkd() can return 0 */
585 if (ret >= 0)
586 ret = 1;
587
588 if (ret < 0) {
589 ret = 0;
590 break;
591 }
592 }
593#if COAP_THREAD_SAFE
595#endif /* COAP_THREAD_SAFE */
597 return ret;
598}
599
600#else /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
601
602#ifdef __clang__
603/* Make compilers happy that do not like empty modules. As this function is
604 * never used, we ignore -Wunused-function at the end of compiling this file
605 */
606#pragma GCC diagnostic ignored "-Wunused-function"
607#endif
608static inline void
609dummy(void) {
610}
611
612#endif /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
static void dummy(void)
const char * coap_socket_strerror(void)
Definition coap_io.c:814
#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:2768
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:2703
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:288
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:762
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:761
void(* coap_io_process_thread_t)(void *arg)
Main thread coap_io_process_loop activity.
Definition coap_net.h:943
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:2100
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