diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d0074f62..ac42c39a 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -608,21 +608,29 @@ namespace client if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { // udp client // TODO: hostnames - boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port); + boost::asio::ip::udp::endpoint end (boost::asio::ip::address::from_string(address), port); if (!localDestination) localDestination = m_SharedLocalDestination; bool gzip = section.second.get (I2P_CLIENT_TUNNEL_GZIP, true); - auto clientTunnel = std::make_shared(name, dest, end, localDestination, destinationPort, gzip); + auto clientTunnel = std::make_shared (name, dest, end, localDestination, destinationPort, gzip); - auto ins = m_ClientForwards.insert(std::make_pair(end, clientTunnel)); + auto ins = m_ClientForwards.insert (std::make_pair (end, clientTunnel)); if (ins.second) { - clientTunnel->Start(); + clientTunnel->Start (); numClientTunnels++; } else { + // TODO: update + if (ins.first->second->GetLocalDestination () != clientTunnel->GetLocalDestination ()) + { + LogPrint (eLogInfo, "Clients: I2P UDP client tunnel destination updated"); + ins.first->second->Stop (); + ins.first->second->SetLocalDestination (clientTunnel->GetLocalDestination ()); + ins.first->second->Start (); + } ins.first->second->isUpdated = true; LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); } @@ -976,11 +984,11 @@ namespace client } } - /* // TODO: Write correct UDP tunnels stop + // TODO: Write correct UDP tunnels stop for (auto it = m_ClientForwards.begin (); it != m_ClientForwards.end ();) { if(clean && !it->second->isUpdated) { - it->second = nullptr; + it->second->Stop (); it = m_ClientForwards.erase(it); } else { it->second->isUpdated = false; @@ -991,13 +999,13 @@ namespace client for (auto it = m_ServerForwards.begin (); it != m_ServerForwards.end ();) { if(clean && !it->second->isUpdated) { - it->second = nullptr; + it->second->Stop (); it = m_ServerForwards.erase(it); } else { it->second->isUpdated = false; it++; } - } */ + } } } } diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 7dd6ff82..d512a55b 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -142,8 +142,8 @@ namespace client i2p::proxy::HTTPProxy * m_HttpProxy; i2p::proxy::SOCKSProxy * m_SocksProxy; - std::map > m_ClientTunnels; // local endpoint->tunnel - std::map, std::shared_ptr > m_ServerTunnels; // ->tunnel + std::map > m_ClientTunnels; // local endpoint -> tunnel + std::map, std::shared_ptr > m_ServerTunnels; // -> tunnel std::mutex m_ForwardsMutex; std::map > m_ClientForwards; // local endpoint -> udp tunnel diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 6d5b58d6..e8af25bd 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -583,7 +583,7 @@ namespace client { if (m_KeepAliveTimer) { - m_KeepAliveTimer->expires_from_now (boost::posix_time::seconds(m_KeepAliveInterval)); + m_KeepAliveTimer->expires_from_now (boost::posix_time::seconds (m_KeepAliveInterval)); m_KeepAliveTimer->async_wait (std::bind (&I2PClientTunnel::HandleKeepAliveTimer, this, std::placeholders::_1)); } @@ -796,7 +796,8 @@ namespace client } } - void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { + void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) + { std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); auto itr = m_Sessions.begin(); @@ -808,7 +809,8 @@ namespace client } } - void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) { + void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) + { std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); std::vector removePorts; @@ -864,7 +866,8 @@ namespace client Receive(); } - void UDPSession::Receive() { + void UDPSession::Receive() + { LogPrint(eLogDebug, "UDPSession: Receive"); IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); @@ -901,230 +904,239 @@ namespace client LogPrint(eLogError, "UDPSession: ", ecode.message()); } - I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, + I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr localDestination, boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip) : - m_IsUniqueLocal(true), - m_Name(name), - m_LocalAddress(localAddress), - m_RemoteEndpoint(forwardTo) + m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress), m_LocalDest (localDestination), m_RemoteEndpoint (forwardTo), m_Gzip (gzip) + { + } + + I2PUDPServerTunnel::~I2PUDPServerTunnel () { - m_LocalDest = localDestination; - m_LocalDest->Start(); - auto dgram = m_LocalDest->CreateDatagramDestination(gzip); - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - dgram->SetRawReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + Stop (); } - I2PUDPServerTunnel::~I2PUDPServerTunnel() + void I2PUDPServerTunnel::Start () { - auto dgram = m_LocalDest->GetDatagramDestination(); - if (dgram) dgram->ResetReceiver(); + m_LocalDest->Start (); - LogPrint(eLogInfo, "UDPServer: Done"); + auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip); + dgram->SetReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + dgram->SetRawReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); } - void I2PUDPServerTunnel::Start() + void I2PUDPServerTunnel::Stop () { - m_LocalDest->Start(); + auto dgram = m_LocalDest->GetDatagramDestination (); + if (dgram) dgram->ResetReceiver (); } - std::vector > I2PUDPServerTunnel::GetSessions() + std::vector > I2PUDPServerTunnel::GetSessions () { std::vector > sessions; - std::lock_guard lock(m_SessionsMutex); + std::lock_guard lock (m_SessionsMutex); - for ( UDPSessionPtr s : m_Sessions ) + for (UDPSessionPtr s: m_Sessions) { if (!s->m_Destination) continue; - auto info = s->m_Destination->GetInfoForRemote(s->Identity); - if(!info) continue; + auto info = s->m_Destination->GetInfoForRemote (s->Identity); + if (!info) continue; - auto sinfo = std::make_shared(); + auto sinfo = std::make_shared (); sinfo->Name = m_Name; - sinfo->LocalIdent = std::make_shared(m_LocalDest->GetIdentHash().data()); - sinfo->RemoteIdent = std::make_shared(s->Identity.data()); + sinfo->LocalIdent = std::make_shared (m_LocalDest->GetIdentHash ().data ()); + sinfo->RemoteIdent = std::make_shared (s->Identity.data ()); sinfo->CurrentIBGW = info->IBGW; sinfo->CurrentOBEP = info->OBEP; - sessions.push_back(sinfo); + sessions.push_back (sinfo); } return sessions; } - I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, + I2PUDPClientTunnel::I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, bool gzip) : - m_Name(name), - m_RemoteDest(remoteDest), - m_LocalDest(localDestination), - m_LocalEndpoint(localEndpoint), - m_RemoteIdent(nullptr), - m_ResolveThread(nullptr), - m_LocalSocket(localDestination->GetService(), localEndpoint), - RemotePort(remotePort), m_LastPort (0), - m_cancel_resolve(false) - { - m_LocalSocket.set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU)); - m_LocalSocket.set_option (boost::asio::socket_base::reuse_address (true)); - - auto dgram = m_LocalDest->CreateDatagramDestination(gzip); - dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, + m_Name (name), m_RemoteDest (remoteDest), m_LocalDest (localDestination), m_LocalEndpoint (localEndpoint), + m_RemoteIdent (nullptr), m_ResolveThread (nullptr), m_LocalSocket (nullptr), RemotePort (remotePort), + m_LastPort (0), m_cancel_resolve (false), m_Gzip (gzip) + { + } + + I2PUDPClientTunnel::~I2PUDPClientTunnel () + { + Stop (); + } + + void I2PUDPClientTunnel::Start () + { + // Reset flag in case of tunnel reload + if (m_cancel_resolve) m_cancel_resolve = false; + + m_LocalSocket.reset (new boost::asio::ip::udp::socket (m_LocalDest->GetService (), m_LocalEndpoint)); + m_LocalSocket->set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU)); + m_LocalSocket->set_option (boost::asio::socket_base::reuse_address (true)); + + auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip); + dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - dgram->SetRawReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this, + dgram->SetRawReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); - } - void I2PUDPClientTunnel::Start() { - m_LocalDest->Start(); + m_LocalDest->Start (); if (m_ResolveThread == nullptr) - m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); - RecvFromLocal(); + m_ResolveThread = new std::thread (std::bind (&I2PUDPClientTunnel::TryResolving, this)); + RecvFromLocal (); + } + + void I2PUDPClientTunnel::Stop () + { + auto dgram = m_LocalDest->GetDatagramDestination (); + if (dgram) dgram->ResetReceiver (); + m_cancel_resolve = true; + + m_Sessions.clear(); + + if(m_LocalSocket && m_LocalSocket->is_open ()) + m_LocalSocket->close (); + + if(m_ResolveThread) + { + m_ResolveThread->join (); + delete m_ResolveThread; + m_ResolveThread = nullptr; + } + if (m_RemoteIdent) + { + delete m_RemoteIdent; + m_RemoteIdent = nullptr; + } } - void I2PUDPClientTunnel::RecvFromLocal() + void I2PUDPClientTunnel::RecvFromLocal () { - m_LocalSocket.async_receive_from(boost::asio::buffer(m_RecvBuff, I2P_UDP_MAX_MTU), - m_RecvEndpoint, std::bind(&I2PUDPClientTunnel::HandleRecvFromLocal, this, std::placeholders::_1, std::placeholders::_2)); + m_LocalSocket->async_receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), + m_RecvEndpoint, std::bind (&I2PUDPClientTunnel::HandleRecvFromLocal, this, std::placeholders::_1, std::placeholders::_2)); } - void I2PUDPClientTunnel::HandleRecvFromLocal(const boost::system::error_code & ec, std::size_t transferred) + void I2PUDPClientTunnel::HandleRecvFromLocal (const boost::system::error_code & ec, std::size_t transferred) { - if(m_cancel_resolve) { - LogPrint(eLogDebug, "UDP Client: Ignoring incomming data: stopping"); + if (m_cancel_resolve) { + LogPrint (eLogDebug, "UDP Client: Ignoring incomming data: stopping"); return; } - if(ec) { - LogPrint(eLogError, "UDP Client: Reading from socket error: ", ec.message(), ". Restarting listener..."); - RecvFromLocal(); // Restart listener and continue work + if (ec) { + LogPrint (eLogError, "UDP Client: Reading from socket error: ", ec.message (), ". Restarting listener..."); + RecvFromLocal (); // Restart listener and continue work return; } - if(!m_RemoteIdent) { - LogPrint(eLogWarning, "UDP Client: Remote endpoint not resolved yet"); - RecvFromLocal(); + if (!m_RemoteIdent) { + LogPrint (eLogWarning, "UDP Client: Remote endpoint not resolved yet"); + RecvFromLocal (); return; // drop, remote not resolved } - auto remotePort = m_RecvEndpoint.port(); + auto remotePort = m_RecvEndpoint.port (); if (!m_LastPort || m_LastPort != remotePort) { - auto itr = m_Sessions.find(remotePort); - if (itr != m_Sessions.end()) + auto itr = m_Sessions.find (remotePort); + if (itr != m_Sessions.end ()) m_LastSession = itr->second; else { - m_LastSession = std::make_shared(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0); + m_LastSession = std::make_shared (boost::asio::ip::udp::endpoint (m_RecvEndpoint), 0); m_Sessions.emplace (remotePort, m_LastSession); } m_LastPort = remotePort; } // send off to remote i2p destination - auto ts = i2p::util::GetMillisecondsSinceEpoch(); - LogPrint(eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); - auto session = m_LocalDest->GetDatagramDestination()->GetSession (*m_RemoteIdent); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + LogPrint (eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32 (), ":", RemotePort); + auto session = m_LocalDest->GetDatagramDestination ()->GetSession (*m_RemoteIdent); if (ts > m_LastSession->second + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL) - m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + m_LocalDest->GetDatagramDestination ()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); else - m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + m_LocalDest->GetDatagramDestination ()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); size_t numPackets = 0; while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) { boost::system::error_code ec; - size_t moreBytes = m_LocalSocket.available(ec); + size_t moreBytes = m_LocalSocket->available (ec); if (ec || !moreBytes) break; - transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); - remotePort = m_RecvEndpoint.port(); + transferred = m_LocalSocket->receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); + remotePort = m_RecvEndpoint.port (); // TODO: check remotePort - m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + m_LocalDest->GetDatagramDestination ()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); numPackets++; } if (numPackets) - LogPrint(eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32()); - m_LocalDest->GetDatagramDestination()->FlushSendQueue (session); + LogPrint (eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32 ()); + m_LocalDest->GetDatagramDestination ()->FlushSendQueue (session); // mark convo as active if (m_LastSession) m_LastSession->second = ts; - RecvFromLocal(); + RecvFromLocal (); } - std::vector > I2PUDPClientTunnel::GetSessions() + std::vector > I2PUDPClientTunnel::GetSessions () { // TODO: implement std::vector > infos; return infos; } - void I2PUDPClientTunnel::TryResolving() { - i2p::util::SetThreadName("UDP Resolver"); - LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); + void I2PUDPClientTunnel::TryResolving () + { + i2p::util::SetThreadName ("UDP Resolver"); + LogPrint (eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); std::shared_ptr addr; - while(!(addr = context.GetAddressBook().GetAddress(m_RemoteDest)) && !m_cancel_resolve) + while (!(addr = context.GetAddressBook().GetAddress(m_RemoteDest)) && !m_cancel_resolve) { - LogPrint(eLogWarning, "UDP Tunnel: Failed to lookup ", m_RemoteDest); - std::this_thread::sleep_for(std::chrono::seconds(1)); + LogPrint (eLogWarning, "UDP Tunnel: Failed to lookup ", m_RemoteDest); + std::this_thread::sleep_for (std::chrono::seconds (1)); } - if(m_cancel_resolve) + if (m_cancel_resolve) { LogPrint(eLogError, "UDP Tunnel: Lookup of ", m_RemoteDest, " was cancelled"); return; } if (!addr || !addr->IsIdentHash ()) { - LogPrint(eLogError, "UDP Tunnel: ", m_RemoteDest, " not found"); + LogPrint (eLogError, "UDP Tunnel: ", m_RemoteDest, " not found"); return; } m_RemoteIdent = new i2p::data::IdentHash; *m_RemoteIdent = addr->identHash; - LogPrint(eLogInfo, "UDP Tunnel: Resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); + LogPrint(eLogInfo, "UDP Tunnel: Resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32 ()); } - void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + void I2PUDPClientTunnel::HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) + if (m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) HandleRecvFromI2PRaw (fromPort, toPort, buf, len); else - LogPrint(eLogWarning, "UDP Client: Unwarranted traffic from ", from.GetIdentHash().ToBase32()); + LogPrint(eLogWarning, "UDP Client: Unwarranted traffic from ", from.GetIdentHash().ToBase32 ()); } - void I2PUDPClientTunnel::HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + void I2PUDPClientTunnel::HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - auto itr = m_Sessions.find(toPort); + auto itr = m_Sessions.find (toPort); // found convo ? - if(itr != m_Sessions.end()) + if (itr != m_Sessions.end ()) { // found convo if (len > 0) { - LogPrint(eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32() : ""); - m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first); + LogPrint (eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32 () : ""); + m_LocalSocket->send_to (boost::asio::buffer (buf, len), itr->second->first); // mark convo as active - itr->second->second = i2p::util::GetMillisecondsSinceEpoch(); + itr->second->second = i2p::util::GetMillisecondsSinceEpoch (); } } else - LogPrint(eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort); - } - - I2PUDPClientTunnel::~I2PUDPClientTunnel() - { - auto dgram = m_LocalDest->GetDatagramDestination(); - if (dgram) dgram->ResetReceiver(); - m_cancel_resolve = true; - - m_Sessions.clear(); - - if(m_LocalSocket.is_open()) - m_LocalSocket.close(); - - if(m_ResolveThread) - { - m_ResolveThread->join(); - delete m_ResolveThread; - m_ResolveThread = nullptr; - } - if (m_RemoteIdent) delete m_RemoteIdent; + LogPrint (eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort); } } } diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 53e893af..cf994765 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -230,25 +230,27 @@ namespace client { public: - I2PUDPServerTunnel(const std::string & name, + I2PUDPServerTunnel (const std::string & name, std::shared_ptr localDestination, boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip); - ~I2PUDPServerTunnel(); + ~I2PUDPServerTunnel (); + /** expire stale udp conversations */ - void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); - void Start(); - const char * GetName() const { return m_Name.c_str(); } - std::vector > GetSessions(); + void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); + void Start (); + void Stop (); + const char * GetName () const { return m_Name.c_str(); } + std::vector > GetSessions (); std::shared_ptr GetLocalDestination () const { return m_LocalDest; } - void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } + void SetUniqueLocal (bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } private: - void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); + UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); private: @@ -260,6 +262,7 @@ namespace client std::vector m_Sessions; std::shared_ptr m_LocalDest; UDPSessionPtr m_LastSession; + bool m_Gzip; public: @@ -270,27 +273,36 @@ namespace client { public: - I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, + I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, bool gzip); - ~I2PUDPClientTunnel(); - void Start(); - const char * GetName() const { return m_Name.c_str(); } - std::vector > GetSessions(); + ~I2PUDPClientTunnel (); + + void Start (); + void Stop (); + const char * GetName () const { return m_Name.c_str(); } + std::vector > GetSessions (); - bool IsLocalDestination(const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); } + bool IsLocalDestination (const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); } std::shared_ptr GetLocalDestination () const { return m_LocalDest; } - void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); + inline void SetLocalDestination (std::shared_ptr dest) + { + if (m_LocalDest) m_LocalDest->Release (); + if (dest) dest->Acquire (); + m_LocalDest = dest; + } + + void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); private: typedef std::pair UDPConvo; - void RecvFromLocal(); - void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); - void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - void HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - void TryResolving(); + void RecvFromLocal (); + void HandleRecvFromLocal (const boost::system::error_code & e, std::size_t transferred); + void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void TryResolving (); private: @@ -302,11 +314,12 @@ namespace client const boost::asio::ip::udp::endpoint m_LocalEndpoint; i2p::data::IdentHash * m_RemoteIdent; std::thread * m_ResolveThread; - boost::asio::ip::udp::socket m_LocalSocket; + std::unique_ptr m_LocalSocket; boost::asio::ip::udp::endpoint m_RecvEndpoint; uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; uint16_t RemotePort, m_LastPort; bool m_cancel_resolve; + bool m_Gzip; std::shared_ptr m_LastSession; public: