// [License] // The Ariba-Underlay Copyright // // Copyright (c) 2008-2009, Institute of Telematics, Universität Karlsruhe (TH) // // Institute of Telematics // Universität Karlsruhe (TH) // Zirkel 2, 76128 Karlsruhe // Germany // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation // are those of the authors and should not be interpreted as representing // official policies, either expressed or implied, of the Institute of // Telematics. // [License] #ifndef BASECOMMUNICATION_H_ #define BASECOMMUNICATION_H_ // boost & std includes #include #include #include #include #include #include #include #include #ifdef ECLIPSE_PARSER #define foreach(a, b) for(a : b) #else #define foreach(a, b) BOOST_FOREACH(a, b) #endif // utilities #include "ariba/utility/types.h" #include "ariba/utility/messages/MessageReceiver.h" #include "ariba/utility/logging/Logging.h" #include "ariba/utility/misc/Demultiplexer.hpp" #include "ariba/utility/system/SystemEventListener.h" // new transport and addressing #include "ariba/utility/transport/transport_peer.hpp" #include "ariba/utility/transport/interfaces/transport_connection.hpp" #include "ariba/utility/transport/interfaces/transport_listener.hpp" #include "ariba/utility/addressing2/endpoint.hpp" // communication #include "ariba/communication/CommunicationEvents.h" #include "ariba/communication/EndpointDescriptor.h" #include "ariba/communication/messages/AribaBaseMsg.h" // network changes #include "ariba/communication/networkinfo/NetworkChangeInterface.h" #include "ariba/communication/networkinfo/NetworkChangeDetection.h" #include "ariba/communication/networkinfo/NetworkInformation.h" namespace ariba { class SideportListener; } namespace ariba { namespace communication { class communication_message_not_sent: public std::runtime_error { public: /** Takes a character string describing the error. */ explicit communication_message_not_sent(const string& __arg) : std::runtime_error(__arg) { } virtual ~communication_message_not_sent() throw() {} }; using namespace std; using namespace ariba::transport; using namespace ariba::utility; // use base ariba types (clarifies multiple definitions) using ariba::utility::Message; using ariba::utility::seqnum_t; /** * This class implements the Ariba Base Communication
* * Its primary task is to provide an abstraction to existing * protocols and addressing schemes. * * @author Sebastian Mies, Christoph Mayer, Mario Hock */ class BaseCommunication: public NetworkChangeInterface, public transport_listener { use_logging_h(BaseCommunication); friend class ariba::SideportListener; public: /// Default ctor that just creates an non-functional base communication BaseCommunication(); /// Default dtor that does nothing virtual ~BaseCommunication(); /// Startup the base communication, start modules etc. void start(addressing2::EndpointSetPtr listen_on); /// Stops the base communication, stop modules etc. void stop(); /// Check whether the base communication has been started up bool isStarted(); /// Establishes a link to another end-point. const LinkID establishLink(const EndpointDescriptor& descriptor, const LinkID& linkid = LinkID::UNSPECIFIED, const QoSParameterSet& qos = QoSParameterSet::DEFAULT, const SecurityParameterSet& sec = SecurityParameterSet::DEFAULT); /// Drops a link void dropLink(const LinkID link); /** * Sends a message though an existing link to an end-point. * * @param lid The link identifier * @param message The message to be sent * @return A sequence number for this message */ seqnum_t sendMessage(const LinkID& lid, reboost::message_t message, uint8_t priority, bool bypass_overlay = false) throw(communication_message_not_sent); /** * Returns the end-point descriptor * * @param link the link id of the requested end-point * @return The end-point descriptor of the link's end-point */ const EndpointDescriptor& getEndpointDescriptor(const LinkID link = LinkID::UNSPECIFIED) const; /** * Get local links to the given endpoint of all local link * using the default parameter EndpointDescriptor::UNSPECIFIED * @param ep The remote endpoint to get all links to. * @return List of LinkID */ // LinkIDs getLocalLinks(const address_v* addr) const; // XXX aktuell /** * Registers a receiver. * * @param _receiver The receiving side */ void registerMessageReceiver(MessageReceiver* receiver) { messageReceiver = receiver; } /** * Unregister a receiver. * * @param _receiver The receiving side */ void unregisterMessageReceiver(MessageReceiver* receiver) { messageReceiver = NULL; } void registerEventListener(CommunicationEvents* _events); void unregisterEventListener(CommunicationEvents* _events); /** * called within the ASIO thread * when a message is received from underlay transport */ virtual void receive_message(transport_connection::sptr connection, reboost::shared_buffer_t msg); /** * called within the ASIO thread * when a connection is terminated (e.g. TCP close) */ virtual void connection_terminated(transport_connection::sptr connection); addressing2::EndpointPtr get_local_endpoint_of_link(const LinkID& linkid); addressing2::EndpointPtr get_remote_endpoint_of_link(const LinkID& linkid); protected: /** * called within the ARIBA thread (System Queue) * when a message is received from underlay transport */ void receiveMessage(transport_connection::sptr connection, reboost::shared_buffer_t message); /** * called within the ARIBA thread (System Queue) * when a connection is terminated (e.g. TCP close) */ void connectionTerminated(transport_connection::sptr connection); /// called when a network interface change happens virtual void onNetworkChange( const NetworkChangeInterface::NetworkChangeInfo& info); private: /** * A link descriptor consisting of the end-point descriptor and currently * used underlay address. */ class LinkDescriptor { public: /// default constructor LinkDescriptor() : localLink(LinkID::UNSPECIFIED), remoteLink(LinkID::UNSPECIFIED), up(false) { } ~LinkDescriptor() { if ( connection ) { connection->unregister_communication_link(&localLink); } } bool isUnspecified() const { return (this == &UNSPECIFIED()); } static LinkDescriptor& UNSPECIFIED(){ static LinkDescriptor* unspec = NULL; if(unspec == NULL) unspec = new LinkDescriptor(); return *unspec; } transport_connection::sptr get_connection() const { return connection; } void set_connection(const transport_connection::sptr& conn) { // unregister from old connection, // if any (but normally there shouldn't..) if ( connection ) { connection->unregister_communication_link(&localLink); } // * set_connection * connection = conn; // register this link with the connection conn->register_communication_link(&localLink); } bool unspecified; /// link identifiers LinkID localLink; addressing2::EndpointPtr localLocator; /// used underlay addresses for the link LinkID remoteLink; addressing2::EndpointPtr remoteLocator; /// the remote end-point descriptor EndpointDescriptor remoteDescriptor; /// flag, whether this link is up bool up; private: /// connection if link is up transport_connection::sptr connection; }; /// Link management: list of links typedef vector LinkSet; /// Link management: the set of currently managed links LinkSet linkSet; /// Link management: add a link void addLink( LinkDescriptor* link ); /// Link management: remove a link void removeLink(const LinkID& localLink); /// Link management: get link information using the local link LinkDescriptor& queryLocalLink(const LinkID& localLink) const; /// Link management: get link information using the remote link LinkDescriptor& queryRemoteLink(const LinkID& remoteLink) const; /// The local end-point descriptor EndpointDescriptor localDescriptor; /** * endpoint_set holding the addresses of the "server"-sockets, * ---> that should be opened * * (e.g. 0.0.0.0:41322) */ addressing2::EndpointSetPtr listenOn_endpoints; /** * endpoint_set holding the addresses of the "server"-sockets, * ---> that are actually open * * (e.g. 0.0.0.0:41322) * * XXX should only be in transport_peer */ addressing2::EndpointSetPtr active_listenOn_endpoints; /** * endpoint_set holding the addresses of the "server"-sockets, * ---> here the discovered "addressable" addresses are stored * * (e.g. 192.168.0.5:41322) * * XXX should only be in localDescriptor */ addressing2::EndpointSetPtr local_endpoints; /// network change detector NetworkChangeDetection networkMonitor; /// list of all remote addresses of links to end-points // XXX DEPRECATED // class endpoint_reference { // public: // int count; ///< the number of open links to this end-point // const address_v* endpoint; ///< the end-point itself // }; // vector remote_endpoints; // XXX DEPRECATED // /// adds an end-point to the list // void add_endpoint( const address_v* endpoint ); // // /// removes an end-point from the list // void remove_endpoint( const address_v* endpoint ); /// event listener typedef set EventListenerSet; EventListenerSet eventListener; /// sequence numbers seqnum_t currentSeqnum; /// transport peer transport_peer* transport; /// the base overlay message receiver MessageReceiver* messageReceiver; /* * Sends a message over an existing link. * ---> Adds »Link Message« Header */ bool send_over_link( const uint8_t type, reboost::message_t message, const LinkDescriptor& desc, const uint8_t priority); /* * Sends a message to a known peer. (To all known endpoints.) * ---> Adds »Peer Message« Header */ void send_to_peer( const uint8_t type, const PeerID& peer_id, reboost::message_t message, const EndpointDescriptor& endpoint, const uint8_t priority ); /// state of the base communication bool started; }; }} // namespace ariba, communication #endif /* BASECOMMUNICATION_H_ */