Browse Source

fix udp tunnels reload

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1756/head
R4SAS 2 years ago
parent
commit
923eb9fdb3
  1. 24
      libi2pd_client/ClientContext.cpp
  2. 4
      libi2pd_client/ClientContext.h
  3. 250
      libi2pd_client/I2PTunnel.cpp
  4. 57
      libi2pd_client/I2PTunnel.h

24
libi2pd_client/ClientContext.cpp

@ -608,21 +608,29 @@ namespace client
if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
// udp client // udp client
// TODO: hostnames // 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) if (!localDestination)
localDestination = m_SharedLocalDestination; localDestination = m_SharedLocalDestination;
bool gzip = section.second.get (I2P_CLIENT_TUNNEL_GZIP, true); bool gzip = section.second.get (I2P_CLIENT_TUNNEL_GZIP, true);
auto clientTunnel = std::make_shared<I2PUDPClientTunnel>(name, dest, end, localDestination, destinationPort, gzip); auto clientTunnel = std::make_shared<I2PUDPClientTunnel> (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) if (ins.second)
{ {
clientTunnel->Start(); clientTunnel->Start ();
numClientTunnels++; numClientTunnels++;
} }
else 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; ins.first->second->isUpdated = true;
LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); 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 ();) for (auto it = m_ClientForwards.begin (); it != m_ClientForwards.end ();)
{ {
if(clean && !it->second->isUpdated) { if(clean && !it->second->isUpdated) {
it->second = nullptr; it->second->Stop ();
it = m_ClientForwards.erase(it); it = m_ClientForwards.erase(it);
} else { } else {
it->second->isUpdated = false; it->second->isUpdated = false;
@ -991,13 +999,13 @@ namespace client
for (auto it = m_ServerForwards.begin (); it != m_ServerForwards.end ();) for (auto it = m_ServerForwards.begin (); it != m_ServerForwards.end ();)
{ {
if(clean && !it->second->isUpdated) { if(clean && !it->second->isUpdated) {
it->second = nullptr; it->second->Stop ();
it = m_ServerForwards.erase(it); it = m_ServerForwards.erase(it);
} else { } else {
it->second->isUpdated = false; it->second->isUpdated = false;
it++; it++;
} }
} */ }
} }
} }
} }

4
libi2pd_client/ClientContext.h

@ -142,8 +142,8 @@ namespace client
i2p::proxy::HTTPProxy * m_HttpProxy; i2p::proxy::HTTPProxy * m_HttpProxy;
i2p::proxy::SOCKSProxy * m_SocksProxy; i2p::proxy::SOCKSProxy * m_SocksProxy;
std::map<boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService> > m_ClientTunnels; // local endpoint->tunnel std::map<boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService> > m_ClientTunnels; // local endpoint -> tunnel
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port>->tunnel std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port> -> tunnel
std::mutex m_ForwardsMutex; std::mutex m_ForwardsMutex;
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel

250
libi2pd_client/I2PTunnel.cpp

@ -583,7 +583,7 @@ namespace client
{ {
if (m_KeepAliveTimer) 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, m_KeepAliveTimer->async_wait (std::bind (&I2PClientTunnel::HandleKeepAliveTimer,
this, std::placeholders::_1)); 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<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
auto itr = m_Sessions.begin(); 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<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
std::vector<uint16_t> removePorts; std::vector<uint16_t> removePorts;
@ -864,7 +866,8 @@ namespace client
Receive(); Receive();
} }
void UDPSession::Receive() { void UDPSession::Receive()
{
LogPrint(eLogDebug, "UDPSession: Receive"); LogPrint(eLogDebug, "UDPSession: Receive");
IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), 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)); FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2));
@ -901,230 +904,239 @@ namespace client
LogPrint(eLogError, "UDPSession: ", ecode.message()); LogPrint(eLogError, "UDPSession: ", ecode.message());
} }
I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination, I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip) : boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip) :
m_IsUniqueLocal(true), m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress), m_LocalDest (localDestination), m_RemoteEndpoint (forwardTo), m_Gzip (gzip)
m_Name(name), {
m_LocalAddress(localAddress), }
m_RemoteEndpoint(forwardTo)
I2PUDPServerTunnel::~I2PUDPServerTunnel ()
{ {
m_LocalDest = localDestination; Stop ();
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));
} }
I2PUDPServerTunnel::~I2PUDPServerTunnel() void I2PUDPServerTunnel::Start ()
{ {
auto dgram = m_LocalDest->GetDatagramDestination(); m_LocalDest->Start ();
if (dgram) dgram->ResetReceiver();
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<std::shared_ptr<DatagramSessionInfo> > I2PUDPServerTunnel::GetSessions() std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPServerTunnel::GetSessions ()
{ {
std::vector<std::shared_ptr<DatagramSessionInfo> > sessions; std::vector<std::shared_ptr<DatagramSessionInfo> > sessions;
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock (m_SessionsMutex);
for ( UDPSessionPtr s : m_Sessions ) for (UDPSessionPtr s: m_Sessions)
{ {
if (!s->m_Destination) continue; if (!s->m_Destination) continue;
auto info = s->m_Destination->GetInfoForRemote(s->Identity); auto info = s->m_Destination->GetInfoForRemote (s->Identity);
if(!info) continue; if (!info) continue;
auto sinfo = std::make_shared<DatagramSessionInfo>(); auto sinfo = std::make_shared<DatagramSessionInfo> ();
sinfo->Name = m_Name; sinfo->Name = m_Name;
sinfo->LocalIdent = std::make_shared<i2p::data::IdentHash>(m_LocalDest->GetIdentHash().data()); sinfo->LocalIdent = std::make_shared<i2p::data::IdentHash> (m_LocalDest->GetIdentHash ().data ());
sinfo->RemoteIdent = std::make_shared<i2p::data::IdentHash>(s->Identity.data()); sinfo->RemoteIdent = std::make_shared<i2p::data::IdentHash> (s->Identity.data ());
sinfo->CurrentIBGW = info->IBGW; sinfo->CurrentIBGW = info->IBGW;
sinfo->CurrentOBEP = info->OBEP; sinfo->CurrentOBEP = info->OBEP;
sessions.push_back(sinfo); sessions.push_back (sinfo);
} }
return sessions; 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, boost::asio::ip::udp::endpoint localEndpoint,
std::shared_ptr<i2p::client::ClientDestination> localDestination, std::shared_ptr<i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip) : uint16_t remotePort, bool gzip) :
m_Name(name), m_Name (name), m_RemoteDest (remoteDest), m_LocalDest (localDestination), m_LocalEndpoint (localEndpoint),
m_RemoteDest(remoteDest), m_RemoteIdent (nullptr), m_ResolveThread (nullptr), m_LocalSocket (nullptr), RemotePort (remotePort),
m_LocalDest(localDestination), m_LastPort (0), m_cancel_resolve (false), m_Gzip (gzip)
m_LocalEndpoint(localEndpoint), {
m_RemoteIdent(nullptr), }
m_ResolveThread(nullptr),
m_LocalSocket(localDestination->GetService(), localEndpoint), I2PUDPClientTunnel::~I2PUDPClientTunnel ()
RemotePort(remotePort), m_LastPort (0), {
m_cancel_resolve(false) Stop ();
{ }
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)); void I2PUDPClientTunnel::Start ()
{
auto dgram = m_LocalDest->CreateDatagramDestination(gzip); // Reset flag in case of tunnel reload
dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, 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::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4, std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5)); 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)); 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) if (m_ResolveThread == nullptr)
m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); m_ResolveThread = new std::thread (std::bind (&I2PUDPClientTunnel::TryResolving, this));
RecvFromLocal(); 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_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_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) { if (m_cancel_resolve) {
LogPrint(eLogDebug, "UDP Client: Ignoring incomming data: stopping"); LogPrint (eLogDebug, "UDP Client: Ignoring incomming data: stopping");
return; return;
} }
if(ec) { if (ec) {
LogPrint(eLogError, "UDP Client: Reading from socket error: ", ec.message(), ". Restarting listener..."); LogPrint (eLogError, "UDP Client: Reading from socket error: ", ec.message (), ". Restarting listener...");
RecvFromLocal(); // Restart listener and continue work RecvFromLocal (); // Restart listener and continue work
return; return;
} }
if(!m_RemoteIdent) { if (!m_RemoteIdent) {
LogPrint(eLogWarning, "UDP Client: Remote endpoint not resolved yet"); LogPrint (eLogWarning, "UDP Client: Remote endpoint not resolved yet");
RecvFromLocal(); RecvFromLocal ();
return; // drop, remote not resolved return; // drop, remote not resolved
} }
auto remotePort = m_RecvEndpoint.port(); auto remotePort = m_RecvEndpoint.port ();
if (!m_LastPort || m_LastPort != remotePort) if (!m_LastPort || m_LastPort != remotePort)
{ {
auto itr = m_Sessions.find(remotePort); auto itr = m_Sessions.find (remotePort);
if (itr != m_Sessions.end()) if (itr != m_Sessions.end ())
m_LastSession = itr->second; m_LastSession = itr->second;
else else
{ {
m_LastSession = std::make_shared<UDPConvo>(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0); m_LastSession = std::make_shared<UDPConvo> (boost::asio::ip::udp::endpoint (m_RecvEndpoint), 0);
m_Sessions.emplace (remotePort, m_LastSession); m_Sessions.emplace (remotePort, m_LastSession);
} }
m_LastPort = remotePort; m_LastPort = remotePort;
} }
// send off to remote i2p destination // send off to remote i2p destination
auto ts = i2p::util::GetMillisecondsSinceEpoch(); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
LogPrint(eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); LogPrint (eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32 (), ":", RemotePort);
auto session = m_LocalDest->GetDatagramDestination()->GetSession (*m_RemoteIdent); auto session = m_LocalDest->GetDatagramDestination ()->GetSession (*m_RemoteIdent);
if (ts > m_LastSession->second + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL) 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 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; size_t numPackets = 0;
while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE)
{ {
boost::system::error_code ec; boost::system::error_code ec;
size_t moreBytes = m_LocalSocket.available(ec); size_t moreBytes = m_LocalSocket->available (ec);
if (ec || !moreBytes) break; if (ec || !moreBytes) break;
transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); transferred = m_LocalSocket->receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec);
remotePort = m_RecvEndpoint.port(); remotePort = m_RecvEndpoint.port ();
// TODO: check remotePort // TODO: check remotePort
m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); m_LocalDest->GetDatagramDestination ()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
numPackets++; numPackets++;
} }
if (numPackets) if (numPackets)
LogPrint(eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32()); LogPrint (eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32 ());
m_LocalDest->GetDatagramDestination()->FlushSendQueue (session); m_LocalDest->GetDatagramDestination ()->FlushSendQueue (session);
// mark convo as active // mark convo as active
if (m_LastSession) if (m_LastSession)
m_LastSession->second = ts; m_LastSession->second = ts;
RecvFromLocal(); RecvFromLocal ();
} }
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPClientTunnel::GetSessions() std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPClientTunnel::GetSessions ()
{ {
// TODO: implement // TODO: implement
std::vector<std::shared_ptr<DatagramSessionInfo> > infos; std::vector<std::shared_ptr<DatagramSessionInfo> > infos;
return infos; return infos;
} }
void I2PUDPClientTunnel::TryResolving() { void I2PUDPClientTunnel::TryResolving ()
i2p::util::SetThreadName("UDP Resolver"); {
LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); i2p::util::SetThreadName ("UDP Resolver");
LogPrint (eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
std::shared_ptr<const Address> addr; std::shared_ptr<const Address> 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); LogPrint (eLogWarning, "UDP Tunnel: Failed to lookup ", m_RemoteDest);
std::this_thread::sleep_for(std::chrono::seconds(1)); 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"); LogPrint(eLogError, "UDP Tunnel: Lookup of ", m_RemoteDest, " was cancelled");
return; return;
} }
if (!addr || !addr->IsIdentHash ()) if (!addr || !addr->IsIdentHash ())
{ {
LogPrint(eLogError, "UDP Tunnel: ", m_RemoteDest, " not found"); LogPrint (eLogError, "UDP Tunnel: ", m_RemoteDest, " not found");
return; return;
} }
m_RemoteIdent = new i2p::data::IdentHash; m_RemoteIdent = new i2p::data::IdentHash;
*m_RemoteIdent = addr->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); HandleRecvFromI2PRaw (fromPort, toPort, buf, len);
else 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 ? // found convo ?
if(itr != m_Sessions.end()) if (itr != m_Sessions.end ())
{ {
// found convo // found convo
if (len > 0) if (len > 0)
{ {
LogPrint(eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32() : ""); 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); m_LocalSocket->send_to (boost::asio::buffer (buf, len), itr->second->first);
// mark convo as active // mark convo as active
itr->second->second = i2p::util::GetMillisecondsSinceEpoch(); itr->second->second = i2p::util::GetMillisecondsSinceEpoch ();
} }
} }
else else
LogPrint(eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort); 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;
} }
} }
} }

