]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
export EVFILT_USER ident to caller, and pass it to control API
authorAlan T. DeKok <aland@freeradius.org>
Mon, 19 Jun 2017 18:16:07 +0000 (14:16 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 19 Jun 2017 18:16:31 +0000 (14:16 -0400)
src/include/event.h
src/lib/io/network.c
src/lib/io/worker.c
src/lib/util/event.c

index e29796537095f0ba9d9e0fc90ece161ead76405f..d82b3687e80961d48a3706aa63daa253b4c45bff 100644 (file)
@@ -97,7 +97,7 @@ int           fr_event_timer_insert(fr_event_list_t *el,
                                      void const *ctx, struct timeval *when, fr_event_timer_t **parent);
 int            fr_event_timer_run(fr_event_list_t *el, struct timeval *when);
 
-int            fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) CC_HINT(nonnull(1,2));
+uintptr_t              fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) CC_HINT(nonnull(1,2));
 int            fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) CC_HINT(nonnull(1,2));
 
 int            fr_event_post_insert(fr_event_list_t *el, fr_event_callback_t callback, void *uctx) CC_HINT(nonnull(1,2));
index cf37f2bd60d628bdbfed7f53b37a55a2d1e658de..568e3005ecfcc2f4a3d2b56467a3ba718424531f 100644 (file)
@@ -69,6 +69,8 @@ struct fr_network_t {
 
        fr_atomic_queue_t       *aq_control;            //!< atomic queue for control messages sent to me
 
+       uintptr_t               aq_ident;               //!< identifier for control-plane events
+
        fr_control_t            *control;               //!< the control plane
 
        fr_ring_buffer_t        *rb;                    //!< ring buffer for my control-plane messages
@@ -609,7 +611,6 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger)
 
        nr = talloc_zero(ctx, fr_network_t);
        if (!nr) {
-       nomem:
                fr_strerror_printf("Failed allocating memory");
                return NULL;
        }
@@ -629,12 +630,22 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger)
        nr->aq_control = fr_atomic_queue_create(nr, 1024);
        if (!nr->aq_control) {
                talloc_free(nr);
-               goto nomem;
+               return NULL;
+       }
+
+       nr->aq_ident = fr_event_user_insert(nr->el, fr_network_evfilt_user, nr);
+       if (!nr->aq_ident) {
+               fr_strerror_printf("Failed updating event list: %s", fr_strerror());
+               talloc_free(nr);
+               return NULL;
        }
 
-       nr->control = fr_control_create(nr, nr->kq, nr->aq_control, 1024);
+
+       nr->control = fr_control_create(nr, nr->kq, nr->aq_control, nr->aq_ident);
        if (!nr->control) {
                fr_strerror_printf("Failed creating control queue: %s", fr_strerror());
+       fail:
+               (void) fr_event_user_delete(nr->el, fr_network_evfilt_user, nr);
                talloc_free(nr);
                return NULL;
        }
@@ -642,26 +653,24 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger)
        nr->rb = fr_ring_buffer_create(nr, FR_CONTROL_MAX_MESSAGES * FR_CONTROL_MAX_SIZE);
        if (!nr->rb) {
                fr_strerror_printf("Failed creating ring buffer: %s", fr_strerror());
-               talloc_free(nr);
-               return NULL;
+       fail2:
+               fr_control_free(nr->control);
+               goto fail;
        }
 
        if (fr_control_callback_add(nr->control, FR_CONTROL_ID_CHANNEL, nr, fr_network_channel_callback) < 0) {
                fr_strerror_printf("Failed adding channel callback: %s", fr_strerror());
-               talloc_free(nr);
-               return NULL;
+               goto fail2;
        }
 
        if (fr_control_callback_add(nr->control, FR_CONTROL_ID_SOCKET, nr, fr_network_socket_callback) < 0) {
                fr_strerror_printf("Failed adding socket callback: %s", fr_strerror());
-               talloc_free(nr);
-               return NULL;
+               goto fail2;
        }
 
        if (fr_control_callback_add(nr->control, FR_CONTROL_ID_WORKER, nr, fr_network_worker_callback) < 0) {
                fr_strerror_printf("Failed adding worker callback: %s", fr_strerror());
-               talloc_free(nr);
-               return NULL;
+               goto fail2;
        }
 
        /*
@@ -669,46 +678,42 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger)
         */
        nr->sockets = rbtree_create(nr, socket_cmp, NULL, RBTREE_FLAG_NONE);
        if (!nr->sockets) {
-               talloc_free(nr);
-               goto nomem;
+               fr_strerror_printf("Failed creating tree for sockets: %s", fr_strerror());
+               goto fail2;
        }
 
        nr->replies = fr_heap_create(reply_cmp, offsetof(fr_channel_data_t, channel.heap_id));
        if (!nr->replies) {
-               talloc_free(nr);
-               goto nomem;
+               fr_strerror_printf("Failed creating heap for replies: %s", fr_strerror());
+               goto fail2;
        }
 
        nr->workers = fr_heap_create(worker_cmp, offsetof(fr_network_worker_t, heap_id));
        if (!nr->workers) {
-               talloc_free(nr);
-               goto nomem;
+               fr_strerror_printf("Failed creating heap for workers: %s", fr_strerror());
+       fail3:
+               fr_heap_delete(nr->replies);
+               goto fail2;
        }
 
        nr->closing = fr_heap_create(worker_cmp, offsetof(fr_network_worker_t, heap_id));
        if (!nr->closing) {
-               talloc_free(nr);
-               goto nomem;
+               fr_strerror_printf("Failed creating heap for exiting workers: %s", fr_strerror());
+               goto fail3;
        }
 
 #ifdef HAVE_PTHREAD_H
        if (pthread_mutex_init(&nr->mutex, NULL) != 0) {
                fr_strerror_printf("Failed initializing mutex");
-               talloc_free(nr);
-               return NULL;
+       fail4:
+               fr_heap_delete(nr->closing);
+               goto fail3;
        }
 #endif
 
-       if (fr_event_user_insert(nr->el, fr_network_evfilt_user, nr) < 0) {
-               fr_strerror_printf("Failed updating event list: %s", fr_strerror());
-               talloc_free(nr);
-               return NULL;
-       }
-
        if (fr_event_post_insert(nr->el, fr_network_post_event, nr) < 0) {
                fr_strerror_printf("Failed inserting post-processing event");
-               talloc_free(nr);
-               return NULL;
+               goto fail4;
        }
 
        return nr;
index 4e2e6f82d5e474487dfdc19c6b94988e21ea8654..854d438861c88334136289e3439fba263a743036 100644 (file)
@@ -91,10 +91,12 @@ struct fr_worker_t {
 
        int                     kq;             //!< my kq
 
-       fr_log_t                *log;                   //!< log destination
+       fr_log_t                *log;           //!< log destination
 
        fr_atomic_queue_t       *aq_control;    //!< atomic queue for control messages sent to me
 
+       uintptr_t               aq_ident;       //!< identifier for control-plane events
+
        fr_control_t            *control;       //!< the control plane
 
        fr_event_list_t         *el;            //!< our event list
@@ -141,6 +143,7 @@ static void fr_worker_post_event(fr_event_list_t *el, struct timeval *now, void
                FR_DLIST_INIT(worker->_name.list); \
                worker->_name.heap = fr_heap_create(_func, offsetof(_type, _member)); \
                if (!worker->_name.heap) { \
+                       (void) fr_event_user_delete(worker->el, fr_worker_evfilt_user, worker); \
                        talloc_free(worker); \
                        goto nomem; \
                } \
@@ -1064,20 +1067,29 @@ nomem:
 
        worker->aq_control = fr_atomic_queue_create(worker, 1024);
        if (!worker->aq_control) {
+               fr_strerror_printf("Failed creating atomic queue");
+       fail:
                talloc_free(worker);
-               goto nomem;
+               return NULL;
        }
 
-       worker->control = fr_control_create(worker, worker->kq, worker->aq_control, 1024);
+       worker->aq_ident = fr_event_user_insert(worker->el, fr_worker_evfilt_user, worker);
+       if (!worker->aq_ident) {
+               fr_strerror_printf("Failed updating event list: %s", fr_strerror());
+               goto fail;
+       }
+
+       worker->control = fr_control_create(worker, worker->kq, worker->aq_control, worker->aq_ident);
        if (!worker->control) {
-               talloc_free(worker);
-               goto nomem;;
+               fr_strerror_printf("Failed creating control plane: %s", fr_strerror());
+       fail2:
+               (void) fr_event_user_delete(worker->el, fr_worker_evfilt_user, worker);
+               goto fail;
        }
 
        if (fr_control_callback_add(worker->control, FR_CONTROL_ID_CHANNEL, worker, fr_worker_channel_callback) < 0) {
                fr_strerror_printf("Failed adding control channel: %s", fr_strerror());
-               talloc_free(worker);
-               return NULL;
+               goto fail2;
        }
 
        WORKER_HEAP_INIT(to_decode, worker_message_cmp, fr_channel_data_t, channel.heap_id);
@@ -1085,22 +1097,16 @@ nomem:
 
        worker->runnable = fr_heap_create(worker_request_cmp, offsetof(REQUEST, heap_id));
        if (!worker->runnable) {
-               talloc_free(worker);
-               goto nomem;;
+               fr_strerror_printf("Failed creating runnable heap");
+               goto fail;
        }
        FR_DLIST_INIT(worker->time_order);
        FR_DLIST_INIT(worker->waiting_to_die);
 
-       if (fr_event_user_insert(worker->el, fr_worker_evfilt_user, worker) < 0) {
-               fr_strerror_printf("Failed updating event list: %s", fr_strerror());
-               talloc_free(worker);
-               return NULL;
-       }
-
        if (fr_event_post_insert(worker->el, fr_worker_post_event, worker) < 0) {
                fr_strerror_printf("Failed inserting post-processing event");
-               talloc_free(worker);
-               return NULL;
+               fr_heap_delerte(worker->runnable);
+               goto fail2;
        }
 
        return worker;
index 41e9a79cbc14028f1b46a1a45801d71675cd0039..a690da26bfc6a2b2d59573daa83dc2d536bca633 100644 (file)
@@ -91,6 +91,18 @@ typedef struct fr_event_post_t {
        void                    *ctx;                   //!< context for the callback.
 } fr_event_post_t;
 
+
+/** Callbacks for user events
+ *
+ */
+typedef struct fr_event_user_t {
+       fr_dlist_t              entry;                  //!< linked list of callback
+       uintptr_t               ident;                  //!< the identifier of this event
+       fr_event_user_handler_t callback;               //!< the callback to call
+       void                    *ctx;                   //!< context for the callback.
+} fr_event_user_t;
+
+
 /** Stores all information relating to an event list
  *
  */
@@ -112,9 +124,7 @@ struct fr_event_list_t {
 
        int                     kq;                     //!< instance associated with this event list.
 
-       fr_event_user_handler_t user;                   //!< callback for EVFILT_USER events
-       void                    *user_ctx;              //!< Context pointer to pass to the user callback.
-
+       fr_dlist_t              user_callbacks;         //!< EVFILT_USER callbacks
        fr_dlist_t              post_callbacks;         //!< post-processing callbacks
 
        struct kevent           events[FR_EV_BATCH_FDS]; /* so it doesn't go on the stack every time */
@@ -577,38 +587,57 @@ int fr_event_timer_insert(fr_event_list_t *el, fr_event_callback_t callback, voi
 /** Add a user callback to the event list.
  *
  * @param[in] el       containing the timer events.
- * @param[in] user     the callback for EVFILT_USER
- * @param[in] ctx      user context for the callback
+ * @param[in] callback the callback for EVFILT_USER
+ * @param[in] uctx     user context for the callback
  * @return
- *     - 0 on error
- *     - 0 on success
+ *     - 0 on error
+ *     - uintptr_t ident for EVFILT_USER signaling
  */
-int fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx)
+uintptr_t fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t callback, void *uctx)
 {
-       el->user = user;
-       el->user_ctx = ctx;
+       fr_event_user_t *user;
 
-       return 0;
+       user = talloc(el, fr_event_user_t);
+       user->callback = callback;
+       user->ctx = uctx;
+       user->ident = (uintptr_t) user;
+
+       fr_dlist_insert_tail(&el->user_callbacks, &user->entry);
+
+       return user->ident;;
 }
 
 
 /** Delete a user callback to the event list.
  *
  * @param[in] el       containing the timer events.
- * @param[in] user     the callback for EVFILT_USER
- * @param[in] ctx      user context for the callback
+ * @param[in] callback the callback for EVFILT_USER
+ * @param[in] uctx     user context for the callback
  * @return
  *     - < 0 on error
  *     - 0 on success
  */
-int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx)
+int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t callback, void *uctx)
 {
-       if ((el->user != user) || (el->user_ctx != ctx)) return -1;
+       fr_dlist_t *entry, *next;
 
-       el->user = NULL;
-       el->user_ctx = NULL;
+       for (entry = FR_DLIST_FIRST(el->user_callbacks);
+            entry != NULL;
+            entry = next) {
+               fr_event_user_t *user;
 
-       return 0;
+               next = FR_DLIST_NEXT(el->user_callbacks, entry);
+
+               user = fr_ptr_to_type(fr_event_user_t, entry, entry);
+               if ((user->callback == callback) &&
+                   (user->ctx == uctx)) {
+                       fr_dlist_remove(entry);
+                       talloc_free(user);
+                       return 0;
+               }
+       }
+
+       return -1;
 }
 
 /** Add a post-event callback to the event list.
@@ -825,14 +854,26 @@ void fr_event_service(fr_event_list_t *el)
                /*
                 *      Process any user events
                 */
-               if (el->user && (el->events[i].filter == EVFILT_USER)) {
+               if (el->events[i].filter == EVFILT_USER) {
                        /*
                         *      This is just a "wakeup" event, which
                         *      is always ignored.
                         */
                        if (el->events[i].ident == 0) continue;
 
-                       el->user(el->kq, &el->events[i], el->user_ctx);
+                       for (entry = FR_DLIST_FIRST(el->user_callbacks);
+                            entry != NULL;
+                            entry = FR_DLIST_NEXT(el->user_callbacks, entry)) {
+                               fr_event_user_t *user;
+
+                               user = fr_ptr_to_type(fr_event_user_t, entry, entry);
+
+                               if (user->ident != el->events[i].ident) continue;
+
+                               user->callback(el->kq, &el->events[i], user->ctx);
+                               break;
+                       }
+
                        continue;
                }
 
@@ -1037,6 +1078,7 @@ fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_t status,
        el->status_ctx = status_ctx;
 
        FR_DLIST_INIT(el->post_callbacks);
+       FR_DLIST_INIT(el->user_callbacks);
 
        /*
         *      Set our "exit" callback as ident 0.