From: Alan T. DeKok Date: Wed, 18 Jan 2017 17:03:06 +0000 (-0500) Subject: add preparation for callbacks based on ident X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=131d1fbbb5509e12496b8324400df193b8325d98;p=thirdparty%2Ffreeradius-server.git add preparation for callbacks based on ident --- diff --git a/src/util/control.c b/src/util/control.c index 2e088629b5f..e131a34100d 100644 --- a/src/util/control.c +++ b/src/util/control.c @@ -53,6 +53,7 @@ typedef enum fr_control_message_status_t { FR_CONTROL_MESSAGE_DONE //!< the message is done (set only by receiver) } fr_control_message_status_t; + /** * The header for the control message */ @@ -62,6 +63,15 @@ typedef struct fr_control_message_t { size_t data_size; //!< size of the data we're sending } fr_control_message_t; + +typedef struct fr_control_ctx_t { + uint32_t id; //!< id of this callback + void *ctx; //!< context for the callback + fr_control_callback_t callback; //!< the function to call +} fr_control_ctx_t; + +#define MAX_IDENT (32) + /** * The control structure. */ @@ -71,6 +81,8 @@ struct fr_control_t { fr_atomic_queue_t *aq; //!< destination AQ fr_ring_buffer_t *rb; //!< a ring buffer containing my messages to send. + + fr_control_ctx_t ident[MAX_IDENT]; //!< callbacks }; @@ -365,3 +377,64 @@ int fr_control_message_service_kevent(UNUSED fr_atomic_queue_t *aq, struct keven return 1; } + + +/** Register a callback for an ID + * + * @param[in] c the control structure + * @param[in] id the ident of this message. + * @param[in] ctx the context for the callback + * @param[in] callback the callback function + * @return + * - <0 on error + * - 0 on success + */ +int fr_control_callback_add(fr_control_t *c, uint32_t id, void *ctx, fr_control_callback_t callback) +{ +#ifndef NDEBUG + (void) talloc_get_type_abort(c, fr_control_t); +#endif + + if (id >= MAX_IDENT) return -1; + + /* + * Re-registering the same thing is OK. + */ + if ((c->ident[id].ctx == ctx) && + (c->ident[id].callback == callback)) { + return 0; + } + + if (c->ident[id].callback != NULL) return -1; + + c->ident[id].id = id; + c->ident[id].ctx = ctx; + c->ident[id].callback = callback; + + return 0; +} + +/** Delete a callback for an ID + * + * @param[in] c the control structure + * @param[in] id the ident of this message. + * @return + * - <0 on error + * - 0 on success + */ +int fr_control_callback_delete(fr_control_t *c, uint32_t id) +{ +#ifndef NDEBUG + (void) talloc_get_type_abort(c, fr_control_t); +#endif + + if (id >= MAX_IDENT) return -1; + + if (c->ident[id].callback == NULL) return 0; + + c->ident[id].id = 0; + c->ident[id].ctx = NULL; + c->ident[id].callback = NULL; + + return 0; +} diff --git a/src/util/control.h b/src/util/control.h index 26485f3a7e4..942a3dca89d 100644 --- a/src/util/control.h +++ b/src/util/control.h @@ -26,6 +26,7 @@ RCSIDH(control_h, "$Id$") #include +#include #include #include @@ -40,6 +41,7 @@ extern "C" { * Multiple-producer, single consumer. */ typedef struct fr_control_t fr_control_t; +typedef void (*fr_control_callback_t)(void *ctx, void const *data, size_t data_size, fr_time_t now); /* * A list of pre-allocated IDs, so that the callers don't have to manage their own. @@ -57,6 +59,8 @@ int fr_control_message_service_kevent(fr_atomic_queue_t *aq, struct kevent const int fr_control_message_push(fr_control_t *c, uint32_t id, void *data, size_t data_size) CC_HINT(nonnull); ssize_t fr_control_message_pop(fr_atomic_queue_t *aq, uint32_t *p_id, void *data, size_t data_size) CC_HINT(nonnull); +int fr_control_callback_add(fr_control_t *c, uint32_t id, void *ctx, fr_control_callback_t callback) CC_HINT(nonnull(1,4)); +int fr_control_callback_delete(fr_control_t *c, uint32_t id) CC_HINT(nonnull); #ifdef __cplusplus }