57
libi2pd_client/I2PTunnel.h

@ -230,25 +230,27 @@ namespace client
{ {
public: public:
I2PUDPServerTunnel(const std::string & name, I2PUDPServerTunnel (const std::string & name,
std::shared_ptr<i2p::client::ClientDestination> localDestination, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::address localAddress,
boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip); boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip);
~I2PUDPServerTunnel(); ~I2PUDPServerTunnel ();
/** expire stale udp conversations */ /** expire stale udp conversations */
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
void Start(); void Start ();
const char * GetName() const { return m_Name.c_str(); } void Stop ();
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions(); const char * GetName () const { return m_Name.c_str(); }
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions ();
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; } std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } void SetUniqueLocal (bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
private: 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); 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: private:
@ -260,6 +262,7 @@ namespace client
std::vector<UDPSessionPtr> m_Sessions; std::vector<UDPSessionPtr> m_Sessions;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest; std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
UDPSessionPtr m_LastSession; UDPSessionPtr m_LastSession;
bool m_Gzip;
public: public:
@ -270,27 +273,36 @@ namespace client
{ {
public: 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<i2p::client::ClientDestination> localDestination, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip); uint16_t remotePort, bool gzip);
~I2PUDPClientTunnel(); ~I2PUDPClientTunnel ();
void Start();
const char * GetName() const { return m_Name.c_str(); } void Start ();
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions(); void Stop ();
const char * GetName () const { return m_Name.c_str(); }
std::vector<std::shared_ptr<DatagramSessionInfo> > 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<ClientDestination> GetLocalDestination () const { return m_LocalDest; } std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); inline void SetLocalDestination (std::shared_ptr<ClientDestination> 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: private:
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo; typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal(); void RecvFromLocal ();
void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); 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 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 HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void TryResolving(); void TryResolving ();
private: private:
@ -302,11 +314,12 @@ namespace client
const boost::asio::ip::udp::endpoint m_LocalEndpoint; const boost::asio::ip::udp::endpoint m_LocalEndpoint;
i2p::data::IdentHash * m_RemoteIdent; i2p::data::IdentHash * m_RemoteIdent;
std::thread * m_ResolveThread; std::thread * m_ResolveThread;
boost::asio::ip::udp::socket m_LocalSocket; std::unique_ptr<boost::asio::ip::udp::socket> m_LocalSocket;
boost::asio::ip::udp::endpoint m_RecvEndpoint; boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
uint16_t RemotePort, m_LastPort; uint16_t RemotePort, m_LastPort;
bool m_cancel_resolve; bool m_cancel_resolve;
bool m_Gzip;
std::shared_ptr<UDPConvo> m_LastSession; std::shared_ptr<UDPConvo> m_LastSession;
public: public:

Loading…
Cancel
Save