shared pointer for SSU

This commit is contained in:
orignal 2014-11-24 12:26:11 -05:00
parent 1a0957b571
commit 95524c8db3
7 changed files with 56 additions and 62 deletions

53
SSU.cpp
View File

@ -27,17 +27,15 @@ namespace transport
SSUServer::~SSUServer ()
{
for (auto it: m_Sessions)
delete it.second;
}
void SSUServer::Start ()
{
m_IsRunning = true;
m_Thread = new std::thread (std::bind (&SSUServer::Run, this));
m_Service.post (boost::bind (&SSUServer::Receive, this));
m_Service.post (std::bind (&SSUServer::Receive, this));
if (context.SupportsV6 ())
m_Service.post (boost::bind (&SSUServer::ReceiveV6, this));
m_Service.post (std::bind (&SSUServer::ReceiveV6, this));
if (i2p::context.IsUnreachable ())
ScheduleIntroducersUpdateTimer ();
}
@ -76,7 +74,7 @@ namespace transport
m_Relays[tag] = relay;
}
SSUSession * SSUServer::FindRelaySession (uint32_t tag)
std::shared_ptr<SSUSession> SSUServer::FindRelaySession (uint32_t tag)
{
auto it = m_Relays.find (tag);
if (it != m_Relays.end ())
@ -128,13 +126,13 @@ namespace transport
void SSUServer::HandleReceivedBuffer (boost::asio::ip::udp::endpoint& from, uint8_t * buf, std::size_t bytes_transferred)
{
SSUSession * session = nullptr;
std::shared_ptr<SSUSession> session;
auto it = m_Sessions.find (from);
if (it != m_Sessions.end ())
session = it->second;
if (!session)
{
session = new SSUSession (*this, from);
session = std::make_shared<SSUSession> (*this, from);
session->WaitForConnect ();
m_Sessions[from] = session;
LogPrint ("New SSU session from ", from.address ().to_string (), ":", from.port (), " created");
@ -142,7 +140,7 @@ namespace transport
session->ProcessNextMessage (buf, bytes_transferred, from);
}
SSUSession * SSUServer::FindSession (const i2p::data::RouterInfo * router) const
std::shared_ptr<SSUSession> SSUServer::FindSession (std::shared_ptr<const i2p::data::RouterInfo> router) const
{
if (!router) return nullptr;
auto address = router->GetSSUAddress (true); // v4 only
@ -156,7 +154,7 @@ namespace transport
return FindSession (boost::asio::ip::udp::endpoint (address->host, address->port));
}
SSUSession * SSUServer::FindSession (const boost::asio::ip::udp::endpoint& e) const
std::shared_ptr<SSUSession> SSUServer::FindSession (const boost::asio::ip::udp::endpoint& e) const
{
auto it = m_Sessions.find (e);
if (it != m_Sessions.end ())
@ -165,9 +163,9 @@ namespace transport
return nullptr;
}
SSUSession * SSUServer::GetSession (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest)
std::shared_ptr<SSUSession> SSUServer::GetSession (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest)
{
SSUSession * session = nullptr;
std::shared_ptr<SSUSession> session;
if (router)
{
auto address = router->GetSSUAddress (!context.SupportsV6 ());
@ -180,7 +178,7 @@ namespace transport
else
{
// otherwise create new session
session = new SSUSession (*this, remoteEndpoint, router, peerTest);
session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
m_Sessions[remoteEndpoint] = session;
if (!router->UsesIntroducer ())
@ -196,7 +194,7 @@ namespace transport
int numIntroducers = address->introducers.size ();
if (numIntroducers > 0)
{
SSUSession * introducerSession = nullptr;
std::shared_ptr<SSUSession> introducerSession;
const i2p::data::RouterInfo::Introducer * introducer = nullptr;
// we might have a session to introducer already
for (int i = 0; i < numIntroducers; i++)
@ -217,7 +215,7 @@ namespace transport
LogPrint ("Creating new session to introducer");
introducer = &(address->introducers[0]); // TODO:
boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort);
introducerSession = new SSUSession (*this, introducerEndpoint, router);
introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = introducerSession;
}
// introduce
@ -232,8 +230,7 @@ namespace transport
{
LogPrint (eLogWarning, "Can't connect to unreachable router. No introducers presented");
m_Sessions.erase (remoteEndpoint);
delete session;
session = nullptr;
session.reset ();
}
}
}
@ -244,30 +241,26 @@ namespace transport
return session;
}
void SSUServer::DeleteSession (SSUSession * session)
void SSUServer::DeleteSession (std::shared_ptr<SSUSession> session)
{
if (session)
{
session->Close ();
m_Sessions.erase (session->GetRemoteEndpoint ());
delete session;
}
}
void SSUServer::DeleteAllSessions ()
{
for (auto it: m_Sessions)
{
it.second->Close ();
delete it.second;
}
m_Sessions.clear ();
}
template<typename Filter>
SSUSession * SSUServer::GetRandomSession (Filter filter)
std::shared_ptr<SSUSession> SSUServer::GetRandomSession (Filter filter)
{
std::vector<SSUSession *> filteredSessions;
std::vector<std::shared_ptr<SSUSession> > filteredSessions;
for (auto s :m_Sessions)
if (filter (s.second)) filteredSessions.push_back (s.second);
if (filteredSessions.size () > 0)
@ -278,10 +271,10 @@ namespace transport
return nullptr;
}
SSUSession * SSUServer::GetRandomEstablishedSession (const SSUSession * excluded)
std::shared_ptr<SSUSession> SSUServer::GetRandomEstablishedSession (std::shared_ptr<const SSUSession> excluded)
{
return GetRandomSession (
[excluded](SSUSession * session)->bool
[excluded](std::shared_ptr<SSUSession> session)->bool
{
return session->GetState () == eSessionStateEstablished &&
session != excluded;
@ -296,16 +289,16 @@ namespace transport
for (int i = 0; i < maxNumIntroducers; i++)
{
auto session = GetRandomSession (
[&ret, ts](SSUSession * session)->bool
[&ret, ts](std::shared_ptr<SSUSession> session)->bool
{
return session->GetRelayTag () && !ret.count (session) &&
return session->GetRelayTag () && !ret.count (session.get ()) &&
session->GetState () == eSessionStateEstablished &&
ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION;
}
);
if (session)
{
ret.insert (session);
ret.insert (session.get ());
break;
}
}
@ -315,8 +308,8 @@ namespace transport
void SSUServer::ScheduleIntroducersUpdateTimer ()
{
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL));
m_IntroducersUpdateTimer.async_wait (boost::bind (&SSUServer::HandleIntroducersUpdateTimer,
this, boost::asio::placeholders::error));
m_IntroducersUpdateTimer.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer,
this, std::placeholders::_1));
}
void SSUServer::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode)

16
SSU.h
View File

@ -31,18 +31,18 @@ namespace transport
~SSUServer ();
void Start ();
void Stop ();
SSUSession * GetSession (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest = false);
SSUSession * FindSession (const i2p::data::RouterInfo * router) const;
SSUSession * FindSession (const boost::asio::ip::udp::endpoint& e) const;
SSUSession * GetRandomEstablishedSession (const SSUSession * excluded);
void DeleteSession (SSUSession * session);
std::shared_ptr<SSUSession> GetSession (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest = false);
std::shared_ptr<SSUSession> FindSession (std::shared_ptr<const i2p::data::RouterInfo> router) const;
std::shared_ptr<SSUSession> FindSession (const boost::asio::ip::udp::endpoint& e) const;
std::shared_ptr<SSUSession> GetRandomEstablishedSession (std::shared_ptr<const SSUSession> excluded);
void DeleteSession (std::shared_ptr<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 (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to);
void AddRelay (uint32_t tag, const boost::asio::ip::udp::endpoint& relay);
SSUSession * FindRelaySession (uint32_t tag);
std::shared_ptr<SSUSession> FindRelaySession (uint32_t tag);
private:
@ -54,7 +54,7 @@ namespace transport
void HandleReceivedBuffer (boost::asio::ip::udp::endpoint& from, uint8_t * buf, std::size_t bytes_transferred);
template<typename Filter>
SSUSession * GetRandomSession (Filter filter);
std::shared_ptr<SSUSession> GetRandomSession (Filter filter);
std::set<SSUSession *> FindIntroducers (int maxNumIntroducers);
void ScheduleIntroducersUpdateTimer ();
@ -73,7 +73,7 @@ namespace transport
std::list<boost::asio::ip::udp::endpoint> m_Introducers; // introducers we are connected to
i2p::crypto::AESAlignedBuffer<2*SSU_MTU_V4> m_ReceiveBuffer;
i2p::crypto::AESAlignedBuffer<2*SSU_MTU_V6> m_ReceiveBufferV6;
std::map<boost::asio::ip::udp::endpoint, SSUSession *> m_Sessions;
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> > m_Sessions;
std::map<uint32_t, boost::asio::ip::udp::endpoint> m_Relays; // we are introducer
public:

View File

@ -401,8 +401,9 @@ namespace transport
{
m_ResendTimer.cancel ();
m_ResendTimer.expires_from_now (boost::posix_time::seconds(RESEND_INTERVAL));
m_ResendTimer.async_wait (boost::bind (&SSUData::HandleResendTimer,
this, boost::asio::placeholders::error));
auto s = m_Session.shared_from_this();
m_ResendTimer.async_wait ([s](const boost::system::error_code& ecode)
{ s->m_Data.HandleResendTimer (ecode); });
}
void SSUData::HandleResendTimer (const boost::system::error_code& ecode)

View File

@ -109,7 +109,7 @@ namespace transport
else
{
LogPrint (eLogError, "MAC verification failed ", len, " bytes from ", senderEndpoint);
m_Server.DeleteSession (this);
m_Server.DeleteSession (shared_from_this ());
return;
}
}
@ -144,13 +144,13 @@ namespace transport
case PAYLOAD_TYPE_SESSION_DESTROYED:
{
LogPrint (eLogDebug, "SSU session destroy received");
m_Server.DeleteSession (this); // delete this
m_Server.DeleteSession (shared_from_this ());
break;
}
case PAYLOAD_TYPE_RELAY_RESPONSE:
ProcessRelayResponse (buf, len);
if (m_State != eSessionStateEstablished)
m_Server.DeleteSession (this);
m_Server.DeleteSession (shared_from_this ());
break;
case PAYLOAD_TYPE_RELAY_REQUEST:
LogPrint (eLogDebug, "SSU relay request received");
@ -459,7 +459,7 @@ namespace transport
buf += 32; // introkey
uint32_t nonce = be32toh (*(uint32_t *)buf);
SendRelayResponse (nonce, from, introKey, session->m_RemoteEndpoint);
SendRelayIntro (session, from);
SendRelayIntro (session.get (), from);
}
}
@ -711,8 +711,8 @@ namespace transport
{
m_Timer.cancel ();
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer,
this, boost::asio::placeholders::error));
m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer,
shared_from_this (), std::placeholders::_1));
}
void SSUSession::HandleConnectTimer (const boost::system::error_code& ecode)
@ -731,8 +731,8 @@ namespace transport
{
// set connect timer
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer,
this, boost::asio::placeholders::error));
m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer,
shared_from_this (), std::placeholders::_1));
}
SendRelayRequest (iTag, iKey);
}
@ -742,8 +742,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 (boost::bind (&SSUSession::HandleConnectTimer,
this, boost::asio::placeholders::error));
m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer,
shared_from_this (), std::placeholders::_1));
}
void SSUSession::Close ()
@ -782,7 +782,7 @@ namespace transport
if (m_State != eSessionStateFailed)
{
m_State = eSessionStateFailed;
m_Server.DeleteSession (this); // delete this
m_Server.DeleteSession (shared_from_this ());
}
}
@ -790,8 +790,8 @@ namespace transport
{
m_Timer.cancel ();
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_TERMINATION_TIMEOUT));
m_Timer.async_wait (boost::bind (&SSUSession::HandleTerminationTimer,
this, boost::asio::placeholders::error));
m_Timer.async_wait (std::bind (&SSUSession::HandleTerminationTimer,
shared_from_this (), std::placeholders::_1));
}
void SSUSession::HandleTerminationTimer (const boost::system::error_code& ecode)
@ -821,7 +821,7 @@ namespace transport
void SSUSession::SendI2NPMessage (I2NPMessage * msg)
{
m_Server.GetService ().post (boost::bind (&SSUSession::PostI2NPMessage, this, msg));
m_Server.GetService ().post (std::bind (&SSUSession::PostI2NPMessage, shared_from_this (), msg));
}
void SSUSession::PostI2NPMessage (I2NPMessage * msg)
@ -897,7 +897,7 @@ namespace transport
else
{
LogPrint (eLogDebug, "SSU peer test from Alice. We are Bob");
auto session = m_Server.GetRandomEstablishedSession (this); // charlie
auto session = m_Server.GetRandomEstablishedSession (shared_from_this ()); // charlie
if (session)
session->SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (),
senderEndpoint.port (), introKey, false);

