All outgoing links in the system have a state variable, described in the enum (copied from Link.h): typedef enum { UNAVAILABLE, ///< The link is closed and not able to be /// opened currently. AVAILABLE, ///< The link is closed but is able to be /// opened, either because it is an on demand /// link, or because an opportunistic peer /// node is in close proximity but no /// convergence layer session has yet been /// opened. OPENING, ///< A convergence layer session is in the /// process of being established. OPEN, ///< A convergence layer session has been /// established, and the link has capacity /// for a bundle to be sent on it. This may /// be because no bundle is currently being /// sent, or because the convergence layer /// can handle multiple simultaneous bundle /// transmissions. BUSY, ///< The link is busy, i.e. a bundle is /// currently being sent on it by the /// convergence layer and no more bundles may /// be delivered to the link. CLOSING ///< The link is in the process of being /// closed. } state_t; To enforce coordination between the threads and correct notification of events to routers, only the BundleDaemon thread can change the state of a link directly. All other threads should post a LinkStateChangeRequest event to the bundle daemon queue. The only exception to this is the setting up of the initial link state when a link is created. For OPPORTUNISTIC and SCHEDULED links, the initial state is UNAVAILABLE. For ONDEMAND and ALWAYSON links, the initial state is AVAILABLE. ALWAYSON links also immediately post an event to attempt to open the link by posting a link state change request of OPENING. XXX/demmer this isn't really true -- the connection reestablishement code in the TCPCL currently sets the state to OPENING from UNAVAILABLE before sending a ContactUpEvent. This should be fixed. --- Link state changes can be broadly divided into two classes: top-down and bottom-up. The former refers to cases where a control or management layer determines that a link should open (or close), i.e. a user configuration command, or a scheduled link timer (when that gets implemented). The latter refers to cases where the underlying transport or convergence layer determines that either a link has opened opportunistically or that link is closed due to a network timeout, error, or an idle ONDEMAND connection. When the link availability changes, a LinkAvailableEvent / LinkUnavailableEvent is delivered to the router(s). --- There is also the Contact structure, which is conceptually a tuple of [link, time interval] for open links. Currently, a contact is created in Link::open and deleted in Link::close. XXX/demmer this causes some clunkiness with opportunistic connections or other connections that are re-established after becoming unavailable At the beginning and end of a contact opportunity, a ContactUpEvent and ContactDownEvent are delivered to the main system, used to inform the router(s) of the new opportunity to send data. These plus the link availability events are all the notifications that the router(s) see currently. --- To effect some flow control between the network layer(s) and the main bundle daemon, the link has a BUSY state that should be respected by the routers in that they should not call send_bundle on a busy link. For connection oriented CLs, the queue that manages bundle flow between the main thread and the CL thread can be capped at a maximum depth, which when exceeded, will put the link into BUSY state. The connection thread should check for this state when a bundle is sent out and deliver a LinkAvailableEvent to re-enable the link and inform the router(s) that there is a new opportunity to send bundles. XXX/demmer this is strange w.r.t. the router interface since they don't get notified when the link becomes busy, but they do get notified when the link is available again... ---