/* * Copyright (c) 2013 Mario Hock mails2013@omnifile.org * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */ #include "Tunnel.h" #include #include #include using namespace std; using ariba::utility::SystemQueue; const ariba::ServiceID Tunnel::TUNNEL_SERVICE_ID(99); Tunnel::Tunnel() : udp_sender(NULL) { } Tunnel::~Tunnel() { } void Tunnel::init_ariba(ptree config) { string my_name; string remote_name; logging_info( "[TUNNEL]\t starting up Tunnel service ... " ); // use node name also in the application my_name = config.get("ariba.node_name", "NO_NAME"); // bind communication and node listener node.bind( this ); /*NodeListener*/ node.bind( this, TUNNEL_SERVICE_ID); /*CommunicationListener*/ // connecting logging_debug( "connecting ... " ); node.connect(config.get_child("ariba")); logging_info( "[TUNNEL]\t ariba-tunnel starting up with" << " [spovnetid " << node.getSpoVNetId().toString() << "]" << " and [nodeid " << node.getNodeId().toString() << "]" ); // get the other tunnel endpoint from config try { remote_name = config.get("tunnel.connect_to_node"); tunnel_endpoint = ariba::Name(remote_name).toNodeId(); logging_info( "[TUNNEL]\t I am »" << my_name << "« and I'll try to connect to: »" << remote_name << "«"); } catch ( boost::property_tree::ptree_bad_path& e ) { logging_warn( "[TUNNEL]\t I am »" << my_name << "« but I don't know the other tunnel endpoint!"); } } /* communication listener interface */ void Tunnel::onMessage(reboost::shared_buffer_t message, const NodeID& remote, const LinkID& lnk, const SequenceNumber& seqnum, const ariba::overlay::OverlayMsg* overlay_msg) { logging_info( "[ARIBA] received " << message.size() << " bytes from node: " << remote.toString() ); /// forward ariba message over UDP if ( udp_sender != NULL ) { udp_sender->SendMessage(message); } else { logging_warn("/// NO UDP SENDER REGISTERED"); } } void Tunnel::onLinkUp(const LinkID& lnk, const NodeID& remote) { logging_info("[TUNNEL]\t LINK UP"); // TODO Maybe we should decide for one link instead of maintaining several.. // only accept links to the other tunnel endpoint if ( remote == tunnel_endpoint ) { links.push_back(lnk); } else { node.dropLink(lnk); } } void Tunnel::onLinkDown(const LinkID& lnk, const NodeID& remote) { std::vector::iterator it = find(links.begin(), links.end(), lnk); if ( it != links.end() ) links.erase(it); } /* node listener interface */ void Tunnel::onOverlayConnected(const SpoVNetID& vid) { logging_info( "/// OverlayConnected" ); // establish link to the other tunnel endpoint node.establishLink(tunnel_endpoint, TUNNEL_SERVICE_ID); } void Tunnel::onOverlayDisconnected(const SpoVNetID& vid) { logging_info( "/// OverlayDisconnected" ); } /// * to be called from an EXTERNAL THREAD * void Tunnel::SendMessage(reboost::message_t msg) { /// synchronize with the Ariba Thread SystemQueue::instance().scheduleCall( boost::bind( &Tunnel::send_message, this, msg) ); } void Tunnel::SendMessage(reboost::shared_buffer_t msg) { reboost::message_t message; message.push_back(msg); this->SendMessage(message); } /// * to be called within the ARIBA THREAD * void Tunnel::send_message(reboost::message_t msg) { if ( ! links.empty() ) { logging_info( "[ARIBA] sending " << msg.size() << " bytes over link: " << links[0].toString() ); node.sendMessage(msg, links[0]); } else { logging_warn( "[ARIBA] would like to send " << msg.size() << " bytes. But there is no active link!" ); } } void Tunnel::register_udp_sender(MessageSenderInterface* udp_sender) { this->udp_sender = udp_sender; } // /// XXX this is only for debug output // void Tunnel::print_message(const string& prefix, reboost::message_t msg) // { // // XXX testing (debug output) // reboost::shared_buffer_t buf = msg.linearize(); // print_message(prefix, buf); // } // void Tunnel::print_message(const string& prefix, reboost::shared_buffer_t buf) // { // string s((const char*) buf.data(), buf.size() - 1); // std::cout << prefix << "»" << s << "«" << std::endl; // }