// [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 INSTITUTE OF TELEMATICS 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] #include "Node.h" #include #include "ariba/overlay/BaseOverlay.h" #include "ariba/communication/BaseCommunication.h" #include "ariba/utility/types/OverlayParameterSet.h" #include "ariba/communication/EndpointDescriptor.h" #include using namespace std; using ariba::communication::EndpointDescriptor; using boost::property_tree::ptree; namespace ariba { use_logging_cpp(Node); //Node::Node(AribaModule& ariba_mod, const Name& node_name) : // name(node_name), ariba_mod(ariba_mod) { // base_overlay = new BaseOverlay(); //} Node::Node() : name(Name::UNSPECIFIED), base_communication(NULL), base_overlay(NULL) { base_communication = new BaseCommunication(); base_overlay = new BaseOverlay(); } Node::~Node() { delete base_overlay; base_overlay = NULL; delete base_communication; base_communication = NULL; } void Node::connect(const ptree& config) { using namespace boost::property_tree; using namespace addressing2; assert( ! base_communication->isStarted() ); assert( ! base_overlay->isStarted() ); // XXX needed since »empty_ptree()« is not working // ---> see: http://stackoverflow.com/questions/5003549/where-is-boost-property-treeempty-ptree static const ptree empty_pt; // SpovNet ID Name spovnet_name(config.get("spovnet_name")); spovnetId = spovnet_name.toSpoVNetId(); // Node ID try { name = config.get("node_name"); } catch ( ptree_bad_path& e ) { name = Name::UNSPECIFIED; } nodeId = generateNodeId(name); /* Base Communication */ EndpointSetPtr listen_on; try { listen_on = endpoint_set::create_EndpointSet( config.get_child("listen_on")); } catch ( ptree_bad_path& e ) { /* no endpoints specified, using default: »[::]:41322+« */ ptree default_listen_on; default_listen_on.put("endp.category", "TCPIP"); default_listen_on.put("endp.addr", "::"); default_listen_on.put("endp.port", 0); // defaults to 41322 (or higher) listen_on = endpoint_set::create_EndpointSet(default_listen_on); // logging_warn("No endpoints specified in config. ---> Using default."); cout << "No endpoints specified in config. ---> Using default." << endl; } base_communication->start(listen_on); // TODO maybe notify the upper layer whether we have any active endpoints /* Base Overlay */ base_overlay->start( base_communication, nodeId ); base_overlay->createSpoVNet( spovnetId ); base_overlay->joinSpoVNet( spovnetId ); /* Bootstrap */ const ptree& bootstrap_pt = config.get_child("bootstrap", empty_pt); // Static Bootstrap try { // read endpoint_set from config EndpointSetPtr ep_set = endpoint_set::create_EndpointSet( bootstrap_pt.get_child("direct")); EndpointDescriptor ep = EndpointDescriptor::UNSPECIFIED(); ep.replace_endpoint_set(ep_set); // try to connect base_overlay->joinSpoVNet( spovnetId, ep); } catch ( ptree_bad_path& e ) { // logging_info("No direct bootstrap info in config."); cout << "No direct bootstrap info in config." << endl; } /* Bootstrap modules */ vector > internalmodules; // Bootstrap: Broadcast if ( bootstrap_pt.get("broadcast", false) ) { internalmodules.push_back(make_pair( BootstrapManager::BootstrapTypePeriodicBroadcast,"")); } // Bootstrap: MDNS if ( bootstrap_pt.get("mdns", false) ) { internalmodules.push_back(make_pair( BootstrapManager::BootstrapTypeMulticastDns,"")); } // Bootstrap: SDP if ( bootstrap_pt.get("sdp", false) ) { internalmodules.push_back(make_pair( BootstrapManager::BootstrapTypeBluetoothSdp,"")); } // start automatic overlay bootstrapping modules base_overlay->startBootstrapModules(internalmodules); } //void Node::join(const Name& vnetname) { // spovnetId = vnetname.toSpoVNetId(); // nodeId = generateNodeId(name); // // // start base comm if not started // if( !ariba_mod.base_comm->isStarted() ) // ariba_mod.base_comm->start(); // // // start base overlay if not started // // join against ourselfs // if( !base_overlay->isStarted() ) // base_overlay->start( *ariba_mod.base_comm, nodeId ); // base_overlay->joinSpoVNet( spovnetId ); // // // join against static bootstrap points and // // start automatic bootstrapping modules // vector mechanisms // = ariba_mod.getBootstrapMechanisms(vnetname); // // vector > internalmodules; // // BOOST_FOREACH(AribaModule::BootstrapMechanism m, mechanisms){ // switch(m){ // case AribaModule::BootstrapMechanismStatic: // { // const communication::EndpointDescriptor* ep = // ariba_mod.getBootstrapNode(vnetname, m); // if( ep != NULL && ep->isUnspecified() == false ) // base_overlay->joinSpoVNet( spovnetId, *ep); // break; // } // case AribaModule::BootstrapMechanismBroadcast: // internalmodules.push_back(make_pair( // BootstrapManager::BootstrapTypePeriodicBroadcast, // ariba_mod.getBootstrapInfo(vnetname, m))); // break; // case AribaModule::BootstrapMechanismMulticastDNS: // internalmodules.push_back(make_pair( // BootstrapManager::BootstrapTypeMulticastDns, // ariba_mod.getBootstrapInfo(vnetname, m))); // break; // case AribaModule::BootstrapMechanismSDP: // internalmodules.push_back(make_pair( // BootstrapManager::BootstrapTypeBluetoothSdp, // ariba_mod.getBootstrapInfo(vnetname, m))); // break; // default: // break; // } // } // // // start automatic overlay bootstrapping modules // base_overlay->startBootstrapModules(internalmodules); // // // done //} // //void Node::initiate(const Name& vnetname, const SpoVNetProperties& parm) { // utility::OverlayParameterSet ovrpset; // ovrpset.setOverlayStructure( // (utility::OverlayParameterSet::_OverlayStructure) // parm.getBaseOverlayType() // ); // // spovnetId = vnetname.toSpoVNetId(); // nodeId = generateNodeId(name); // // // start base comm if not started // if( !ariba_mod.base_comm->isStarted() ) // ariba_mod.base_comm->start(); // // // start base overlay if not started // if( !base_overlay->isStarted() ) // base_overlay->start( *ariba_mod.base_comm, nodeId ); // // base_overlay->createSpoVNet( spovnetId, ovrpset ); //} void Node::leave() { base_overlay->stopBootstrapModules(); base_overlay->leaveSpoVNet(); base_communication->stop(); // XXX before »base_overlay->stop()« ?? base_overlay->stop(); } const SpoVNetProperties& Node::getSpoVNetProperties() const { return SpoVNetProperties::DEFAULT; } const SpoVNetID& Node::getSpoVNetId() const { return spovnetId; } const NodeID& Node::getNodeId(const LinkID& lid) const { if( lid == LinkID::UNSPECIFIED ) return nodeId; else return base_overlay->getNodeID( lid ); } NodeID Node::generateNodeId(const Name& name) const { if (name == Name::UNSPECIFIED) return Name::random().toNodeId(); else return name.toNodeId(); } vector Node::getNeighborNodes() const { return base_overlay->getOverlayNeighbors(); } LinkID Node::establishLink(const NodeID& nid, const ServiceID& sid) { return base_overlay->establishLink(nid, sid); } void Node::dropLink(const LinkID& lnk) { base_overlay->dropLink(lnk); } bool Node::isLinkDirect(const ariba::LinkID& lnk) const { return base_overlay->isLinkDirect(lnk); } int Node::getHopCount(const ariba::LinkID& lnk) const { return base_overlay->getHopCount(lnk); } /* +++++ Message sending +++++ */ void Node::check_send_priority(uint8_t priority) { if ( priority < send_priority::HIGHEST || priority > send_priority::LOWEST ) throw std::invalid_argument("Illegal priority"); } // +++ new interface +++ const SequenceNumber& Node::sendMessage(reboost::message_t msg, const LinkID& lnk, uint8_t priority) { // check priority check_send_priority(priority); // * call base overlay * return base_overlay->sendMessage(msg, lnk, priority); } // +++ legacy interface +++ seqnum_t Node::sendMessage(const DataMessage& msg, const LinkID& lnk) { reboost::message_t message = ((Message*) msg)->wrap_up_for_sending(); try { base_overlay->sendMessage(message, lnk, send_priority::NORMAL); return 0; } catch ( ariba::overlay::message_not_sent& e ) { logging_warn("Message could not be sent. Dropped."); return -1; } } // +++ new interface +++ const SequenceNumber& Node::sendMessage(reboost::message_t msg, const NodeID& nid, const ServiceID& sid, uint8_t priority, const LinkProperties& req) { // check priority check_send_priority(priority); // * call base overlay * return base_overlay->sendMessage(msg, nid, priority, sid); } // +++ legacy interface +++ seqnum_t Node::sendMessage(const DataMessage& msg, const NodeID& nid, const ServiceID& sid, const LinkProperties& req) { // reboost::message_t message = ((Message*) msg)->wrap_up_for_sending(); reboost::message_t message; message.push_back( ((Message*) msg)->serialize_into_shared_buffer() ); try { sendMessage(message, nid, sid, send_priority::NORMAL, req); return 0; } catch ( ariba::overlay::message_not_sent& e ) { logging_warn("Message could not be sent. Dropped."); return -1; } } // +++ new interface +++ NodeID Node::sendMessageCloserToNodeID(reboost::message_t msg, const NodeID& nid, const ServiceID& sid, uint8_t priority, const LinkProperties& req) { // check priority check_send_priority(priority); // * call base overlay * return base_overlay->sendMessageCloserToNodeID(msg, nid, priority, sid); } // +++ legacy interface +++ NodeID Node::sendMessageCloserToNodeID(const DataMessage& msg, const NodeID& nid, const ServiceID& sid, const LinkProperties& req) { reboost::message_t message = ((Message*) msg)->wrap_up_for_sending(); return sendMessageCloserToNodeID(message, nid, sid, send_priority::NORMAL, req); } // +++ new interface +++ void Node::sendBroadcastMessage(reboost::message_t msg, const ServiceID& sid, uint8_t priority) { // check priority check_send_priority(priority); // * call base overlay * return base_overlay->broadcastMessage(msg, sid, priority); } // +++ legacy interface +++ void Node::sendBroadcastMessage(const DataMessage& msg, const ServiceID& sid) { reboost::message_t message = ((Message*) msg)->wrap_up_for_sending(); return sendBroadcastMessage(message, sid); } /* +++++ [Message sending] +++++ */ bool Node::bind(NodeListener* listener) { return base_overlay->bind(listener); } bool Node::unbind(NodeListener* listener) { return base_overlay->unbind(listener); } bool Node::bind(CommunicationListener* listener, const ServiceID& sid) { // bind the listener bool ret = base_overlay->bind(listener, sid); // // now that we have a listener, we can ask if sniffing is ok // if( ariba_mod.sideport_sniffer != NULL ){ // base_overlay->registerSidePort(ariba_mod.sideport_sniffer); // } return ret; } bool Node::unbind(CommunicationListener* listener, const ServiceID& sid) { return base_overlay->unbind(listener, sid); } // @see Module.h string Node::getName() const { return name.toString(); } } // namespace ariba