servlib/bundling/BundleEvent.h
changeset 0 2b3e5ec03512
child 5 1849bf57d910
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/bundling/BundleEvent.h	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,1474 @@
+/*
+ *    Copyright 2004-2006 Intel Corporation
+ * 
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef _BUNDLE_EVENT_H_
+#define _BUNDLE_EVENT_H_
+
+#include "Bundle.h"
+#include "BundleProtocol.h"
+#include "BundleRef.h"
+#include "BundleList.h"
+#include "CustodySignal.h"
+#include "contacts/Link.h"
+#include "contacts/NamedAttribute.h"
+#include "GbofId.h"
+
+namespace dtn {
+
+/**
+ * All signaling from various components to the routing layer is done
+ * via the Bundle Event message abstraction. This file defines the
+ * event type codes and corresponding classes.
+ */
+
+class Bundle;
+class Contact;
+class Interface;
+class Registration;
+class RouteEntry;
+
+/**
+ * Type codes for events / requests.
+ */
+typedef enum {
+    BUNDLE_RECEIVED = 0x1,      ///< New bundle arrival
+    BUNDLE_TRANSMITTED,         ///< Bundle or fragment successfully sent
+    BUNDLE_DELIVERED,           ///< Bundle locally delivered
+    BUNDLE_DELIVERY,            ///< Bundle delivery (with payload)
+    BUNDLE_EXPIRED,             ///< Bundle expired
+    BUNDLE_NOT_NEEDED,          ///< Bundle no longer needed
+    BUNDLE_FREE,                ///< No more references to the bundle
+    BUNDLE_FORWARD_TIMEOUT,     ///< A Mapping timed out
+    BUNDLE_SEND,                ///< Send a bundle
+    BUNDLE_CANCEL,              ///< Cancel a bundle transmission
+    BUNDLE_CANCELLED,           ///< Bundle send cancelled
+    BUNDLE_INJECT,              ///< Inject a bundle
+    BUNDLE_INJECTED,            ///< A bundle was injected
+    BUNDLE_ACCEPT_REQUEST,      ///< Request acceptance of a new bundle
+    BUNDLE_DELETE,              ///< Request deletion of a bundle
+    BUNDLE_QUERY,               ///< Bundle query
+    BUNDLE_REPORT,              ///< Response to bundle query
+    BUNDLE_ATTRIB_QUERY,        ///< Query for a bundle's attributes
+    BUNDLE_ATTRIB_REPORT,       ///< Report with bundle attributes
+
+    CONTACT_UP,                 ///< Contact is up
+    CONTACT_DOWN,               ///< Contact abnormally terminated
+    CONTACT_QUERY,              ///< Contact query
+    CONTACT_REPORT,             ///< Response to contact query
+    CONTACT_ATTRIB_CHANGED,     ///< An attribute changed
+
+    LINK_CREATED,               ///< Link is created into the system
+    LINK_DELETED,               ///< Link is deleted from the system
+    LINK_AVAILABLE,             ///< Link is available
+    LINK_UNAVAILABLE,           ///< Link is unavailable
+    LINK_BUSY,                  ///< Link is busy 
+    LINK_CREATE,                ///< Create and open a new link
+    LINK_DELETE,                ///< Delete a link
+    LINK_RECONFIGURE,           ///< Reconfigure a link
+    LINK_QUERY,                 ///< Link query
+    LINK_REPORT,                ///< Response to link query
+    LINK_ATTRIB_CHANGED,        ///< An attribute changed
+
+    LINK_STATE_CHANGE_REQUEST,  ///< Link state should be changed
+
+    REASSEMBLY_COMPLETED,       ///< Reassembly completed
+
+    REGISTRATION_ADDED,         ///< New registration arrived
+    REGISTRATION_REMOVED,       ///< Registration removed
+    REGISTRATION_EXPIRED,       ///< Registration expired
+    REGISTRATION_DELETE,	///< Registration to be deleted
+
+    ROUTE_ADD,                  ///< Add a new entry to the route table
+    ROUTE_DEL,                  ///< Remove an entry from the route table
+    ROUTE_QUERY,                ///< Static route query
+    ROUTE_REPORT,               ///< Response to static route query
+
+    CUSTODY_SIGNAL,             ///< Custody transfer signal received
+    CUSTODY_TIMEOUT,            ///< Custody transfer timer fired
+
+    DAEMON_SHUTDOWN,            ///< Shut the daemon down cleanly
+    DAEMON_STATUS,              ///< No-op event to check the daemon
+
+    CLA_SET_PARAMS,             ///< Set CLA configuration
+    CLA_PARAMS_SET,             ///< CLA configuration changed
+    CLA_SET_LINK_DEFAULTS,      ///< Set defaults for new links
+    CLA_EID_REACHABLE,          ///< A new EID has been discovered
+
+    CLA_BUNDLE_QUEUED_QUERY,    ///< Query if a bundle is queued at the CLA
+    CLA_BUNDLE_QUEUED_REPORT,   ///< Report if a bundle is queued at the CLA
+    CLA_EID_REACHABLE_QUERY,    ///< Query if an EID is reachable by the CLA
+    CLA_EID_REACHABLE_REPORT,   ///< Report if an EID is reachable by the CLA
+    CLA_LINK_ATTRIB_QUERY,      ///< Query CLA for a link's attributes
+    CLA_LINK_ATTRIB_REPORT,     ///< Report from CLA with link attributes
+    CLA_IFACE_ATTRIB_QUERY,     ///< Query CLA for an interface's attributes
+    CLA_IFACE_ATTRIB_REPORT,    ///< Report from CLA with interface attributes
+    CLA_PARAMS_QUERY,           ///< Query CLA for config parameters
+    CLA_PARAMS_REPORT,          ///< Report from CLA with config paramters
+
+} event_type_t;
+
+/**
+ * Conversion function from an event to a string.
+ */
+inline const char*
+event_to_str(event_type_t event)
+{
+    switch(event) {
+
+    case BUNDLE_RECEIVED:       return "BUNDLE_RECEIVED";
+    case BUNDLE_TRANSMITTED:    return "BUNDLE_TRANSMITTED";
+    case BUNDLE_DELIVERED:      return "BUNDLE_DELIVERED";
+    case BUNDLE_DELIVERY:       return "BUNDLE_DELIVERY";
+    case BUNDLE_EXPIRED:        return "BUNDLE_EXPIRED";
+    case BUNDLE_FREE:           return "BUNDLE_FREE";
+    case BUNDLE_NOT_NEEDED:     return "BUNDLE_NOT_NEEDED";
+    case BUNDLE_FORWARD_TIMEOUT:return "BUNDLE_FORWARD_TIMEOUT";
+    case BUNDLE_SEND:           return "BUNDLE_SEND";
+    case BUNDLE_CANCEL:         return "BUNDLE_CANCEL";
+    case BUNDLE_CANCELLED:      return "BUNDLE_CANCELLED";
+    case BUNDLE_INJECT:         return "BUNDLE_INJECT";
+    case BUNDLE_INJECTED:       return "BUNDLE_INJECTED";
+    case BUNDLE_ACCEPT_REQUEST: return "BUNDLE_ACCEPT_REQUEST";
+    case BUNDLE_DELETE:         return "BUNDLE_DELETE";
+    case BUNDLE_QUERY:          return "BUNDLE_QUERY";
+    case BUNDLE_REPORT:         return "BUNDLE_REPORT";
+    case BUNDLE_ATTRIB_QUERY:   return "BUNDLE_ATTRIB_QUERY";
+    case BUNDLE_ATTRIB_REPORT:  return "BUNDLE_ATTRIB_REPORT";
+
+    case CONTACT_UP:            return "CONTACT_UP";
+    case CONTACT_DOWN:          return "CONTACT_DOWN";
+    case CONTACT_QUERY:         return "CONTACT_QUERY";
+    case CONTACT_REPORT:        return "CONTACT_REPORT";
+    case CONTACT_ATTRIB_CHANGED:return "CONTACT_ATTRIB_CHANGED";
+
+    case LINK_CREATED:          return "LINK_CREATED";
+    case LINK_DELETED:          return "LINK_DELETED";
+    case LINK_AVAILABLE:        return "LINK_AVAILABLE";
+    case LINK_UNAVAILABLE:      return "LINK_UNAVAILABLE";
+    case LINK_BUSY:             return "LINK_BUSY";
+    case LINK_CREATE:           return "LINK_CREATE";
+    case LINK_DELETE:           return "LINK_DELETE";
+    case LINK_RECONFIGURE:      return "LINK_RECONFIGURE";
+    case LINK_QUERY:            return "LINK_QUERY";
+    case LINK_REPORT:           return "LINK_REPORT";
+    case LINK_ATTRIB_CHANGED:   return "LINK_ATTRIB_CHANGED";
+
+    case LINK_STATE_CHANGE_REQUEST:return "LINK_STATE_CHANGE_REQUEST";
+
+    case REASSEMBLY_COMPLETED:  return "REASSEMBLY_COMPLETED";
+
+    case REGISTRATION_ADDED:    return "REGISTRATION_ADDED";
+    case REGISTRATION_REMOVED:  return "REGISTRATION_REMOVED";
+    case REGISTRATION_EXPIRED:  return "REGISTRATION_EXPIRED";
+    case REGISTRATION_DELETE:   return "REGISTRATION_DELETE";
+
+    case ROUTE_ADD:             return "ROUTE_ADD";
+    case ROUTE_DEL:             return "ROUTE_DEL";
+    case ROUTE_QUERY:           return "ROUTE_QUERY";
+    case ROUTE_REPORT:          return "ROUTE_REPORT";
+
+    case CUSTODY_SIGNAL:        return "CUSTODY_SIGNAL";
+    case CUSTODY_TIMEOUT:       return "CUSTODY_TIMEOUT";
+    
+    case DAEMON_SHUTDOWN:       return "SHUTDOWN";
+    case DAEMON_STATUS:         return "DAEMON_STATUS";
+        
+    case CLA_SET_PARAMS:        return "CLA_SET_PARAMS";
+    case CLA_PARAMS_SET:        return "CLA_PARAMS_SET";
+    case CLA_SET_LINK_DEFAULTS: return "CLA_SET_LINK_DEFAULTS";
+    case CLA_EID_REACHABLE:     return "CLA_EID_REACHABLE";
+
+    case CLA_BUNDLE_QUEUED_QUERY:  return "CLA_BUNDLE_QUEUED_QUERY";
+    case CLA_BUNDLE_QUEUED_REPORT: return "CLA_BUNDLE_QUEUED_REPORT";
+    case CLA_EID_REACHABLE_QUERY:  return "CLA_EID_REACHABLE_QUERY";
+    case CLA_EID_REACHABLE_REPORT: return "CLA_EID_REACHABLE_REPORT";
+    case CLA_LINK_ATTRIB_QUERY:    return "CLA_LINK_ATTRIB_QUERY";
+    case CLA_LINK_ATTRIB_REPORT:   return "CLA_LINK_ATTRIB_REPORT";
+    case CLA_IFACE_ATTRIB_QUERY:   return "CLA_IFACE_ATTRIB_QUERY";
+    case CLA_IFACE_ATTRIB_REPORT:  return "CLA_IFACE_ATTRIB_REPORT";
+    case CLA_PARAMS_QUERY:         return "CLA_PARAMS_QUERY";
+    case CLA_PARAMS_REPORT:        return "CLA_PARAMS_REPORT";
+
+    default:                   return "(invalid event type)";
+        
+    }
+}
+
+/**
+ * Possible sources for events.
+ */
+typedef enum {
+    EVENTSRC_PEER   = 1,        ///< a peer dtn forwarder
+    EVENTSRC_APP    = 2,        ///< a local application
+    EVENTSRC_STORE  = 3,        ///< the data store
+    EVENTSRC_ADMIN  = 4,        ///< the admin logic
+    EVENTSRC_FRAGMENTATION = 5, ///< the fragmentation engine
+    EVENTSRC_ROUTER = 6         ///< the routing logic
+} event_source_t;
+
+/**
+ * Conversion function from a source to a string
+ * suitable for use with plug-in arch XML messaging.
+ */
+inline const char*
+source_to_str(event_source_t source)
+{
+    switch(source) {
+
+    case EVENTSRC_PEER:             return "peer";
+    case EVENTSRC_APP:              return "application";
+    case EVENTSRC_STORE:            return "dataStore";
+    case EVENTSRC_ADMIN:            return "admin";
+    case EVENTSRC_FRAGMENTATION:    return "fragmentation";
+    case EVENTSRC_ROUTER:           return "router";
+
+    default:                        return "(invalid source type)";
+    }
+}
+
+class MetadataBlockRequest {
+public:
+    enum QueryType { QueryByIdentifier, QueryByType, QueryAll };
+
+    MetadataBlockRequest(QueryType query_type, unsigned int query_value) :
+        _query_type(query_type), _query_value(query_value) { }
+
+    int          query_type()  const { return _query_type; }
+    unsigned int query_value() const { return _query_value; }
+
+private:
+    QueryType    _query_type;
+    unsigned int _query_value;
+};
+typedef std::vector<MetadataBlockRequest> MetaBlockRequestVector;
+
+/**
+ * Event base class.
+ */
+class BundleEvent {
+public:
+    /**
+     * The event type code.
+     */
+    const event_type_t type_;
+
+    /**
+     * Bit indicating whether this event is for the daemon only or if
+     * it should be propagated to other components (i.e. the various
+     * routers).
+     */
+    bool daemon_only_;
+
+    /**
+     * Slot for a notifier to indicate that the event was processed.
+     */
+    oasys::Notifier* processed_notifier_;
+
+    /**
+     * Slot to record the time that the event was put into the queue.
+     */
+    oasys::Time posted_time_;
+
+    /**
+     * Used for printing
+     */
+    const char* type_str() {
+        return event_to_str(type_);
+    }
+
+    /**
+     * Need a virtual destructor to make sure all the right bits are
+     * cleaned up.
+     */
+    virtual ~BundleEvent() {}
+
+protected:
+    /**
+     * Constructor (protected since one of the subclasses should
+     * always be that which is actually initialized.
+     */
+    BundleEvent(event_type_t type)
+        : type_(type),
+          daemon_only_(false),
+          processed_notifier_(NULL) {}
+};
+
+/**
+ * Event class for new bundle arrivals.
+ */
+class BundleReceivedEvent : public BundleEvent {
+public:
+    /*
+     * Constructor for bundles arriving from a peer, named by the
+     * prevhop and optionally marked with the link it arrived on.
+     */
+    BundleReceivedEvent(Bundle*           bundle,
+                        event_source_t    source,
+                        u_int32_t         bytes_received,
+                        const EndpointID& prevhop,
+                        Link*             originator = NULL)
+
+        : BundleEvent(BUNDLE_RECEIVED),
+          bundleref_(bundle, "BundleReceivedEvent"),
+          source_(source),
+          bytes_received_(bytes_received),
+          link_(originator, "BundleReceivedEvent"),
+          prevhop_(prevhop),
+          registration_(NULL)
+    {
+        ASSERT(source == EVENTSRC_PEER);
+    }
+
+    /*
+     * Constructor for bundles arriving from a local application
+     * identified by the given Registration.
+     */
+    BundleReceivedEvent(Bundle*        bundle,
+                        event_source_t source,
+                        Registration*  registration)
+        : BundleEvent(BUNDLE_RECEIVED),
+          bundleref_(bundle, "BundleReceivedEvent"),
+          source_(source),
+          bytes_received_(0),
+          link_("BundleReceivedEvent"),
+          prevhop_(EndpointID::NULL_EID()),
+          registration_(registration)
+    {
+    }
+
+    /*
+     * Constructor for other "arriving" bundles, including reloading
+     * from storage and generated signals.
+     */
+    BundleReceivedEvent(Bundle*        bundle,
+                        event_source_t source)
+        : BundleEvent(BUNDLE_RECEIVED),
+          bundleref_(bundle, "BundleReceivedEvent"),
+          source_(source),
+          bytes_received_(0),
+          link_("BundleReceivedEvent"),
+          prevhop_(EndpointID::NULL_EID()),
+          registration_(NULL)
+    {
+    }
+
+    /// The newly arrived bundle
+    BundleRef bundleref_;
+
+    /// The source of the bundle
+    int source_;
+
+    /// The total bytes actually received
+    u_int32_t bytes_received_;
+
+    /// Link from which bundle was received, if applicable
+    LinkRef link_;
+
+    /// Previous hop endpoint id
+    EndpointID prevhop_;
+
+    /// Registration where the bundle arrived
+    Registration* registration_;
+};
+
+/**
+ * Event class for bundle or fragment transmission.
+ */
+class BundleTransmittedEvent : public BundleEvent {
+public:
+    BundleTransmittedEvent(Bundle* bundle, const ContactRef& contact,
+                           const LinkRef& link, u_int32_t bytes_sent,
+                           u_int32_t reliably_sent)
+        : BundleEvent(BUNDLE_TRANSMITTED),
+          bundleref_(bundle, "BundleTransmittedEvent"),
+          contact_(contact.object(), "BundleTransmittedEvent"),
+          bytes_sent_(bytes_sent),
+          reliably_sent_(reliably_sent),
+          link_(link.object(), "BundleTransmittedEvent") {}
+
+    /// The transmitted bundle
+    BundleRef bundleref_;
+
+    /// The contact where the bundle was sent
+    ContactRef contact_;
+
+    /// Total number of bytes sent
+    u_int32_t bytes_sent_;
+
+    /// If the convergence layer that we sent on is reliable, this is
+    /// the count of the bytes reliably sent, which must be less than
+    /// or equal to the bytes transmitted
+    u_int32_t reliably_sent_;
+
+    /// The link over which the bundle was sent
+    /// (may not have a contact when the transmission result is reported)
+    LinkRef link_;
+
+};
+
+/**
+ * Event class for local bundle delivery.
+ */
+class BundleDeliveredEvent : public BundleEvent {
+public:
+    BundleDeliveredEvent(Bundle* bundle, Registration* registration)
+        : BundleEvent(BUNDLE_DELIVERED),
+          bundleref_(bundle, "BundleDeliveredEvent"),
+          registration_(registration) {}
+
+    /// The delivered bundle
+    BundleRef bundleref_;
+
+    /// The registration that got it
+    Registration* registration_;
+};
+
+/**
+ * Event class for local bundle delivery.
+ */
+class BundleDeliveryEvent : public BundleEvent {
+public:
+    BundleDeliveryEvent(Bundle* bundle,
+                         event_source_t source)
+        : BundleEvent(BUNDLE_DELIVERY),
+          bundleref_(bundle, "BundleDeliveryEvent"),
+          source_(source) {}
+
+    /// The bundle we're delivering
+    BundleRef bundleref_;
+
+    /// The source of the bundle
+    int source_;
+};
+
+/**
+ * Event class for bundle expiration.
+ */
+class BundleExpiredEvent : public BundleEvent {
+public:
+    BundleExpiredEvent(Bundle* bundle)
+        : BundleEvent(BUNDLE_EXPIRED),
+          bundleref_(bundle, "BundleExpiredEvent") {}
+
+    /// The expired bundle
+    BundleRef bundleref_;
+};
+
+/**
+ * Event class for bundles that have no more references to them.
+ */
+class BundleFreeEvent : public BundleEvent {
+public:
+    BundleFreeEvent(Bundle* bundle)
+        : BundleEvent(BUNDLE_FREE),
+          bundle_(bundle)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    /// The freed bundle
+    Bundle* bundle_;
+};
+
+/**
+ * Abstract class for the subset of events related to contacts and
+ * links that defines a reason code enumerated type.
+ */
+class ContactEvent : public BundleEvent {
+public:
+    /**
+     * Reason codes for contact state operations
+     */
+    typedef enum {
+        INVALID = 0,    ///< Should not be used
+        NO_INFO,        ///< No additional info
+        USER,           ///< User action (i.e. console / config)
+        BROKEN,         ///< Unexpected session interruption
+        DISCOVERY,      ///< Dynamically discovered link
+        CL_ERROR,       ///< Convergence layer protocol error
+        CL_VERSION,     ///< Convergence layer version mismatch
+        SHUTDOWN,       ///< Clean connection shutdown
+        RECONNECT,      ///< Re-establish link after failure
+        IDLE,           ///< Idle connection shut down by the CL
+        TIMEOUT,        ///< Scheduled link ended duration
+    } reason_t;
+
+    /**
+     * Reason to string conversion.
+     */
+    static const char* reason_to_str(int reason) {
+        switch(reason) {
+        case INVALID:   return "INVALID";
+        case NO_INFO:   return "no additional info";
+        case USER:      return "user action";
+        case DISCOVERY: return "link discovery";
+        case SHUTDOWN:  return "peer shut down";
+        case BROKEN:    return "connection broken";
+        case CL_ERROR:  return "cl protocol error";
+        case CL_VERSION:return "cl version mismatch";
+        case RECONNECT: return "re-establishing connection";
+        case IDLE:      return "connection idle";
+        case TIMEOUT:   return "schedule timed out";
+        }
+        NOTREACHED;
+    }
+
+    /// Constructor
+    ContactEvent(event_type_t type, reason_t reason = NO_INFO)
+        : BundleEvent(type), reason_(reason) {}
+
+    int reason_;        ///< reason code for the event
+};
+
+/**
+ * Event class for contact up events
+ */
+class ContactUpEvent : public ContactEvent {
+public:
+    ContactUpEvent(const ContactRef& contact)
+        : ContactEvent(CONTACT_UP),
+          contact_(contact.object(), "ContactUpEvent") {}
+
+    /// The contact that is up
+    ContactRef contact_;
+};
+
+/**
+ * Event class for contact down events
+ */
+class ContactDownEvent : public ContactEvent {
+public:
+    ContactDownEvent(const ContactRef& contact, reason_t reason)
+        : ContactEvent(CONTACT_DOWN, reason),
+          contact_(contact.object(), "ContactDownEvent") {}
+
+    /// The contact that is now down
+    ContactRef contact_;
+};
+
+/**
+ * Event classes for contact queries and responses
+ */
+class ContactQueryRequest: public BundleEvent {
+public:
+    ContactQueryRequest() : BundleEvent(CONTACT_QUERY)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+};
+
+class ContactReportEvent : public BundleEvent {
+public:
+    ContactReportEvent() : BundleEvent(CONTACT_REPORT) {}
+};
+
+/**
+ * Event class for a change in contact attributes.
+ */
+class ContactAttributeChangedEvent: public ContactEvent {
+public:
+    ContactAttributeChangedEvent(const ContactRef& contact, reason_t reason)
+        : ContactEvent(CONTACT_ATTRIB_CHANGED, reason),
+          contact_(contact.object(), "ContactAttributeChangedEvent") {}
+
+    ///< The link/contact that changed
+    ContactRef contact_;
+};
+
+/**
+ * Event class for link creation events
+ */
+class LinkCreatedEvent : public ContactEvent {
+public:
+    LinkCreatedEvent(const LinkRef& link, reason_t reason = ContactEvent::USER)
+        : ContactEvent(LINK_CREATED, reason),
+          link_(link.object(), "LinkCreatedEvent") {}
+
+    /// The link that was created
+    LinkRef link_;
+};
+
+/**
+ * Event class for link deletion events
+ */
+class LinkDeletedEvent : public ContactEvent {
+public:
+    LinkDeletedEvent(const LinkRef& link, reason_t reason = ContactEvent::USER)
+        : ContactEvent(LINK_DELETED, reason),
+          link_(link.object(), "LinkDeletedEvent") {}
+
+    /// The link that was deleted
+    LinkRef link_;
+};
+
+/**
+ * Event class for link available events
+ */
+class LinkAvailableEvent : public ContactEvent {
+public:
+    LinkAvailableEvent(const LinkRef& link, reason_t reason)
+        : ContactEvent(LINK_AVAILABLE, reason),
+          link_(link.object(), "LinkAvailableEvent") {}
+
+    /// The link that is available
+    LinkRef link_;
+};
+
+/**
+ * Event class for link unavailable events
+ */
+class LinkUnavailableEvent : public ContactEvent {
+public:
+    LinkUnavailableEvent(const LinkRef& link, reason_t reason)
+        : ContactEvent(LINK_UNAVAILABLE, reason),
+          link_(link.object(), "LinkUnavailableEvent") {}
+
+    /// The link that is unavailable
+    LinkRef link_;
+};
+
+/**
+ * Request class for link state change requests that are sent to the
+ * daemon thread for processing. This includes requests to open or
+ * close the link, and changing its status to available or
+ * unavailable.
+ *
+ * When closing a link, a reason must be given for the event.
+ */
+class LinkStateChangeRequest : public ContactEvent {
+public:
+    /// Shared type code for state_t with Link
+    typedef Link::state_t state_t;
+
+    LinkStateChangeRequest(const LinkRef& link, state_t state, reason_t reason)
+        : ContactEvent(LINK_STATE_CHANGE_REQUEST, reason),
+          link_(link.object(), "LinkStateChangeRequest"),
+          state_(state), contact_("LinkStateChangeRequest")
+    {
+        daemon_only_ = true;
+        
+        contact_   = link->contact();
+        old_state_ = link->state();
+    }
+
+    LinkStateChangeRequest(const oasys::Builder&,
+                           state_t state, reason_t reason)
+        : ContactEvent(LINK_STATE_CHANGE_REQUEST, reason),
+          state_(state), contact_("LinkStateChangeRequest")
+    {
+        daemon_only_ = true;
+    }
+
+    /// The link to be changed
+    LinkRef link_;
+
+    /// Requested state
+    int state_;
+    
+    /// The active Contact when the request was made
+    ContactRef contact_;
+
+    /// State when the request was made
+    int old_state_;
+};
+
+/**
+ * Event class for new registration arrivals.
+ */
+class RegistrationAddedEvent : public BundleEvent {
+public:
+    RegistrationAddedEvent(Registration* reg, event_source_t source)
+        : BundleEvent(REGISTRATION_ADDED), registration_(reg),
+          source_(source) {}
+
+    /// The newly added registration
+    Registration* registration_;
+
+    /// Why is the registration added
+    int source_;
+};
+
+/**
+ * Event class for registration removals.
+ */
+class RegistrationRemovedEvent : public BundleEvent {
+public:
+    RegistrationRemovedEvent(Registration* reg)
+        : BundleEvent(REGISTRATION_REMOVED), registration_(reg) {}
+
+    /// The to-be-removed registration
+    Registration* registration_;
+};
+
+/**
+ * Event class for registration expiration.
+ */
+class RegistrationExpiredEvent : public BundleEvent {
+public:
+    RegistrationExpiredEvent(Registration* registration)
+        : BundleEvent(REGISTRATION_EXPIRED),
+          registration_(registration) {}
+    
+    /// The to-be-removed registration 
+    Registration* registration_;
+};
+
+/**
+ * Daemon-only event class used to delete a registration after it's
+ * removed or expired.
+ */
+class RegistrationDeleteRequest : public BundleEvent {
+public:
+    RegistrationDeleteRequest(Registration* registration)
+        : BundleEvent(REGISTRATION_DELETE),
+          registration_(registration)
+    {
+        daemon_only_ = true;
+    }
+
+    /// The registration to be deleted
+    Registration* registration_;
+};
+
+/**
+ * Event class for route add events
+ */
+class RouteAddEvent : public BundleEvent {
+public:
+    RouteAddEvent(RouteEntry* entry)
+        : BundleEvent(ROUTE_ADD), entry_(entry) {}
+
+    /// The route table entry to be added
+    RouteEntry* entry_;
+};
+
+/**
+ * Event class for route delete events
+ */
+class RouteDelEvent : public BundleEvent {
+public:
+    RouteDelEvent(const EndpointIDPattern& dest)
+        : BundleEvent(ROUTE_DEL), dest_(dest) {}
+
+    /// The destination eid to be removed
+    EndpointIDPattern dest_;
+};
+
+/**
+ * Event classes for static route queries and responses
+ */
+class RouteQueryRequest: public BundleEvent {
+public:
+    RouteQueryRequest() : BundleEvent(ROUTE_QUERY)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+};
+
+class RouteReportEvent : public BundleEvent {
+public:
+    RouteReportEvent() : BundleEvent(ROUTE_REPORT) {}
+};
+
+/**
+ * Event class for reassembly completion.
+ */
+class ReassemblyCompletedEvent : public BundleEvent {
+public:
+    ReassemblyCompletedEvent(Bundle* bundle, BundleList* fragments)
+        : BundleEvent(REASSEMBLY_COMPLETED),
+          bundle_(bundle, "ReassemblyCompletedEvent"),
+          fragments_("ReassemblyCompletedEvent")
+    {
+        fragments->move_contents(&fragments_);
+    }
+
+    /// The newly reassembled bundle
+    BundleRef bundle_;
+
+    /// The list of bundle fragments
+    BundleList fragments_;
+};
+
+/**
+ * Event class for custody transfer signal arrivals.
+ */
+class CustodySignalEvent : public BundleEvent {
+public:
+    CustodySignalEvent(const CustodySignal::data_t& data)
+        : BundleEvent(CUSTODY_SIGNAL), data_(data) {}
+    
+    /// The parsed data from the custody transfer signal
+    CustodySignal::data_t data_;
+};
+
+/**
+ * Event class for custody transfer timeout events
+ */
+class CustodyTimeoutEvent : public BundleEvent {
+public:
+    CustodyTimeoutEvent(Bundle* bundle, const LinkRef& link)
+        : BundleEvent(CUSTODY_TIMEOUT),
+          bundle_(bundle, "CustodyTimeoutEvent"),
+          link_(link.object(), "CustodyTimeoutEvent") {}
+
+    ///< The bundle whose timer fired
+    BundleRef bundle_;
+
+    ///< The link it was sent on
+    LinkRef link_;
+};
+
+/**
+ * Event class for shutting down a daemon. The daemon closes and
+ * deletes all links, then cleanly closes the various data stores,
+ * then calls exit().
+ */
+class ShutdownRequest : public BundleEvent {
+public:
+    ShutdownRequest() : BundleEvent(DAEMON_SHUTDOWN)
+    {
+        daemon_only_ = true;
+    }
+};
+
+/**
+ * Event class for checking that the daemon is still running.
+ */
+class StatusRequest : public BundleEvent {
+public:
+    StatusRequest() : BundleEvent(DAEMON_STATUS)
+    {
+        daemon_only_ = true;
+    }
+};
+
+/**
+ * Event class for sending a bundle
+ */
+class BundleSendRequest: public BundleEvent {
+public:
+    BundleSendRequest() : BundleEvent(BUNDLE_SEND)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+ 
+    BundleSendRequest(const BundleRef& bundle,
+                      const std::string& link,
+                      int action)
+        : BundleEvent(BUNDLE_SEND),
+          bundle_(bundle.object(), "BundleSendRequest"),
+          link_(link),
+          action_(action)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+ 
+    ///< Bundle to be sent
+    BundleRef bundle_;
+
+    ///< Link on which to send the bundle
+    std::string link_;
+
+    ///< Forwarding action to use when sending bundle
+    int action_;
+};
+
+/**
+ * Event class for canceling a bundle transmission
+ */
+class BundleCancelRequest: public BundleEvent {
+public:
+    BundleCancelRequest() : BundleEvent(BUNDLE_CANCEL)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    BundleCancelRequest(const BundleRef& bundle, const std::string& link) 
+        : BundleEvent(BUNDLE_CANCEL),
+          bundle_(bundle.object(), "BundleCancelRequest"),
+          link_(link)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< Bundle to be cancelled
+    BundleRef bundle_;
+
+    ///< Link where the bundle is destined
+    std::string link_;
+};
+
+/**
+ * Event class for succesful cancellation of a bundle send.
+ */
+class BundleSendCancelledEvent : public BundleEvent {
+public:
+    BundleSendCancelledEvent(Bundle* bundle, const LinkRef& link)
+        : BundleEvent(BUNDLE_CANCELLED),
+          bundleref_(bundle, "BundleSendCancelledEvent"),
+          link_(link.object(), "BundleSendCancelledEvent") {}
+
+    /// The cancelled bundle
+    BundleRef bundleref_;
+
+    /// The link it was queued on
+    LinkRef link_;
+};
+
+/**
+ * Event class for injecting a bundle
+ */
+class BundleInjectRequest: public BundleEvent {
+public:
+    BundleInjectRequest() : BundleEvent(BUNDLE_INJECT)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+    
+    // Bundle properties
+    std::string src_;
+    std::string dest_;
+    std::string replyto_;
+    std::string custodian_;
+    u_int8_t    priority_;
+    u_int32_t   expiration_;
+    std::string payload_file_;
+
+    // Outgoing link
+    std::string link_;
+
+    // Forwarding action
+    int action_;
+
+    // Request ID for the event, to identify corresponding BundleInjectedEvent
+    std::string request_id_;
+};
+
+/**
+ * Event class for a succesful bundle injection
+ */
+class BundleInjectedEvent: public BundleEvent {
+public:
+    BundleInjectedEvent(Bundle *bundle, const std::string &request_id)
+        : BundleEvent(BUNDLE_INJECTED),
+          bundleref_(bundle, "BundleInjectedEvent"),
+          request_id_(request_id)
+    {
+    }
+
+    /// The injected bundle
+    BundleRef bundleref_;
+
+    // Request ID from the inject request
+    std::string request_id_;
+};
+
+/**
+ * Event class for requestion deletion of a bundle
+ */
+class BundleDeleteRequest: public BundleEvent {
+public:
+    BundleDeleteRequest() : BundleEvent(BUNDLE_DELETE)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    BundleDeleteRequest(Bundle* bundle,
+                        BundleProtocol::status_report_reason_t reason)
+        : BundleEvent(BUNDLE_DELETE),
+          bundle_(bundle, "BundleDeleteRequest"),
+          reason_(reason)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    BundleDeleteRequest(const BundleRef& bundle,
+                        BundleProtocol::status_report_reason_t reason)
+        : BundleEvent(BUNDLE_DELETE),
+          bundle_(bundle.object(), "BundleDeleteRequest"),
+          reason_(reason)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< Bundle to be deleted
+    BundleRef bundle_;
+
+    /// The reason code
+    BundleProtocol::status_report_reason_t reason_;
+};
+
+/**
+ * Event class to optionally probe if a bundle can be accepted by the
+ * system before a BundleReceivedEvent is posted. Currently used for
+ * backpressure via the API.
+ *
+ * Note that the bundle may not be completely constructed when this
+ * event is posted. In particular, the payload need not be filled in
+ * yet, and other security fields may not be present. At a minimum
+ * though, the fields from the primary block and the payload length
+ * must be known.
+ */
+class BundleAcceptRequest : public BundleEvent {
+public:
+    BundleAcceptRequest(const BundleRef& bundle,
+                        event_source_t   source,
+                        bool*            result,
+                        int*             reason)
+        : BundleEvent(BUNDLE_ACCEPT_REQUEST),
+          bundle_(bundle.object(), "BundleAcceptRequest"),
+          source_(source),
+          result_(result),
+          reason_(reason)
+    {
+    }
+    
+    /// The newly arrived bundle
+    BundleRef bundle_;
+
+    /// The source of the event
+    int source_;
+
+    /// Pointer to the expected result
+    bool* result_;
+
+    /// Pointer to the reason code
+    int* reason_;
+};
+
+/**
+ * Event classes for bundle queries and responses
+ */
+class BundleQueryRequest: public BundleEvent {
+public:
+    BundleQueryRequest() : BundleEvent(BUNDLE_QUERY)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+};
+
+class BundleReportEvent : public BundleEvent {
+public:
+    BundleReportEvent() : BundleEvent(BUNDLE_REPORT) {}
+};
+
+class BundleAttributesQueryRequest: public BundleEvent {
+public:
+    BundleAttributesQueryRequest(const std::string& query_id,
+                                 const BundleRef& bundle,
+                                 const AttributeNameVector& attribute_names)
+        : BundleEvent(BUNDLE_ATTRIB_QUERY),
+          query_id_(query_id),
+          bundle_(bundle.object(), "BundleAttributesQueryRequest"),
+          attribute_names_(attribute_names) {}
+
+    /// Query Identifier
+    std::string query_id_;
+
+    ///< Bundle being queried
+    BundleRef bundle_;
+
+    /// bundle attributes requested by name.
+    AttributeNameVector attribute_names_;
+
+    /// metadata blocks requested by type/identifier
+    MetaBlockRequestVector metadata_blocks_;
+};
+
+class BundleAttributesReportEvent: public BundleEvent {
+public:
+    BundleAttributesReportEvent(const std::string& query_id,
+                                const BundleRef& bundle,
+                                const AttributeNameVector& attribute_names,
+                                const MetaBlockRequestVector& metadata_blocks)
+        : BundleEvent(BUNDLE_ATTRIB_REPORT),
+          query_id_(query_id),
+          bundle_(bundle.object(), "BundleAttributesReportEvent"),
+          attribute_names_(attribute_names),
+          metadata_blocks_(metadata_blocks) {}
+
+    /// Query Identifier
+    std::string query_id_;
+
+    /// Bundle that was queried
+    BundleRef bundle_;
+
+    /// bundle attributes requested by name.
+    AttributeNameVector attribute_names_;
+
+    /// metadata blocks requested by type/identifier
+    MetaBlockRequestVector metadata_blocks_;
+};
+
+/**
+ * Event class for creating and opening a link
+ */
+class LinkCreateRequest: public BundleEvent {
+public:
+    LinkCreateRequest(const std::string &name, Link::link_type_t link_type,
+                      const std::string &endpoint,
+                      ConvergenceLayer *cla, AttributeVector &parameters)
+        : BundleEvent(LINK_CREATE),
+          name_(name),
+          endpoint_(endpoint),
+          link_type_(link_type),
+          cla_(cla),
+          parameters_(parameters)
+        
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< Identifier for the link
+    std::string name_;
+
+    ///< Next hop EID
+    std::string endpoint_;
+
+    ///< Type of link
+    Link::link_type_t link_type_;
+
+    ///< CL to use
+    ConvergenceLayer *cla_;
+
+    ///< An optional set of key, value pairs
+    AttributeVector parameters_;
+};
+
+/**
+ * Event class for reconfiguring an existing link.
+ */
+class LinkReconfigureRequest: public BundleEvent {
+public:
+    LinkReconfigureRequest(const LinkRef& link,
+                           AttributeVector &parameters)
+        : BundleEvent(LINK_RECONFIGURE),
+          link_(link.object(), "LinkReconfigureRequest"),
+          parameters_(parameters)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< The link to be changed
+    LinkRef link_;
+
+    ///< Set of key, value pairs
+    AttributeVector parameters_;
+};
+
+/**
+ * Event class for requesting deletion of a link.
+ */
+class LinkDeleteRequest: public BundleEvent {
+public:
+    LinkDeleteRequest(const LinkRef& link) :
+        BundleEvent(LINK_DELETE),
+        link_(link.object(), "LinkDeleteRequest")
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< The link to be deleted
+    LinkRef link_;
+};
+
+/**
+ * Event class for a change in link attributes.
+ */
+class LinkAttributeChangedEvent: public ContactEvent {
+public:
+    LinkAttributeChangedEvent(const LinkRef& link,
+                              AttributeVector attributes,
+                              reason_t reason = ContactEvent::NO_INFO)
+        : ContactEvent(LINK_ATTRIB_CHANGED, reason),
+          link_(link.object(), "LinkAttributeChangedEvent"),
+          attributes_(attributes)
+    {
+    }
+
+    ///< The link that changed
+    LinkRef link_;
+
+    ///< Attributes that changed
+    AttributeVector attributes_;
+};
+
+/**
+ * Event classes for link queries and responses
+ */
+class LinkQueryRequest: public BundleEvent {
+public:
+    LinkQueryRequest() : BundleEvent(LINK_QUERY)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+};
+
+class LinkReportEvent : public BundleEvent {
+public:
+    LinkReportEvent() : BundleEvent(LINK_REPORT) {}
+};
+
+/**
+ * Event class for DP-originated CLA parameter change requests.
+ */
+class CLASetParamsRequest : public BundleEvent {
+public:
+    CLASetParamsRequest(ConvergenceLayer *cla, AttributeVector &parameters)
+        : BundleEvent(CLA_SET_PARAMS), cla_(cla), parameters_(parameters)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< CL to change
+    ConvergenceLayer *cla_;
+
+    ///< Set of key, value pairs
+    AttributeVector parameters_;
+};
+
+/**
+ * Event class for CLA parameter change request completion events.
+ */
+class CLAParamsSetEvent : public BundleEvent {
+public:
+    CLAParamsSetEvent(ConvergenceLayer *cla, std::string name)
+        : BundleEvent(CLA_PARAMS_SET), cla_(cla), name_(name) {}
+
+    ///< CL that changed
+    ConvergenceLayer *cla_;
+
+    ///< Name of CL (if cla_ is External)
+    std::string name_;
+};
+
+/**
+ * Event class for DP-originated requests to set link defaults.
+ */
+class SetLinkDefaultsRequest : public BundleEvent {
+public:
+    SetLinkDefaultsRequest(AttributeVector &parameters)
+        : BundleEvent(CLA_SET_LINK_DEFAULTS), parameters_(parameters)
+    {
+        // should be processed only by the daemon
+        daemon_only_ = true;
+    }
+
+    ///< Set of key, value pairs
+    AttributeVector parameters_;
+};
+
+/**
+ * Event class for discovery of a new EID.
+ */
+class NewEIDReachableEvent: public BundleEvent {
+public:
+    NewEIDReachableEvent(Interface* iface, const std::string &endpoint)
+        : BundleEvent(CLA_EID_REACHABLE),
+          iface_(iface),
+          endpoint_(endpoint) {}
+
+    ///< The interface the peer was discovered on
+    Interface* iface_;
+
+    ///> The EID of the discovered peer
+    std::string endpoint_;
+};
+
+/**
+ *  Event classes for queries to and reports from the CLA.
+ */
+
+class CLAQueryReport: public BundleEvent {
+public:
+
+    /// Query Identifier
+    std::string query_id_;
+
+protected:
+
+    /**
+     * Constructor; protected because this class should only be
+     * instantiated via a subclass.
+     */
+    CLAQueryReport(event_type_t type,
+                   const std::string& query_id,
+                   bool daemon_only = false)
+        : BundleEvent(type),
+          query_id_(query_id)
+    {
+        daemon_only_ = daemon_only;
+    }
+};
+
+class BundleQueuedQueryRequest: public CLAQueryReport {
+public:
+    BundleQueuedQueryRequest(const std::string& query_id,
+                             Bundle* bundle,
+                             const LinkRef& link)
+        : CLAQueryReport(CLA_BUNDLE_QUEUED_QUERY, query_id, true),
+          bundle_(bundle, "BundleQueuedQueryRequest"),
+          link_(link.object(), "BundleQueuedQueryRequest") {}
+
+    /// Bundle to be checked for queued status.
+    BundleRef bundle_;
+
+    /// Link on which to check if the given bundle is queued.
+    LinkRef link_;
+};
+
+class BundleQueuedReportEvent: public CLAQueryReport {
+public:
+    BundleQueuedReportEvent(const std::string& query_id,
+                            bool is_queued)
+        : CLAQueryReport(CLA_BUNDLE_QUEUED_REPORT, query_id),
+          is_queued_(is_queued) {}
+
+    /// True if the queried bundle was queued on the given link;
+    /// otherwise false.
+    bool is_queued_;
+};
+
+class EIDReachableQueryRequest: public CLAQueryReport {
+public:
+    EIDReachableQueryRequest(const std::string& query_id,
+                             Interface* iface,
+                             const std::string& endpoint)
+        : CLAQueryReport(CLA_EID_REACHABLE_QUERY, query_id, true),
+          iface_(iface),
+          endpoint_(endpoint) {}
+
+    /// Interface on which to check if the given endpoint is reachable.
+    Interface* iface_;
+
+    /// Endpoint to be checked for reachable status.
+    std::string endpoint_;
+};
+
+class EIDReachableReportEvent: public CLAQueryReport {
+public:
+    EIDReachableReportEvent(const std::string& query_id,
+                            bool is_reachable)
+        : CLAQueryReport(CLA_EID_REACHABLE_REPORT, query_id),
+          is_reachable_(is_reachable) {}
+
+    /// True if the queried endpoint is reachable via the given interface;
+    /// otherwise false.
+    bool is_reachable_;
+};
+
+class LinkAttributesQueryRequest: public CLAQueryReport {
+public:
+    LinkAttributesQueryRequest(const std::string& query_id,
+                               const LinkRef& link,
+                               const AttributeNameVector& attribute_names)
+        : CLAQueryReport(CLA_LINK_ATTRIB_QUERY, query_id, true),
+          link_(link.object(), "LinkAttributesQueryRequest"),
+          attribute_names_(attribute_names) {}
+
+    /// Link for which the given attributes are requested.
+    LinkRef link_;
+
+    /// Link attributes requested by name.
+    AttributeNameVector attribute_names_;
+};
+
+class LinkAttributesReportEvent: public CLAQueryReport {
+public:
+    LinkAttributesReportEvent(const std::string& query_id,
+                              const AttributeVector& attributes)
+        : CLAQueryReport(CLA_LINK_ATTRIB_REPORT, query_id),
+          attributes_(attributes) {}
+
+    /// Link attribute values given by name.
+    AttributeVector attributes_;
+};
+
+class IfaceAttributesQueryRequest: public CLAQueryReport {
+public:
+    IfaceAttributesQueryRequest(const std::string& query_id,
+                                Interface* iface,
+                                const AttributeNameVector& attribute_names)
+        : CLAQueryReport(CLA_IFACE_ATTRIB_QUERY, query_id, true),
+          iface_(iface),
+          attribute_names_(attribute_names) {}
+
+    /// Interface for which the given attributes are requested.
+    Interface* iface_;
+
+    /// Link attributes requested by name.
+    AttributeNameVector attribute_names_;
+};
+
+class IfaceAttributesReportEvent: public CLAQueryReport {
+public:
+    IfaceAttributesReportEvent(const std::string& query_id,
+                               const AttributeVector& attributes)
+        : CLAQueryReport(CLA_IFACE_ATTRIB_REPORT, query_id),
+          attributes_(attributes) {}
+
+    /// Interface attribute values by name.
+    AttributeVector attributes_;
+};
+
+class CLAParametersQueryRequest: public CLAQueryReport {
+public:
+    CLAParametersQueryRequest(const std::string& query_id,
+                              ConvergenceLayer* cla,
+                              const AttributeNameVector& parameter_names)
+        : CLAQueryReport(CLA_PARAMS_QUERY, query_id, true),
+          cla_(cla),
+          parameter_names_(parameter_names) {}
+
+    /// Convergence layer for which the given parameters are requested.
+    ConvergenceLayer* cla_;
+
+    /// Convergence layer parameters requested by name.
+    AttributeNameVector parameter_names_;
+};
+
+class CLAParametersReportEvent: public CLAQueryReport {
+public:
+    CLAParametersReportEvent(const std::string& query_id,
+                             const AttributeVector& parameters)
+        : CLAQueryReport(CLA_PARAMS_REPORT, query_id),
+          parameters_(parameters) {}
+
+    /// Convergence layer parameter values by name.
+    AttributeVector parameters_;
+};
+
+} // namespace dtn
+
+#endif /* _BUNDLE_EVENT_H_ */