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