void UdpFace::closeIfIdle() { // Face can be switched from on-demand to non-on-demand mode // (non-on-demand -> on-demand transition is not allowed) if (this->getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) { if (!hasBeenUsedRecently()) { NFD_LOG_FACE_INFO("Closing for inactivity"); close(); // #1718 manual test: uncomment, run NFD in valgrind, send in a UDP packet // expect read-after-free error and crash // getGlobalIoService().post([this] { // NFD_LOG_FACE_ERROR("Remaining references: " << this->shared_from_this().use_count()); // }); } else { resetRecentUsage(); m_lastIdleCheck = time::steady_clock::now(); m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, bind(&UdpFace::closeIfIdle, this)); } } // else do nothing and do not reschedule the event }
WebSocketTransport::WebSocketTransport(websocketpp::connection_hdl hdl, websocket::Server& server, time::milliseconds pingInterval) : m_handle(hdl) , m_server(server) , m_pingInterval(pingInterval) { const auto& sock = m_server.get_con_from_hdl(hdl)->get_socket(); this->setLocalUri(FaceUri(sock.local_endpoint(), "ws")); this->setRemoteUri(FaceUri(sock.remote_endpoint(), "wsclient")); if (isLoopback(sock.local_endpoint().address()) && isLoopback(sock.remote_endpoint().address())) { this->setScope(ndn::nfd::FACE_SCOPE_LOCAL); } else { this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL); } this->setPersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND); this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT); this->setMtu(MTU_UNLIMITED); this->schedulePing(); NFD_LOG_FACE_INFO("Creating transport"); }
void UnicastUdpTransport::scheduleClosureWhenIdle() { m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, [this] { if (!hasBeenUsedRecently()) { NFD_LOG_FACE_INFO("Closing due to inactivity"); this->close(); } else { resetRecentUsage(); scheduleClosureWhenIdle(); } }); setExpirationTime(time::steady_clock::now() + m_idleTimeout); }
void Transport::setPersistency(ndn::nfd::FacePersistency newPersistency) { BOOST_ASSERT(canChangePersistencyTo(newPersistency)); if (m_persistency == newPersistency) { return; } auto oldPersistency = m_persistency; m_persistency = newPersistency; if (oldPersistency != ndn::nfd::FACE_PERSISTENCY_NONE) { NFD_LOG_FACE_INFO("setPersistency " << oldPersistency << " -> " << newPersistency); this->afterChangePersistency(oldPersistency); } }
TcpTransport::TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency) : StreamTransport(std::move(socket)) , m_remoteEndpoint(m_socket.remote_endpoint()) , m_nextReconnectWait(s_initialReconnectWait) { this->setLocalUri(FaceUri(m_socket.local_endpoint())); this->setRemoteUri(FaceUri(m_socket.remote_endpoint())); if (m_socket.local_endpoint().address().is_loopback() && m_socket.remote_endpoint().address().is_loopback()) this->setScope(ndn::nfd::FACE_SCOPE_LOCAL); else this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL); this->setPersistency(persistency); this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT); this->setMtu(MTU_UNLIMITED); NFD_LOG_FACE_INFO("Creating transport"); }
UnicastUdpTransport::UnicastUdpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency, time::nanoseconds idleTimeout) : DatagramTransport(std::move(socket)) , m_idleTimeout(idleTimeout) { this->setLocalUri(FaceUri(m_socket.local_endpoint())); this->setRemoteUri(FaceUri(m_socket.remote_endpoint())); this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL); this->setPersistency(persistency); this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT); this->setMtu(udp::computeMtu(m_socket.local_endpoint())); NFD_LOG_FACE_INFO("Creating transport"); #ifdef __linux__ // // By default, Linux does path MTU discovery on IPv4 sockets, // and sets the DF (Don't Fragment) flag on datagrams smaller // than the interface MTU. However this does not work for us, // because we cannot properly respond to ICMP "packet too big" // messages by fragmenting the packet at the application level, // since we want to rely on IP for fragmentation and reassembly. // // Therefore, we disable PMTU discovery, which prevents the kernel // from setting the DF flag on outgoing datagrams, and thus allows // routers along the path to perform fragmentation as needed. // const int value = IP_PMTUDISC_DONT; if (::setsockopt(m_socket.native_handle(), IPPROTO_IP, IP_MTU_DISCOVER, &value, sizeof(value)) < 0) { NFD_LOG_FACE_WARN("Failed to disable path MTU discovery: " << std::strerror(errno)); } #endif if (getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND && m_idleTimeout > time::nanoseconds::zero()) { scheduleClosureWhenIdle(); } }
void Transport::setState(TransportState newState) { if (m_state == newState) { return; } bool isValid = false; switch (m_state) { case TransportState::UP: isValid = newState == TransportState::DOWN || newState == TransportState::CLOSING || newState == TransportState::FAILED; break; case TransportState::DOWN: isValid = newState == TransportState::UP || newState == TransportState::CLOSING || newState == TransportState::FAILED; break; case TransportState::CLOSING: case TransportState::FAILED: isValid = newState == TransportState::CLOSED; break; default: break; } if (!isValid) { NDN_THROW(std::runtime_error("Invalid state transition")); } NFD_LOG_FACE_INFO("setState " << m_state << " -> " << newState); TransportState oldState = m_state; m_state = newState; afterStateChange(oldState, newState); // warning: don't access any members after this: // the Transport may be deallocated in the signal handler if newState is CLOSED }