11cb0ef41Sopenharmony_ci/* MIT License
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright (c) 2023 Brad House
41cb0ef41Sopenharmony_ci *
51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights
81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
111cb0ef41Sopenharmony_ci *
121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next
131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
141cb0ef41Sopenharmony_ci * Software.
151cb0ef41Sopenharmony_ci *
161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
221cb0ef41Sopenharmony_ci * SOFTWARE.
231cb0ef41Sopenharmony_ci *
241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
251cb0ef41Sopenharmony_ci */
261cb0ef41Sopenharmony_ci#ifndef __ARES__EVENT_H
271cb0ef41Sopenharmony_ci#define __ARES__EVENT_H
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include "ares_setup.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cistruct ares_event;
321cb0ef41Sopenharmony_citypedef struct ares_event ares_event_t;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_citypedef enum {
351cb0ef41Sopenharmony_ci  ARES_EVENT_FLAG_NONE  = 0,
361cb0ef41Sopenharmony_ci  ARES_EVENT_FLAG_READ  = 1 << 0,
371cb0ef41Sopenharmony_ci  ARES_EVENT_FLAG_WRITE = 1 << 1,
381cb0ef41Sopenharmony_ci  ARES_EVENT_FLAG_OTHER = 1 << 2
391cb0ef41Sopenharmony_ci} ares_event_flags_t;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_citypedef void (*ares_event_cb_t)(ares_event_thread_t *e, ares_socket_t fd,
421cb0ef41Sopenharmony_ci                                void *data, ares_event_flags_t flags);
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_citypedef void (*ares_event_free_data_t)(void *data);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_citypedef void (*ares_event_signal_cb_t)(const ares_event_t *event);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_cistruct ares_event {
491cb0ef41Sopenharmony_ci  /*! Registered event thread this event is bound to */
501cb0ef41Sopenharmony_ci  ares_event_thread_t   *e;
511cb0ef41Sopenharmony_ci  /*! Flags to monitor. OTHER is only allowed if the socket is ARES_SOCKET_BAD.
521cb0ef41Sopenharmony_ci   */
531cb0ef41Sopenharmony_ci  ares_event_flags_t     flags;
541cb0ef41Sopenharmony_ci  /*! Callback to be called when event is triggered */
551cb0ef41Sopenharmony_ci  ares_event_cb_t        cb;
561cb0ef41Sopenharmony_ci  /*! Socket to monitor, allowed to be ARES_SOCKET_BAD if not monitoring a
571cb0ef41Sopenharmony_ci   *  socket. */
581cb0ef41Sopenharmony_ci  ares_socket_t          fd;
591cb0ef41Sopenharmony_ci  /*! Data associated with event handle that will be passed to the callback.
601cb0ef41Sopenharmony_ci   *  Typically OS/event subsystem specific data.
611cb0ef41Sopenharmony_ci   *  Optional, may be NULL. */
621cb0ef41Sopenharmony_ci  /*! Data to be passed to callback. Optional, may be NULL. */
631cb0ef41Sopenharmony_ci  void                  *data;
641cb0ef41Sopenharmony_ci  /*! When cleaning up the registered event (either when removed or during
651cb0ef41Sopenharmony_ci   *  shutdown), this function will be called to clean up the user-supplied
661cb0ef41Sopenharmony_ci   *  data. Optional, May be NULL. */
671cb0ef41Sopenharmony_ci  ares_event_free_data_t free_data_cb;
681cb0ef41Sopenharmony_ci  /*! Callback to call to trigger an event. */
691cb0ef41Sopenharmony_ci  ares_event_signal_cb_t signal_cb;
701cb0ef41Sopenharmony_ci};
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_citypedef struct {
731cb0ef41Sopenharmony_ci  const char *name;
741cb0ef41Sopenharmony_ci  ares_bool_t (*init)(ares_event_thread_t *e);
751cb0ef41Sopenharmony_ci  void        (*destroy)(ares_event_thread_t *e);
761cb0ef41Sopenharmony_ci  ares_bool_t (*event_add)(ares_event_t *event);
771cb0ef41Sopenharmony_ci  void        (*event_del)(ares_event_t *event);
781cb0ef41Sopenharmony_ci  void        (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags);
791cb0ef41Sopenharmony_ci  size_t      (*wait)(ares_event_thread_t *e, unsigned long timeout_ms);
801cb0ef41Sopenharmony_ci} ares_event_sys_t;
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_cistruct ares_event_thread {
831cb0ef41Sopenharmony_ci  /*! Whether the event thread should be online or not.  Checked on every wake
841cb0ef41Sopenharmony_ci   *  event before sleeping. */
851cb0ef41Sopenharmony_ci  ares_bool_t             isup;
861cb0ef41Sopenharmony_ci  /*! Handle to the thread for joining during shutdown */
871cb0ef41Sopenharmony_ci  ares__thread_t         *thread;
881cb0ef41Sopenharmony_ci  /*! Lock to protect the data contained within the event thread itself */
891cb0ef41Sopenharmony_ci  ares__thread_mutex_t   *mutex;
901cb0ef41Sopenharmony_ci  /*! Reference to the ares channel, for being able to call things like
911cb0ef41Sopenharmony_ci   *  ares_timeout() and ares_process_fd(). */
921cb0ef41Sopenharmony_ci  ares_channel_t         *channel;
931cb0ef41Sopenharmony_ci  /*! Not-yet-processed event handle updates.  These will get enqueued by a
941cb0ef41Sopenharmony_ci   *  thread other than the event thread itself. The event thread will then
951cb0ef41Sopenharmony_ci   *  be woken then process these updates itself */
961cb0ef41Sopenharmony_ci  ares__llist_t          *ev_updates;
971cb0ef41Sopenharmony_ci  /*! Registered event handles. */
981cb0ef41Sopenharmony_ci  ares__htable_asvp_t    *ev_handles;
991cb0ef41Sopenharmony_ci  /*! Pointer to the event handle which is used to signal and wake the event
1001cb0ef41Sopenharmony_ci   *  thread itself.  This is needed to be able to do things like update the
1011cb0ef41Sopenharmony_ci   *  file descriptors being waited on and to wake the event subsystem during
1021cb0ef41Sopenharmony_ci   *  shutdown */
1031cb0ef41Sopenharmony_ci  ares_event_t           *ev_signal;
1041cb0ef41Sopenharmony_ci  /* Event subsystem callbacks */
1051cb0ef41Sopenharmony_ci  const ares_event_sys_t *ev_sys;
1061cb0ef41Sopenharmony_ci  /* Event subsystem private data */
1071cb0ef41Sopenharmony_ci  void                   *ev_sys_data;
1081cb0ef41Sopenharmony_ci};
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci/*! Queue an update for the event handle.
1111cb0ef41Sopenharmony_ci *
1121cb0ef41Sopenharmony_ci *  Will search by the fd passed if not ARES_SOCKET_BAD to find a match and
1131cb0ef41Sopenharmony_ci *  perform an update or delete (depending on flags).  Otherwise will add.
1141cb0ef41Sopenharmony_ci *  Do not use the event handle returned if its not guaranteed to be an add
1151cb0ef41Sopenharmony_ci *  operation.
1161cb0ef41Sopenharmony_ci *
1171cb0ef41Sopenharmony_ci *  \param[out] event        Event handle. Optional, can be NULL.  This handle
1181cb0ef41Sopenharmony_ci *                           will be invalidate quickly if the result of the
1191cb0ef41Sopenharmony_ci *                           operation is not an ADD.
1201cb0ef41Sopenharmony_ci *  \param[in]  e            pointer to event thread handle
1211cb0ef41Sopenharmony_ci *  \param[in]  flags        flags for the event handle.  Use
1221cb0ef41Sopenharmony_ci *                           ARES_EVENT_FLAG_NONE if removing a socket from
1231cb0ef41Sopenharmony_ci *                           queue (not valid if socket is ARES_SOCKET_BAD).
1241cb0ef41Sopenharmony_ci *                           Non-socket events cannot be removed, and must have
1251cb0ef41Sopenharmony_ci *                           ARES_EVENT_FLAG_OTHER set.
1261cb0ef41Sopenharmony_ci *  \param[in]  cb           Callback to call when
1271cb0ef41Sopenharmony_ci *                           event is triggered. Required. Not allowed to be
1281cb0ef41Sopenharmony_ci *                           changed, ignored on modification.
1291cb0ef41Sopenharmony_ci *  \param[in]  fd           File descriptor/socket to monitor. May
1301cb0ef41Sopenharmony_ci *                           be ARES_SOCKET_BAD if not monitoring file
1311cb0ef41Sopenharmony_ci *                           descriptor.
1321cb0ef41Sopenharmony_ci *  \param[in]  data         Optional. Caller-supplied data to be passed to
1331cb0ef41Sopenharmony_ci *                           callback. Only allowed on initial add, cannot be
1341cb0ef41Sopenharmony_ci *                           modified later, ignored on modification.
1351cb0ef41Sopenharmony_ci *  \param[in]  free_data_cb Optional. Callback to clean up caller-supplied
1361cb0ef41Sopenharmony_ci *                           data. Only allowed on initial add, cannot be
1371cb0ef41Sopenharmony_ci *                           modified later, ignored on modification.
1381cb0ef41Sopenharmony_ci *  \param[in]  signal_cb    Optional. Callback to call to trigger an event.
1391cb0ef41Sopenharmony_ci *  \return ARES_SUCCESS on success
1401cb0ef41Sopenharmony_ci */
1411cb0ef41Sopenharmony_ciares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e,
1421cb0ef41Sopenharmony_ci                                ares_event_flags_t flags, ares_event_cb_t cb,
1431cb0ef41Sopenharmony_ci                                ares_socket_t fd, void *data,
1441cb0ef41Sopenharmony_ci                                ares_event_free_data_t free_data_cb,
1451cb0ef41Sopenharmony_ci                                ares_event_signal_cb_t signal_cb);
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci#ifdef HAVE_PIPE
1491cb0ef41Sopenharmony_ciares_event_t *ares_pipeevent_create(ares_event_thread_t *e);
1501cb0ef41Sopenharmony_ci#endif
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci#ifdef HAVE_POLL
1531cb0ef41Sopenharmony_ciextern const ares_event_sys_t ares_evsys_poll;
1541cb0ef41Sopenharmony_ci#endif
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci#ifdef HAVE_KQUEUE
1571cb0ef41Sopenharmony_ciextern const ares_event_sys_t ares_evsys_kqueue;
1581cb0ef41Sopenharmony_ci#endif
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci#ifdef HAVE_EPOLL
1611cb0ef41Sopenharmony_ciextern const ares_event_sys_t ares_evsys_epoll;
1621cb0ef41Sopenharmony_ci#endif
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci#ifdef _WIN32
1651cb0ef41Sopenharmony_ciextern const ares_event_sys_t ares_evsys_win32;
1661cb0ef41Sopenharmony_ci#endif
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci/* All systems have select(), but not all have a way to wake, so we require
1691cb0ef41Sopenharmony_ci * pipe() to wake the select() */
1701cb0ef41Sopenharmony_ci#ifdef HAVE_PIPE
1711cb0ef41Sopenharmony_ciextern const ares_event_sys_t ares_evsys_select;
1721cb0ef41Sopenharmony_ci#endif
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci#endif
175