diff --git a/HTTPServer.cpp b/HTTPServer.cpp index bf0a3159..5a3e5190 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -71,6 +71,7 @@ namespace http { const char HTTP_PAGE_TRANSPORTS[] = "transports"; const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations"; const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination"; + const char HTTP_PAGE_I2CP_LOCAL_DESTINATION[] = "i2cp_local_destination"; const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions"; const char HTTP_PAGE_SAM_SESSION[] = "sam_session"; const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels"; @@ -86,7 +87,8 @@ namespace http { const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_ADDRESS[] = "address"; - void ShowUptime (std::stringstream& s, int seconds) { + static void ShowUptime (std::stringstream& s, int seconds) + { int num; if ((num = seconds / 86400) > 0) { @@ -104,7 +106,7 @@ namespace http { s << seconds << " seconds"; } - void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, int bytes) + static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, int bytes) { std::string state; switch (eState) { @@ -121,7 +123,7 @@ namespace http { s << " " << (int) (bytes / 1024) << " KiB
\r\n"; } - void ShowPageHead (std::stringstream& s) + static void ShowPageHead (std::stringstream& s) { s << "\r\n" @@ -156,7 +158,7 @@ namespace http { "
"; } - void ShowPageTail (std::stringstream& s) + static void ShowPageTail (std::stringstream& s) { s << "
\r\n" @@ -164,12 +166,12 @@ namespace http { "\r\n"; } - void ShowError(std::stringstream& s, const std::string& string) + static void ShowError(std::stringstream& s, const std::string& string) { s << "ERROR: " << string << "
\r\n"; } - void ShowStatus (std::stringstream& s) + static void ShowStatus (std::stringstream& s) { s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); @@ -265,18 +267,75 @@ namespace http { s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n"; } - void ShowLocalDestinations (std::stringstream& s) + static void ShowLocalDestinations (std::stringstream& s) { s << "Local Destinations:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetDestinations ()) { - auto ident = it.second->GetIdentHash ();; + auto ident = it.second->GetIdentHash (); s << ""; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; } + + auto i2cpServer = i2p::client::context.GetI2CPServer (); + if (i2cpServer) + { + s << "
I2CP Local Destinations:
\r\n
\r\n"; + for (auto& it: i2cpServer->GetSessions ()) + { + auto dest = it.second->GetDestination (); + if (dest) + { + auto ident = dest->GetIdentHash (); + s << ""; + s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; + } + } + } + } + + static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest) + { + s << "Base64:
\r\n
\r\n
\r\n"; + s << "LeaseSets: " << dest->GetNumRemoteLeaseSets () << "
\r\n"; + if(dest->GetNumRemoteLeaseSets()) + { + s << "
\r\n\r\n

\r\n"; + for(auto& it: dest->GetLeaseSets ()) + s << it.second->GetIdentHash ().ToBase32 () << "
\r\n"; + s << "

\r\n
\r\n"; + } + auto pool = dest->GetTunnelPool (); + if (pool) + { + s << "Inbound tunnels:
\r\n"; + for (auto & it : pool->GetInboundTunnels ()) { + it->Print(s); + if(it->LatencyIsKnown()) + s << " ( " << it->GetMeanLatency() << "ms )"; + ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ()); + } + s << "
\r\n"; + s << "Outbound tunnels:
\r\n"; + for (auto & it : pool->GetOutboundTunnels ()) { + it->Print(s); + if(it->LatencyIsKnown()) + s << " ( " << it->GetMeanLatency() << "ms )"; + ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); + } + } + s << "
\r\n"; + s << "Tags
Incoming: " << dest->GetNumIncomingTags () << "
Outgoing:
" << std::endl; + for (const auto& it: dest->GetSessions ()) + { + s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " "; + s << it.second->GetNumOutgoingTags () << "
" << std::endl; + } + s << "
" << std::endl; } - void ShowLocalDestination (std::stringstream& s, const std::string& b32) + static void ShowLocalDestination (std::stringstream& s, const std::string& b32) { s << "Local Destination:
\r\n
\r\n"; i2p::data::IdentHash ident; @@ -284,55 +343,8 @@ namespace http { auto dest = i2p::client::context.FindLocalDestination (ident); if (dest) { - s << "Base64:
\r\n
\r\n
\r\n"; - s << "LeaseSets: " << dest->GetNumRemoteLeaseSets () << "
\r\n"; - if(dest->GetNumRemoteLeaseSets()) - { - s << "
\r\n\r\n

\r\n"; - for(auto& it: dest->GetLeaseSets ()) - s << it.second->GetIdentHash ().ToBase32 () << "
\r\n"; - s << "

\r\n
\r\n"; - } - auto pool = dest->GetTunnelPool (); - if (pool) - { - s << "Inbound tunnels:
\r\n"; - for (auto & it : pool->GetInboundTunnels ()) { - it->Print(s); - if(it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << "ms )"; - ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ()); - } - s << "
\r\n"; - s << "Outbound tunnels:
\r\n"; - for (auto & it : pool->GetOutboundTunnels ()) { - it->Print(s); - if(it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << "ms )"; - ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); - } - } - s << "
\r\n"; - s << "Tags
Incoming: " << dest->GetNumIncomingTags () << "
Outgoing:
" << std::endl; - for (const auto& it: dest->GetSessions ()) - { - s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " "; - s << it.second->GetNumOutgoingTags () << "
" << std::endl; - } - s << "
" << std::endl; - // s << "
\r\nStreams:
\r\n"; - // for (auto it: dest->GetStreamingDestination ()->GetStreams ()) - // { - // s << it.first << "->" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetRemoteIdentity ()) << " "; - // s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; - // s << " [out:" << it.second->GetSendQueueSize () << "][in:" << it.second->GetReceiveQueueSize () << "]"; - // s << "[buf:" << it.second->GetSendBufferSize () << "]"; - // s << "[RTT:" << it.second->GetRTT () << "]"; - // s << "[Window:" << it.second->GetWindowSize () << "]"; - // s << "[Status:" << (int)it.second->GetStatus () << "]"; - // s << "
\r\n"<< std::endl; - // } + ShowLeaseSetDestination (s, dest); + // show streams s << "
\r\n"; s << ""; s << ""; @@ -365,7 +377,23 @@ namespace http { } } - void ShowLeasesSets(std::stringstream& s) + static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id) + { + auto i2cpServer = i2p::client::context.GetI2CPServer (); + if (i2cpServer) + { + s << "I2CP Local Destination:
\r\n
\r\n"; + auto it = i2cpServer->GetSessions ().find (std::stoi (id)); + if (it != i2cpServer->GetSessions ().end ()) + ShowLeaseSetDestination (s, it->second->GetDestination ()); + else + ShowError(s, "I2CP session not found"); + } + else + ShowError(s, "I2CP is not enabled"); + } + + static void ShowLeasesSets(std::stringstream& s) { s << "
LeaseSets (click on to show info):

\r\n"; int counter = 1; @@ -398,7 +426,7 @@ namespace http { // end for each lease set } - void ShowTunnels (std::stringstream& s) + static void ShowTunnels (std::stringstream& s) { s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n"; @@ -420,7 +448,7 @@ namespace http { s << "
\r\n"; } - void ShowCommands (std::stringstream& s) + static void ShowCommands (std::stringstream& s) { /* commands */ s << "Router Commands
\r\n"; @@ -442,7 +470,7 @@ namespace http { s << " Force shutdown
\r\n"; } - void ShowTransitTunnels (std::stringstream& s) + static void ShowTransitTunnels (std::stringstream& s) { s << "Transit tunnels:
\r\n
\r\n"; for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) @@ -457,7 +485,7 @@ namespace http { } } - void ShowTransports (std::stringstream& s) + static void ShowTransports (std::stringstream& s) { s << "Transports:
\r\n
\r\n"; auto ntcpServer = i2p::transport::transports.GetNTCPServer (); @@ -506,7 +534,7 @@ namespace http { } } - void ShowSAMSessions (std::stringstream& s) + static void ShowSAMSessions (std::stringstream& s) { auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { @@ -521,7 +549,7 @@ namespace http { } } - void ShowSAMSession (std::stringstream& s, const std::string& id) + static void ShowSAMSession (std::stringstream& s, const std::string& id) { s << "SAM Session:
\r\n
\r\n"; auto sam = i2p::client::context.GetSAMBridge (); @@ -553,7 +581,7 @@ namespace http { } } - void ShowI2PTunnels (std::stringstream& s) + static void ShowI2PTunnels (std::stringstream& s) { s << "Client Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetClientTunnels ()) @@ -743,6 +771,8 @@ namespace http { ShowLocalDestinations (s); else if (page == HTTP_PAGE_LOCAL_DESTINATION) ShowLocalDestination (s, params["b32"]); + else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION) + ShowI2CPLocalDestination (s, params["i2cp_id"]); else if (page == HTTP_PAGE_SAM_SESSIONS) ShowSAMSessions (s); else if (page == HTTP_PAGE_SAM_SESSION) diff --git a/I2CP.cpp b/I2CP.cpp index e0139b9f..e9fb4335 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -346,6 +346,7 @@ namespace client void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) { RAND_bytes ((uint8_t *)&m_SessionID, 2); + m_Owner.InsertSession (shared_from_this ()); auto identity = std::make_shared(); size_t offset = identity->FromBuffer (buf, len); if (!offset) @@ -460,23 +461,23 @@ namespace client { i2p::data::IdentityEx identity; size_t identsize = identity.FromBuffer (buf + offset, len - offset); - if (identsize) - { - offset += identsize; - uint32_t payloadLen = bufbe32toh (buf + offset); - if (payloadLen + offset <= len) - { - offset += 4; - uint32_t nonce = bufbe32toh (buf + offset + payloadLen); - if (m_IsSendAccepted) - SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted - m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); - } - else - LogPrint(eLogError, "I2CP: cannot send message, too big"); - } - else - LogPrint(eLogError, "I2CP: invalid identity"); + if (identsize) + { + offset += identsize; + uint32_t payloadLen = bufbe32toh (buf + offset); + if (payloadLen + offset <= len) + { + offset += 4; + uint32_t nonce = bufbe32toh (buf + offset + payloadLen); + if (m_IsSendAccepted) + SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted + m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); + } + else + LogPrint(eLogError, "I2CP: cannot send message, too big"); + } + else + LogPrint(eLogError, "I2CP: invalid identity"); } } else @@ -711,7 +712,6 @@ namespace client { LogPrint (eLogDebug, "I2CP: new connection from ", ep); auto session = std::make_shared(*this, socket); - m_Sessions[session->GetSessionID ()] = session; session->Start (); } else @@ -724,6 +724,17 @@ namespace client Accept (); } + bool I2CPServer::InsertSession (std::shared_ptr session) + { + if (!session) return false; + if (!m_Sessions.insert({session->GetSessionID (), session}).second) + { + LogPrint (eLogError, "I2CP: duplicate session id ", session->GetSessionID ()); + return false; + } + return true; + } + void I2CPServer::RemoveSession (uint16_t sessionID) { m_Sessions.erase (sessionID); diff --git a/I2CP.h b/I2CP.h index 4964c575..b55f43c1 100644 --- a/I2CP.h +++ b/I2CP.h @@ -112,6 +112,7 @@ namespace client void Start (); void Stop (); uint16_t GetSessionID () const { return m_SessionID; }; + std::shared_ptr GetDestination () const { return m_Destination; }; // called from I2CPDestination void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); @@ -173,6 +174,7 @@ namespace client void Stop (); boost::asio::io_service& GetService () { return m_Service; }; + bool InsertSession (std::shared_ptr session); void RemoveSession (uint16_t sessionID); private: @@ -196,6 +198,9 @@ namespace client public: const decltype(m_MessagesHandlers)& GetMessagesHandlers () const { return m_MessagesHandlers; }; + + // for HTTP + const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; }; } }
Streams
StreamIDDestination