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);
		}
Exemple #2
0
		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;
			}
		}
Exemple #3
0
		void TCPConnection::keepalive()
		{
			(*getProtocolStream()).keepalive();
		}
Exemple #4
0
		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&) {};
			}
		}
Exemple #5
0
		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&) { };
		}