View File

@ -4,7 +4,7 @@
#include <inttypes.h>
#include <set>
#include <list>
#include <boost/asio.hpp>
#include <memory>
#include "aes.h"
#include "hmac.h"
#include "I2NPProtocol.h"
@ -50,7 +50,7 @@ namespace transport
};
class SSUServer;
class SSUSession: public TransportSession
class SSUSession: public TransportSession, public std::enable_shared_from_this<SSUSession>
{
public:

View File

@ -280,7 +280,7 @@ namespace transport
auto r = netdb.FindRouter (ident);
if (r)
{
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (r.get ()) : nullptr;
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (r) : nullptr;
if (ssuSession)
ssuSession->SendI2NPMessage (msg);
else
@ -337,13 +337,13 @@ namespace transport
delete timer;
}
void Transports::CloseSession (const i2p::data::RouterInfo * router)
void Transports::CloseSession (std::shared_ptr<const i2p::data::RouterInfo> router)
{
if (!router) return;
m_Service.post (boost::bind (&Transports::PostCloseSession, this, router));
}
void Transports::PostCloseSession (const i2p::data::RouterInfo * router)
void Transports::PostCloseSession (std::shared_ptr<const i2p::data::RouterInfo> router)
{
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (router) : nullptr;
if (ssuSession) // try SSU first

View File

@ -70,7 +70,7 @@ namespace transport
NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
void CloseSession (const i2p::data::RouterInfo * router);
void CloseSession (std::shared_ptr<const i2p::data::RouterInfo> router);
private:
@ -80,7 +80,7 @@ namespace transport
void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer,
const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
void PostCloseSession (const i2p::data::RouterInfo * router);
void PostCloseSession (std::shared_ptr<const i2p::data::RouterInfo> router);
void DetectExternalIP ();