diff --git a/Garlic.cpp b/Garlic.cpp index d1c580cd..2757b4d9 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -139,21 +139,20 @@ namespace garlic I2NPMessage * GarlicRouting::WrapSingleMessage (const i2p::data::RoutingDestination * destination, I2NPMessage * msg) { if (!destination) return nullptr; - std::string dest ((const char *)destination->GetIdentHash (), 32); - auto it = m_Sessions.find (dest); + auto it = m_Sessions.find (destination->GetIdentHash ()); GarlicRoutingSession * session = nullptr; if (it != m_Sessions.end ()) session = it->second; if (!session) { session = new GarlicRoutingSession (destination, 4); // TODO: change it later - m_Sessions[dest] = session; + m_Sessions[destination->GetIdentHash ()] = session; } I2NPMessage * ret = session->WrapSingleMessage (msg); if (session->GetNumRemainingSessionTags () <= 0) { - m_Sessions.erase (dest); + m_Sessions.erase (destination->GetIdentHash ()); delete session; } return ret; diff --git a/Garlic.h b/Garlic.h index cda55a04..2116dc56 100644 --- a/Garlic.h +++ b/Garlic.h @@ -69,7 +69,7 @@ namespace garlic private: - std::map m_Sessions; + std::map m_Sessions; }; extern GarlicRouting routing; diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index b88172bb..ddf4f43b 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -144,36 +144,6 @@ namespace i2p return m; } - void HandleDatabaseStoreMsg (uint8_t * buf, size_t len) - { - I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)buf; - size_t offset = sizeof (I2NPDatabaseStoreMsg); - if (msg->replyToken) - offset += 36; - if (msg->type) - { - LogPrint ("LeaseSet"); - i2p::data::netdb.AddLeaseSet (buf + offset, len - offset); - } - else - { - LogPrint ("RouterInfo"); - size_t size = be16toh (*(uint16_t *)(buf + offset)); - if (size > 2048) - { - LogPrint ("Invalid RouterInfo length ", (int)size); - return; - } - offset += 2; - CryptoPP::Gunzip decompressor; - decompressor.Put (buf + offset, size); - decompressor.MessageEnd(); - uint8_t uncompressed[2048]; - int uncomressedSize = decompressor.MaxRetrievable (); - decompressor.Get (uncompressed, uncomressedSize); - i2p::data::netdb.AddRouterInfo (uncompressed, uncomressedSize); - } - } I2NPBuildRequestRecordClearText CreateBuildRequestRecord ( const uint8_t * ourIdent, uint32_t receiveTunnelID, @@ -204,7 +174,7 @@ namespace i2p I2NPBuildRequestRecordElGamalEncrypted& record) { i2p::crypto::ElGamalEncrypt (router.GetRouterIdentity ().publicKey, (uint8_t *)&clearText, sizeof(clearText), record.encrypted); - memcpy (record.toPeer, router.GetIdentHash (), 16); + memcpy (record.toPeer, (const uint8_t *)router.GetIdentHash (), 16); } void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) @@ -233,7 +203,7 @@ namespace i2p I2NPBuildRequestRecordElGamalEncrypted * records = (I2NPBuildRequestRecordElGamalEncrypted *)(buf+1); for (int i = 0; i < num; i++) { - if (!memcmp (records[i].toPeer, i2p::context.GetRouterInfo ().GetIdentHash (), 16)) + if (!memcmp (records[i].toPeer, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) { LogPrint ("Record ",i," is ours"); @@ -241,7 +211,7 @@ namespace i2p i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKey (), records[i].encrypted, (uint8_t *)&clearText); i2p::tunnel::TransitTunnel * transitTunnel = - new i2p::tunnel::TransitTunnel ( + i2p::tunnel::CreateTransitTunnel ( be32toh (clearText.receiveTunnel), clearText.nextIdent, be32toh (clearText.nextTunnel), clearText.layerKey, clearText.ivKey, @@ -303,8 +273,8 @@ namespace i2p I2NPMessage * CreateTunnelDataMsg (const uint8_t * buf) { I2NPMessage * msg = NewI2NPMessage (); - memcpy (msg->GetPayload (), buf, 1028); - msg->len += 1028; + memcpy (msg->GetPayload (), buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); + msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; FillI2NPMessageHeader (msg, eI2NPTunnelData); return msg; } @@ -312,9 +282,9 @@ namespace i2p I2NPMessage * CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) { I2NPMessage * msg = NewI2NPMessage (); - memcpy (msg->GetPayload () + 4, payload, 1024); + memcpy (msg->GetPayload () + 4, payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4); *(uint32_t *)(msg->GetPayload ()) = htobe32 (tunnelID); - msg->len += 1028; + msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; FillI2NPMessageHeader (msg, eI2NPTunnelData); return msg; } diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 3bfefbb2..b97312b0 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -108,7 +108,6 @@ namespace i2p uint32_t replyTunnelID, bool exploratory = false); I2NPMessage * CreateDatabaseStoreMsg (); - void HandleDatabaseStoreMsg (uint8_t * buf, size_t len); I2NPBuildRequestRecordClearText CreateBuildRequestRecord ( const uint8_t * ourIdent, uint32_t receiveTunnelID, diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 24d5ac0e..b52a6223 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -20,7 +20,7 @@ namespace i2p { namespace ntcp { - NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouterInfo): + NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo * in_RemoteRouterInfo): m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false), m_ReceiveBufferOffset (0), m_NextMessage (nullptr) { @@ -521,7 +521,7 @@ namespace ntcp NTCPClient::NTCPClient (boost::asio::io_service& service, const char * address, - int port, const i2p::data::RouterInfo& in_RouterInfo): NTCPSession (service, &in_RouterInfo), + int port, i2p::data::RouterInfo& in_RouterInfo): NTCPSession (service, &in_RouterInfo), m_Endpoint (boost::asio::ip::address::from_string (address), port) { Connect (); @@ -539,6 +539,7 @@ namespace ntcp if (ecode) { LogPrint ("Connect error: ", ecode.message ()); + GetRemoteRouterInfo ().SetUnreachable (true); Terminate (); } else diff --git a/NetDb.cpp b/NetDb.cpp index ae987d4b..a4925353 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -319,7 +319,8 @@ namespace data RouterInfo * last = nullptr; for (auto it: m_RouterInfos) { - if (it.second->IsNTCP () && (!floodfillOnly || it.second->IsFloodfill ())) + if (it.second->IsNTCP () && !it.second->IsUnreachable () && + (!floodfillOnly || it.second->IsFloodfill ())) last = it.second; if (i >= ind) break; else i++; diff --git a/RouterContext.cpp b/RouterContext.cpp index 371f63e3..b6b4e9c4 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -40,14 +40,27 @@ namespace i2p m_RouterInfo.AddNTCPAddress ("127.0.0.1", 17007); // TODO: m_RouterInfo.SetProperty ("caps", "LR"); - m_RouterInfo.SetProperty ("coreVersion", "0.9.7"); + m_RouterInfo.SetProperty ("coreVersion", "0.9.8.1"); m_RouterInfo.SetProperty ("netId", "2"); - m_RouterInfo.SetProperty ("router.version", "0.9.7"); + m_RouterInfo.SetProperty ("router.version", "0.9.8.1"); m_RouterInfo.SetProperty ("start_uptime", "90m"); m_RouterInfo.CreateBuffer (); } + void RouterContext::OverrideNTCPAddress (const char * host, int port) + { + m_RouterInfo.CreateBuffer (); + auto address = m_RouterInfo.GetNTCPAddress (); + if (address) + { + address->host = host; + address->port = port; + } + + m_RouterInfo.CreateBuffer (); + } + void RouterContext::Sign (uint8_t * buf, int len, uint8_t * signature) { CryptoPP::DSA::Signer signer (m_SigningPrivateKey); diff --git a/RouterContext.h b/RouterContext.h index 5ec89057..a292b1cb 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -24,6 +24,8 @@ namespace i2p CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; }; void Sign (uint8_t * buf, int len, uint8_t * signature); + + void OverrideNTCPAddress (const char * host, int port); // temporary private: diff --git a/RouterInfo.cpp b/RouterInfo.cpp index efc6a5bd..4c85626f 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -17,7 +17,7 @@ namespace i2p namespace data { RouterInfo::RouterInfo (const char * filename): - m_IsUpdated (false) + m_IsUpdated (false), m_IsUnreachable (false) { ReadFromFile (filename); } diff --git a/RouterInfo.h b/RouterInfo.h index ed947ab9..8787ca32 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -62,6 +62,8 @@ namespace data const char * GetProperty (const char * key) const; bool IsFloodfill () const; bool IsNTCP () const; + void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; + bool IsUnreachable () const { return m_IsUnreachable; }; void CreateBuffer (); const char * GetBuffer () const { return m_Buffer; }; @@ -94,7 +96,7 @@ namespace data uint64_t m_Timestamp; std::vector
m_Addresses; std::map m_Properties; - bool m_IsUpdated; + bool m_IsUpdated, m_IsUnreachable; }; } } diff --git a/Timestamp.h b/Timestamp.h index f1775dcb..f70bb97f 100644 --- a/Timestamp.h +++ b/Timestamp.h @@ -19,6 +19,12 @@ namespace util return std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count (); } + + inline uint32_t GetSecondsSinceEpoch () + { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count (); + } } } diff --git a/Transports.h b/Transports.h index 90b1704a..ea5453cc 100644 --- a/Transports.h +++ b/Transports.h @@ -45,6 +45,11 @@ namespace i2p boost::asio::ip::tcp::acceptor * m_NTCPAcceptor; std::map m_NTCPSessions; + + public: + + // for HTTP only + const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; }; }; extern Transports transports; diff --git a/Tunnel.cpp b/Tunnel.cpp index 07f61161..d1e910f7 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -151,8 +151,8 @@ namespace tunnel Tunnels tunnels; - Tunnels::Tunnels (): m_IsRunning (false), m_IsTunnelCreated (false), m_NextReplyMsgID (555), - m_ZeroHopsInboundTunnel (nullptr), m_ZeroHopsOutboundTunnel (nullptr), m_Thread (0) + Tunnels::Tunnels (): m_IsRunning (false), m_IsTunnelCreated (false), + m_NextReplyMsgID (555),m_Thread (0) { } @@ -173,9 +173,6 @@ namespace tunnel for (auto& it : m_PendingTunnels) delete it.second; m_PendingTunnels.clear (); - - delete m_ZeroHopsInboundTunnel; - delete m_ZeroHopsOutboundTunnel; } InboundTunnel * Tunnels::GetInboundTunnel (uint32_t tunnelID) @@ -258,10 +255,6 @@ namespace tunnel void Tunnels::Run () { sleep (1); // wait for other parts are ready - - // we must start with zero hops tunnels - CreateZeroHopsInboundTunnel (); - CreateZeroHopsOutboundTunnel (); uint32_t lastTs = 0; while (m_IsRunning) @@ -314,8 +307,8 @@ namespace tunnel } m_PendingTunnels.clear (); - ManageOutboundTunnels (); ManageInboundTunnels (); + ManageOutboundTunnels (); /* if (!m_IsTunnelCreated) { @@ -347,10 +340,9 @@ namespace tunnel if (m_OutboundTunnels.size () < 10) { // trying to create one more oubound tunnel - InboundTunnel * inboundTunnel = m_ZeroHopsInboundTunnel; - if (!m_InboundTunnels.empty ()) - inboundTunnel = m_InboundTunnels.rbegin ()->second; - + if (m_InboundTunnels.empty ()) return; + + InboundTunnel * inboundTunnel = GetNextInboundTunnel (); if (m_OutboundTunnels.empty () || m_OutboundTunnels.size () < 3) { LogPrint ("Creating one hop outbound tunnel..."); @@ -360,10 +352,10 @@ namespace tunnel } else { - OutboundTunnel * outboundTunnel = *m_OutboundTunnels.begin (); + OutboundTunnel * outboundTunnel = GetNextOutboundTunnel (); LogPrint ("Creating two hops outbound tunnel..."); CreateTunnel ( - new TunnelConfig (inboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router, + new TunnelConfig (i2p::data::netdb.GetRandomNTCPRouter (), i2p::data::netdb.GetRandomNTCPRouter (), inboundTunnel->GetTunnelConfig ()), outboundTunnel); @@ -384,6 +376,13 @@ namespace tunnel else it++; } + + if (m_InboundTunnels.empty ()) + { + LogPrint ("Creating zero hops inbound tunnel..."); + CreateZeroHopsInboundTunnel (); + return; + } if (m_InboundTunnels.size () < 10) { @@ -395,12 +394,11 @@ namespace tunnel } else { - OutboundTunnel * outboundTunnel = *m_OutboundTunnels.rbegin (); - InboundTunnel * inboundTunnel = m_InboundTunnels.rbegin ()->second; + OutboundTunnel * outboundTunnel = GetNextOutboundTunnel (); LogPrint ("Creating two hops inbound tunnel..."); CreateTunnel ( new TunnelConfig (i2p::data::netdb.GetRandomNTCPRouter (), - inboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router), + outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router), outboundTunnel); } } @@ -423,26 +421,20 @@ namespace tunnel void Tunnels::AddOutboundTunnel (OutboundTunnel * newTunnel) { - if (newTunnel != m_ZeroHopsOutboundTunnel) - m_OutboundTunnels.push_back (newTunnel); + m_OutboundTunnels.push_back (newTunnel); } void Tunnels::AddInboundTunnel (InboundTunnel * newTunnel) { - if (newTunnel != m_ZeroHopsInboundTunnel) - m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; + m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; + // build symmetric outbound tunnel + CreateTunnel (newTunnel->GetTunnelConfig ()->Invert (), GetNextOutboundTunnel ()); } - void Tunnels::CreateZeroHopsOutboundTunnel () - { - m_ZeroHopsOutboundTunnel = CreateTunnel ( - new TunnelConfig (&i2p::context.GetRouterInfo (), - m_ZeroHopsInboundTunnel->GetTunnelConfig ())); - } void Tunnels::CreateZeroHopsInboundTunnel () { - m_ZeroHopsInboundTunnel = CreateTunnel ( + CreateTunnel ( new TunnelConfig (&i2p::context.GetRouterInfo ())); } diff --git a/Tunnel.h b/Tunnel.h index a2d72355..9ecf6ff3 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -129,7 +129,6 @@ namespace tunnel void ManageOutboundTunnels (); void ManageInboundTunnels (); - void CreateZeroHopsOutboundTunnel (); void CreateZeroHopsInboundTunnel (); private: @@ -137,8 +136,6 @@ namespace tunnel bool m_IsRunning; bool m_IsTunnelCreated; // TODO: temporary uint32_t m_NextReplyMsgID; // TODO: make it random later - InboundTunnel * m_ZeroHopsInboundTunnel; - OutboundTunnel * m_ZeroHopsOutboundTunnel; std::thread * m_Thread; std::map m_PendingTunnels; // by replyMsgID std::map m_InboundTunnels; @@ -151,6 +148,7 @@ namespace tunnel // for HTTP only const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }; const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; + const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; }; }; extern Tunnels tunnels; diff --git a/TunnelBase.h b/TunnelBase.h index 6f86376b..829270ce 100644 --- a/TunnelBase.h +++ b/TunnelBase.h @@ -9,6 +9,7 @@ namespace i2p namespace tunnel { const size_t TUNNEL_DATA_MSG_SIZE = 1028; + const size_t TUNNEL_DATA_ENCRYPTED_SIZE = 1008; const size_t TUNNEL_DATA_MAX_PAYLOAD_SIZE = 1003; enum TunnelDeliveryType @@ -29,9 +30,11 @@ namespace tunnel { public: + virtual ~TunnelBase () {}; + virtual void EncryptTunnelMsg (I2NPMessage * tunnelMsg) = 0; virtual uint32_t GetNextTunnelID () const = 0; - virtual const uint8_t * GetNextIdentHash () const = 0; + virtual const i2p::data::IdentHash& GetNextIdentHash () const = 0; }; } } diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index 4c7a0749..9cf1917a 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -10,13 +10,15 @@ namespace tunnel { void TunnelEndpoint::HandleDecryptedTunnelDataMsg (I2NPMessage * msg) { + m_NumReceivedBytes += TUNNEL_DATA_MSG_SIZE; + uint8_t * decrypted = msg->GetPayload () + 20; // 4 + 16 - uint8_t * zero = (uint8_t *)memchr (decrypted + 4, 0, 1004); // witout checksum + uint8_t * zero = (uint8_t *)memchr (decrypted + 4, 0, TUNNEL_DATA_ENCRYPTED_SIZE - 4); // witout 4-byte checksum if (zero) { LogPrint ("TunnelMessage: zero found at ", (int)(zero-decrypted)); uint8_t * fragment = zero + 1; - while (fragment < decrypted + 1008) + while (fragment < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) { uint8_t flag = fragment[0]; fragment++; @@ -77,7 +79,7 @@ namespace tunnel msg->offset = fragment - msg->buf; msg->len = msg->offset + size; bool isLastMessage = false; - if (fragment + size < decrypted + 1008) + if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) { // this is not last message. we have to copy it m.data = NewI2NPMessage (); @@ -140,6 +142,7 @@ namespace tunnel void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) { + LogPrint ("TunnelMessage: handle fragment of ", msg.data->GetLength ()," bytes"); switch (msg.deliveryType) { case eDeliveryTypeLocal: @@ -152,7 +155,7 @@ namespace tunnel i2p::transports.SendMessage (msg.hash, msg.data); break; default: - ; + LogPrint ("TunnelMessage: Unknown delivery type ", (int)msg.deliveryType); }; } } diff --git a/TunnelEndpoint.h b/TunnelEndpoint.h index 405780df..b18f204b 100644 --- a/TunnelEndpoint.h +++ b/TunnelEndpoint.h @@ -15,6 +15,9 @@ namespace tunnel { public: + TunnelEndpoint (): m_NumReceivedBytes (0) {}; + size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; + void HandleDecryptedTunnelDataMsg (I2NPMessage * msg); private: @@ -24,6 +27,7 @@ namespace tunnel private: std::map m_IncompleteMessages; + size_t m_NumReceivedBytes; }; } }