diff --git a/HTTPServer.cpp b/HTTPServer.cpp index f10289ef..fdc5b38f 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -174,7 +174,7 @@ namespace http { s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); s << "
\r\n"; - s << "Status: "; + s << "Network status: "; switch (i2p::context.GetStatus ()) { case eRouterStatusOK: s << "OK"; break; @@ -183,6 +183,13 @@ namespace http { default: s << "Unknown"; } s << "
\r\n"; +#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) + if (auto remains = Daemon.gracefullShutdownInterval) { + s << "Stopping in: "; + s << remains << " seconds"; + s << "
\r\n"; + } +#endif auto family = i2p::context.GetFamily (); if (family.length () > 0) s << "Family: " << family << "
\r\n"; @@ -415,15 +422,9 @@ namespace http { s << " Accept transit tunnels
\r\n"; #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) if (Daemon.gracefullShutdownInterval) - { - s << " Cancel gracefull shutdown ("; - s << Daemon.gracefullShutdownInterval; - s << " seconds remains)
\r\n"; - } + s << " Cancel gracefull shutdown
"; else - { s << " Start gracefull shutdown
\r\n"; - } #endif #ifdef WIN32_APP s << " Gracefull shutdown
\r\n"; diff --git a/Makefile.linux b/Makefile.linux index 1376260a..b0549f43 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -28,15 +28,13 @@ endif NEEDED_CXXFLAGS += -fPIC ifeq ($(USE_STATIC),yes) +# NOTE: on glibc you will get this warning: +# Using 'getaddrinfo' in statically linked applications requires at runtime +# the shared libraries from the glibc version used for linking LIBDIR := /usr/lib - LDLIBS = $(LIBDIR)/libboost_system.a - LDLIBS += $(LIBDIR)/libboost_date_time.a - LDLIBS += $(LIBDIR)/libboost_filesystem.a - LDLIBS += $(LIBDIR)/libboost_program_options.a - LDLIBS += $(LIBDIR)/libssl.a - LDLIBS += $(LIBDIR)/libcrypto.a - LDLIBS += $(LIBDIR)/libz.a - LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt + LDLIBS = -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options + LDLIBS += -lssl -lcrypto -lz -ldl -lpthread -lrt + LDLIBS += -static-libstdc++ -static-libgcc -static USE_AESNI := no else LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 2f99a772..1f177aa3 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -21,7 +21,7 @@ namespace transport NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr in_RemoteRouter): TransportSession (in_RemoteRouter, NTCP_TERMINATION_TIMEOUT), m_Server (server), m_Socket (m_Server.GetService ()), - m_TerminationTimer (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false), + m_IsEstablished (false), m_IsTerminated (false), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false) { m_Establisher = new Establisher; @@ -78,7 +78,6 @@ namespace transport m_Server.RemoveNTCPSession (shared_from_this ()); m_SendQueue.clear (); m_NextMessage = nullptr; - m_TerminationTimer.cancel (); LogPrint (eLogDebug, "NTCP: session terminated"); } } @@ -110,7 +109,6 @@ namespace transport boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (), std::bind(&NTCPSession::HandlePhase1Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - ScheduleTermination (); } void NTCPSession::ServerLogin () @@ -124,7 +122,6 @@ namespace transport boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (), std::bind(&NTCPSession::HandlePhase1Received, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - ScheduleTermination (); } } @@ -558,7 +555,7 @@ namespace transport m_Handler.Flush (); } - ScheduleTermination (); // reset termination timer + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); Receive (); } } @@ -685,6 +682,7 @@ namespace transport } else { + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_NumSentBytes += bytes_transferred; i2p::transport::transports.UpdateSentBytes (bytes_transferred); if (!m_SendQueue.empty()) @@ -692,8 +690,6 @@ namespace transport Send (m_SendQueue); m_SendQueue.clear (); } - else - ScheduleTermination (); // reset termination timer } } @@ -728,29 +724,11 @@ namespace transport else Send (msgs); } - - void NTCPSession::ScheduleTermination () - { - m_TerminationTimer.cancel (); - m_TerminationTimer.expires_from_now (boost::posix_time::seconds(GetTerminationTimeout ())); - m_TerminationTimer.async_wait (std::bind (&NTCPSession::HandleTerminationTimer, - shared_from_this (), std::placeholders::_1)); - } - - void NTCPSession::HandleTerminationTimer (const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint (eLogDebug, "NTCP: No activity for ", GetTerminationTimeout (), " seconds"); - //Terminate (); - m_Socket.close ();// invoke Terminate () from HandleReceive - } - } //----------------------------------------- NTCPServer::NTCPServer (): m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), - m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr) + m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr) { } @@ -810,7 +788,8 @@ namespace transport } } } - } + } + ScheduleTermination (); } } @@ -821,13 +800,17 @@ namespace transport if (m_IsRunning) { m_IsRunning = false; - if (m_NTCPAcceptor) - delete m_NTCPAcceptor; - m_NTCPAcceptor = nullptr; - if (m_NTCPV6Acceptor) - delete m_NTCPV6Acceptor; - m_NTCPV6Acceptor = nullptr; - + m_TerminationTimer.cancel (); + if (m_NTCPAcceptor) + { + delete m_NTCPAcceptor; + m_NTCPAcceptor = nullptr; + } + if (m_NTCPV6Acceptor) + { + delete m_NTCPV6Acceptor; + m_NTCPV6Acceptor = nullptr; + } m_Service.stop (); if (m_Thread) { @@ -991,5 +974,31 @@ namespace transport m_BanList[addr] = ts + NTCP_BAN_EXPIRATION_TIMEOUT; LogPrint (eLogWarning, "NTCP: ", addr, " has been banned for ", NTCP_BAN_EXPIRATION_TIMEOUT, " seconds"); } + + void NTCPServer::ScheduleTermination () + { + m_TerminationTimer.expires_from_now (boost::posix_time::seconds(NTCP_TERMINATION_CHECK_TIMEOUT)); + m_TerminationTimer.async_wait (std::bind (&NTCPServer::HandleTerminationTimer, + this, std::placeholders::_1)); + } + + void NTCPServer::HandleTerminationTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto& it: m_NTCPSessions) + if (it.second->IsTerminationTimeoutExpired (ts)) + { + auto session = it.second; + m_Service.post ([session] + { + LogPrint (eLogDebug, "NTCP: No activity for ", session->GetTerminationTimeout (), " seconds"); + session->Terminate (); + }); + } + ScheduleTermination (); + } + } } } diff --git a/NTCPSession.h b/NTCPSession.h index 59b6bb58..a3d95c62 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -37,6 +37,7 @@ namespace transport const size_t NTCP_MAX_MESSAGE_SIZE = 16384; const size_t NTCP_BUFFER_SIZE = 4160; // fits 4 tunnel messages (4*1028) const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes + const int NTCP_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds const size_t NTCP_DEFAULT_PHASE3_SIZE = 2/*size*/ + i2p::data::DEFAULT_IDENTITY_SIZE/*387*/ + 4/*ts*/ + 15/*padding*/ + 40/*signature*/; // 448 const int NTCP_BAN_EXPIRATION_TIMEOUT = 70; // in second const int NTCP_CLOCK_SKEW = 60; // in seconds @@ -53,8 +54,8 @@ namespace transport void Done (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; - bool IsEstablished () const { return m_IsEstablished; }; - + bool IsEstablished () const { return m_IsEstablished; }; + void ClientLogin (); void ServerLogin (); void SendI2NPMessages (const std::vector >& msgs); @@ -95,16 +96,10 @@ namespace transport void Send (const std::vector >& msgs); void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector > msgs); - - // timer - void ScheduleTermination (); - void HandleTerminationTimer (const boost::system::error_code& ecode); - private: NTCPServer& m_Server; boost::asio::ip::tcp::socket m_Socket; - boost::asio::deadline_timer m_TerminationTimer; bool m_IsEstablished, m_IsTerminated; i2p::crypto::CBCDecryption m_Decryption; @@ -146,8 +141,8 @@ namespace transport std::shared_ptr FindNTCPSession (const i2p::data::IdentHash& ident); void Connect (const boost::asio::ip::address& address, int port, std::shared_ptr conn); - bool IsBoundV4() const { return m_NTCPAcceptor != nullptr; }; - bool IsBoundV6() const { return m_NTCPV6Acceptor != nullptr; }; + bool IsBoundV4() const { return m_NTCPAcceptor != nullptr; }; + bool IsBoundV6() const { return m_NTCPV6Acceptor != nullptr; }; boost::asio::io_service& GetService () { return m_Service; }; void Ban (const boost::asio::ip::address& addr); @@ -159,6 +154,10 @@ namespace transport void HandleAcceptV6 (std::shared_ptr conn, const boost::system::error_code& error); void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr conn); + + // timer + void ScheduleTermination (); + void HandleTerminationTimer (const boost::system::error_code& ecode); private: @@ -166,6 +165,7 @@ namespace transport std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::io_service::work m_Work; + boost::asio::deadline_timer m_TerminationTimer; boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor; std::map > m_NTCPSessions; // access from m_Thread only std::map m_BanList; // IP -> ban expiration time in seconds diff --git a/SSU.cpp b/SSU.cpp index 0c3662d3..3d3fefdd 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -17,7 +17,8 @@ namespace transport m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversService), - m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service) + m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) { m_SocketV6.open (boost::asio::ip::udp::v6()); m_SocketV6.set_option (boost::asio::ip::v6_only (true)); @@ -32,7 +33,8 @@ namespace transport m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversService), - m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service) + m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) { m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (65535)); @@ -59,11 +61,13 @@ namespace transport { m_Thread = new std::thread (std::bind (&SSUServer::Run, this)); m_ReceiversService.post (std::bind (&SSUServer::Receive, this)); + ScheduleTermination (); } if (context.SupportsV6 ()) { m_ThreadV6 = new std::thread (std::bind (&SSUServer::RunV6, this)); m_ReceiversService.post (std::bind (&SSUServer::ReceiveV6, this)); + ScheduleTerminationV6 (); } SchedulePeerTestsCleanupTimer (); ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers @@ -640,6 +644,58 @@ namespace transport SchedulePeerTestsCleanupTimer (); } } + + void SSUServer::ScheduleTermination () + { + m_TerminationTimer.expires_from_now (boost::posix_time::seconds(SSU_TERMINATION_CHECK_TIMEOUT)); + m_TerminationTimer.async_wait (std::bind (&SSUServer::HandleTerminationTimer, + this, std::placeholders::_1)); + } + + void SSUServer::HandleTerminationTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto& it: m_Sessions) + if (it.second->IsTerminationTimeoutExpired (ts)) + { + auto session = it.second; + m_Service.post ([session] + { + LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); + session->Failed (); + }); + } + ScheduleTermination (); + } + } + + void SSUServer::ScheduleTerminationV6 () + { + m_TerminationTimerV6.expires_from_now (boost::posix_time::seconds(SSU_TERMINATION_CHECK_TIMEOUT)); + m_TerminationTimerV6.async_wait (std::bind (&SSUServer::HandleTerminationTimerV6, + this, std::placeholders::_1)); + } + + void SSUServer::HandleTerminationTimerV6 (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto& it: m_SessionsV6) + if (it.second->IsTerminationTimeoutExpired (ts)) + { + auto session = it.second; + m_ServiceV6.post ([session] + { + LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); + session->Failed (); + }); + } + ScheduleTerminationV6 (); + } + } } } diff --git a/SSU.h b/SSU.h index d779c025..182fa0eb 100644 --- a/SSU.h +++ b/SSU.h @@ -23,6 +23,7 @@ namespace transport const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds const int SSU_PEER_TEST_TIMEOUT = 60; // 60 seconds const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour + const int SSU_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds const size_t SSU_MAX_NUM_INTRODUCERS = 3; struct SSUPacket @@ -90,6 +91,12 @@ namespace transport void SchedulePeerTestsCleanupTimer (); void HandlePeerTestsCleanupTimer (const boost::system::error_code& ecode); + // timer + void ScheduleTermination (); + void HandleTerminationTimer (const boost::system::error_code& ecode); + void ScheduleTerminationV6 (); + void HandleTerminationTimerV6 (const boost::system::error_code& ecode); + private: struct PeerTest @@ -106,7 +113,8 @@ namespace transport boost::asio::io_service::work m_Work, m_WorkV6, m_ReceiversWork; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6; boost::asio::ip::udp::socket m_Socket, m_SocketV6; - boost::asio::deadline_timer m_IntroducersUpdateTimer, m_PeerTestsCleanupTimer; + boost::asio::deadline_timer m_IntroducersUpdateTimer, m_PeerTestsCleanupTimer, + m_TerminationTimer, m_TerminationTimerV6; std::list m_Introducers; // introducers we are connected to std::map > m_Sessions, m_SessionsV6; std::map m_Relays; // we are introducer diff --git a/SSUSession.cpp b/SSUSession.cpp index bf4058a5..9245f652 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -14,7 +14,7 @@ namespace transport SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, std::shared_ptr router, bool peerTest ): TransportSession (router, SSU_TERMINATION_TIMEOUT), - m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_Timer (GetService ()), + m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_ConnectTimer (GetService ()), m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0),m_Data (*this), m_IsDataReceived (false) { @@ -97,7 +97,7 @@ namespace transport { if (!len) return; // ignore zero-length packets if (m_State == eSessionStateEstablished) - ScheduleTermination (); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first DecryptSessionKey (buf, len); @@ -229,7 +229,7 @@ namespace transport } LogPrint (eLogDebug, "SSU message: session created"); - m_Timer.cancel (); // connect timer + m_ConnectTimer.cancel (); // connect timer SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) @@ -804,9 +804,9 @@ namespace transport void SSUSession::ScheduleConnectTimer () { - m_Timer.cancel (); - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); - m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer, + m_ConnectTimer.cancel (); + m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); + m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, shared_from_this (), std::placeholders::_1)); } @@ -826,8 +826,8 @@ namespace transport if (m_State == eSessionStateUnknown) { // set connect timer - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); - m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer, + m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); + m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, shared_from_this (), std::placeholders::_1)); } uint32_t nonce; @@ -840,8 +840,8 @@ namespace transport { m_State = eSessionStateIntroduced; // set connect timer - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); - m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer, + m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); + m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, shared_from_this (), std::placeholders::_1)); } @@ -851,7 +851,7 @@ namespace transport SendSesionDestroyed (); transports.PeerDisconnected (shared_from_this ()); m_Data.Stop (); - m_Timer.cancel (); + m_ConnectTimer.cancel (); } void SSUSession::Done () @@ -868,7 +868,7 @@ namespace transport transports.PeerConnected (shared_from_this ()); if (m_IsPeerTest) SendPeerTest (); - ScheduleTermination (); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); } void SSUSession::Failed () @@ -880,24 +880,6 @@ namespace transport } } - void SSUSession::ScheduleTermination () - { - m_Timer.cancel (); - m_Timer.expires_from_now (boost::posix_time::seconds(GetTerminationTimeout ())); - m_Timer.async_wait (std::bind (&SSUSession::HandleTerminationTimer, - shared_from_this (), std::placeholders::_1)); - } - - void SSUSession::HandleTerminationTimer (const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint (eLogWarning, "SSU: no activity with ", m_RemoteEndpoint, " for ", GetTerminationTimeout (), " seconds"); - Failed (); - } - } - - void SSUSession::SendI2NPMessages (const std::vector >& msgs) { GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs)); @@ -1126,7 +1108,7 @@ namespace transport FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); Send (buf, 48); LogPrint (eLogDebug, "SSU: keep-alive sent"); - ScheduleTermination (); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); } } diff --git a/SSUSession.h b/SSUSession.h index c2f24ce3..69669187 100644 --- a/SSUSession.h +++ b/SSUSession.h @@ -77,6 +77,7 @@ namespace transport void WaitForIntroduction (); void Close (); void Done (); + void Failed (); boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); }; void SendI2NPMessages (const std::vector >& msgs); @@ -114,7 +115,6 @@ namespace transport void ProcessRelayResponse (const uint8_t * buf, size_t len); void ProcessRelayIntro (const uint8_t * buf, size_t len); void Established (); - void Failed (); void ScheduleConnectTimer (); void HandleConnectTimer (const boost::system::error_code& ecode); void ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); @@ -131,15 +131,12 @@ namespace transport void DecryptSessionKey (uint8_t * buf, size_t len); bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); - void ScheduleTermination (); - void HandleTerminationTimer (const boost::system::error_code& ecode); - private: friend class SSUData; // TODO: change in later SSUServer& m_Server; boost::asio::ip::udp::endpoint m_RemoteEndpoint; - boost::asio::deadline_timer m_Timer; + boost::asio::deadline_timer m_ConnectTimer; bool m_IsPeerTest; SessionState m_State; bool m_IsSessionKey; diff --git a/TransportSession.h b/TransportSession.h index 1b057bc7..9c97d02e 100644 --- a/TransportSession.h +++ b/TransportSession.h @@ -9,6 +9,7 @@ #include "Crypto.h" #include "RouterInfo.h" #include "I2NPProtocol.h" +#include "Timestamp.h" namespace i2p { @@ -54,7 +55,8 @@ namespace transport public: TransportSession (std::shared_ptr router, int terminationTimeout): - m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout) + m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), + m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) { if (router) m_RemoteIdentity = router->GetRouterIdentity (); @@ -72,6 +74,8 @@ namespace transport int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; + bool IsTerminationTimeoutExpired (uint64_t ts) const + { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; @@ -82,6 +86,7 @@ namespace transport size_t m_NumSentBytes, m_NumReceivedBytes; bool m_IsOutgoing; int m_TerminationTimeout; + uint64_t m_LastActivityTimestamp; }; } } diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 99d6a5ad..f9f21fd4 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -357,7 +357,7 @@ if (WITH_BINARY) endif () if (WITH_UPNP) - target_link_libraries("${PROJECT_NAME}" "miniupnpc") + target_link_libraries("${PROJECT_NAME}" "${MINIUPNPC_LIBRARY}") endif () # FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04 diff --git a/build/cmake_modules/FindMiniUPnPc.cmake b/build/cmake_modules/FindMiniUPnPc.cmake index 8d5d3860..6a5d4220 100644 --- a/build/cmake_modules/FindMiniUPnPc.cmake +++ b/build/cmake_modules/FindMiniUPnPc.cmake @@ -1,6 +1,6 @@ # - Find MINIUPNPC -if(MINIUPNPC_INCLUDE_DIR) +if(MINIUPNPC_INCLUDE_DIR AND MINIUPNPC_LIBRARY) set(MINIUPNPC_FOUND TRUE) else() @@ -11,15 +11,18 @@ else() $ENV{SystemDrive} ${PROJECT_SOURCE_DIR}/../.. ) - - if(MINIUPNPC_INCLUDE_DIR) + + find_library(MINIUPNPC_LIBRARY miniupnpc) + + if(MINIUPNPC_INCLUDE_DIR AND MINIUPNPC_LIBRARY) set(MINIUPNPC_FOUND TRUE) message(STATUS "Found MiniUPnP headers: ${MINIUPNPC_INCLUDE_DIR}") + message(STATUS "Found MiniUPnP library: ${MINIUPNPC_LIBRARY}") else() set(MINIUPNPC_FOUND FALSE) message(STATUS "MiniUPnP not found.") endif() - mark_as_advanced(MINIUPNPC_INCLUDE_DIR) + mark_as_advanced(MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) endif()