From 9a5a04ca70ed2986a484dc835882f30a63fd849e Mon Sep 17 00:00:00 2001
From: orignal <romakoshelkin@yandex.ru>
Date: Sun, 30 Mar 2014 22:55:03 -0400
Subject: [PATCH] delete non-responding SSU sessions

---
 SSU.cpp | 38 +++++++++++++++++++++++++++++++++-----
 SSU.h   |  7 ++++++-
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/SSU.cpp b/SSU.cpp
index 9075d157..4d80afd1 100644
--- a/SSU.cpp
+++ b/SSU.cpp
@@ -16,10 +16,16 @@ namespace ssu
 
 	SSUSession::SSUSession (SSUServer * server, boost::asio::ip::udp::endpoint& remoteEndpoint,
 		const i2p::data::RouterInfo * router): m_Server (server), m_RemoteEndpoint (remoteEndpoint), 
-		m_RemoteRouter (router), m_State (eSessionStateUnknown)
+		m_RemoteRouter (router), m_ConnectTimer (nullptr),m_State (eSessionStateUnknown)
 	{
 	}
 
+	SSUSession::~SSUSession ()
+	{
+		if (m_ConnectTimer)
+			delete m_ConnectTimer;
+	}	
+	
 	void SSUSession::CreateAESandMacKey (uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey)
 	{
 		CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
@@ -160,6 +166,7 @@ namespace ssu
 		{
 			m_State = eSessionStateCreatedReceived;
 			LogPrint ("Session created received");	
+			if (m_ConnectTimer) m_ConnectTimer->cancel ();
 			uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time 
 			uint8_t * payload = buf + sizeof (SSUHeader);
 			uint8_t * y = payload;
@@ -485,9 +492,27 @@ namespace ssu
 
 	void SSUSession::Connect ()
 	{
+		if (m_Server)
+		{	
+			if (!m_ConnectTimer)
+				m_ConnectTimer = new boost::asio::deadline_timer (m_Server->GetService ());
+			m_ConnectTimer->expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
+			m_ConnectTimer->async_wait (boost::bind (&SSUSession::HandleConnectTimer,
+				this, boost::asio::placeholders::error));
+		}		
 		SendSessionRequest ();
 	}
 
+	void SSUSession::HandleConnectTimer (const boost::system::error_code& ecode)
+	{
+		if (!ecode)
+		{
+			// timeout expired
+			LogPrint ("SSU session was not established after ", SSU_CONNECT_TIMEOUT, " second");
+			Failed ();
+		}	
+	}	
+	
 	void SSUSession::ConnectThroughIntroducer (const i2p::data::RouterInfo::Introducer& introducer)
 	{	
 		SendRelayRequest (introducer);
@@ -517,10 +542,13 @@ namespace ssu
 
 	void SSUSession::Failed ()
 	{
-		m_State = eSessionStateFailed;
-		Close ();
-		if (m_Server)
-			m_Server->DeleteSession (this); // delete this 
+		if (m_State != eSessionStateFailed)
+		{	
+			m_State = eSessionStateFailed;
+			Close ();
+			if (m_Server)
+				m_Server->DeleteSession (this); // delete this 
+		}	
 	}	
 	
 	const uint8_t * SSUSession::GetIntroKey () const
diff --git a/SSU.h b/SSU.h
index c3b2c476..e43fa4ad 100644
--- a/SSU.h
+++ b/SSU.h
@@ -26,6 +26,7 @@ namespace ssu
 #pragma pack()
 
 	const int SSU_MTU = 1484;
+	const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
 
 	// payload types (4 bits)
 	const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
@@ -70,7 +71,8 @@ namespace ssu
 			SSUSession (SSUServer * server, boost::asio::ip::udp::endpoint& remoteEndpoint,
 				const i2p::data::RouterInfo * router = nullptr);
 			void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);		
-
+			~SSUSession ();
+			
 			void Connect ();
 			void ConnectThroughIntroducer (const i2p::data::RouterInfo::Introducer& introducer);	
 			void Close ();
@@ -93,6 +95,7 @@ namespace ssu
 			void ProcessRelayResponse (uint8_t * buf, size_t len);
 			void Established ();
 			void Failed ();
+			void HandleConnectTimer (const boost::system::error_code& ecode);
 			void ProcessData (uint8_t * buf, size_t len);	
 			void SendMsgAck (uint32_t msgID);
 			void SendSesionDestroyed ();
@@ -109,6 +112,7 @@ namespace ssu
 			SSUServer * m_Server;
 			boost::asio::ip::udp::endpoint m_RemoteEndpoint;
 			const i2p::data::RouterInfo * m_RemoteRouter;
+			boost::asio::deadline_timer * m_ConnectTimer;
 			SessionState m_State;	
 			CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;	
 			CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;	
@@ -130,6 +134,7 @@ namespace ssu
 			void DeleteSession (SSUSession * session);
 			void DeleteAllSessions ();			
 
+			boost::asio::io_service& GetService () { return m_Socket.get_io_service(); };
 			const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; };			
 			void Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to);
 			void ReassignSession (const boost::asio::ip::udp::endpoint& oldEndpoint, const boost::asio::ip::udp::endpoint& newEndpoint);