diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp
index e32bd459..2ac636ce 100644
--- a/daemon/HTTPServer.cpp
+++ b/daemon/HTTPServer.cpp
@@ -826,7 +826,7 @@ namespace http {
if (i2p::tunnel::tunnels.CountTransitTunnels())
{
s << "" << tr("Transit Tunnels") << ":
\r\n";
- s << "
⇒ | ID | ⇒ | " << tr("Amount") << " | ";
+ s << "⇒ | ID | ⇒ | " << tr("Amount") << " | " << tr("Next") << " | ";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
{
if (std::dynamic_pointer_cast(it))
@@ -836,7 +836,7 @@ namespace http {
else
s << "⇒ | " << it->GetTunnelID () << " | ⇒ | ";
ShowTraffic(s, it->GetNumTransmittedBytes ());
- s << " |
\r\n";
+ s << "" << it->GetNextPeerName () << " | \r\n";
}
s << "
\r\n";
}
diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp
index 76b056cf..5ab577c0 100644
--- a/libi2pd/NTCP2.cpp
+++ b/libi2pd/NTCP2.cpp
@@ -1435,6 +1435,12 @@ namespace transport
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
}
+ i2p::data::RouterInfo::SupportedTransports NTCP2Session::GetTransportType () const
+ {
+ if (m_RemoteEndpoint.address ().is_v4 ()) return i2p::data::RouterInfo::eNTCP2V4;
+ return i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? i2p::data::RouterInfo::eNTCP2V6Mesh : i2p::data::RouterInfo::eNTCP2V6;
+ }
+
NTCP2Server::NTCP2Server ():
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
m_ProxyType(eNoProxy), m_Resolver(GetService ()),
diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h
index 5df4de6e..47354f32 100644
--- a/libi2pd/NTCP2.h
+++ b/libi2pd/NTCP2.h
@@ -147,6 +147,7 @@ namespace transport
void SetRemoteEndpoint (const boost::asio::ip::tcp::endpoint& ep) { m_RemoteEndpoint = ep; };
bool IsEstablished () const override { return m_IsEstablished; };
+ i2p::data::RouterInfo::SupportedTransports GetTransportType () const override;
bool IsTerminated () const { return m_IsTerminated; };
void ClientLogin (); // Alice
diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp
index 0d53f6cd..3c074031 100644
--- a/libi2pd/RouterInfo.cpp
+++ b/libi2pd/RouterInfo.cpp
@@ -1195,6 +1195,19 @@ namespace data
return false;
}
}
+
+ std::string RouterInfo::GetTransportName (SupportedTransports tr)
+ {
+ switch (tr)
+ {
+ case eNTCP2V4: return "NTCP2V4";
+ case eNTCP2V6: return "NTCP2V6";
+ case eSSU2V4: return "SSU2V4";
+ case eSSU2V6: return "SSU2V6";
+ case eNTCP2V6Mesh: return "Mesh";
+ default: return "";
+ }
+ }
void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys)
{
diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h
index beeba5bf..8d11f661 100644
--- a/libi2pd/RouterInfo.h
+++ b/libi2pd/RouterInfo.h
@@ -363,6 +363,10 @@ namespace data
int m_Version;
Congestion m_Congestion;
mutable std::shared_ptr m_Profile;
+
+ public:
+
+ static std::string GetTransportName (SupportedTransports tr);
};
class LocalRouterInfo: public RouterInfo
diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp
index 4196e785..284ab4d8 100644
--- a/libi2pd/SSU2Session.cpp
+++ b/libi2pd/SSU2Session.cpp
@@ -3114,5 +3114,10 @@ namespace transport
else if (!sent && !m_SentPackets.empty ()) // if only acks received, nothing sent and we still have something to resend
Resend (i2p::util::GetMillisecondsSinceEpoch ()); // than right time to resend
}
+
+ i2p::data::RouterInfo::SupportedTransports SSU2Session::GetTransportType () const
+ {
+ return m_RemoteEndpoint.address ().is_v4 () ? i2p::data::RouterInfo::eSSU2V4 : i2p::data::RouterInfo::eSSU2V6;
+ }
}
}
diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h
index 4b3139a7..acd46dd1 100644
--- a/libi2pd/SSU2Session.h
+++ b/libi2pd/SSU2Session.h
@@ -267,6 +267,7 @@ namespace transport
size_t Resend (uint64_t ts); // return number of resent packets
uint64_t GetLastResendTime () const { return m_LastResendTime; };
bool IsEstablished () const override { return m_State == eSSU2SessionStateEstablished; };
+ i2p::data::RouterInfo::SupportedTransports GetTransportType () const override;
uint64_t GetConnID () const { return m_SourceConnID; };
SSU2SessionState GetState () const { return m_State; };
void SetState (SSU2SessionState state) { m_State = state; };
diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp
index 7dbed003..3d3f20f2 100644
--- a/libi2pd/TransitTunnel.cpp
+++ b/libi2pd/TransitTunnel.cpp
@@ -10,6 +10,8 @@
#include "I2PEndian.h"
#include "Crypto.h"
#include "Log.h"
+#include "Identity.h"
+#include "RouterInfo.h"
#include "RouterContext.h"
#include "I2NPProtocol.h"
#include "Garlic.h"
@@ -41,6 +43,21 @@ namespace tunnel
i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE);
}
+ std::string TransitTunnel::GetNextPeerName () const
+ {
+ return i2p::data::GetIdentHashAbbreviation (GetNextIdentHash ());
+ }
+
+ void TransitTunnel::SendTunnelDataMsg (std::shared_ptr msg)
+ {
+ LogPrint (eLogError, "TransitTunnel: We are not a gateway for ", GetTunnelID ());
+ }
+
+ void TransitTunnel::HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg)
+ {
+ LogPrint (eLogError, "TransitTunnel: Incoming tunnel message is not supported ", GetTunnelID ());
+ }
+
TransitTunnelParticipant::~TransitTunnelParticipant ()
{
}
@@ -67,16 +84,18 @@ namespace tunnel
}
}
- void TransitTunnel::SendTunnelDataMsg (std::shared_ptr msg)
+ std::string TransitTunnelParticipant::GetNextPeerName () const
{
- LogPrint (eLogError, "TransitTunnel: We are not a gateway for ", GetTunnelID ());
- }
-
- void TransitTunnel::HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg)
- {
- LogPrint (eLogError, "TransitTunnel: Incoming tunnel message is not supported ", GetTunnelID ());
- }
-
+ if (m_Sender)
+ {
+ auto transport = m_Sender->GetCurrentTransport ();
+ if (transport)
+ return TransitTunnel::GetNextPeerName () + "-" +
+ i2p::data::RouterInfo::GetTransportName (transport->GetTransportType ());
+ }
+ return TransitTunnel::GetNextPeerName ();
+ }
+
void TransitTunnelGateway::SendTunnelDataMsg (std::shared_ptr msg)
{
TunnelMessageBlock block;
@@ -92,6 +111,19 @@ namespace tunnel
m_Gateway.SendBuffer ();
}
+ std::string TransitTunnelGateway::GetNextPeerName () const
+ {
+ const auto& sender = m_Gateway.GetSender ();
+ if (sender)
+ {
+ auto transport = sender->GetCurrentTransport ();
+ if (transport)
+ return TransitTunnel::GetNextPeerName () + "-" +
+ i2p::data::RouterInfo::GetTransportName (transport->GetTransportType ());
+ }
+ return TransitTunnel::GetNextPeerName ();
+ }
+
void TransitTunnelEndpoint::HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg)
{
auto newMsg = CreateEmptyTunnelDataMsg (true);
diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h
index 89653931..58aba35b 100644
--- a/libi2pd/TransitTunnel.h
+++ b/libi2pd/TransitTunnel.h
@@ -33,11 +33,13 @@ namespace tunnel
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey);
virtual size_t GetNumTransmittedBytes () const { return 0; };
+ virtual std::string GetNextPeerName () const;
// implements TunnelBase
void SendTunnelDataMsg (std::shared_ptr msg) override;
void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override;
void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) override;
+
private:
i2p::crypto::AESKey m_LayerKey, m_IVKey;
@@ -56,6 +58,7 @@ namespace tunnel
~TransitTunnelParticipant ();
size_t GetNumTransmittedBytes () const override { return m_NumTransmittedBytes; };
+ std::string GetNextPeerName () const override;
void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override;
void FlushTunnelDataMsgs () override;
@@ -79,7 +82,8 @@ namespace tunnel
void SendTunnelDataMsg (std::shared_ptr msg) override;
void FlushTunnelDataMsgs () override;
size_t GetNumTransmittedBytes () const override { return m_Gateway.GetNumSentBytes (); };
-
+ std::string GetNextPeerName () const override;
+
private:
std::mutex m_SendMutex;
@@ -97,10 +101,11 @@ namespace tunnel
m_Endpoint (false) {}; // transit endpoint is always outbound
void Cleanup () override { m_Endpoint.Cleanup (); }
-
+
void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override;
size_t GetNumTransmittedBytes () const override { return m_Endpoint.GetNumReceivedBytes (); }
-
+ std::string GetNextPeerName () const override { return ""; }
+
private:
TunnelEndpoint m_Endpoint;
diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h
index 6c878d11..ef0044c0 100644
--- a/libi2pd/TransportSession.h
+++ b/libi2pd/TransportSession.h
@@ -151,6 +151,7 @@ namespace transport
};
virtual void SendI2NPMessages (std::list >& msgs) = 0;
virtual bool IsEstablished () const = 0;
+ virtual i2p::data::RouterInfo::SupportedTransports GetTransportType () const = 0;
private:
diff --git a/libi2pd/TunnelBase.cpp b/libi2pd/TunnelBase.cpp
index 031988a6..1f437758 100644
--- a/libi2pd/TunnelBase.cpp
+++ b/libi2pd/TunnelBase.cpp
@@ -60,5 +60,11 @@ namespace tunnel
msgs.swap (msgs1);
SendMessagesTo (to, std::move (msgs1));
}
+
+ void TunnelTransportSender::Reset ()
+ {
+ m_CurrentTransport.reset ();
+ m_PendingTransport = std::future >();
+ }
}
}
diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h
index 91d0fafc..39d6e780 100644
--- a/libi2pd/TunnelBase.h
+++ b/libi2pd/TunnelBase.h
@@ -93,6 +93,9 @@ namespace tunnel
void SendMessagesTo (const i2p::data::IdentHash& to, std::list >&& msgs);
void SendMessagesTo (const i2p::data::IdentHash& to, std::list >& msgs); // send and clear
+
+ std::shared_ptr GetCurrentTransport () const { return m_CurrentTransport.lock (); }
+ void Reset ();
private:
diff --git a/libi2pd/TunnelGateway.h b/libi2pd/TunnelGateway.h
index 292392ae..75f27581 100644
--- a/libi2pd/TunnelGateway.h
+++ b/libi2pd/TunnelGateway.h
@@ -51,6 +51,7 @@ namespace tunnel
void PutTunnelDataMsg (const TunnelMessageBlock& block);
void SendBuffer ();
size_t GetNumSentBytes () const { return m_NumSentBytes; };
+ const std::unique_ptr& GetSender () const { return m_Sender; };
private: