ProFTPD Developer's Guide: Events

ProFTPD Version 1.2


Table of Contents

What Events Are
Events are an intraprocess notification system, used to indicate certain conditions to other parts of the code that have registered an interest in these conditions. A module can register a callback for any given event; when that event is generated, the callback is invoked. All registered callbacks, or listeners, are invoked in the usual module load order.

The Events API replaces the old registration functions that were specifically for process exits, daemon startup, and configuration parsing. That old system would not scale well, as several new functions would need to be added to the core API for every new event handled. The new Events API can handle any number of arbitrary events; modules can easily generate their own custom events without requiring code changes in the core code.

When Not To Use Events
The ProFTPD API contains many hooks and entry points into the lifecycle of an FTP session: authentication handlers, command handlers, configuration directive handlers, filesystem and network callbacks, etc. These APIs cover most of the situations in which a module developer is interested. Events are not needed in cases where the existing API can be used to achieve the same goal.

Event List
Some of the current Events generated by proftpd are:

Note that if a non-NULL void *user_data pointer is provided when registering an event handler, and that pointer is allocated from a pool that does not survive a restart, then the caller should unregister that event handler during a restart, and re-register the handler again with an updated pointer. The problem is that the Events API keeps a pointer to the given user_data, and when the pool from which that data is destroyed, the pointer becomes invalid. The invalid pointer would be passed to the event handler, after a restart, unless the pointer is properly replaced via re-registration.

Code Example

  /* Event handler for the 'mod_foo.foo' event. */
  static void my_foo_ev(const void *event_data, void *user_data) {
    (void) pr_log_writefile(my_logfd, MOD_MY_VERSION, "the 'mod_foo.foo' event occurred");
    return;
  }

  ...

    /* Register our callback for the 'mod_foo.foo' event.
     * The last NULL argument indicates that we are not interested in passing our
     * own "user_data" parameter to the callback.
     */
    pr_event_register(&my_module, "mod_foo.foo", my_foo_ev, NULL);

  ...

    /* Meanwhile, back in mod_foo.c's handlers...*/
    pr_event_generate("mod_foo.foo", NULL);
That's it. Events can be generated for which there are no listeners registered, and listeners can be registered for events which are never generated.

Table of Contents



Author: $Author: castaglia $
Last Updated: $Date: 2004/12/31 18:32:22 $


© Copyright 2000-2004 TJ Saunders
All Rights Reserved