void TCPConnection::eventConnectionUp(const dtn::streams::StreamContactHeader &header) throw () { _peer = header; // copy old attributes and urls to the new node object Node n_old = _node; _node = Node(header._localeid); _node += n_old; // check if the peer has the same EID if (_node.getEID() == dtn::core::BundleCore::getInstance().local) { // abort the connection shutdown(); IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, warning) << "connection to local endpoint rejected" << IBRCOMMON_LOGGER_ENDL; return; } _keepalive_timeout = header._keepalive * 1000; try { // initiate extended handshake (e.g. TLS) initiateExtendedHandshake(); } catch (const ibrcommon::Exception &ex) { IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, warning) << ex.what() << IBRCOMMON_LOGGER_ENDL; // abort the connection shutdown(); return; } // set the timer timeval timeout; timerclear(&timeout); // set the incoming timer if set (> 0) if (_peer._keepalive > 0) { timeout.tv_sec = header._keepalive * 2; } // change time-out _socket_stream->setTimeout(timeout); try { // enable idle timeout size_t _idle_timeout = dtn::daemon::Configuration::getInstance().getNetwork().getTCPIdleTimeout(); if (_idle_timeout > 0) { (*getProtocolStream()).enableIdleTimeout(_idle_timeout); } } catch (const ibrcommon::Exception&) {}; // raise up event ConnectionEvent::raise(ConnectionEvent::CONNECTION_UP, _node); }
void TCPConnection::shutdown() throw () { try { // shutdown (*getProtocolStream()).shutdown(dtn::streams::StreamConnection::CONNECTION_SHUTDOWN_ERROR); } catch (const ibrcommon::Exception&) {}; try { // abort the connection thread ibrcommon::DetachedThread::stop(); } catch (const ibrcommon::ThreadException &ex) { IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, error) << "shutdown failed (" << ex.what() << ")" << IBRCOMMON_LOGGER_ENDL; } }
void TCPConnection::keepalive() { (*getProtocolStream()).keepalive(); }
void TCPConnection::run() throw () { try { if (_socket == NULL) { // connect to the peer connect(); } else { // accept remote connection as server __setup_socket(_socket, true); } TCPConnection::safe_streamconnection sc = getProtocolStream(); std::iostream &stream = (*sc); // do the handshake (*sc).handshake(dtn::core::BundleCore::local, _timeout, _flags); // start the sender _sender.start(); // start keepalive sender _keepalive_sender.start(); // create a deserializer for next bundle dtn::data::DefaultDeserializer deserializer(stream, dtn::core::BundleCore::getInstance()); while (!(*sc).eof()) { try { // create a new empty bundle dtn::data::Bundle bundle; // check if the stream is still good if (!stream.good()) throw ibrcommon::IOException("stream went bad"); // enable/disable fragmentation support according to the contact header. deserializer.setFragmentationSupport(_peer._flags.getBit(dtn::streams::StreamContactHeader::REQUEST_FRAGMENTATION)); // read the bundle (or the fragment if fragmentation is enabled) deserializer >> bundle; // check the bundle if ( ( bundle.destination == EID() ) || ( bundle.source == EID() ) ) { // invalid bundle! throw dtn::data::Validator::RejectedException("destination or source EID is null"); } // raise default bundle received event dtn::net::BundleReceivedEvent::raise(_peer._localeid, bundle, false); } catch (const dtn::data::Validator::RejectedException &ex) { // bundle rejected rejectTransmission(); // display the rejection IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, warning) << "bundle has been rejected: " << ex.what() << IBRCOMMON_LOGGER_ENDL; } catch (const dtn::InvalidDataException &ex) { // bundle rejected rejectTransmission(); // display the rejection IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, warning) << "invalid bundle-data received: " << ex.what() << IBRCOMMON_LOGGER_ENDL; } yield(); } } catch (const ibrcommon::ThreadException &ex) { IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, error) << "failed to start thread in TCPConnection\n" << ex.what() << IBRCOMMON_LOGGER_ENDL; try { (*getProtocolStream()).shutdown(dtn::streams::StreamConnection::CONNECTION_SHUTDOWN_ERROR); } catch (const ibrcommon::Exception&) {}; } catch (const std::exception &ex) { IBRCOMMON_LOGGER_DEBUG_TAG(TCPConnection::TAG, 10) << "run(): std::exception (" << ex.what() << ")" << IBRCOMMON_LOGGER_ENDL; try { (*getProtocolStream()).shutdown(dtn::streams::StreamConnection::CONNECTION_SHUTDOWN_ERROR); } catch (const ibrcommon::Exception&) {}; } }
void TCPConnection::connect() { // do not connect to other hosts if we are in server if (_socket != NULL) return; // do not connect to anyone if we are already connected if (_socket_stream != NULL) return; // variables for address and port std::string address = "0.0.0.0"; unsigned int port = 0; // try to connect to the other side try { const std::list<dtn::core::Node::URI> uri_list = _node.get(dtn::core::Node::CONN_TCPIP); for (std::list<dtn::core::Node::URI>::const_iterator iter = uri_list.begin(); iter != uri_list.end(); ++iter) { // break-out if the connection has been aborted if (_aborted) throw ibrcommon::socket_exception("connection has been aborted"); try { // decode address and port const dtn::core::Node::URI &uri = (*iter); uri.decode(address, port); // create a virtual address to connect to ibrcommon::vaddress addr(address, port); IBRCOMMON_LOGGER_DEBUG_TAG(TCPConnection::TAG, 15) << "Initiate TCP connection to " << address << ":" << port << IBRCOMMON_LOGGER_ENDL; // create a new tcpsocket timeval tv; timerclear(&tv); tv.tv_sec = _timeout; // create a new tcp connection via the tcpsocket object ibrcommon::tcpsocket *client = new ibrcommon::tcpsocket(addr, &tv); try { // connect to the node client->up(); // setup a new tcp connection __setup_socket(client, false); // add TCP connection descriptor to the node object _node.clear(); _node.add( dtn::core::Node::URI(Node::NODE_CONNECTED, Node::CONN_TCPIP, uri.value, 0, 30) ); // connection successful return; } catch (const ibrcommon::socket_exception&) { delete client; } } catch (const ibrcommon::socket_exception&) { }; } // no connection has been established throw ibrcommon::socket_exception("no address available to connect"); } catch (const ibrcommon::socket_exception&) { // error on open, requeue all bundles in the queue IBRCOMMON_LOGGER_TAG(TCPConnection::TAG, warning) << "connection to " << _node.toString() << " failed" << IBRCOMMON_LOGGER_ENDL; try { (*getProtocolStream()).shutdown(dtn::streams::StreamConnection::CONNECTION_SHUTDOWN_ERROR); } catch (const ibrcommon::Exception&) {}; throw; } catch (const bad_cast&) { }; }