bool TransportPublisherLink::initialize(const ConnectionPtr& connection) { connection_ = connection; connection_->addDropListener(boost::bind(&TransportPublisherLink::onConnectionDropped, this, _1, _2)); if (connection_->getTransport()->requiresHeader()) { connection_->setHeaderReceivedCallback(boost::bind(&TransportPublisherLink::onHeaderReceived, this, _1, _2)); SubscriptionPtr parent = parent_.lock(); M_string header; header["topic"] = parent->getName(); header["md5sum"] = parent->md5sum(); header["callerid"] = this_node::getName(); header["type"] = parent->datatype(); header["tcp_nodelay"] = transport_hints_.getTCPNoDelay() ? "1" : "0"; connection_->writeHeader(header, boost::bind(&TransportPublisherLink::onHeaderWritten, this, _1)); } else { connection_->read(4, boost::bind(&TransportPublisherLink::onMessageLength, this, _1, _2, _3, _4)); } return true; }
void TransportPublisherLink::onRetryTimer(const ros::WallTimerEvent&) { if (dropping_) { return; } if (needs_retry_ && WallTime::now() > next_retry_) { retry_period_ = std::min(retry_period_ * 2, WallDuration(20)); needs_retry_ = false; SubscriptionPtr parent = parent_.lock(); // TODO: support retry on more than just TCP // For now, since UDP does not have a heartbeat, we do not attempt to retry // UDP connections since an error there likely means some invalid operation has // happened. if (connection_->getTransport()->getType() == std::string("TCPROS")) { std::string topic = parent ? parent->getName() : "unknown"; TransportTCPPtr old_transport = boost::dynamic_pointer_cast<TransportTCP>(connection_->getTransport()); ROS_ASSERT(old_transport); const std::string& host = old_transport->getConnectedHost(); int port = old_transport->getConnectedPort(); ROSCPP_LOG_DEBUG("Retrying connection to [%s:%d] for topic [%s]", host.c_str(), port, topic.c_str()); TransportTCPPtr transport(new TransportTCP(&PollManager::instance()->getPollSet())); if (transport->connect(host, port)) { ConnectionPtr connection(new Connection); connection->initialize(transport, false, HeaderReceivedFunc()); initialize(connection); ConnectionManager::instance()->addConnection(connection); } else { ROSCPP_LOG_DEBUG("connect() failed when retrying connection to [%s:%d] for topic [%s]", host.c_str(), port, topic.c_str()); } } else if (parent) { parent->removePublisherLink(shared_from_this()); } } }
void IntraProcessPublisherLink::setPublisher(const IntraProcessSubscriberLinkPtr& publisher) { publisher_ = publisher; SubscriptionPtr parent = parent_.lock(); ROS_ASSERT(parent); Header header; M_stringPtr values = header.getValues(); (*values)["callerid"] = this_node::getName(); (*values)["topic"] = parent->getName(); (*values)["type"] = publisher->getDataType(); (*values)["md5sum"] = publisher->getMD5Sum(); (*values)["message_definition"] = publisher->getMessageDefinition(); (*values)["latching"] = publisher->isLatching() ? "1" : "0"; setHeader(header); }
void TransportPublisherLink::onConnectionDropped(const ConnectionPtr& conn, Connection::DropReason reason) { if (dropping_) { return; } ROS_ASSERT(conn == connection_); SubscriptionPtr parent = parent_.lock(); if (reason == Connection::TransportDisconnect) { std::string topic = parent ? parent->getName() : "unknown"; ROSCPP_LOG_DEBUG("Connection to publisher [%s] to topic [%s] dropped", connection_->getTransport()->getTransportInfo().c_str(), topic.c_str()); ROS_ASSERT(!needs_retry_); needs_retry_ = true; next_retry_ = WallTime::now() + retry_period_; if (retry_timer_handle_ == -1) { retry_period_ = WallDuration(0.1); next_retry_ = WallTime::now() + retry_period_; retry_timer_handle_ = getInternalTimerManager()->add(WallDuration(retry_period_), boost::bind(&TransportPublisherLink::onRetryTimer, this, _1), getInternalCallbackQueue().get(), VoidConstPtr(), false); } else { getInternalTimerManager()->setPeriod(retry_timer_handle_, retry_period_); } } else { drop(); } }