From a8871d9f98f6c3defa00534c6ce92fec82904585 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 20 Oct 2014 15:19:56 -0400 Subject: [PATCH 01/35] moved DHKeysPair to Transport --- Identity.cpp | 9 --------- Identity.h | 15 ++------------- NTCPSession.h | 5 ++++- SSU.h | 4 +++- Transports.cpp | 28 ++++++++++++++++++---------- Transports.h | 20 ++++++++++++++------ 6 files changed, 41 insertions(+), 40 deletions(-) diff --git a/Identity.cpp b/Identity.cpp index 67bdd900..24a7f50c 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include "base64.h" #include "CryptoConst.h" @@ -293,14 +292,6 @@ namespace data return keys; } - void CreateRandomDHKeysPair (DHKeysPair * keys) - { - if (!keys) return; - CryptoPP::AutoSeededRandomPool rnd; - CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); - dh.GenerateKeyPair(rnd, keys->privateKey, keys->publicKey); - } - IdentHash CreateRoutingKey (const IdentHash& ident) { uint8_t buf[41]; // ident + yyyymmdd diff --git a/Identity.h b/Identity.h index 290422ea..b839832d 100644 --- a/Identity.h +++ b/Identity.h @@ -67,13 +67,6 @@ namespace data typedef Tag<32> IdentHash; #pragma pack(1) - - struct DHKeysPair // transient keys for transport sessions - { - uint8_t publicKey[256]; - uint8_t privateKey[256]; - }; - struct Keys { uint8_t privateKey[256]; @@ -81,7 +74,8 @@ namespace data uint8_t publicKey[256]; uint8_t signingKey[128]; }; - +#pragma pack() + Keys CreateRandomKeys (); const uint8_t CERTIFICATE_TYPE_NULL = 0; const uint8_t CERTIFICATE_TYPE_HASHCASH = 1; @@ -183,11 +177,6 @@ namespace data uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes i2p::crypto::Signer * m_Signer; }; - -#pragma pack() - - Keys CreateRandomKeys (); - void CreateRandomDHKeysPair (DHKeysPair * keys); // for transport sessions // kademlia struct XORMetric diff --git a/NTCPSession.h b/NTCPSession.h index 363a81cf..51215c38 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -14,6 +14,8 @@ namespace i2p { + class DHKeysPair; + namespace ntcp { @@ -65,6 +67,7 @@ namespace ntcp const size_t NTCP_MAX_MESSAGE_SIZE = 16384; const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028) const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes + class NTCPSession { public: @@ -127,7 +130,7 @@ namespace ntcp boost::asio::ip::tcp::socket m_Socket; boost::asio::deadline_timer m_TerminationTimer; bool m_IsEstablished; - i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server + DHKeysPair * m_DHKeysPair; // X - for client and Y - for server i2p::crypto::CBCDecryption m_Decryption; i2p::crypto::CBCEncryption m_Encryption; diff --git a/SSU.h b/SSU.h index f69f8c4e..d14fc4c4 100644 --- a/SSU.h +++ b/SSU.h @@ -17,6 +17,8 @@ namespace i2p { + class DHKeysPair; + namespace ssu { #pragma pack(1) @@ -131,7 +133,7 @@ namespace ssu const i2p::data::RouterInfo * m_RemoteRouter; i2p::data::IdentHash m_RemoteIdent; // if m_RemoteRouter is null boost::asio::deadline_timer m_Timer; - i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server + DHKeysPair * m_DHKeysPair; // X - for client and Y - for server bool m_PeerTest; SessionState m_State; bool m_IsSessionKey; diff --git a/Transports.cpp b/Transports.cpp index a49923c1..d5e2aefd 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -1,5 +1,7 @@ +#include #include #include "Log.h" +#include "CryptoConst.h" #include "RouterContext.h" #include "I2NPProtocol.h" #include "NetDb.h" @@ -9,6 +11,11 @@ using namespace i2p::data; namespace i2p { + DHKeysPairSupplier::DHKeysPairSupplier (int size): + m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) + { + } + DHKeysPairSupplier::~DHKeysPairSupplier () { Stop (); @@ -48,17 +55,18 @@ namespace i2p { if (num > 0) { + CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); for (int i = 0; i < num; i++) { - i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair (); - i2p::data::CreateRandomDHKeysPair (pair); + DHKeysPair * pair = new DHKeysPair (); + dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey); std::unique_lock l(m_AcquiredMutex); m_Queue.push (pair); } } } - i2p::data::DHKeysPair * DHKeysPairSupplier::Acquire () + DHKeysPair * DHKeysPairSupplier::Acquire () { if (!m_Queue.empty ()) { @@ -70,13 +78,14 @@ namespace i2p } else // queue is empty, create new { - i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair (); - i2p::data::CreateRandomDHKeysPair (pair); + DHKeysPair * pair = new DHKeysPair (); + CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); + dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey); return pair; } } - void DHKeysPairSupplier::Return (i2p::data::DHKeysPair * pair) + void DHKeysPairSupplier::Return (DHKeysPair * pair) { std::unique_lock l(m_AcquiredMutex); m_Queue.push (pair); @@ -318,14 +327,13 @@ namespace i2p m_SSUServer->GetSession (router, true); // peer test } } - - - i2p::data::DHKeysPair * Transports::GetNextDHKeysPair () + + DHKeysPair * Transports::GetNextDHKeysPair () { return m_DHKeysPairSupplier.Acquire (); } - void Transports::ReuseDHKeysPair (i2p::data::DHKeysPair * pair) + void Transports::ReuseDHKeysPair (DHKeysPair * pair) { m_DHKeysPairSupplier.Return (pair); } diff --git a/Transports.h b/Transports.h index 88f43b26..f740a8f7 100644 --- a/Transports.h +++ b/Transports.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "NTCPSession.h" #include "SSU.h" @@ -17,16 +18,22 @@ namespace i2p { + struct DHKeysPair // transient keys for transport sessions + { + uint8_t publicKey[256]; + uint8_t privateKey[256]; + }; + class DHKeysPairSupplier { public: - DHKeysPairSupplier (int size): m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) {}; + DHKeysPairSupplier (int size); ~DHKeysPairSupplier (); void Start (); void Stop (); - i2p::data::DHKeysPair * Acquire (); - void Return (i2p::data::DHKeysPair * pair); + DHKeysPair * Acquire (); + void Return (DHKeysPair * pair); private: @@ -36,12 +43,13 @@ namespace i2p private: const int m_QueueSize; - std::queue m_Queue; + std::queue m_Queue; bool m_IsRunning; std::thread * m_Thread; std::condition_variable m_Acquired; std::mutex m_AcquiredMutex; + CryptoPP::AutoSeededRandomPool m_Rnd; }; class Transports @@ -55,8 +63,8 @@ namespace i2p void Stop (); boost::asio::io_service& GetService () { return m_Service; }; - i2p::data::DHKeysPair * GetNextDHKeysPair (); - void ReuseDHKeysPair (i2p::data::DHKeysPair * pair); + DHKeysPair * GetNextDHKeysPair (); + void ReuseDHKeysPair (DHKeysPair * pair); void AddNTCPSession (i2p::ntcp::NTCPSession * session); void RemoveNTCPSession (i2p::ntcp::NTCPSession * session); From c4dda06cdeddd1ae273f4004a931f0fa9cf97c8c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 20 Oct 2014 16:09:59 -0400 Subject: [PATCH 02/35] TransportSession added --- NTCPSession.cpp | 6 ++---- NTCPSession.h | 6 ++---- SSU.cpp | 5 ++--- SSU.h | 6 ++---- TransportSession.h | 30 ++++++++++++++++++++++++++++++ Transports.cpp | 12 ++++++------ Transports.h | 17 ++++++----------- 7 files changed, 50 insertions(+), 32 deletions(-) create mode 100644 TransportSession.h diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 5c9c8a8a..aabe7fd4 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -21,9 +21,8 @@ namespace ntcp { NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo): m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false), - m_DHKeysPair (nullptr), m_RemoteRouterInfo (in_RemoteRouterInfo), - m_ReceiveBufferOffset (0), m_NextMessage (nullptr), - m_NumSentBytes (0), m_NumReceivedBytes (0) + m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), + m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0) { m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); m_Establisher = new Establisher; @@ -32,7 +31,6 @@ namespace ntcp NTCPSession::~NTCPSession () { delete m_Establisher; - delete m_DHKeysPair; if (m_NextMessage) i2p::DeleteI2NPMessage (m_NextMessage); for (auto it :m_DelayedMessages) diff --git a/NTCPSession.h b/NTCPSession.h index 51215c38..adb69da6 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -11,11 +11,10 @@ #include "Identity.h" #include "RouterInfo.h" #include "I2NPProtocol.h" +#include "TransportSession.h" namespace i2p { - class DHKeysPair; - namespace ntcp { @@ -68,7 +67,7 @@ namespace ntcp const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028) const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes - class NTCPSession + class NTCPSession: public i2p::transport::TransportSession { public: @@ -130,7 +129,6 @@ namespace ntcp boost::asio::ip::tcp::socket m_Socket; boost::asio::deadline_timer m_TerminationTimer; bool m_IsEstablished; - DHKeysPair * m_DHKeysPair; // X - for client and Y - for server i2p::crypto::CBCDecryption m_Decryption; i2p::crypto::CBCEncryption m_Encryption; diff --git a/SSU.cpp b/SSU.cpp index b26b8319..ce4c37bd 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -18,7 +18,7 @@ namespace ssu SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, const i2p::data::RouterInfo * router, bool peerTest ): m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_RemoteRouter (router), - m_Timer (m_Server.GetService ()), m_DHKeysPair (nullptr), m_PeerTest (peerTest), + m_Timer (m_Server.GetService ()), m_PeerTest (peerTest), m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0), m_Data (*this), m_NumSentBytes (0), m_NumReceivedBytes (0) { @@ -28,8 +28,7 @@ namespace ssu } SSUSession::~SSUSession () - { - delete m_DHKeysPair; + { } void SSUSession::CreateAESandMacKey (const uint8_t * pubKey) diff --git a/SSU.h b/SSU.h index d14fc4c4..261494ab 100644 --- a/SSU.h +++ b/SSU.h @@ -13,12 +13,11 @@ #include "Identity.h" #include "RouterInfo.h" #include "I2NPProtocol.h" +#include "TransportSession.h" #include "SSUData.h" namespace i2p { - class DHKeysPair; - namespace ssu { #pragma pack(1) @@ -59,7 +58,7 @@ namespace ssu }; class SSUServer; - class SSUSession + class SSUSession: public i2p::transport::TransportSession { public: @@ -133,7 +132,6 @@ namespace ssu const i2p::data::RouterInfo * m_RemoteRouter; i2p::data::IdentHash m_RemoteIdent; // if m_RemoteRouter is null boost::asio::deadline_timer m_Timer; - DHKeysPair * m_DHKeysPair; // X - for client and Y - for server bool m_PeerTest; SessionState m_State; bool m_IsSessionKey; diff --git a/TransportSession.h b/TransportSession.h new file mode 100644 index 00000000..37b58fe8 --- /dev/null +++ b/TransportSession.h @@ -0,0 +1,30 @@ +#ifndef TRANSPORT_SESSION_H__ +#define TRANSPORT_SESSION_H__ + +#include + +namespace i2p +{ +namespace transport +{ + struct DHKeysPair // transient keys for transport sessions + { + uint8_t publicKey[256]; + uint8_t privateKey[256]; + }; + + class TransportSession + { + public: + + TransportSession (): m_DHKeysPair (nullptr) {}; + virtual ~TransportSession () { delete m_DHKeysPair; }; + + protected: + + DHKeysPair * m_DHKeysPair; // X - for client and Y - for server + }; +} +} + +#endif diff --git a/Transports.cpp b/Transports.cpp index d5e2aefd..590dfa77 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -58,7 +58,7 @@ namespace i2p CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); for (int i = 0; i < num; i++) { - DHKeysPair * pair = new DHKeysPair (); + i2p::transport::DHKeysPair * pair = new i2p::transport::DHKeysPair (); dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey); std::unique_lock l(m_AcquiredMutex); m_Queue.push (pair); @@ -66,7 +66,7 @@ namespace i2p } } - DHKeysPair * DHKeysPairSupplier::Acquire () + i2p::transport::DHKeysPair * DHKeysPairSupplier::Acquire () { if (!m_Queue.empty ()) { @@ -78,14 +78,14 @@ namespace i2p } else // queue is empty, create new { - DHKeysPair * pair = new DHKeysPair (); + i2p::transport::DHKeysPair * pair = new i2p::transport::DHKeysPair (); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey); return pair; } } - void DHKeysPairSupplier::Return (DHKeysPair * pair) + void DHKeysPairSupplier::Return (i2p::transport::DHKeysPair * pair) { std::unique_lock l(m_AcquiredMutex); m_Queue.push (pair); @@ -328,12 +328,12 @@ namespace i2p } } - DHKeysPair * Transports::GetNextDHKeysPair () + i2p::transport::DHKeysPair * Transports::GetNextDHKeysPair () { return m_DHKeysPairSupplier.Acquire (); } - void Transports::ReuseDHKeysPair (DHKeysPair * pair) + void Transports::ReuseDHKeysPair (i2p::transport::DHKeysPair * pair) { m_DHKeysPairSupplier.Return (pair); } diff --git a/Transports.h b/Transports.h index f740a8f7..aa9812e4 100644 --- a/Transports.h +++ b/Transports.h @@ -10,6 +10,7 @@ #include #include #include +#include "TransportSession.h" #include "NTCPSession.h" #include "SSU.h" #include "RouterInfo.h" @@ -18,12 +19,6 @@ namespace i2p { - struct DHKeysPair // transient keys for transport sessions - { - uint8_t publicKey[256]; - uint8_t privateKey[256]; - }; - class DHKeysPairSupplier { public: @@ -32,8 +27,8 @@ namespace i2p ~DHKeysPairSupplier (); void Start (); void Stop (); - DHKeysPair * Acquire (); - void Return (DHKeysPair * pair); + i2p::transport::DHKeysPair * Acquire (); + void Return (i2p::transport::DHKeysPair * pair); private: @@ -43,7 +38,7 @@ namespace i2p private: const int m_QueueSize; - std::queue m_Queue; + std::queue m_Queue; bool m_IsRunning; std::thread * m_Thread; @@ -63,8 +58,8 @@ namespace i2p void Stop (); boost::asio::io_service& GetService () { return m_Service; }; - DHKeysPair * GetNextDHKeysPair (); - void ReuseDHKeysPair (DHKeysPair * pair); + i2p::transport::DHKeysPair * GetNextDHKeysPair (); + void ReuseDHKeysPair (i2p::transport::DHKeysPair * pair); void AddNTCPSession (i2p::ntcp::NTCPSession * session); void RemoveNTCPSession (i2p::ntcp::NTCPSession * session); From 43a989872dd114c37b02b30cb17af99aa79903b7 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 20 Oct 2014 16:57:18 -0400 Subject: [PATCH 03/35] fixed typo --- Identity.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Identity.h b/Identity.h index b839832d..baa40106 100644 --- a/Identity.h +++ b/Identity.h @@ -74,8 +74,6 @@ namespace data uint8_t publicKey[256]; uint8_t signingKey[128]; }; -#pragma pack() - Keys CreateRandomKeys (); const uint8_t CERTIFICATE_TYPE_NULL = 0; const uint8_t CERTIFICATE_TYPE_HASHCASH = 1; @@ -99,7 +97,10 @@ namespace data Identity& operator=(const Keys& keys); size_t FromBuffer (const uint8_t * buf, size_t len); IdentHash Hash () const; - }; + }; +#pragma pack() + Keys CreateRandomKeys (); + const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; From 898c81b5d6caa3266196f67357948527ecbada6c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 20 Oct 2014 21:39:32 -0400 Subject: [PATCH 04/35] better packaging --- TunnelGateway.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/TunnelGateway.cpp b/TunnelGateway.cpp index be9c6a4b..c12c4519 100644 --- a/TunnelGateway.cpp +++ b/TunnelGateway.cpp @@ -12,8 +12,12 @@ namespace tunnel { void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block) { + bool messageCreated = false; if (!m_CurrentTunnelDataMsg) + { CreateCurrentTunnelDataMessage (); + messageCreated = true; + } // create delivery instructions uint8_t di[43]; // max delivery instruction length is 43 for tunnel @@ -33,7 +37,8 @@ namespace tunnel // create fragments I2NPMessage * msg = block.data; - if (diLen + msg->GetLength () + 2<= m_RemainingSize) + auto fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length + if (fullMsgLen <= m_RemainingSize) { // message fits. First and last fragment *(uint16_t *)(di + diLen) = htobe16 (msg->GetLength ()); @@ -48,6 +53,18 @@ namespace tunnel } else { + if (!messageCreated) // check if we should complete previous message + { + auto numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE; + // length of bytes don't fit full tunnel message + // every follow-on fragment adds 7 bytes + auto nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE; + if (!nonFit || nonFit > m_RemainingSize) + { + CompleteCurrentTunnelDataMessage (); + CreateCurrentTunnelDataMessage (); + } + } if (diLen + 6 <= m_RemainingSize) { // delivery instructions fit From 165af090b69544ac3a5ba1e66c64ecd038e6393a Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Oct 2014 07:44:48 -0400 Subject: [PATCH 05/35] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 695986e9..b9da1f3e 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,10 @@ $ ./i2p --host=YOUR_PUBLIC_IP The client should now reseed by itself. To visit an I2P page, you need to find the b32 address of your destination. -After that, go to the webconsole and add it behind the url. (Remove http:// and b32.i2p from the address) +After that, go to the webconsole and add it behind the url. (Remove http:// from the address) This should resulting in for example: -http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa +http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa.b32.i2p Options From 7b768ccb26a96b17cdf6ffb160519778339498cf Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Oct 2014 12:25:53 -0400 Subject: [PATCH 06/35] moved transports to 'transport' namespace --- Daemon.cpp | 4 ++-- HTTPServer.cpp | 4 ++-- I2NPProtocol.cpp | 11 ++++++----- NTCPSession.cpp | 18 +++++++++--------- NTCPSession.h | 4 ++-- NetDb.cpp | 10 ++++++---- SSU.cpp | 6 +++--- SSU.h | 4 ++-- SSUData.cpp | 2 +- SSUData.h | 2 +- TransitTunnel.cpp | 2 +- Transports.cpp | 34 +++++++++++++++++++--------------- Transports.h | 27 +++++++++++++++------------ Tunnel.cpp | 2 +- TunnelEndpoint.cpp | 4 ++-- TunnelGateway.cpp | 2 +- 16 files changed, 73 insertions(+), 63 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index 13f99db6..ea98378b 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -103,7 +103,7 @@ namespace i2p LogPrint("HTTP Server started"); i2p::data::netdb.Start(); LogPrint("NetDB started"); - i2p::transports.Start(); + i2p::transport::transports.Start(); LogPrint("Transports started"); i2p::tunnel::tunnels.Start(); LogPrint("Tunnels started"); @@ -120,7 +120,7 @@ namespace i2p LogPrint("Client stoped"); i2p::tunnel::tunnels.Stop(); LogPrint("Tunnels stoped"); - i2p::transports.Stop(); + i2p::transport::transports.Stop(); LogPrint("Transports stoped"); i2p::data::netdb.Stop(); LogPrint("NetDB stoped"); diff --git a/HTTPServer.cpp b/HTTPServer.cpp index b08948d1..93cfb528 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -699,7 +699,7 @@ namespace util void HTTPConnection::ShowTransports (std::stringstream& s) { s << "NTCP
"; - for (auto it: i2p::transports.GetNTCPSessions ()) + for (auto it: i2p::transport::transports.GetNTCPSessions ()) { // RouterInfo of incoming connection doesn't have address bool outgoing = it.second->GetRemoteRouterInfo ().GetNTCPAddress (); @@ -714,7 +714,7 @@ namespace util } s << std::endl; } - auto ssuServer = i2p::transports.GetSSUServer (); + auto ssuServer = i2p::transport::transports.GetSSUServer (); if (ssuServer) { s << "
SSU
"; diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 12ee678f..d4c6d71e 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -13,9 +13,10 @@ #include "Garlic.h" #include "I2NPProtocol.h" +using namespace i2p::transport; + namespace i2p { - I2NPMessage * NewI2NPMessage () { return new I2NPMessageBuffer(); @@ -353,13 +354,13 @@ namespace i2p if (clearText.flag & 0x40) // we are endpoint of outboud tunnel { // so we send it to reply tunnel - i2p::transports.SendMessage (clearText.nextIdent, + transports.SendMessage (clearText.nextIdent, CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), eI2NPVariableTunnelBuildReply, buf, len, be32toh (clearText.nextMessageID))); } else - i2p::transports.SendMessage (clearText.nextIdent, + transports.SendMessage (clearText.nextIdent, CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); } } @@ -373,13 +374,13 @@ namespace i2p if (clearText.flag & 0x40) // we are endpoint of outbound tunnel { // so we send it to reply tunnel - i2p::transports.SendMessage (clearText.nextIdent, + transports.SendMessage (clearText.nextIdent, CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), eI2NPTunnelBuildReply, buf, len, be32toh (clearText.nextMessageID))); } else - i2p::transports.SendMessage (clearText.nextIdent, + transports.SendMessage (clearText.nextIdent, CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); } } diff --git a/NTCPSession.cpp b/NTCPSession.cpp index aabe7fd4..a4a73dd4 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -17,14 +17,14 @@ using namespace i2p::crypto; namespace i2p { -namespace ntcp +namespace transport { NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo): m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false), m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0) { - m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); + m_DHKeysPair = transports.GetNextDHKeysPair (); m_Establisher = new Establisher; } @@ -77,12 +77,12 @@ namespace ntcp { m_IsEstablished = false; m_Socket.close (); - i2p::transports.RemoveNTCPSession (this); + transports.RemoveNTCPSession (this); int numDelayed = 0; for (auto it :m_DelayedMessages) { // try to send them again - i2p::transports.SendMessage (m_RemoteRouterInfo.GetIdentHash (), it); + transports.SendMessage (m_RemoteRouterInfo.GetIdentHash (), it); numDelayed++; } m_DelayedMessages.clear (); @@ -119,7 +119,7 @@ namespace ntcp void NTCPSession::ClientLogin () { if (!m_DHKeysPair) - m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); + m_DHKeysPair = transports.GetNextDHKeysPair (); // send Phase1 const uint8_t * x = m_DHKeysPair->publicKey; memcpy (m_Establisher->phase1.pubKey, x, 256); @@ -189,7 +189,7 @@ namespace ntcp void NTCPSession::SendPhase2 () { if (!m_DHKeysPair) - m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); + m_DHKeysPair = transports.GetNextDHKeysPair (); const uint8_t * y = m_DHKeysPair->publicKey; memcpy (m_Establisher->phase2.pubKey, y, 256); uint8_t xy[512]; @@ -238,7 +238,7 @@ namespace ntcp if (ecode != boost::asio::error::operation_aborted) { GetRemoteRouterInfo ().SetUnreachable (true); // this RouterInfo is not valid - i2p::transports.ReuseDHKeysPair (m_DHKeysPair); + transports.ReuseDHKeysPair (m_DHKeysPair); m_DHKeysPair = nullptr; Terminate (); } @@ -263,7 +263,7 @@ namespace ntcp if (memcmp (hxy, m_Establisher->phase2.encrypted.hxy, 32)) { LogPrint ("Incorrect hash"); - i2p::transports.ReuseDHKeysPair (m_DHKeysPair); + transports.ReuseDHKeysPair (m_DHKeysPair); m_DHKeysPair = nullptr; Terminate (); return ; @@ -635,7 +635,7 @@ namespace ntcp { LogPrint ("NTCP server session connected"); SetIsEstablished (true); - i2p::transports.AddNTCPSession (this); + transports.AddNTCPSession (this); SendTimeSyncMessage (); SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are diff --git a/NTCPSession.h b/NTCPSession.h index adb69da6..4a5e463a 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -15,7 +15,7 @@ namespace i2p { -namespace ntcp +namespace transport { #pragma pack(1) @@ -67,7 +67,7 @@ namespace ntcp const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028) const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes - class NTCPSession: public i2p::transport::TransportSession + class NTCPSession: public TransportSession { public: diff --git a/NetDb.cpp b/NetDb.cpp index eb7561f7..f1c20498 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -15,6 +15,8 @@ #include "Reseed.h" #include "util.h" +using namespace i2p::transport; + namespace i2p { namespace data @@ -403,7 +405,7 @@ namespace data RequestedDestination * dest = CreateRequestedDestination (destination, false, false, pool); auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ()); if (floodfill) - i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); } } @@ -655,10 +657,10 @@ namespace data if (outbound) outbound->SendTunnelDataMsg (buf+32, replyTunnelID, replyMsg); else - i2p::transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg)); + transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg)); } else - i2p::transports.SendMessage (buf+32, replyMsg); + transports.SendMessage (buf+32, replyMsg); } i2p::DeleteI2NPMessage (msg); } @@ -712,7 +714,7 @@ namespace data }); } else - i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); } else DeleteRequestedDestination (dest); diff --git a/SSU.cpp b/SSU.cpp index ce4c37bd..0ceff06e 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -12,7 +12,7 @@ namespace i2p { -namespace ssu +namespace transport { SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, @@ -173,7 +173,7 @@ namespace ssu LogPrint ("Session request received"); m_RemoteEndpoint = senderEndpoint; if (!m_DHKeysPair) - m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); + m_DHKeysPair = transports.GetNextDHKeysPair (); CreateAESandMacKey (buf + sizeof (SSUHeader)); SendSessionCreated (buf + sizeof (SSUHeader)); } @@ -608,7 +608,7 @@ namespace ssu { // set connect timer ScheduleConnectTimer (); - m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); + m_DHKeysPair = transports.GetNextDHKeysPair (); SendSessionRequest (); } } diff --git a/SSU.h b/SSU.h index 261494ab..7f1d2563 100644 --- a/SSU.h +++ b/SSU.h @@ -18,7 +18,7 @@ namespace i2p { -namespace ssu +namespace transport { #pragma pack(1) struct SSUHeader @@ -58,7 +58,7 @@ namespace ssu }; class SSUServer; - class SSUSession: public i2p::transport::TransportSession + class SSUSession: public TransportSession { public: diff --git a/SSUData.cpp b/SSUData.cpp index 377c8fbb..8eb69051 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -8,7 +8,7 @@ namespace i2p { -namespace ssu +namespace transport { SSUData::SSUData (SSUSession& session): m_Session (session), m_ResendTimer (session.m_Server.GetService ()) diff --git a/SSUData.h b/SSUData.h index 9ac431a2..2b6abead 100644 --- a/SSUData.h +++ b/SSUData.h @@ -13,7 +13,7 @@ namespace i2p { -namespace ssu +namespace transport { const size_t SSU_MTU = 1484; diff --git a/TransitTunnel.cpp b/TransitTunnel.cpp index 9ed8a542..25b82424 100644 --- a/TransitTunnel.cpp +++ b/TransitTunnel.cpp @@ -34,7 +34,7 @@ namespace tunnel *(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID); FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); - i2p::transports.SendMessage (m_NextIdent, tunnelMsg); + i2p::transport::transports.SendMessage (m_NextIdent, tunnelMsg); } void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg) diff --git a/Transports.cpp b/Transports.cpp index 590dfa77..6747febd 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -10,6 +10,8 @@ using namespace i2p::data; namespace i2p +{ +namespace transport { DHKeysPairSupplier::DHKeysPairSupplier (int size): m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) @@ -66,7 +68,7 @@ namespace i2p } } - i2p::transport::DHKeysPair * DHKeysPairSupplier::Acquire () + DHKeysPair * DHKeysPairSupplier::Acquire () { if (!m_Queue.empty ()) { @@ -78,14 +80,14 @@ namespace i2p } else // queue is empty, create new { - i2p::transport::DHKeysPair * pair = new i2p::transport::DHKeysPair (); + DHKeysPair * pair = new DHKeysPair (); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey); return pair; } } - void DHKeysPairSupplier::Return (i2p::transport::DHKeysPair * pair) + void DHKeysPairSupplier::Return (DHKeysPair * pair) { std::unique_lock l(m_AcquiredMutex); m_Queue.push (pair); @@ -119,7 +121,7 @@ namespace i2p boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port)); LogPrint ("Start listening TCP port ", address.port); - auto conn = new i2p::ntcp::NTCPServerConnection (m_Service); + auto conn = new NTCPServerConnection (m_Service); m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this, conn, boost::asio::placeholders::error)); } @@ -127,7 +129,7 @@ namespace i2p { if (!m_SSUServer) { - m_SSUServer = new i2p::ssu::SSUServer (address.port); + m_SSUServer = new SSUServer (address.port); LogPrint ("Start listening UDP port ", address.port); m_SSUServer->Start (); DetectExternalIP (); @@ -179,19 +181,19 @@ namespace i2p } } - void Transports::AddNTCPSession (i2p::ntcp::NTCPSession * session) + void Transports::AddNTCPSession (NTCPSession * session) { if (session) m_NTCPSessions[session->GetRemoteRouterInfo ().GetIdentHash ()] = session; } - void Transports::RemoveNTCPSession (i2p::ntcp::NTCPSession * session) + void Transports::RemoveNTCPSession (NTCPSession * session) { if (session) m_NTCPSessions.erase (session->GetRemoteRouterInfo ().GetIdentHash ()); } - void Transports::HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error) + void Transports::HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error) { if (!error) { @@ -203,13 +205,13 @@ namespace i2p if (error != boost::asio::error::operation_aborted) { - conn = new i2p::ntcp::NTCPServerConnection (m_Service); + conn = new NTCPServerConnection (m_Service); m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this, conn, boost::asio::placeholders::error)); } } - i2p::ntcp::NTCPSession * Transports::GetNextNTCPSession () + NTCPSession * Transports::GetNextNTCPSession () { for (auto session: m_NTCPSessions) if (session.second->IsEstablished ()) @@ -217,7 +219,7 @@ namespace i2p return 0; } - i2p::ntcp::NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident) + NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident) { auto it = m_NTCPSessions.find (ident); if (it != m_NTCPSessions.end ()) @@ -252,9 +254,9 @@ namespace i2p // existing session not found. create new // try NTCP first if message size < 16K auto address = r->GetNTCPAddress (); - if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < i2p::ntcp::NTCP_MAX_MESSAGE_SIZE) + if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE) { - auto s = new i2p::ntcp::NTCPClient (m_Service, address->host, address->port, *r); + auto s = new NTCPClient (m_Service, address->host, address->port, *r); AddNTCPSession (s); s->SendI2NPMessage (msg); } @@ -328,13 +330,15 @@ namespace i2p } } - i2p::transport::DHKeysPair * Transports::GetNextDHKeysPair () + DHKeysPair * Transports::GetNextDHKeysPair () { return m_DHKeysPairSupplier.Acquire (); } - void Transports::ReuseDHKeysPair (i2p::transport::DHKeysPair * pair) + void Transports::ReuseDHKeysPair (DHKeysPair * pair) { m_DHKeysPairSupplier.Return (pair); } } +} + diff --git a/Transports.h b/Transports.h index aa9812e4..c795c2b4 100644 --- a/Transports.h +++ b/Transports.h @@ -18,6 +18,8 @@ #include "Identity.h" namespace i2p +{ +namespace transport { class DHKeysPairSupplier { @@ -27,8 +29,8 @@ namespace i2p ~DHKeysPairSupplier (); void Start (); void Stop (); - i2p::transport::DHKeysPair * Acquire (); - void Return (i2p::transport::DHKeysPair * pair); + DHKeysPair * Acquire (); + void Return (DHKeysPair * pair); private: @@ -38,7 +40,7 @@ namespace i2p private: const int m_QueueSize; - std::queue m_Queue; + std::queue m_Queue; bool m_IsRunning; std::thread * m_Thread; @@ -59,13 +61,13 @@ namespace i2p boost::asio::io_service& GetService () { return m_Service; }; i2p::transport::DHKeysPair * GetNextDHKeysPair (); - void ReuseDHKeysPair (i2p::transport::DHKeysPair * pair); + void ReuseDHKeysPair (DHKeysPair * pair); - void AddNTCPSession (i2p::ntcp::NTCPSession * session); - void RemoveNTCPSession (i2p::ntcp::NTCPSession * session); + void AddNTCPSession (NTCPSession * session); + void RemoveNTCPSession (NTCPSession * session); - i2p::ntcp::NTCPSession * GetNextNTCPSession (); - i2p::ntcp::NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident); + NTCPSession * GetNextNTCPSession (); + NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident); void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); void CloseSession (const i2p::data::RouterInfo * router); @@ -73,7 +75,7 @@ namespace i2p private: void Run (); - void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error); + void HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error); void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer, const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); @@ -89,8 +91,8 @@ namespace i2p boost::asio::io_service::work m_Work; boost::asio::ip::tcp::acceptor * m_NTCPAcceptor; - std::map m_NTCPSessions; - i2p::ssu::SSUServer * m_SSUServer; + std::map m_NTCPSessions; + SSUServer * m_SSUServer; DHKeysPairSupplier m_DHKeysPairSupplier; @@ -98,10 +100,11 @@ namespace i2p // for HTTP only const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; }; - const i2p::ssu::SSUServer * GetSSUServer () const { return m_SSUServer; }; + const SSUServer * GetSSUServer () const { return m_SSUServer; }; }; extern Transports transports; } +} #endif diff --git a/Tunnel.cpp b/Tunnel.cpp index 2da68772..c16981ae 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -92,7 +92,7 @@ namespace tunnel if (outboundTunnel) outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); else - i2p::transports.SendMessage (GetNextIdentHash (), msg); + i2p::transport::transports.SendMessage (GetNextIdentHash (), msg); } bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index ca46199a..6074254e 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -235,7 +235,7 @@ namespace tunnel i2p::HandleI2NPMessage (msg.data); break; case eDeliveryTypeTunnel: - i2p::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); + i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); break; case eDeliveryTypeRouter: if (msg.hash == i2p::context.GetRouterInfo ().GetIdentHash ()) // check if message is sent to us @@ -253,7 +253,7 @@ namespace tunnel *ds = *(msg.data); i2p::data::netdb.PostI2NPMsg (ds); } - i2p::transports.SendMessage (msg.hash, msg.data); + i2p::transport::transports.SendMessage (msg.hash, msg.data); } else // we shouldn't send this message. possible leakage { diff --git a/TunnelGateway.cpp b/TunnelGateway.cpp index c12c4519..d2996b17 100644 --- a/TunnelGateway.cpp +++ b/TunnelGateway.cpp @@ -186,7 +186,7 @@ namespace tunnel { m_Tunnel->EncryptTunnelMsg (tunnelMsg); FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); - i2p::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg); + i2p::transport::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg); m_NumSentBytes += TUNNEL_DATA_MSG_SIZE; } m_Buffer.ClearTunnelDataMsgs (); From e96ffd41894f2ece8f694b57c922b61d698f228a Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Oct 2014 14:28:56 -0400 Subject: [PATCH 07/35] don't block HTTP server/proxy for 10 seconds anymore --- HTTPServer.cpp | 40 +++++++++++++++++++++++++--------------- HTTPServer.h | 9 +++++++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 93cfb528..06ed3e74 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -852,32 +852,42 @@ namespace util return; } - SendToDestination (destination, buf, len); - } - - void HTTPConnection::SendToDestination (const i2p::data::IdentHash& destination, const char * buf, size_t len) - { auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) + if (leaseSet && leaseSet->HasNonExpiredLeases ()) + SendToDestination (leaseSet, buf, len); + else { i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ()); - std::this_thread::sleep_for (std::chrono::seconds(10)); // wait for 10 seconds - leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) // still no LeaseSet - { + m_Timer.expires_from_now (boost::posix_time::seconds(HTTP_DESTINATION_REQUEST_TIMEOUT)); + m_Timer.async_wait (boost::bind (&HTTPConnection::HandleDestinationRequestTimeout, + this, boost::asio::placeholders::error, destination, buf, len)); + } + } + + void HTTPConnection::HandleDestinationRequestTimeout (const boost::system::error_code& ecode, i2p::data::IdentHash destination, const char * buf, size_t len) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); + if (leaseSet && leaseSet->HasNonExpiredLeases ()) + SendToDestination (leaseSet, buf, len); + else + // still no LeaseSet SendReply (leaseSet ? "" + itoopieImage + "
Leases expired" : "" + itoopieImage + "LeaseSet not found", 504); - return; - } } + } + + void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, const char * buf, size_t len) + { if (!m_Stream) - m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream (*leaseSet); + m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream (*remote); if (m_Stream) { m_Stream->Send ((uint8_t *)buf, len); AsyncStreamReceive (); } - } - + } + void HTTPConnection::AsyncStreamReceive () { if (m_Stream) diff --git a/HTTPServer.h b/HTTPServer.h index 7559b975..30545639 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -5,6 +5,7 @@ #include #include #include +#include "LeaseSet.h" #include "Streaming.h" namespace i2p @@ -12,6 +13,7 @@ namespace i2p namespace util { const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; + const int HTTP_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds class HTTPConnection { protected: @@ -43,7 +45,8 @@ namespace util public: HTTPConnection (boost::asio::ip::tcp::socket * socket): - m_Socket (socket), m_Stream (nullptr), m_BufferLen (0) { Receive (); }; + m_Socket (socket), m_Timer (socket->get_io_service ()), + m_Stream (nullptr), m_BufferLen (0) { Receive (); }; virtual ~HTTPConnection() { delete m_Socket; } private: @@ -74,6 +77,7 @@ namespace util protected: boost::asio::ip::tcp::socket * m_Socket; + boost::asio::deadline_timer m_Timer; i2p::stream::Stream * m_Stream; char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1], m_StreamBuffer[HTTP_CONNECTION_BUFFER_SIZE + 1]; size_t m_BufferLen; @@ -85,7 +89,8 @@ namespace util virtual void RunRequest (); void HandleDestinationRequest(const std::string& address, const std::string& uri); void SendToAddress (const std::string& address, const char * buf, size_t len); - void SendToDestination (const i2p::data::IdentHash& destination, const char * buf, size_t len); + void HandleDestinationRequestTimeout (const boost::system::error_code& ecode, i2p::data::IdentHash destination, const char * buf, size_t len); + void SendToDestination (const i2p::data::LeaseSet * remote, const char * buf, size_t len); public: From ab843b6552b3b840f6a1ba21a5fa2f4b3336a5ae Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Oct 2014 15:44:28 -0400 Subject: [PATCH 08/35] cleaned up from duplicated methods --- I2NPProtocol.cpp | 2 +- NTCPSession.cpp | 2 +- RouterContext.h | 3 --- SSU.cpp | 4 ++-- TunnelPool.cpp | 2 +- TunnelPool.h | 2 +- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index d4c6d71e..75606295 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -290,7 +290,7 @@ namespace i2p { LogPrint ("Record ",i," is ours"); - i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKey (), records[i].encrypted, (uint8_t *)&clearText); + i2p::crypto::ElGamalDecrypt (i2p::context.GetEncryptionPrivateKey (), records[i].encrypted, (uint8_t *)&clearText); // replace record to reply I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i); if (i2p::context.AcceptsTunnels ()) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index a4a73dd4..d1689bc1 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -275,7 +275,7 @@ namespace transport void NTCPSession::SendPhase3 () { m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE); - memcpy (&m_Establisher->phase3.ident, &i2p::context.GetRouterIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE); + memcpy (&m_Establisher->phase3.ident, &i2p::context.GetIdentity ().GetStandardIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE); // TODO: uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ()); m_Establisher->phase3.timestamp = tsA; diff --git a/RouterContext.h b/RouterContext.h index 777482b8..e10a4192 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -22,9 +22,6 @@ namespace i2p void Init (); i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; }; - const uint8_t * GetPrivateKey () const { return m_Keys.GetPrivateKey (); }; - const i2p::data::Identity& GetRouterIdentity () const { return m_RouterInfo.GetRouterIdentity (); }; - const i2p::data::IdentHash& GetRouterIdentHash () const { return m_RouterInfo.GetIdentHash (); }; CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; }; void UpdatePort (int port); // called from Daemon diff --git a/SSU.cpp b/SSU.cpp index 0ceff06e..a316bddd 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -359,10 +359,10 @@ namespace transport uint8_t * payload = buf + sizeof (SSUHeader); *payload = 1; // 1 fragment payload++; // info - size_t identLen = sizeof (i2p::context.GetRouterIdentity ()); // 387 bytes + size_t identLen = i2p::data::DEFAULT_IDENTITY_SIZE; // 387 bytes *(uint16_t *)(payload) = htobe16 (identLen); payload += 2; // cursize - memcpy (payload, (uint8_t *)&i2p::context.GetRouterIdentity (), identLen); + memcpy (payload, (uint8_t *)&i2p::context.GetIdentity ().GetStandardIdentity (), identLen); // TODO payload += identLen; uint32_t signedOnTime = i2p::util::GetSecondsSinceEpoch (); *(uint32_t *)(payload) = htobe32 (signedOnTime); // signed on time diff --git a/TunnelPool.cpp b/TunnelPool.cpp index ac63cf7b..f756ebd4 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -257,7 +257,7 @@ namespace tunnel { // last hop auto hop = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router; - if (hop->GetIdentHash () != i2p::context.GetRouterIdentHash ()) // outbound shouldn't be zero-hop tunnel + if (hop->GetIdentHash () != i2p::context.GetIdentHash ()) // outbound shouldn't be zero-hop tunnel { prevHop = hop; hops.push_back (prevHop); diff --git a/TunnelPool.h b/TunnelPool.h index da59866c..76ba45d8 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -33,7 +33,7 @@ namespace tunnel const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); }; const i2p::data::LocalDestination& GetLocalDestination () const { return m_LocalDestination; }; i2p::garlic::GarlicDestination& GetGarlicDestination () const { return m_LocalDestination; }; - bool IsExploratory () const { return GetIdentHash () == i2p::context.GetRouterIdentHash (); }; + bool IsExploratory () const { return GetIdentHash () == i2p::context.GetIdentHash (); }; void CreateTunnels (); void TunnelCreated (InboundTunnel * createdTunnel); From 4d97b0e20635ccb8b5fbffc5e5a4847b31972ce6 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Oct 2014 11:46:54 -0400 Subject: [PATCH 09/35] moved StreamingDestination inside ClientDestination --- ClientContext.cpp | 22 +++++----- ClientContext.h | 16 ++++---- Destination.cpp | 91 ++++------------------------------------- Destination.h | 52 ++--------------------- HTTPServer.cpp | 6 +-- I2PTunnel.cpp | 12 +++--- I2PTunnel.h | 13 +++--- SAM.cpp | 16 ++++---- SAM.h | 3 +- SOCKS.cpp | 2 +- Streaming.cpp | 102 ++++++++++++++++++++++++++++++++++++++++------ Streaming.h | 41 +++++++++++++++++++ 12 files changed, 187 insertions(+), 189 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index aa8e8c95..5937e8f8 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -27,7 +27,7 @@ namespace client { if (!m_SharedLocalDestination) { - m_SharedLocalDestination = new i2p::stream::StreamingDestination (false, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // non-public, DSA + m_SharedLocalDestination = new ClientDestination (false, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // non-public, DSA m_Destinations[m_SharedLocalDestination->GetIdentity ().GetIdentHash ()] = m_SharedLocalDestination; m_SharedLocalDestination->Start (); } @@ -41,7 +41,7 @@ namespace client std::string ircDestination = i2p::util::config::GetArg("-ircdest", ""); if (ircDestination.length () > 0) // ircdest is presented { - i2p::stream::StreamingDestination * localDestination = nullptr; + ClientDestination * localDestination = nullptr; std::string ircKeys = i2p::util::config::GetArg("-irckeys", ""); if (ircKeys.length () > 0) localDestination = i2p::client::context.LoadLocalDestination (ircKeys, false); @@ -125,7 +125,7 @@ namespace client #else it->path(); #endif - auto localDestination = new i2p::stream::StreamingDestination (fullPath, true); + auto localDestination = new ClientDestination (fullPath, true); m_Destinations[localDestination->GetIdentHash ()] = localDestination; numDestinations++; } @@ -134,25 +134,25 @@ namespace client LogPrint (numDestinations, " local destinations loaded"); } - i2p::stream::StreamingDestination * ClientContext::LoadLocalDestination (const std::string& filename, bool isPublic) + ClientDestination * ClientContext::LoadLocalDestination (const std::string& filename, bool isPublic) { - auto localDestination = new i2p::stream::StreamingDestination (i2p::util::filesystem::GetFullPath (filename), isPublic); + auto localDestination = new ClientDestination (i2p::util::filesystem::GetFullPath (filename), isPublic); std::unique_lock l(m_DestinationsMutex); m_Destinations[localDestination->GetIdentHash ()] = localDestination; localDestination->Start (); return localDestination; } - i2p::stream::StreamingDestination * ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType) + ClientDestination * ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType) { - auto localDestination = new i2p::stream::StreamingDestination (isPublic, sigType); + auto localDestination = new ClientDestination (isPublic, sigType); std::unique_lock l(m_DestinationsMutex); m_Destinations[localDestination->GetIdentHash ()] = localDestination; localDestination->Start (); return localDestination; } - void ClientContext::DeleteLocalDestination (i2p::stream::StreamingDestination * destination) + void ClientContext::DeleteLocalDestination (ClientDestination * destination) { if (!destination) return; auto it = m_Destinations.find (destination->GetIdentHash ()); @@ -168,7 +168,7 @@ namespace client } } - i2p::stream::StreamingDestination * ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic) + ClientDestination * ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic) { auto it = m_Destinations.find (keys.GetPublic ().GetIdentHash ()); if (it != m_Destinations.end ()) @@ -181,14 +181,14 @@ namespace client } return nullptr; } - auto localDestination = new i2p::stream::StreamingDestination (keys, isPublic); + auto localDestination = new ClientDestination (keys, isPublic); std::unique_lock l(m_DestinationsMutex); m_Destinations[keys.GetPublic ().GetIdentHash ()] = localDestination; localDestination->Start (); return localDestination; } - i2p::stream::StreamingDestination * ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const + ClientDestination * ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const { auto it = m_Destinations.find (destination); if (it != m_Destinations.end ()) diff --git a/ClientContext.h b/ClientContext.h index 8fbef267..58c2cf36 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -22,12 +22,12 @@ namespace client void Start (); void Stop (); - i2p::stream::StreamingDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; }; - i2p::stream::StreamingDestination * CreateNewLocalDestination (bool isPublic = true, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient - i2p::stream::StreamingDestination * CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true); - void DeleteLocalDestination (i2p::stream::StreamingDestination * destination); - i2p::stream::StreamingDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const; - i2p::stream::StreamingDestination * LoadLocalDestination (const std::string& filename, bool isPublic); + ClientDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; }; + ClientDestination * CreateNewLocalDestination (bool isPublic = true, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient + ClientDestination * CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true); + void DeleteLocalDestination (ClientDestination * destination); + ClientDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const; + ClientDestination * LoadLocalDestination (const std::string& filename, bool isPublic); private: @@ -36,8 +36,8 @@ namespace client private: std::mutex m_DestinationsMutex; - std::map m_Destinations; - i2p::stream::StreamingDestination * m_SharedLocalDestination; + std::map m_Destinations; + ClientDestination * m_SharedLocalDestination; i2p::proxy::HTTPProxy * m_HttpProxy; i2p::proxy::SOCKSProxy * m_SocksProxy; diff --git a/Destination.cpp b/Destination.cpp index da877f53..254f9829 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -21,6 +21,7 @@ namespace client m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel if (m_IsPublic) LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created"); + m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO: } ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic): @@ -56,6 +57,7 @@ namespace client CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel + m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO: } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic): @@ -67,6 +69,7 @@ namespace client m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel if (m_IsPublic) LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created"); + m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO: } ClientDestination::~ClientDestination () @@ -79,6 +82,7 @@ namespace client delete m_LeaseSet; delete m_Work; delete m_Service; + delete m_StreamingDestination; // TODO } void ClientDestination::Run () @@ -94,10 +98,12 @@ namespace client m_Pool->SetActive (true); m_IsRunning = true; m_Thread = new std::thread (std::bind (&ClientDestination::Run, this)); + m_StreamingDestination->Start (); } void ClientDestination::Stop () { + m_StreamingDestination->Stop (); if (m_Pool) i2p::tunnel::tunnels.StopTunnelPool (m_Pool); m_IsRunning = false; @@ -250,7 +256,7 @@ namespace client if (uncompressed->len <= i2p::stream::MAX_PACKET_SIZE) { decompressor.Get (uncompressed->buf, uncompressed->len); - HandleNextPacket (uncompressed); + m_StreamingDestination->HandleNextPacket (uncompressed); } else { @@ -286,87 +292,4 @@ namespace client return msg; } } - -namespace stream -{ - - void StreamingDestination::Start () - { - ClientDestination::Start (); - } - - void StreamingDestination::Stop () - { - ResetAcceptor (); - { - std::unique_lock l(m_StreamsMutex); - for (auto it: m_Streams) - delete it.second; - m_Streams.clear (); - } - ClientDestination::Stop (); - } - - - void StreamingDestination::HandleNextPacket (Packet * packet) - { - uint32_t sendStreamID = packet->GetSendStreamID (); - if (sendStreamID) - { - auto it = m_Streams.find (sendStreamID); - if (it != m_Streams.end ()) - it->second->HandleNextPacket (packet); - else - { - LogPrint ("Unknown stream ", sendStreamID); - delete packet; - } - } - else // new incoming stream - { - auto incomingStream = CreateNewIncomingStream (); - incomingStream->HandleNextPacket (packet); - if (m_Acceptor != nullptr) - m_Acceptor (incomingStream); - else - { - LogPrint ("Acceptor for incoming stream is not set"); - DeleteStream (incomingStream); - } - } - } - - Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote) - { - Stream * s = new Stream (*GetService (), *this, remote); - std::unique_lock l(m_StreamsMutex); - m_Streams[s->GetRecvStreamID ()] = s; - return s; - } - - Stream * StreamingDestination::CreateNewIncomingStream () - { - Stream * s = new Stream (*GetService (), *this); - std::unique_lock l(m_StreamsMutex); - m_Streams[s->GetRecvStreamID ()] = s; - return s; - } - - void StreamingDestination::DeleteStream (Stream * stream) - { - if (stream) - { - std::unique_lock l(m_StreamsMutex); - auto it = m_Streams.find (stream->GetRecvStreamID ()); - if (it != m_Streams.end ()) - { - m_Streams.erase (it); - if (GetService ()) - GetService ()->post ([stream](void) { delete stream; }); - else - delete stream; - } - } - } -} } diff --git a/Destination.h b/Destination.h index 6b41b231..c7f0b981 100644 --- a/Destination.h +++ b/Destination.h @@ -28,6 +28,7 @@ namespace client bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service * GetService () { return m_Service; }; i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; }; + i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; }; bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases (); }; void ResetCurrentOutboundTunnel () { m_CurrentOutboundTunnel = nullptr; }; @@ -52,10 +53,6 @@ namespace client void HandleDataMessage (const uint8_t * buf, size_t len); I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); - protected: - - virtual void HandleNextPacket (i2p::stream::Packet * packet) = 0; // TODO - private: void Run (); @@ -77,55 +74,14 @@ namespace client i2p::data::LeaseSet * m_LeaseSet; bool m_IsPublic; + i2p::stream::StreamingDestination * m_StreamingDestination; + public: // for HTTP only int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); }; }; -} - -namespace stream -{ - class StreamingDestination: public i2p::client::ClientDestination - { - public: - - StreamingDestination (bool isPublic, i2p::data::SigningKeyType sigType): - ClientDestination (isPublic, sigType) {}; - StreamingDestination (const std::string& fullPath, bool isPublic): - ClientDestination (fullPath, isPublic) {}; - StreamingDestination (const i2p::data::PrivateKeys& keys, bool isPublic): - ClientDestination (keys, isPublic) {}; - ~StreamingDestination () {}; - - void Start (); - void Stop (); - - Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote); - void DeleteStream (Stream * stream); - void SetAcceptor (const std::function& acceptor) { m_Acceptor = acceptor; }; - void ResetAcceptor () { m_Acceptor = nullptr; }; - bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; - - // ClientDestination - void HandleNextPacket (Packet * packet); - - private: - - Stream * CreateNewIncomingStream (); - - private: - - std::mutex m_StreamsMutex; - std::map m_Streams; - std::function m_Acceptor; - - public: - - // for HTTP only - const decltype(m_Streams)& GetStreams () const { return m_Streams; }; - }; -} +} } #endif diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 06ed3e74..78e3bd38 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -517,7 +517,7 @@ namespace util if (m_Stream) { m_Stream->Close (); - i2p::client::context.GetSharedLocalDestination ()->DeleteStream (m_Stream); + i2p::client::context.GetSharedLocalDestination ()->GetStreamingDestination ()->DeleteStream (m_Stream); m_Stream = nullptr; } m_Socket->close (); @@ -813,7 +813,7 @@ namespace util } } s << "
Streams:
"; - for (auto it: dest->GetStreams ()) + for (auto it: dest->GetStreamingDestination ()->GetStreams ()) { s << it.first << "->" << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase32 () << ".b32.i2p "; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; @@ -880,7 +880,7 @@ namespace util void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, const char * buf, size_t len) { if (!m_Stream) - m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream (*remote); + m_Stream = i2p::client::context.GetSharedLocalDestination ()->GetStreamingDestination ()->CreateNewOutgoingStream (*remote); if (m_Stream) { m_Stream->Send ((uint8_t *)buf, len); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 3c8b9234..9569a25e 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -14,7 +14,7 @@ namespace client boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet): m_Socket (socket), m_Owner (owner) { - m_Stream = m_Owner->GetLocalDestination ()->CreateNewOutgoingStream (*leaseSet); + m_Stream = m_Owner->GetLocalDestination ()->GetStreamingDestination ()->CreateNewOutgoingStream (*leaseSet); m_Stream->Send (m_Buffer, 0); // connect StreamReceive (); Receive (); @@ -39,7 +39,7 @@ namespace client if (m_Stream) { m_Stream->Close (); - m_Owner->GetLocalDestination ()->DeleteStream (m_Stream); + m_Owner->GetLocalDestination ()->GetStreamingDestination ()->DeleteStream (m_Stream); m_Stream = nullptr; } m_Socket->close (); @@ -115,7 +115,7 @@ namespace client if (ecode != boost::asio::error::operation_aborted) { if (m_Stream) m_Stream->Close (); - m_Owner->GetLocalDestination ()->DeleteStream (m_Stream); + m_Owner->GetLocalDestination ()->GetStreamingDestination ()->DeleteStream (m_Stream); m_Stream = nullptr; } } @@ -145,7 +145,7 @@ namespace client } I2PClientTunnel::I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, - int port, i2p::stream::StreamingDestination * localDestination): + int port, ClientDestination * localDestination): I2PTunnel (service, localDestination ? localDestination : i2p::client::context.CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256)), m_Acceptor (service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)), @@ -251,7 +251,7 @@ namespace client } I2PServerTunnel::I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port, - i2p::stream::StreamingDestination * localDestination): I2PTunnel (service, localDestination), + ClientDestination * localDestination): I2PTunnel (service, localDestination), m_Endpoint (boost::asio::ip::address::from_string (address), port) { } @@ -270,7 +270,7 @@ namespace client { auto localDestination = GetLocalDestination (); if (localDestination) - localDestination->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); + localDestination->GetStreamingDestination ()->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); else LogPrint ("Local destination not set for server tunnel"); } diff --git a/I2PTunnel.h b/I2PTunnel.h index 47d7e212..4f99bc79 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -6,6 +6,7 @@ #include #include #include "Identity.h" +#include "Destination.h" #include "Streaming.h" namespace i2p @@ -51,22 +52,22 @@ namespace client { public: - I2PTunnel (boost::asio::io_service& service, i2p::stream::StreamingDestination * localDestination): + I2PTunnel (boost::asio::io_service& service, ClientDestination * localDestination): m_Service (service), m_LocalDestination (localDestination) {}; virtual ~I2PTunnel () { ClearConnections (); }; void AddConnection (I2PTunnelConnection * conn); void RemoveConnection (I2PTunnelConnection * conn); void ClearConnections (); - i2p::stream::StreamingDestination * GetLocalDestination () { return m_LocalDestination; }; - void SetLocalDestination (i2p::stream::StreamingDestination * dest) { m_LocalDestination = dest; }; + ClientDestination * GetLocalDestination () { return m_LocalDestination; }; + void SetLocalDestination (ClientDestination * dest) { m_LocalDestination = dest; }; boost::asio::io_service& GetService () { return m_Service; }; private: boost::asio::io_service& m_Service; - i2p::stream::StreamingDestination * m_LocalDestination; + ClientDestination * m_LocalDestination; std::set m_Connections; }; @@ -75,7 +76,7 @@ namespace client public: I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, int port, - i2p::stream::StreamingDestination * localDestination = nullptr); + ClientDestination * localDestination = nullptr); ~I2PClientTunnel (); void Start (); @@ -102,7 +103,7 @@ namespace client public: I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port, - i2p::stream::StreamingDestination * localDestination); + ClientDestination * localDestination); void Start (); void Stop (); diff --git a/SAM.cpp b/SAM.cpp index 4b96fd26..dd5ed5b7 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -26,7 +26,7 @@ namespace client { m_Stream->Close (); if (m_Session && m_Session->localDestination) - m_Session->localDestination->DeleteStream (m_Stream); + m_Session->localDestination->GetStreamingDestination ()->DeleteStream (m_Stream); } } @@ -36,7 +36,7 @@ namespace client { m_Stream->Close (); if (m_Session && m_Session->localDestination) - m_Session->localDestination->DeleteStream (m_Stream); + m_Session->localDestination->GetStreamingDestination ()->DeleteStream (m_Stream); m_Stream = nullptr; } switch (m_SocketType) @@ -55,7 +55,7 @@ namespace client if (m_Session) { m_Session->sockets.remove (this); - m_Session->localDestination->ResetAcceptor (); + m_Session->localDestination->GetStreamingDestination ()->ResetAcceptor (); } break; } @@ -295,7 +295,7 @@ namespace client { m_SocketType = eSAMSocketTypeStream; m_Session->sockets.push_back (this); - m_Stream = m_Session->localDestination->CreateNewOutgoingStream (remote); + m_Stream = m_Session->localDestination->GetStreamingDestination ()->CreateNewOutgoingStream (remote); m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect I2PReceive (); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); @@ -344,11 +344,11 @@ namespace client m_Session = m_Owner.FindSession (id); if (m_Session) { - if (!m_Session->localDestination->IsAcceptorSet ()) + if (!m_Session->localDestination->GetStreamingDestination ()->IsAcceptorSet ()) { m_SocketType = eSAMSocketTypeAcceptor; m_Session->sockets.push_back (this); - m_Session->localDestination->SetAcceptor (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1)); + m_Session->localDestination->GetStreamingDestination ()->SetAcceptor (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1)); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } else @@ -507,7 +507,7 @@ namespace client m_Stream = stream; auto session = m_Owner.FindSession (m_ID); if (session) - session->localDestination->ResetAcceptor (); + session->localDestination->GetStreamingDestination ()->ResetAcceptor (); if (!m_IsSilent) { // send remote peer address @@ -595,7 +595,7 @@ namespace client SAMSession * SAMBridge::CreateSession (const std::string& id, const std::string& destination) { - i2p::stream::StreamingDestination * localDestination = nullptr; + ClientDestination * localDestination = nullptr; if (destination != "") { uint8_t * buf = new uint8_t[destination.length ()]; diff --git a/SAM.h b/SAM.h index dff0e8e2..00ce366d 100644 --- a/SAM.h +++ b/SAM.h @@ -11,6 +11,7 @@ #include "Identity.h" #include "LeaseSet.h" #include "Streaming.h" +#include "Destination.h" namespace i2p { @@ -115,7 +116,7 @@ namespace client struct SAMSession { - i2p::stream::StreamingDestination * localDestination; + ClientDestination * localDestination; std::list sockets; }; diff --git a/SOCKS.cpp b/SOCKS.cpp index 83f8a5d0..9d5a5209 100644 --- a/SOCKS.cpp +++ b/SOCKS.cpp @@ -224,7 +224,7 @@ namespace proxy void SOCKS4AHandler::SentConnectionSuccess(const boost::system::error_code & ecode) { LogPrint("--- socks4a making connection"); - m_stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream(*m_ls); + m_stream = i2p::client::context.GetSharedLocalDestination ()->GetStreamingDestination ()->CreateNewOutgoingStream(*m_ls); m_state = OKAY; LogPrint("--- socks4a state is ", m_state); AsyncSockRead(); diff --git a/Streaming.cpp b/Streaming.cpp index 5b871cf2..f6762370 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -115,7 +115,7 @@ namespace stream { // we have received duplicate. Most likely our outbound tunnel is dead LogPrint ("Duplicate message ", receivedSeqn, " received"); - m_LocalDestination.ResetCurrentOutboundTunnel (); // pick another outbound tunnel + m_LocalDestination.GetOwner ().ResetCurrentOutboundTunnel (); // pick another outbound tunnel UpdateCurrentRemoteLease (); // pick another lease SendQuickAck (); // resend ack for previous message again delete packet; // packet dropped @@ -274,11 +274,11 @@ namespace stream if (isNoAck) flags |= PACKET_FLAG_NO_ACK; *(uint16_t *)(packet + size) = htobe16 (flags); size += 2; // flags - size_t identityLen = m_LocalDestination.GetIdentity ().GetFullLen (); - size_t signatureLen = m_LocalDestination.GetIdentity ().GetSignatureLen (); + size_t identityLen = m_LocalDestination.GetOwner ().GetIdentity ().GetFullLen (); + size_t signatureLen = m_LocalDestination.GetOwner ().GetIdentity ().GetSignatureLen (); *(uint16_t *)(packet + size) = htobe16 (identityLen + signatureLen + 2); // identity + signature + packet size size += 2; // options size - m_LocalDestination.GetIdentity ().ToBuffer (packet + size, identityLen); + m_LocalDestination.GetOwner ().GetIdentity ().ToBuffer (packet + size, identityLen); size += identityLen; // from *(uint16_t *)(packet + size) = htobe16 (STREAMING_MTU); size += 2; // max packet size @@ -291,7 +291,7 @@ namespace stream buf += sentLen; len -= sentLen; size += sentLen; // payload - m_LocalDestination.Sign (packet, size, signature); + m_LocalDestination.GetOwner ().Sign (packet, size, signature); } else { @@ -362,13 +362,13 @@ namespace stream size++; // resend delay *(uint16_t *)(packet + size) = htobe16 (PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED); size += 2; // flags - size_t signatureLen = m_LocalDestination.GetIdentity ().GetSignatureLen (); + size_t signatureLen = m_LocalDestination.GetOwner ().GetIdentity ().GetSignatureLen (); *(uint16_t *)(packet + size) = htobe16 (signatureLen); // signature only size += 2; // options size uint8_t * signature = packet + size; memset (packet + size, 0, signatureLen); size += signatureLen; // signature - m_LocalDestination.Sign (packet, size, signature); + m_LocalDestination.GetOwner ().Sign (packet, size, signature); p->len = size; SendPacket (p); @@ -441,7 +441,7 @@ namespace stream for (auto it: packets) { auto msg = m_RoutingSession->WrapSingleMessage ( - m_LocalDestination.CreateDataMessage (it->GetBuffer (), it->GetLength ())); + m_LocalDestination.GetOwner ().CreateDataMessage (it->GetBuffer (), it->GetLength ())); msgs.push_back (i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, @@ -450,7 +450,7 @@ namespace stream }); m_NumSentBytes += it->GetLength (); } - m_LocalDestination.SendTunnelDataMsgs (msgs); + m_LocalDestination.GetOwner ().SendTunnelDataMsgs (msgs); } else LogPrint ("All leases are expired"); @@ -484,7 +484,7 @@ namespace stream } if (packets.size () > 0) { - m_LocalDestination.ResetCurrentOutboundTunnel (); // pick another outbound tunnel + m_LocalDestination.GetOwner ().ResetCurrentOutboundTunnel (); // pick another outbound tunnel UpdateCurrentRemoteLease (); // pick another lease SendPackets (packets); } @@ -506,14 +506,14 @@ namespace stream { if (!m_RemoteLeaseSet) { - m_RemoteLeaseSet = m_LocalDestination.FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); + m_RemoteLeaseSet = m_LocalDestination.GetOwner ().FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); if (!m_RemoteLeaseSet) LogPrint ("LeaseSet ", m_RemoteIdentity.GetIdentHash ().ToBase64 (), " not found"); } if (m_RemoteLeaseSet) { if (!m_RoutingSession) - m_RoutingSession = m_LocalDestination.GetRoutingSession (*m_RemoteLeaseSet, 32); + m_RoutingSession = m_LocalDestination.GetOwner ().GetRoutingSession (*m_RemoteLeaseSet, 32); auto leases = m_RemoteLeaseSet->GetNonExpiredLeases (); if (!leases.empty ()) { @@ -522,12 +522,88 @@ namespace stream } else { - m_RemoteLeaseSet = m_LocalDestination.FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); // re-request expired + m_RemoteLeaseSet = m_LocalDestination.GetOwner ().FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); // re-request expired m_CurrentRemoteLease.endDate = 0; } } else m_CurrentRemoteLease.endDate = 0; + } + + void StreamingDestination::Start () + { + } + + void StreamingDestination::Stop () + { + ResetAcceptor (); + { + std::unique_lock l(m_StreamsMutex); + for (auto it: m_Streams) + delete it.second; + m_Streams.clear (); + } + } + + void StreamingDestination::HandleNextPacket (Packet * packet) + { + uint32_t sendStreamID = packet->GetSendStreamID (); + if (sendStreamID) + { + auto it = m_Streams.find (sendStreamID); + if (it != m_Streams.end ()) + it->second->HandleNextPacket (packet); + else + { + LogPrint ("Unknown stream ", sendStreamID); + delete packet; + } + } + else // new incoming stream + { + auto incomingStream = CreateNewIncomingStream (); + incomingStream->HandleNextPacket (packet); + if (m_Acceptor != nullptr) + m_Acceptor (incomingStream); + else + { + LogPrint ("Acceptor for incoming stream is not set"); + DeleteStream (incomingStream); + } + } + } + + Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote) + { + Stream * s = new Stream (*m_Owner.GetService (), *this, remote); + std::unique_lock l(m_StreamsMutex); + m_Streams[s->GetRecvStreamID ()] = s; + return s; + } + + Stream * StreamingDestination::CreateNewIncomingStream () + { + Stream * s = new Stream (*m_Owner.GetService (), *this); + std::unique_lock l(m_StreamsMutex); + m_Streams[s->GetRecvStreamID ()] = s; + return s; + } + + void StreamingDestination::DeleteStream (Stream * stream) + { + if (stream) + { + std::unique_lock l(m_StreamsMutex); + auto it = m_Streams.find (stream->GetRecvStreamID ()); + if (it != m_Streams.end ()) + { + m_Streams.erase (it); + if (m_Owner.GetService ()) + m_Owner.GetService ()->post ([stream](void) { delete stream; }); + else + delete stream; + } + } } } } diff --git a/Streaming.h b/Streaming.h index 5c02913d..29f98088 100644 --- a/Streaming.h +++ b/Streaming.h @@ -18,6 +18,10 @@ namespace i2p { +namespace client +{ + class ClientDestination; +} namespace stream { const uint16_t PACKET_FLAG_SYNCHRONIZE = 0x0001; @@ -141,6 +145,43 @@ namespace stream size_t m_NumSentBytes, m_NumReceivedBytes; }; + class StreamingDestination + { + public: + + StreamingDestination (i2p::client::ClientDestination& owner): m_Owner (owner) {}; + ~StreamingDestination () {}; + + void Start (); + void Stop (); + + Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote); + void DeleteStream (Stream * stream); + void SetAcceptor (const std::function& acceptor) { m_Acceptor = acceptor; }; + void ResetAcceptor () { m_Acceptor = nullptr; }; + bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; + + // ClientDestination + i2p::client::ClientDestination& GetOwner () { return m_Owner; }; + void HandleNextPacket (Packet * packet); + + private: + + Stream * CreateNewIncomingStream (); + + private: + + i2p::client::ClientDestination& m_Owner; + std::mutex m_StreamsMutex; + std::map m_Streams; + std::function m_Acceptor; + + public: + + // for HTTP only + const decltype(m_Streams)& GetStreams () const { return m_Streams; }; + }; + //------------------------------------------------- template From b11877d002b02807deca2c137aeea580a099e095 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Oct 2014 14:01:23 -0400 Subject: [PATCH 10/35] create streams through ClientDestination --- Destination.cpp | 33 +++++++++++++++++++++++++++++---- Destination.h | 12 +++++++++++- HTTPServer.cpp | 4 ++-- I2PTunnel.cpp | 8 ++++---- SAM.cpp | 17 ++++++++--------- SOCKS.cpp | 2 +- Streaming.cpp | 6 ++++++ Streaming.h | 2 ++ 8 files changed, 63 insertions(+), 21 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 254f9829..9053c271 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -244,7 +244,7 @@ namespace client uint32_t length = be32toh (*(uint32_t *)buf); buf += 4; // we assume I2CP payload - if (buf[9] == 6) // streaming protocol + if (buf[9] == PROTOCOL_TYPE_STREAMING && m_StreamingDestination) // streaming protocol { // unzip it CryptoPP::Gunzip decompressor; @@ -261,7 +261,6 @@ namespace client else { LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped"); - decompressor.Skip (); delete uncompressed; } } @@ -285,11 +284,37 @@ namespace client buf += 4; compressor.Get (buf, size); memset (buf + 4, 0, 4); // source and destination ports. TODO: fill with proper values later - buf[9] = 6; // streaming protocol + buf[9] = PROTOCOL_TYPE_STREAMING; // streaming protocol. TODO: msg->len += size + 4; FillI2NPMessageHeader (msg, eI2NPData); return msg; - } + } + + i2p::stream::Stream * ClientDestination::CreateStream (const i2p::data::LeaseSet& remote) + { + if (m_StreamingDestination) + return m_StreamingDestination->CreateNewOutgoingStream (remote); + return nullptr; + } + + void ClientDestination::AcceptStreams (const std::function& acceptor) + { + if (m_StreamingDestination) + m_StreamingDestination->SetAcceptor (acceptor); + } + + void ClientDestination::StopAcceptingStreams () + { + if (m_StreamingDestination) + m_StreamingDestination->ResetAcceptor (); + } + + bool ClientDestination::IsAcceptingStreams () const + { + if (m_StreamingDestination) + return m_StreamingDestination->IsAcceptorSet (); + return false; + } } } diff --git a/Destination.h b/Destination.h index c7f0b981..f15c1588 100644 --- a/Destination.h +++ b/Destination.h @@ -14,6 +14,10 @@ namespace i2p { namespace client { + const uint8_t PROTOCOL_TYPE_STREAMING = 6; + const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; + const uint8_t PROTOCOL_TYPE_RAW = 18; + class ClientDestination: public i2p::garlic::GarlicDestination { public: @@ -28,13 +32,19 @@ namespace client bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service * GetService () { return m_Service; }; i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; }; - i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; }; bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases (); }; void ResetCurrentOutboundTunnel () { m_CurrentOutboundTunnel = nullptr; }; const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident); void SendTunnelDataMsgs (const std::vector& msgs); + // streaming + i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; }; + i2p::stream::Stream * CreateStream (const i2p::data::LeaseSet& remote); + void AcceptStreams (const std::function& acceptor); + void StopAcceptingStreams (); + bool IsAcceptingStreams () const; + // implements LocalDestination const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 78e3bd38..7ab07005 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -517,7 +517,7 @@ namespace util if (m_Stream) { m_Stream->Close (); - i2p::client::context.GetSharedLocalDestination ()->GetStreamingDestination ()->DeleteStream (m_Stream); + i2p::stream::DeleteStream (m_Stream); m_Stream = nullptr; } m_Socket->close (); @@ -880,7 +880,7 @@ namespace util void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, const char * buf, size_t len) { if (!m_Stream) - m_Stream = i2p::client::context.GetSharedLocalDestination ()->GetStreamingDestination ()->CreateNewOutgoingStream (*remote); + m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (*remote); if (m_Stream) { m_Stream->Send ((uint8_t *)buf, len); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 9569a25e..a8193bdd 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -14,7 +14,7 @@ namespace client boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet): m_Socket (socket), m_Owner (owner) { - m_Stream = m_Owner->GetLocalDestination ()->GetStreamingDestination ()->CreateNewOutgoingStream (*leaseSet); + m_Stream = m_Owner->GetLocalDestination ()->CreateStream (*leaseSet); m_Stream->Send (m_Buffer, 0); // connect StreamReceive (); Receive (); @@ -39,7 +39,7 @@ namespace client if (m_Stream) { m_Stream->Close (); - m_Owner->GetLocalDestination ()->GetStreamingDestination ()->DeleteStream (m_Stream); + i2p::stream::DeleteStream (m_Stream); m_Stream = nullptr; } m_Socket->close (); @@ -115,7 +115,7 @@ namespace client if (ecode != boost::asio::error::operation_aborted) { if (m_Stream) m_Stream->Close (); - m_Owner->GetLocalDestination ()->GetStreamingDestination ()->DeleteStream (m_Stream); + i2p::stream::DeleteStream (m_Stream); m_Stream = nullptr; } } @@ -270,7 +270,7 @@ namespace client { auto localDestination = GetLocalDestination (); if (localDestination) - localDestination->GetStreamingDestination ()->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); + localDestination->AcceptStreams (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); else LogPrint ("Local destination not set for server tunnel"); } diff --git a/SAM.cpp b/SAM.cpp index dd5ed5b7..897fe5a0 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -25,8 +25,8 @@ namespace client if (m_Stream) { m_Stream->Close (); - if (m_Session && m_Session->localDestination) - m_Session->localDestination->GetStreamingDestination ()->DeleteStream (m_Stream); + i2p::stream::DeleteStream (m_Stream); + m_Stream = nullptr; } } @@ -35,8 +35,7 @@ namespace client if (m_Stream) { m_Stream->Close (); - if (m_Session && m_Session->localDestination) - m_Session->localDestination->GetStreamingDestination ()->DeleteStream (m_Stream); + i2p::stream::DeleteStream (m_Stream); m_Stream = nullptr; } switch (m_SocketType) @@ -55,7 +54,7 @@ namespace client if (m_Session) { m_Session->sockets.remove (this); - m_Session->localDestination->GetStreamingDestination ()->ResetAcceptor (); + m_Session->localDestination->StopAcceptingStreams (); } break; } @@ -295,7 +294,7 @@ namespace client { m_SocketType = eSAMSocketTypeStream; m_Session->sockets.push_back (this); - m_Stream = m_Session->localDestination->GetStreamingDestination ()->CreateNewOutgoingStream (remote); + m_Stream = m_Session->localDestination->CreateStream (remote); m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect I2PReceive (); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); @@ -344,11 +343,11 @@ namespace client m_Session = m_Owner.FindSession (id); if (m_Session) { - if (!m_Session->localDestination->GetStreamingDestination ()->IsAcceptorSet ()) + if (!m_Session->localDestination->IsAcceptingStreams ()) { m_SocketType = eSAMSocketTypeAcceptor; m_Session->sockets.push_back (this); - m_Session->localDestination->GetStreamingDestination ()->SetAcceptor (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1)); + m_Session->localDestination->AcceptStreams (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1)); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } else @@ -507,7 +506,7 @@ namespace client m_Stream = stream; auto session = m_Owner.FindSession (m_ID); if (session) - session->localDestination->GetStreamingDestination ()->ResetAcceptor (); + session->localDestination->StopAcceptingStreams (); if (!m_IsSilent) { // send remote peer address diff --git a/SOCKS.cpp b/SOCKS.cpp index 9d5a5209..f2386321 100644 --- a/SOCKS.cpp +++ b/SOCKS.cpp @@ -224,7 +224,7 @@ namespace proxy void SOCKS4AHandler::SentConnectionSuccess(const boost::system::error_code & ecode) { LogPrint("--- socks4a making connection"); - m_stream = i2p::client::context.GetSharedLocalDestination ()->GetStreamingDestination ()->CreateNewOutgoingStream(*m_ls); + m_stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream(*m_ls); m_state = OKAY; LogPrint("--- socks4a state is ", m_state); AsyncSockRead(); diff --git a/Streaming.cpp b/Streaming.cpp index f6762370..82bd90dd 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -605,5 +605,11 @@ namespace stream } } } + + void DeleteStream (Stream * stream) + { + if (stream) + stream->GetLocalDestination ().DeleteStream (stream); + } } } diff --git a/Streaming.h b/Streaming.h index 29f98088..ee7d9eb0 100644 --- a/Streaming.h +++ b/Streaming.h @@ -182,6 +182,8 @@ namespace stream const decltype(m_Streams)& GetStreams () const { return m_Streams; }; }; + void DeleteStream (Stream * stream); + //------------------------------------------------- template From 3da35c592f2e1d41fac2885e95a3fe37ee75fba3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Oct 2014 15:01:30 -0400 Subject: [PATCH 11/35] moved Data payload processing to StreamingDestination --- Destination.cpp | 56 +++++++++---------------------------------------- Destination.h | 1 - Streaming.cpp | 47 ++++++++++++++++++++++++++++++++++++++++- Streaming.h | 7 ++++--- 4 files changed, 60 insertions(+), 51 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 9053c271..dc544ba6 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "Log.h" #include "util.h" #include "NetDb.h" @@ -244,51 +243,16 @@ namespace client uint32_t length = be32toh (*(uint32_t *)buf); buf += 4; // we assume I2CP payload - if (buf[9] == PROTOCOL_TYPE_STREAMING && m_StreamingDestination) // streaming protocol - { - // unzip it - CryptoPP::Gunzip decompressor; - decompressor.Put (buf, length); - decompressor.MessageEnd(); - i2p::stream::Packet * uncompressed = new i2p::stream::Packet; - uncompressed->offset = 0; - uncompressed->len = decompressor.MaxRetrievable (); - if (uncompressed->len <= i2p::stream::MAX_PACKET_SIZE) - { - decompressor.Get (uncompressed->buf, uncompressed->len); - m_StreamingDestination->HandleNextPacket (uncompressed); - } - else - { - LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped"); - delete uncompressed; - } - } - else - LogPrint ("Data: unexpected protocol ", buf[9]); - } - - I2NPMessage * ClientDestination::CreateDataMessage (const uint8_t * payload, size_t len) - { - I2NPMessage * msg = NewI2NPShortMessage (); - CryptoPP::Gzip compressor; - if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE) - compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL); - else - compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL); - compressor.Put (payload, len); - compressor.MessageEnd(); - int size = compressor.MaxRetrievable (); - uint8_t * buf = msg->GetPayload (); - *(uint32_t *)buf = htobe32 (size); // length - buf += 4; - compressor.Get (buf, size); - memset (buf + 4, 0, 4); // source and destination ports. TODO: fill with proper values later - buf[9] = PROTOCOL_TYPE_STREAMING; // streaming protocol. TODO: - msg->len += size + 4; - FillI2NPMessageHeader (msg, eI2NPData); - - return msg; + switch (buf[9]) + { + case PROTOCOL_TYPE_STREAMING: + // streaming protocol + if (m_StreamingDestination) + m_StreamingDestination->HandleDataMessagePayload (buf, length); + break; + default: + LogPrint ("Data: unexpected protocol ", buf[9]); + } } i2p::stream::Stream * ClientDestination::CreateStream (const i2p::data::LeaseSet& remote) diff --git a/Destination.h b/Destination.h index f15c1588..d7547ecf 100644 --- a/Destination.h +++ b/Destination.h @@ -61,7 +61,6 @@ namespace client // I2CP void HandleDataMessage (const uint8_t * buf, size_t len); - I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); private: diff --git a/Streaming.cpp b/Streaming.cpp index 82bd90dd..572d12c2 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -1,3 +1,4 @@ +#include #include "Log.h" #include "RouterInfo.h" #include "RouterContext.h" @@ -441,7 +442,7 @@ namespace stream for (auto it: packets) { auto msg = m_RoutingSession->WrapSingleMessage ( - m_LocalDestination.GetOwner ().CreateDataMessage (it->GetBuffer (), it->GetLength ())); + m_LocalDestination.CreateDataMessage (it->GetBuffer (), it->GetLength ())); msgs.push_back (i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, @@ -606,6 +607,50 @@ namespace stream } } + void StreamingDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len) + { + // unzip it + CryptoPP::Gunzip decompressor; + decompressor.Put (buf, len); + decompressor.MessageEnd(); + Packet * uncompressed = new Packet; + uncompressed->offset = 0; + uncompressed->len = decompressor.MaxRetrievable (); + if (uncompressed->len <= MAX_PACKET_SIZE) + { + decompressor.Get (uncompressed->buf, uncompressed->len); + HandleNextPacket (uncompressed); + } + else + { + LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped"); + delete uncompressed; + } + } + + I2NPMessage * StreamingDestination::CreateDataMessage (const uint8_t * payload, size_t len) + { + I2NPMessage * msg = NewI2NPShortMessage (); + CryptoPP::Gzip compressor; + if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE) + compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL); + else + compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL); + compressor.Put (payload, len); + compressor.MessageEnd(); + int size = compressor.MaxRetrievable (); + uint8_t * buf = msg->GetPayload (); + *(uint32_t *)buf = htobe32 (size); // length + buf += 4; + compressor.Get (buf, size); + memset (buf + 4, 0, 4); // source and destination ports. TODO: fill with proper values later + buf[9] = i2p::client::PROTOCOL_TYPE_STREAMING; // streaming protocol + msg->len += size + 4; + FillI2NPMessageHeader (msg, eI2NPData); + + return msg; + } + void DeleteStream (Stream * stream) { if (stream) diff --git a/Streaming.h b/Streaming.h index ee7d9eb0..6d57a8ad 100644 --- a/Streaming.h +++ b/Streaming.h @@ -160,13 +160,14 @@ namespace stream void SetAcceptor (const std::function& acceptor) { m_Acceptor = acceptor; }; void ResetAcceptor () { m_Acceptor = nullptr; }; bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; - - // ClientDestination i2p::client::ClientDestination& GetOwner () { return m_Owner; }; - void HandleNextPacket (Packet * packet); + + I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); + void HandleDataMessagePayload (const uint8_t * buf, size_t len); private: + void HandleNextPacket (Packet * packet); Stream * CreateNewIncomingStream (); private: From 78d8d34e3b013b4a7b5a78a8245bc0875acaf0e3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Oct 2014 15:30:25 -0400 Subject: [PATCH 12/35] Datagram added --- Datagram.cpp | 29 +++++++++++++++++++++++++++++ Datagram.h | 32 ++++++++++++++++++++++++++++++++ Destination.cpp | 18 +++++++++++++++--- Destination.h | 2 ++ Win32/i2pd.vcxproj | 3 +++ build/CMakeLists.txt | 3 ++- build/autotools/Makefile.in | 6 ++++-- filelist.mk | 4 ++-- 8 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 Datagram.cpp create mode 100644 Datagram.h diff --git a/Datagram.cpp b/Datagram.cpp new file mode 100644 index 00000000..5c3cd259 --- /dev/null +++ b/Datagram.cpp @@ -0,0 +1,29 @@ +#include +#include "Log.h" +#include "Datagram.h" + +namespace i2p +{ +namespace datagram +{ + void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len) + { + // unzip it + CryptoPP::Gunzip decompressor; + decompressor.Put (buf, len); + decompressor.MessageEnd(); + uint8_t uncompressed[MAX_DATAGRAM_SIZE]; + auto uncompressedLen = decompressor.MaxRetrievable (); + if (uncompressedLen <= MAX_DATAGRAM_SIZE) + { + decompressor.Get (uncompressed, uncompressedLen); + //HandleNextPacket (uncompressed); + } + else + LogPrint ("Received datagram size ", uncompressedLen, " exceeds max size"); + + } + +} +} + diff --git a/Datagram.h b/Datagram.h new file mode 100644 index 00000000..d5c21f6b --- /dev/null +++ b/Datagram.h @@ -0,0 +1,32 @@ +#ifndef DATAGRAM_H__ +#define DATAGRAM_H__ + +#include + +namespace i2p +{ +namespace client +{ + class ClientDestination; +} +namespace datagram +{ + const size_t MAX_DATAGRAM_SIZE = 32768; + class DatagramDestination + { + public: + + DatagramDestination (i2p::client::ClientDestination& owner): m_Owner (owner) {}; + ~DatagramDestination () {}; + + void HandleDataMessagePayload (const uint8_t * buf, size_t len); + + private: + + i2p::client::ClientDestination& m_Owner; + }; +} +} + +#endif + diff --git a/Destination.cpp b/Destination.cpp index dc544ba6..af425694 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -12,7 +12,8 @@ namespace client { ClientDestination::ClientDestination (bool isPublic, i2p::data::SigningKeyType sigType): m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), - m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic) + m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic), + m_DatagramDestination (nullptr) { m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); @@ -25,7 +26,8 @@ namespace client ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic): m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), - m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic) + m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic), + m_DatagramDestination (nullptr) { std::ifstream s(fullPath.c_str (), std::ifstream::binary); if (s.is_open ()) @@ -61,7 +63,8 @@ namespace client ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic): m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), - m_Keys (keys), m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic) + m_Keys (keys), m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic), + m_DatagramDestination (nullptr) { CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); @@ -249,6 +252,15 @@ namespace client // streaming protocol if (m_StreamingDestination) m_StreamingDestination->HandleDataMessagePayload (buf, length); + else + LogPrint ("Missing streaming destination"); + break; + case PROTOCOL_TYPE_DATAGRAM: + // datagram protocol + if (m_DatagramDestination) + m_DatagramDestination->HandleDataMessagePayload (buf, length); + else + LogPrint ("Missing streaming destination"); break; default: LogPrint ("Data: unexpected protocol ", buf[9]); diff --git a/Destination.h b/Destination.h index d7547ecf..fcb8329d 100644 --- a/Destination.h +++ b/Destination.h @@ -9,6 +9,7 @@ #include "LeaseSet.h" #include "Garlic.h" #include "Streaming.h" +#include "Datagram.h" namespace i2p { @@ -84,6 +85,7 @@ namespace client bool m_IsPublic; i2p::stream::StreamingDestination * m_StreamingDestination; + i2p::datagram::DatagramDestination * m_DatagramDestination; public: diff --git a/Win32/i2pd.vcxproj b/Win32/i2pd.vcxproj index c071c131..2bbba99b 100644 --- a/Win32/i2pd.vcxproj +++ b/Win32/i2pd.vcxproj @@ -47,6 +47,7 @@ + @@ -91,6 +92,8 @@ + + diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 55b5e6e5..02475c0d 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -43,7 +43,8 @@ set (SOURCES "${CMAKE_SOURCE_DIR}/i2p.cpp" "${CMAKE_SOURCE_DIR}/util.cpp" "${CMAKE_SOURCE_DIR}/SAM.cpp" - "${CMAKE_SOURCE_DIR}/ClientContext.cpp" + "${CMAKE_SOURCE_DIR}/ClientContext.cpp" + "${CMAKE_SOURCE_DIR}/Datagram.cpp" ) file (GLOB HEADERS "${CMAKE_SOURCE_DIR}/*.h") diff --git a/build/autotools/Makefile.in b/build/autotools/Makefile.in index 16b2cc2b..d80dfd62 100644 --- a/build/autotools/Makefile.in +++ b/build/autotools/Makefile.in @@ -325,7 +325,7 @@ i2p_SOURCES = AddressBook.cpp CryptoConst.cpp Daemon.cpp \ Transports.cpp Tunnel.cpp TunnelEndpoint.cpp \ TunnelGateway.cpp TunnelPool.cpp UPnP.cpp aes.cpp \ base64.cpp i2p.cpp util.cpp SAM.cpp Destination.cpp \ - ClientContext.cpp \ + ClientContext.cpp DataFram.cpp \ \ AddressBook.h CryptoConst.h Daemon.h ElGamal.h \ Garlic.h HTTPProxy.h HTTPServer.h I2NPProtocol.h \ @@ -336,7 +336,8 @@ i2p_SOURCES = AddressBook.cpp CryptoConst.cpp Daemon.cpp \ TransitTunnel.h Transports.h Tunnel.h TunnelBase.h \ TunnelConfig.h TunnelEndpoint.h TunnelGateway.h \ TunnelPool.h UPnP.h aes.h base64.h config.h hmac.h \ - util.h version.h Destination.h ClientContext.h + util.h version.h Destination.h ClientContext.h \ + TransportSession.h Datagram.h AM_LDFLAGS = @BOOST_DATE_TIME_LIB@ @BOOST_FILESYSTEM_LIB@ \ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_REGEX_LIB@ \ @@ -485,6 +486,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SAM.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientContext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Datagram.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/filelist.mk b/filelist.mk index 1c413f7d..3ca5e9a5 100644 --- a/filelist.mk +++ b/filelist.mk @@ -5,7 +5,7 @@ CPP_FILES := CryptoConst.cpp base64.cpp NTCPSession.cpp RouterInfo.cpp Transport TransitTunnel.cpp I2NPProtocol.cpp Log.cpp Garlic.cpp HTTPServer.cpp Streaming.cpp \ Destination.cpp Identity.cpp SSU.cpp util.cpp Reseed.cpp DaemonLinux.cpp SSUData.cpp \ aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.cpp AddressBook.cpp Daemon.cpp \ - I2PTunnel.cpp SAM.cpp ClientContext.cpp i2p.cpp + I2PTunnel.cpp SAM.cpp ClientContext.cpp Datagram.cpp i2p.cpp H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \ @@ -13,7 +13,7 @@ H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \ TransitTunnel.h I2NPProtocol.h Log.h Garlic.h HTTPServer.h Streaming.h Destination.h \ Identity.h SSU.h util.h Reseed.h DaemonLinux.h SSUData.h i2p.h aes.h SOCKS.h \ UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h version.h \ - Signature.h SAM.h ClientContext.h + Signature.h SAM.h ClientContext.h TransportSession.h Datagram.h OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o))) From 4ae8c3c62ceb94496d869c5eb0eef7a77ec28cb1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Oct 2014 16:42:26 -0400 Subject: [PATCH 13/35] create datagram destination through SAM --- Destination.cpp | 9 ++++++++- Destination.h | 4 ++++ SAM.cpp | 27 ++++++++++++++++++++++++++- SAM.h | 9 +++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index af425694..b0e33d63 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -84,7 +84,8 @@ namespace client delete m_LeaseSet; delete m_Work; delete m_Service; - delete m_StreamingDestination; // TODO + delete m_StreamingDestination; + delete m_DatagramDestination; } void ClientDestination::Run () @@ -292,5 +293,11 @@ namespace client return m_StreamingDestination->IsAcceptorSet (); return false; } + + void ClientDestination::CreateDatagramDestination () + { + if (!m_DatagramDestination) + m_DatagramDestination = new i2p::datagram::DatagramDestination (*this); + } } } diff --git a/Destination.h b/Destination.h index fcb8329d..b605cc9d 100644 --- a/Destination.h +++ b/Destination.h @@ -46,6 +46,10 @@ namespace client void StopAcceptingStreams (); bool IsAcceptingStreams () const; + // datagram + i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; + void CreateDatagramDestination (); + // implements LocalDestination const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; diff --git a/SAM.cpp b/SAM.cpp index 897fe5a0..fcc90106 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -206,6 +206,7 @@ namespace client LogPrint ("SAM session create: ", buf); std::map params; ExtractParams (buf, len, params); + std::string& style = params[SAM_PARAM_STYLE]; std::string& id = params[SAM_PARAM_ID]; std::string& destination = params[SAM_PARAM_DESTINATION]; m_ID = id; @@ -220,7 +221,11 @@ namespace client { m_SocketType = eSAMSocketTypeSession; if (m_Session->localDestination->IsReady ()) + { + if (style == SAM_VALUE_DATAGRAM) + m_Session->localDestination->CreateDatagramDestination (); SendSessionCreateReplyOk (); + } else { m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); @@ -523,7 +528,8 @@ namespace client SAMBridge::SAMBridge (int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)), - m_NewSocket (nullptr) + m_DatagramEndpoint (boost::asio::ip::udp::v4 (), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint), + m_NewSocket (nullptr) { } @@ -536,6 +542,7 @@ namespace client void SAMBridge::Start () { Accept (); + ReceiveDatagram (); m_IsRunning = true; m_Thread = new std::thread (std::bind (&SAMBridge::Run, this)); } @@ -641,5 +648,23 @@ namespace client return &it->second; return nullptr; } + + void SAMBridge::ReceiveDatagram () + { + m_DatagramSocket.async_receive_from ( + boost::asio::buffer (m_DatagramReceiveBuffer, i2p::datagram::MAX_DATAGRAM_SIZE), + m_SenderEndpoint, + boost::bind (&SAMBridge::HandleReceivedDatagram, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + + void SAMBridge::HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred) + { + if (!ecode) + { + ReceiveDatagram (); + } + else + LogPrint ("SAM datagram receive error: ", ecode.message ()); + } } } diff --git a/SAM.h b/SAM.h index 00ce366d..abf2b609 100644 --- a/SAM.h +++ b/SAM.h @@ -47,6 +47,9 @@ namespace client const char SAM_PARAM_DESTINATION[] = "DESTINATION"; const char SAM_PARAM_NAME[] = "NAME"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; + const char SAM_VALUE_STREAM[] = "STREAM"; + const char SAM_VALUE_DATAGRAM[] = "DATAGRAM"; + const char SAM_VALUE_RAW[] = "RAW"; const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_FALSE[] = "false"; @@ -142,15 +145,21 @@ namespace client void Accept (); void HandleAccept(const boost::system::error_code& ecode); + void ReceiveDatagram (); + void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred); + private: bool m_IsRunning; std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::ip::tcp::acceptor m_Acceptor; + boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint; + boost::asio::ip::udp::socket m_DatagramSocket; SAMSocket * m_NewSocket; std::mutex m_SessionsMutex; std::map m_Sessions; + uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE]; }; } } From 65719ae64577f99509f3f8b58125d7ada4a12d94 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Oct 2014 21:36:11 -0400 Subject: [PATCH 14/35] send destination port for streaming --- Destination.cpp | 4 ++-- Destination.h | 2 +- HTTPProxy.cpp | 7 +++--- HTTPServer.cpp | 17 +++++++------- HTTPServer.h | 8 ++++--- Streaming.cpp | 60 ++++++++++++++++++++++++------------------------- Streaming.h | 9 +++++--- 7 files changed, 57 insertions(+), 50 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index b0e33d63..eb793d7f 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -268,10 +268,10 @@ namespace client } } - i2p::stream::Stream * ClientDestination::CreateStream (const i2p::data::LeaseSet& remote) + i2p::stream::Stream * ClientDestination::CreateStream (const i2p::data::LeaseSet& remote, int port) { if (m_StreamingDestination) - return m_StreamingDestination->CreateNewOutgoingStream (remote); + return m_StreamingDestination->CreateNewOutgoingStream (remote, port); return nullptr; } diff --git a/Destination.h b/Destination.h index b605cc9d..35a1653b 100644 --- a/Destination.h +++ b/Destination.h @@ -41,7 +41,7 @@ namespace client // streaming i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; }; - i2p::stream::Stream * CreateStream (const i2p::data::LeaseSet& remote); + i2p::stream::Stream * CreateStream (const i2p::data::LeaseSet& remote, int port = 0); void AcceptStreams (const std::function& acceptor); void StopAcceptingStreams (); bool IsAcceptingStreams () const; diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 7ad64cfa..a3d95842 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -52,10 +52,11 @@ namespace proxy } path=m[4].str(); } - LogPrint("server is: ",server, "\n path is: ",path); + LogPrint("server is: ",server, " port is: ", port, "\n path is: ",path); r.uri = path; r.method = method; r.host = server; + r.port = boost::lexical_cast(port); } @@ -77,8 +78,8 @@ namespace proxy } } - LogPrint("Requesting ", r.host, " with path ", r.uri, " and method ", r.method); - SendToAddress (r.host, m_Buffer, m_BufferLen); + LogPrint("Requesting ", r.host, ":", r.port, " with path ", r.uri, " and method ", r.method); + SendToAddress (r.host, r.port, m_Buffer, m_BufferLen); } } diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 7ab07005..b4c7f1dc 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -839,10 +839,10 @@ namespace util { std::string request = "GET " + uri + " HTTP/1.1\r\nHost:" + address + "\r\n"; LogPrint("HTTP Client Request: ", request); - SendToAddress (address, request.c_str (), request.size ()); + SendToAddress (address, 80, request.c_str (), request.size ()); } - void HTTPConnection::SendToAddress (const std::string& address, const char * buf, size_t len) + void HTTPConnection::SendToAddress (const std::string& address, int port, const char * buf, size_t len) { i2p::data::IdentHash destination; if (!i2p::data::netdb.GetAddressBook ().GetIdentHash (address, destination)) @@ -854,33 +854,34 @@ namespace util auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); if (leaseSet && leaseSet->HasNonExpiredLeases ()) - SendToDestination (leaseSet, buf, len); + SendToDestination (leaseSet, port, buf, len); else { i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ()); m_Timer.expires_from_now (boost::posix_time::seconds(HTTP_DESTINATION_REQUEST_TIMEOUT)); m_Timer.async_wait (boost::bind (&HTTPConnection::HandleDestinationRequestTimeout, - this, boost::asio::placeholders::error, destination, buf, len)); + this, boost::asio::placeholders::error, destination, port, buf, len)); } } - void HTTPConnection::HandleDestinationRequestTimeout (const boost::system::error_code& ecode, i2p::data::IdentHash destination, const char * buf, size_t len) + void HTTPConnection::HandleDestinationRequestTimeout (const boost::system::error_code& ecode, + i2p::data::IdentHash destination, int port, const char * buf, size_t len) { if (ecode != boost::asio::error::operation_aborted) { auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); if (leaseSet && leaseSet->HasNonExpiredLeases ()) - SendToDestination (leaseSet, buf, len); + SendToDestination (leaseSet, port, buf, len); else // still no LeaseSet SendReply (leaseSet ? "" + itoopieImage + "
Leases expired" : "" + itoopieImage + "LeaseSet not found", 504); } } - void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, const char * buf, size_t len) + void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, int port, const char * buf, size_t len) { if (!m_Stream) - m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (*remote); + m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (*remote, port); if (m_Stream) { m_Stream->Send ((uint8_t *)buf, len); diff --git a/HTTPServer.h b/HTTPServer.h index 30545639..c7d6b0e4 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -29,6 +29,7 @@ namespace util std::string method; std::string uri; std::string host; + int port; int http_version_major; int http_version_minor; std::vector
headers; @@ -88,9 +89,10 @@ namespace util virtual void RunRequest (); void HandleDestinationRequest(const std::string& address, const std::string& uri); - void SendToAddress (const std::string& address, const char * buf, size_t len); - void HandleDestinationRequestTimeout (const boost::system::error_code& ecode, i2p::data::IdentHash destination, const char * buf, size_t len); - void SendToDestination (const i2p::data::LeaseSet * remote, const char * buf, size_t len); + void SendToAddress (const std::string& address, int port, const char * buf, size_t len); + void HandleDestinationRequestTimeout (const boost::system::error_code& ecode, + i2p::data::IdentHash destination, int port, const char * buf, size_t len); + void SendToDestination (const i2p::data::LeaseSet * remote, int port, const char * buf, size_t len); public: diff --git a/Streaming.cpp b/Streaming.cpp index 572d12c2..dba42d29 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -12,12 +12,12 @@ namespace i2p namespace stream { Stream::Stream (boost::asio::io_service& service, StreamingDestination& local, - const i2p::data::LeaseSet& remote): m_Service (service), m_SendStreamID (0), + const i2p::data::LeaseSet& remote, int port): m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_IsOpen (false), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local), m_RemoteLeaseSet (&remote), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), - m_NumReceivedBytes (0) + m_NumReceivedBytes (0), m_Port (port) { m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); UpdateCurrentRemoteLease (); @@ -28,7 +28,7 @@ namespace stream m_IsOpen (false), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local), m_RemoteLeaseSet (nullptr), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), - m_NumReceivedBytes (0) + m_NumReceivedBytes (0), m_Port (0) { m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); } @@ -441,8 +441,7 @@ namespace stream std::vector msgs; for (auto it: packets) { - auto msg = m_RoutingSession->WrapSingleMessage ( - m_LocalDestination.CreateDataMessage (it->GetBuffer (), it->GetLength ())); + auto msg = m_RoutingSession->WrapSingleMessage (CreateDataMessage (it->GetBuffer (), it->GetLength ())); msgs.push_back (i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, @@ -531,6 +530,30 @@ namespace stream m_CurrentRemoteLease.endDate = 0; } + I2NPMessage * Stream::CreateDataMessage (const uint8_t * payload, size_t len) + { + I2NPMessage * msg = NewI2NPShortMessage (); + CryptoPP::Gzip compressor; + if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE) + compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL); + else + compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL); + compressor.Put (payload, len); + compressor.MessageEnd(); + int size = compressor.MaxRetrievable (); + uint8_t * buf = msg->GetPayload (); + *(uint32_t *)buf = htobe32 (size); // length + buf += 4; + compressor.Get (buf, size); + *(uint16_t *)(buf + 4) = 0; // source port + *(uint16_t *)(buf + 6) = htobe16 (m_Port); // destination port + buf[9] = i2p::client::PROTOCOL_TYPE_STREAMING; // streaming protocol + msg->len += size + 4; + FillI2NPMessageHeader (msg, eI2NPData); + + return msg; + } + void StreamingDestination::Start () { } @@ -574,9 +597,9 @@ namespace stream } } - Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote) + Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port) { - Stream * s = new Stream (*m_Owner.GetService (), *this, remote); + Stream * s = new Stream (*m_Owner.GetService (), *this, remote, port); std::unique_lock l(m_StreamsMutex); m_Streams[s->GetRecvStreamID ()] = s; return s; @@ -628,29 +651,6 @@ namespace stream } } - I2NPMessage * StreamingDestination::CreateDataMessage (const uint8_t * payload, size_t len) - { - I2NPMessage * msg = NewI2NPShortMessage (); - CryptoPP::Gzip compressor; - if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE) - compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL); - else - compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL); - compressor.Put (payload, len); - compressor.MessageEnd(); - int size = compressor.MaxRetrievable (); - uint8_t * buf = msg->GetPayload (); - *(uint32_t *)buf = htobe32 (size); // length - buf += 4; - compressor.Get (buf, size); - memset (buf + 4, 0, 4); // source and destination ports. TODO: fill with proper values later - buf[9] = i2p::client::PROTOCOL_TYPE_STREAMING; // streaming protocol - msg->len += size + 4; - FillI2NPMessageHeader (msg, eI2NPData); - - return msg; - } - void DeleteStream (Stream * stream) { if (stream) diff --git a/Streaming.h b/Streaming.h index 6d57a8ad..1c8958b2 100644 --- a/Streaming.h +++ b/Streaming.h @@ -82,7 +82,8 @@ namespace stream { public: - Stream (boost::asio::io_service& service, StreamingDestination& local, const i2p::data::LeaseSet& remote); // outgoing + Stream (boost::asio::io_service& service, StreamingDestination& local, + const i2p::data::LeaseSet& remote, int port = 0); // outgoing Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming ~Stream (); @@ -126,6 +127,8 @@ namespace stream void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); void HandleAckSendTimer (const boost::system::error_code& ecode); + + I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); private: @@ -143,6 +146,7 @@ namespace stream std::set m_SentPackets; boost::asio::deadline_timer m_ReceiveTimer, m_ResendTimer, m_AckSendTimer; size_t m_NumSentBytes, m_NumReceivedBytes; + uint16_t m_Port; }; class StreamingDestination @@ -155,14 +159,13 @@ namespace stream void Start (); void Stop (); - Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote); + Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port = 0); void DeleteStream (Stream * stream); void SetAcceptor (const std::function& acceptor) { m_Acceptor = acceptor; }; void ResetAcceptor () { m_Acceptor = nullptr; }; bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; i2p::client::ClientDestination& GetOwner () { return m_Owner; }; - I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); void HandleDataMessagePayload (const uint8_t * buf, size_t len); private: From 61d36ea8c390e79d494b044610a33cc0dbcb95c8 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Oct 2014 16:56:50 -0400 Subject: [PATCH 15/35] send datagram --- Datagram.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Datagram.h | 12 +++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index 5c3cd259..e05b5463 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -1,11 +1,56 @@ +#include +#include +#include #include #include "Log.h" +#include "TunnelBase.h" +#include "RouterContext.h" +#include "Destination.h" #include "Datagram.h" namespace i2p { namespace datagram { + DatagramDestination::DatagramDestination (i2p::client::ClientDestination& owner): + m_Owner (owner) + { + auto identityLen = m_Owner.GetIdentity ().ToBuffer (m_OutgoingBuffer, MAX_DATAGRAM_SIZE); + m_Signature = m_OutgoingBuffer + identityLen; + auto signatureLen = m_Owner.GetIdentity ().GetSignatureLen (); + m_Payload = m_Signature + signatureLen; + m_HeaderLen = identityLen + signatureLen; + } + + void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote) + { + auto leases = remote.GetNonExpiredLeases (); + if (!leases.empty ()) + { + memcpy (m_Payload, payload, len); + if (m_Owner.GetIdentity ().GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + CryptoPP::SHA256().CalculateDigest (hash, m_Payload, len); + m_Owner.Sign (hash, 32, m_Signature); + } + else + m_Owner.Sign (m_Payload, len, m_Signature); + + std::vector msgs; + uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1); + auto msg = m_Owner.WrapMessage (remote, CreateDataMessage (m_OutgoingBuffer, len + m_HeaderLen)); + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { + i2p::tunnel::eDeliveryTypeTunnel, + leases[i].tunnelGateway, leases[i].tunnelID, + msg + }); + } + else + LogPrint ("Failed to send datagram. All leases expired"); + } + void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len) { // unzip it @@ -24,6 +69,23 @@ namespace datagram } + I2NPMessage * DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len) + { + I2NPMessage * msg = NewI2NPMessage (); + CryptoPP::Gzip compressor; // default level + compressor.Put (payload, len); + compressor.MessageEnd(); + int size = compressor.MaxRetrievable (); + uint8_t * buf = msg->GetPayload (); + *(uint32_t *)buf = htobe32 (size); // length + buf += 4; + compressor.Get (buf, size); + memset (buf + 4, 0, 4); // source and destination are zeroes + buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol + msg->len += size + 4; + FillI2NPMessageHeader (msg, eI2NPData); + return msg; + } } } diff --git a/Datagram.h b/Datagram.h index d5c21f6b..5d8f6f5b 100644 --- a/Datagram.h +++ b/Datagram.h @@ -2,6 +2,8 @@ #define DATAGRAM_H__ #include +#include "LeaseSet.h" +#include "I2NPProtocol.h" namespace i2p { @@ -16,14 +18,22 @@ namespace datagram { public: - DatagramDestination (i2p::client::ClientDestination& owner): m_Owner (owner) {}; + DatagramDestination (i2p::client::ClientDestination& owner); ~DatagramDestination () {}; + void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote); void HandleDataMessagePayload (const uint8_t * buf, size_t len); + private: + + I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); + private: i2p::client::ClientDestination& m_Owner; + uint8_t m_OutgoingBuffer[MAX_DATAGRAM_SIZE]; + uint8_t * m_Signature, * m_Payload; + size_t m_HeaderLen; }; } } From 336fa8eed79eecd13984719b3de592b08e59220a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Oct 2014 19:04:46 -0400 Subject: [PATCH 16/35] fixed windows build --- SAM.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/SAM.cpp b/SAM.cpp index fcc90106..00bb40f6 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -259,7 +259,11 @@ namespace client size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); priv[l1] = 0; +#ifdef _WIN32 + size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); +#else size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); +#endif SendMessageReply (m_Buffer, l2, false); } @@ -377,7 +381,11 @@ namespace client l = localDestination->GetIdentity ().ToBuffer (buf, 1024); l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024); pub[l1] = 0; +#ifdef _WIN32 + size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv); +#else size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv); +#endif SendMessageReply (m_Buffer, len, true); } else @@ -408,7 +416,11 @@ namespace client } else { +#ifdef _WIN32 + size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str()); +#else size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str()); +#endif SendMessageReply (m_Buffer, len, false); } } @@ -421,7 +433,11 @@ namespace client size_t l = identity.ToBuffer (buf, 1024); size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024); pub[l1] = 0; +#ifdef _WIN32 + size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub); +#else size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub); +#endif SendMessageReply (m_Buffer, l2, false); } From 47fb6f6e04b6b0b8a30b3b9c44b407ae134967a3 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Oct 2014 21:14:17 -0400 Subject: [PATCH 17/35] send datagram from SAM --- Datagram.cpp | 3 ++- SAM.cpp | 39 +++++++++++++++++++++++++++++++++++++++ SAM.h | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index e05b5463..dc4a01f9 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -39,13 +39,14 @@ namespace datagram std::vector msgs; uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1); - auto msg = m_Owner.WrapMessage (remote, CreateDataMessage (m_OutgoingBuffer, len + m_HeaderLen)); + auto msg = m_Owner.WrapMessage (remote, CreateDataMessage (m_OutgoingBuffer, len + m_HeaderLen), true); msgs.push_back (i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, leases[i].tunnelGateway, leases[i].tunnelID, msg }); + m_Owner.SendTunnelDataMsgs (msgs); } else LogPrint ("Failed to send datagram. All leases expired"); diff --git a/SAM.cpp b/SAM.cpp index 00bb40f6..7f9f4b9f 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -677,6 +677,45 @@ namespace client { if (!ecode) { + m_DatagramReceiveBuffer[bytes_transferred] = 0; + char * eol = strchr ((char *)m_DatagramReceiveBuffer, '\n'); + *eol = 0; eol++; + size_t payloadLen = bytes_transferred - ((uint8_t *)eol - m_DatagramReceiveBuffer); + LogPrint ("SAM datagram received ", m_DatagramReceiveBuffer," size=", payloadLen); + char * sessionID = strchr ((char *)m_DatagramReceiveBuffer, ' '); + if (sessionID) + { + sessionID++; + char * destination = strchr (sessionID, ' '); + if (destination) + { + *destination = 0; destination++; + auto session = FindSession (sessionID); + if (session) + { + uint8_t ident[1024]; + size_t l = i2p::data::Base64ToByteStream (destination, strlen(destination), ident, 1024); + i2p::data::IdentityEx dest; + dest.FromBuffer (ident, l); + auto leaseSet = i2p::data::netdb.FindLeaseSet (dest.GetIdentHash ()); + if (leaseSet) + session->localDestination->GetDatagramDestination ()-> + SendDatagramTo ((uint8_t *)eol, payloadLen, *leaseSet); + else + { + LogPrint ("SAM datagram destination not found"); + i2p::data::netdb.RequestDestination (dest.GetIdentHash (), true, + session->localDestination->GetTunnelPool ()); + } + } + else + LogPrint ("Session ", sessionID, " not found"); + } + else + LogPrint ("Missing destination key"); + } + else + LogPrint ("Missing sessionID"); ReceiveDatagram (); } else diff --git a/SAM.h b/SAM.h index abf2b609..e1e369b6 100644 --- a/SAM.h +++ b/SAM.h @@ -159,7 +159,7 @@ namespace client SAMSocket * m_NewSocket; std::mutex m_SessionsMutex; std::map m_Sessions; - uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE]; + uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1]; }; } } From 39bdfa879139d5a9b885e6ec2b846b7bf95c5657 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 11:25:07 -0400 Subject: [PATCH 18/35] take identity of local RI from private keys --- RouterInfo.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index f6203a1d..0793e996 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -290,7 +290,6 @@ namespace data void RouterInfo::WriteToStream (std::ostream& s) { - s.write ((char *)&m_RouterIdentity, sizeof (m_RouterIdentity)); uint64_t ts = htobe64 (m_Timestamp); s.write ((char *)&ts, sizeof (ts)); @@ -419,6 +418,9 @@ namespace data { m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); // refresh timstamp std::stringstream s; + uint8_t ident[1024]; + auto identLen = privateKeys.GetPublic ().ToBuffer (ident, 1024); + s.write ((char *)ident, identLen); WriteToStream (s); m_BufferLen = s.str ().size (); if (!m_Buffer) From f81a122223862711f82aedf182eb7de8bf103bab Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 13:04:14 -0400 Subject: [PATCH 19/35] use remote router indentity --- NTCPSession.cpp | 18 ++++++------------ NTCPSession.h | 1 + 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index d1689bc1..1cdbca48 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -3,7 +3,6 @@ #include "I2PEndian.h" #include #include -#include #include "base64.h" #include "Log.h" #include "Timestamp.h" @@ -120,11 +119,12 @@ namespace transport { if (!m_DHKeysPair) m_DHKeysPair = transports.GetNextDHKeysPair (); + m_RemoteRouterIdentity = m_RemoteRouterInfo. GetRouterIdentity (); // send Phase1 const uint8_t * x = m_DHKeysPair->publicKey; memcpy (m_Establisher->phase1.pubKey, x, 256); CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256); - const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash (); + const uint8_t * ident = m_RemoteRouterIdentity.GetIdentHash (); for (int i = 0; i < 32; i++) m_Establisher->phase1.HXxorHI[i] ^= ident[i]; @@ -322,7 +322,7 @@ namespace transport { LogPrint ("Phase 3 received: ", bytes_transferred); m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3); - m_RemoteRouterInfo.SetRouterIdentity (m_Establisher->phase3.ident); + m_RemoteRouterIdentity = m_Establisher->phase3.ident; SignedData s; memcpy (s.x, m_Establisher->phase1.pubKey, 256); @@ -331,10 +331,7 @@ namespace transport s.tsA = m_Establisher->phase3.timestamp; s.tsB = tsB; - CryptoPP::DSA::PublicKey pubKey; - pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128)); - CryptoPP::DSA::Verifier verifier (pubKey); - if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature, 40)) + if (!m_RemoteRouterIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature)) { LogPrint ("signature verification failed"); Terminate (); @@ -350,7 +347,7 @@ namespace transport SignedData s; memcpy (s.x, m_Establisher->phase1.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256); - memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32); + memcpy (s.ident, m_RemoteRouterIdentity.GetIdentHash (), 32); s.tsA = m_Establisher->phase3.timestamp; s.tsB = tsB; i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature); @@ -402,10 +399,7 @@ namespace transport s.tsA = tsA; s.tsB = m_Establisher->phase2.encrypted.timestamp; - CryptoPP::DSA::PublicKey pubKey; - pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128)); - CryptoPP::DSA::Verifier verifier (pubKey); - if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature, 40)) + if (!m_RemoteRouterIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature)) { LogPrint ("signature verification failed"); Terminate (); diff --git a/NTCPSession.h b/NTCPSession.h index 4a5e463a..112144a1 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -135,6 +135,7 @@ namespace transport CryptoPP::Adler32 m_Adler; i2p::data::RouterInfo& m_RemoteRouterInfo; + i2p::data::IdentityEx m_RemoteRouterIdentity; struct Establisher { From 8d75d518031a3cc350821152d214d2f4a22c482f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 13:36:55 -0400 Subject: [PATCH 20/35] don't specify RI for inbound NTCP connections --- HTTPServer.cpp | 6 +++--- NTCPSession.cpp | 24 +++++++++++++++--------- NTCPSession.h | 13 +++++-------- Transports.cpp | 4 ++-- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index b4c7f1dc..3a0aedc9 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -701,12 +701,12 @@ namespace util s << "NTCP
"; for (auto it: i2p::transport::transports.GetNTCPSessions ()) { - // RouterInfo of incoming connection doesn't have address - bool outgoing = it.second->GetRemoteRouterInfo ().GetNTCPAddress (); if (it.second->IsEstablished ()) { + // incoming connection doesn't have remote RI + bool outgoing = it.second->GetRemoteRouterInfo (); if (outgoing) s << "-->"; - s << it.second->GetRemoteRouterInfo ().GetIdentHashAbbreviation () << ": " + s << it.second->GetRemoteRouterIdentity ().GetIdentHash ().ToBase64 ().substr (0, 4) << ": " << it.second->GetSocket ().remote_endpoint().address ().to_string (); if (!outgoing) s << "-->"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 1cdbca48..5a41bada 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -18,7 +18,7 @@ namespace i2p { namespace transport { - NTCPSession::NTCPSession (boost::asio::io_service& service, 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_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0) @@ -81,7 +81,8 @@ namespace transport for (auto it :m_DelayedMessages) { // try to send them again - transports.SendMessage (m_RemoteRouterInfo.GetIdentHash (), it); + if (m_RemoteRouterInfo) + transports.SendMessage (m_RemoteRouterInfo->GetIdentHash (), it); numDelayed++; } m_DelayedMessages.clear (); @@ -117,9 +118,14 @@ namespace transport void NTCPSession::ClientLogin () { + if (!m_RemoteRouterInfo) + { + LogPrint ("Remote router info is not set"); + Terminate (); + } if (!m_DHKeysPair) m_DHKeysPair = transports.GetNextDHKeysPair (); - m_RemoteRouterIdentity = m_RemoteRouterInfo. GetRouterIdentity (); + m_RemoteRouterIdentity = m_RemoteRouterInfo->GetRouterIdentity (); // send Phase1 const uint8_t * x = m_DHKeysPair->publicKey; memcpy (m_Establisher->phase1.pubKey, x, 256); @@ -237,7 +243,7 @@ namespace transport LogPrint ("Phase 2 read error: ", ecode.message (), ". Wrong ident assumed"); if (ecode != boost::asio::error::operation_aborted) { - GetRemoteRouterInfo ().SetUnreachable (true); // this RouterInfo is not valid + m_RemoteRouterInfo->SetUnreachable (true); // this RouterInfo is not valid transports.ReuseDHKeysPair (m_DHKeysPair); m_DHKeysPair = nullptr; Terminate (); @@ -282,7 +288,7 @@ namespace transport SignedData s; memcpy (s.x, m_Establisher->phase1.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256); - memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32); + memcpy (s.ident, m_RemoteRouterIdentity.GetIdentHash (), 32); s.tsA = tsA; s.tsB = m_Establisher->phase2.encrypted.timestamp; i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase3.signature); @@ -382,7 +388,7 @@ namespace transport LogPrint ("Phase 4 read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) { - GetRemoteRouterInfo ().SetUnreachable (true); // this router doesn't like us + m_RemoteRouterInfo->SetUnreachable (true); // this router doesn't like us Terminate (); } } @@ -594,8 +600,7 @@ namespace transport NTCPClient::NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, i2p::data::RouterInfo& in_RouterInfo): - NTCPSession (service, in_RouterInfo), - m_Endpoint (address, port) + NTCPSession (service, &in_RouterInfo), m_Endpoint (address, port) { Connect (); } @@ -614,7 +619,8 @@ namespace transport LogPrint ("Connect error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) { - GetRemoteRouterInfo ().SetUnreachable (true); + if (GetRemoteRouterInfo ()) + GetRemoteRouterInfo ()->SetUnreachable (true); Terminate (); } } diff --git a/NTCPSession.h b/NTCPSession.h index 112144a1..1af00eba 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -71,12 +71,13 @@ namespace transport { public: - NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo); + NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo * in_RemoteRouterInfo = nullptr); virtual ~NTCPSession (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; bool IsEstablished () const { return m_IsEstablished; }; - i2p::data::RouterInfo& GetRemoteRouterInfo () { return m_RemoteRouterInfo; }; + i2p::data::RouterInfo * GetRemoteRouterInfo () { return m_RemoteRouterInfo; }; + const i2p::data::IdentityEx& GetRemoteRouterIdentity () { return m_RemoteRouterIdentity; }; void ClientLogin (); void ServerLogin (); @@ -134,7 +135,7 @@ namespace transport i2p::crypto::CBCEncryption m_Encryption; CryptoPP::Adler32 m_Adler; - i2p::data::RouterInfo& m_RemoteRouterInfo; + i2p::data::RouterInfo * m_RemoteRouterInfo; i2p::data::IdentityEx m_RemoteRouterIdentity; struct Establisher @@ -176,15 +177,11 @@ namespace transport public: NTCPServerConnection (boost::asio::io_service& service): - NTCPSession (service, m_DummyRemoteRouterInfo) {}; + NTCPSession (service) {}; protected: virtual void Connected (); - - private: - - i2p::data::RouterInfo m_DummyRemoteRouterInfo; }; } } diff --git a/Transports.cpp b/Transports.cpp index 6747febd..4661d439 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -184,13 +184,13 @@ namespace transport void Transports::AddNTCPSession (NTCPSession * session) { if (session) - m_NTCPSessions[session->GetRemoteRouterInfo ().GetIdentHash ()] = session; + m_NTCPSessions[session->GetRemoteRouterIdentity ().GetIdentHash ()] = session; } void Transports::RemoveNTCPSession (NTCPSession * session) { if (session) - m_NTCPSessions.erase (session->GetRemoteRouterInfo ().GetIdentHash ()); + m_NTCPSessions.erase (session->GetRemoteRouterIdentity ().GetIdentHash ()); } void Transports::HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error) From a96d70a94ceb4fd2a5def1057b5a740a07d6eda0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 14:24:48 -0400 Subject: [PATCH 21/35] initialize router identity --- NTCPSession.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 5a41bada..46670bb7 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -23,6 +23,8 @@ namespace transport m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0) { + if (m_RemoteRouterInfo) + m_RemoteRouterIdentity = m_RemoteRouterInfo->GetRouterIdentity (); m_DHKeysPair = transports.GetNextDHKeysPair (); m_Establisher = new Establisher; } @@ -118,14 +120,8 @@ namespace transport void NTCPSession::ClientLogin () { - if (!m_RemoteRouterInfo) - { - LogPrint ("Remote router info is not set"); - Terminate (); - } if (!m_DHKeysPair) m_DHKeysPair = transports.GetNextDHKeysPair (); - m_RemoteRouterIdentity = m_RemoteRouterInfo->GetRouterIdentity (); // send Phase1 const uint8_t * x = m_DHKeysPair->publicKey; memcpy (m_Establisher->phase1.pubKey, x, 256); @@ -634,11 +630,8 @@ namespace transport void NTCPServerConnection::Connected () { LogPrint ("NTCP server session connected"); - SetIsEstablished (true); transports.AddNTCPSession (this); - - SendTimeSyncMessage (); - SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are + NTCPSession::Connected (); } } } From af997473b227e173a4717124858230fc6a283e21 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 15:22:36 -0400 Subject: [PATCH 22/35] moved AddressBook to ClientContext --- AddressBook.cpp | 10 +++++----- AddressBook.h | 8 ++++---- ClientContext.h | 5 +++++ HTTPProxy.cpp | 4 ++-- HTTPServer.cpp | 2 +- I2PTunnel.cpp | 4 ++-- NetDb.h | 3 --- SAM.cpp | 2 +- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 2d0d2624..7fc39841 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -11,14 +11,14 @@ namespace i2p { -namespace data +namespace client { AddressBook::AddressBook (): m_IsLoaded (false), m_IsDowloading (false) { } - bool AddressBook::GetIdentHash (const std::string& address, IdentHash& ident) + bool AddressBook::GetIdentHash (const std::string& address, i2p::data::IdentHash& ident) { auto pos = address.find(".b32.i2p"); if (pos != std::string::npos) @@ -42,7 +42,7 @@ namespace data return false; } - const IdentHash * AddressBook::FindAddress (const std::string& address) + const i2p::data::IdentHash * AddressBook::FindAddress (const std::string& address) { if (!m_IsLoaded) LoadHosts (); @@ -57,7 +57,7 @@ namespace data void AddressBook::InsertAddress (const std::string& address, const std::string& base64) { - IdentityEx ident; + i2p::data::IdentityEx ident; ident.FromBase64 (base64); m_Addresses[address] = ident.GetIdentHash (); LogPrint (address,"->",ident.GetIdentHash ().ToBase32 (), ".b32.i2p added"); @@ -118,7 +118,7 @@ namespace data std::string name = s.substr(0, pos++); std::string addr = s.substr(pos); - IdentityEx ident; + i2p::data::IdentityEx ident; ident.FromBase64(addr); m_Addresses[name] = ident.GetIdentHash (); numAddresses++; diff --git a/AddressBook.h b/AddressBook.h index db9d2319..8131a032 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -11,15 +11,15 @@ namespace i2p { -namespace data +namespace client { class AddressBook { public: AddressBook (); - bool GetIdentHash (const std::string& address, IdentHash& ident); - const IdentHash * FindAddress (const std::string& address); + bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident); + const i2p::data::IdentHash * FindAddress (const std::string& address); void InsertAddress (const std::string& address, const std::string& base64); // for jump service private: @@ -27,7 +27,7 @@ namespace data void LoadHosts (); void LoadHostsFromI2P (); - std::map m_Addresses; + std::map m_Addresses; bool m_IsLoaded, m_IsDowloading; }; } diff --git a/ClientContext.h b/ClientContext.h index 58c2cf36..da65f3f8 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -7,6 +7,7 @@ #include "SOCKS.h" #include "I2PTunnel.h" #include "SAM.h" +#include "AddressBook.h" namespace i2p { @@ -29,6 +30,8 @@ namespace client ClientDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const; ClientDestination * LoadLocalDestination (const std::string& filename, bool isPublic); + AddressBook& GetAddressBook () { return m_AddressBook; }; + private: void LoadLocalDestinations (); @@ -39,6 +42,8 @@ namespace client std::map m_Destinations; ClientDestination * m_SharedLocalDestination; + AddressBook m_AddressBook; + i2p::proxy::HTTPProxy * m_HttpProxy; i2p::proxy::SOCKSProxy * m_SocksProxy; I2PClientTunnel * m_IrcTunnel; diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index a3d95842..ae644b6a 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -1,7 +1,7 @@ #include #include -#include "NetDb.h" +#include "ClientContext.h" #include "HTTPProxy.h" namespace i2p @@ -74,7 +74,7 @@ namespace proxy { LogPrint ("Jump service for ", r.host, " found. Inserting to address book"); auto base64 = r.uri.substr (addressPos + 1); - i2p::data::netdb.GetAddressBook ().InsertAddress (r.host, base64); + i2p::client::context.GetAddressBook ().InsertAddress (r.host, base64); } } diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 3a0aedc9..3f385af6 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -845,7 +845,7 @@ namespace util void HTTPConnection::SendToAddress (const std::string& address, int port, const char * buf, size_t len) { i2p::data::IdentHash destination; - if (!i2p::data::netdb.GetAddressBook ().GetIdentHash (address, destination)) + if (!i2p::client::context.GetAddressBook ().GetIdentHash (address, destination)) { LogPrint ("Unknown address ", address); SendReply ("" + itoopieImage + "
Unknown address " + address + "", 404); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index a8193bdd..8dadabae 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -162,7 +162,7 @@ namespace client void I2PClientTunnel::Start () { i2p::data::IdentHash identHash; - if (i2p::data::netdb.GetAddressBook ().GetIdentHash (m_Destination, identHash)) + if (i2p::client::context.GetAddressBook ().GetIdentHash (m_Destination, identHash)) m_DestinationIdentHash = new i2p::data::IdentHash (identHash); if (!m_DestinationIdentHash) LogPrint ("I2PTunnel unknown destination ", m_Destination); @@ -192,7 +192,7 @@ namespace client if (!m_DestinationIdentHash) { i2p::data::IdentHash identHash; - if (i2p::data::netdb.GetAddressBook ().GetIdentHash (m_Destination, identHash)) + if (i2p::client::context.GetAddressBook ().GetIdentHash (m_Destination, identHash)) m_DestinationIdentHash = new i2p::data::IdentHash (identHash); } if (m_DestinationIdentHash) diff --git a/NetDb.h b/NetDb.h index ca62163c..384d1c80 100644 --- a/NetDb.h +++ b/NetDb.h @@ -15,7 +15,6 @@ #include "LeaseSet.h" #include "Tunnel.h" #include "TunnelPool.h" -#include "AddressBook.h" namespace i2p { @@ -67,7 +66,6 @@ namespace data void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, i2p::tunnel::InboundTunnel * from); RouterInfo * FindRouter (const IdentHash& ident) const; LeaseSet * FindLeaseSet (const IdentHash& destination) const; - AddressBook& GetAddressBook () { return m_AddressBook; };// TODO: move AddressBook away from NetDb void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool); void RequestDestination (const IdentHash& destination, bool isLeaseSet = false, @@ -120,7 +118,6 @@ namespace data int m_ReseedRetries; std::thread * m_Thread; i2p::util::Queue m_Queue; // of I2NPDatabaseStoreMsg - AddressBook m_AddressBook; static const char m_NetDbPath[]; }; diff --git a/SAM.cpp b/SAM.cpp index 7f9f4b9f..cd976aa4 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -401,7 +401,7 @@ namespace client i2p::data::IdentHash ident; if (name == "ME") SendNamingLookupReply (nullptr); - else if (m_Session && i2p::data::netdb.GetAddressBook ().GetIdentHash (name, ident)) + else if (m_Session && context.GetAddressBook ().GetIdentHash (name, ident)) { auto leaseSet = m_Session->localDestination->FindLeaseSet (ident); if (leaseSet) From c9abb62988f7f8d78c4fe944b66a0a1568605c38 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 15:39:53 -0400 Subject: [PATCH 23/35] set unreachable trough NetDb --- HTTPServer.cpp | 4 ++-- NTCPSession.cpp | 36 +++++++++++++++++++----------------- NTCPSession.h | 12 ++++++------ NetDb.cpp | 7 +++++++ NetDb.h | 3 ++- Transports.cpp | 4 ++-- 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 3f385af6..35ef512c 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -704,9 +704,9 @@ namespace util if (it.second->IsEstablished ()) { // incoming connection doesn't have remote RI - bool outgoing = it.second->GetRemoteRouterInfo (); + bool outgoing = it.second->GetRemoteRouter (); if (outgoing) s << "-->"; - s << it.second->GetRemoteRouterIdentity ().GetIdentHash ().ToBase64 ().substr (0, 4) << ": " + s << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase64 ().substr (0, 4) << ": " << it.second->GetSocket ().remote_endpoint().address ().to_string (); if (!outgoing) s << "-->"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 46670bb7..a1950200 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -10,6 +10,7 @@ #include "I2NPProtocol.h" #include "RouterContext.h" #include "Transports.h" +#include "NetDb.h" #include "NTCPSession.h" using namespace i2p::crypto; @@ -18,13 +19,13 @@ namespace i2p { namespace transport { - NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo * in_RemoteRouterInfo): + NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter): m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false), - m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), + m_RemoteRouter (in_RemoteRouter), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0) { - if (m_RemoteRouterInfo) - m_RemoteRouterIdentity = m_RemoteRouterInfo->GetRouterIdentity (); + if (m_RemoteRouter) + m_RemoteIdentity = m_RemoteRouter->GetRouterIdentity (); m_DHKeysPair = transports.GetNextDHKeysPair (); m_Establisher = new Establisher; } @@ -83,8 +84,8 @@ namespace transport for (auto it :m_DelayedMessages) { // try to send them again - if (m_RemoteRouterInfo) - transports.SendMessage (m_RemoteRouterInfo->GetIdentHash (), it); + if (m_RemoteRouter) + transports.SendMessage (m_RemoteRouter->GetIdentHash (), it); numDelayed++; } m_DelayedMessages.clear (); @@ -126,7 +127,7 @@ namespace transport const uint8_t * x = m_DHKeysPair->publicKey; memcpy (m_Establisher->phase1.pubKey, x, 256); CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256); - const uint8_t * ident = m_RemoteRouterIdentity.GetIdentHash (); + const uint8_t * ident = m_RemoteIdentity.GetIdentHash (); for (int i = 0; i < 32; i++) m_Establisher->phase1.HXxorHI[i] ^= ident[i]; @@ -239,7 +240,8 @@ namespace transport LogPrint ("Phase 2 read error: ", ecode.message (), ". Wrong ident assumed"); if (ecode != boost::asio::error::operation_aborted) { - m_RemoteRouterInfo->SetUnreachable (true); // this RouterInfo is not valid + // this RI is not valid + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true); transports.ReuseDHKeysPair (m_DHKeysPair); m_DHKeysPair = nullptr; Terminate (); @@ -284,7 +286,7 @@ namespace transport SignedData s; memcpy (s.x, m_Establisher->phase1.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256); - memcpy (s.ident, m_RemoteRouterIdentity.GetIdentHash (), 32); + memcpy (s.ident, m_RemoteIdentity.GetIdentHash (), 32); s.tsA = tsA; s.tsB = m_Establisher->phase2.encrypted.timestamp; i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase3.signature); @@ -324,7 +326,7 @@ namespace transport { LogPrint ("Phase 3 received: ", bytes_transferred); m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3); - m_RemoteRouterIdentity = m_Establisher->phase3.ident; + m_RemoteIdentity = m_Establisher->phase3.ident; SignedData s; memcpy (s.x, m_Establisher->phase1.pubKey, 256); @@ -333,7 +335,7 @@ namespace transport s.tsA = m_Establisher->phase3.timestamp; s.tsB = tsB; - if (!m_RemoteRouterIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature)) + if (!m_RemoteIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature)) { LogPrint ("signature verification failed"); Terminate (); @@ -349,7 +351,7 @@ namespace transport SignedData s; memcpy (s.x, m_Establisher->phase1.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256); - memcpy (s.ident, m_RemoteRouterIdentity.GetIdentHash (), 32); + memcpy (s.ident, m_RemoteIdentity.GetIdentHash (), 32); s.tsA = m_Establisher->phase3.timestamp; s.tsB = tsB; i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature); @@ -384,7 +386,8 @@ namespace transport LogPrint ("Phase 4 read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) { - m_RemoteRouterInfo->SetUnreachable (true); // this router doesn't like us + // this router doesn't like us + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true); Terminate (); } } @@ -401,7 +404,7 @@ namespace transport s.tsA = tsA; s.tsB = m_Establisher->phase2.encrypted.timestamp; - if (!m_RemoteRouterIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature)) + if (!m_RemoteIdentity.Verify ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature)) { LogPrint ("signature verification failed"); Terminate (); @@ -595,7 +598,7 @@ namespace transport NTCPClient::NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, - int port, i2p::data::RouterInfo& in_RouterInfo): + int port, const i2p::data::RouterInfo& in_RouterInfo): NTCPSession (service, &in_RouterInfo), m_Endpoint (address, port) { Connect (); @@ -615,8 +618,7 @@ namespace transport LogPrint ("Connect error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) { - if (GetRemoteRouterInfo ()) - GetRemoteRouterInfo ()->SetUnreachable (true); + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true); Terminate (); } } diff --git a/NTCPSession.h b/NTCPSession.h index 1af00eba..8d8b1d67 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -71,13 +71,13 @@ namespace transport { public: - NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo * in_RemoteRouterInfo = nullptr); + NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter = nullptr); virtual ~NTCPSession (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; bool IsEstablished () const { return m_IsEstablished; }; - i2p::data::RouterInfo * GetRemoteRouterInfo () { return m_RemoteRouterInfo; }; - const i2p::data::IdentityEx& GetRemoteRouterIdentity () { return m_RemoteRouterIdentity; }; + const i2p::data::RouterInfo * GetRemoteRouter () { return m_RemoteRouter; }; + const i2p::data::IdentityEx& GetRemoteIdentity () { return m_RemoteIdentity; }; void ClientLogin (); void ServerLogin (); @@ -135,8 +135,8 @@ namespace transport i2p::crypto::CBCEncryption m_Encryption; CryptoPP::Adler32 m_Adler; - i2p::data::RouterInfo * m_RemoteRouterInfo; - i2p::data::IdentityEx m_RemoteRouterIdentity; + const i2p::data::RouterInfo * m_RemoteRouter; + i2p::data::IdentityEx m_RemoteIdentity; struct Establisher { @@ -160,7 +160,7 @@ namespace transport { public: - NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, i2p::data::RouterInfo& in_RouterInfo); + NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, const i2p::data::RouterInfo& in_RouterInfo); private: diff --git a/NetDb.cpp b/NetDb.cpp index f1c20498..eb2800a2 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -229,6 +229,13 @@ namespace data return nullptr; } + void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable) + { + auto it = m_RouterInfos.find (ident); + if (it != m_RouterInfos.end ()) + return it->second->SetUnreachable (unreachable); + } + // TODO: Move to reseed and/or scheduled tasks. (In java version, scheduler fix this as well as sort RIs.) bool NetDb::CreateNetDb(boost::filesystem::path directory) { diff --git a/NetDb.h b/NetDb.h index 384d1c80..b90bef19 100644 --- a/NetDb.h +++ b/NetDb.h @@ -78,7 +78,8 @@ namespace data const RouterInfo * GetRandomRouter () const; const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith) const; const RouterInfo * GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const; - + void SetUnreachable (const IdentHash& ident, bool unreachable); + void PostI2NPMsg (I2NPMessage * msg); // for web interface diff --git a/Transports.cpp b/Transports.cpp index 4661d439..b3a01aee 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -184,13 +184,13 @@ namespace transport void Transports::AddNTCPSession (NTCPSession * session) { if (session) - m_NTCPSessions[session->GetRemoteRouterIdentity ().GetIdentHash ()] = session; + m_NTCPSessions[session->GetRemoteIdentity ().GetIdentHash ()] = session; } void Transports::RemoveNTCPSession (NTCPSession * session) { if (session) - m_NTCPSessions.erase (session->GetRemoteRouterIdentity ().GetIdentHash ()); + m_NTCPSessions.erase (session->GetRemoteIdentity ().GetIdentHash ()); } void Transports::HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error) From 6281fa625abc8812a98d65b1cc641d3c1f89fbd7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 15:50:48 -0400 Subject: [PATCH 24/35] moved remote RI and identity to TransportSession --- NTCPSession.cpp | 6 ++---- NTCPSession.h | 7 +------ SSU.cpp | 10 ++++------ SSU.h | 3 --- TransportSession.h | 15 ++++++++++++++- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index a1950200..8f6faa4b 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -20,12 +20,10 @@ namespace i2p namespace transport { NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter): - m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false), - m_RemoteRouter (in_RemoteRouter), m_ReceiveBufferOffset (0), + TransportSession (in_RemoteRouter), m_Socket (service), + m_TerminationTimer (service), m_IsEstablished (false), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0) { - if (m_RemoteRouter) - m_RemoteIdentity = m_RemoteRouter->GetRouterIdentity (); m_DHKeysPair = transports.GetNextDHKeysPair (); m_Establisher = new Establisher; } diff --git a/NTCPSession.h b/NTCPSession.h index 8d8b1d67..61113772 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -72,12 +72,10 @@ namespace transport public: NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter = nullptr); - virtual ~NTCPSession (); + ~NTCPSession (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; bool IsEstablished () const { return m_IsEstablished; }; - const i2p::data::RouterInfo * GetRemoteRouter () { return m_RemoteRouter; }; - const i2p::data::IdentityEx& GetRemoteIdentity () { return m_RemoteIdentity; }; void ClientLogin (); void ServerLogin (); @@ -134,9 +132,6 @@ namespace transport i2p::crypto::CBCDecryption m_Decryption; i2p::crypto::CBCEncryption m_Encryption; CryptoPP::Adler32 m_Adler; - - const i2p::data::RouterInfo * m_RemoteRouter; - i2p::data::IdentityEx m_RemoteIdentity; struct Establisher { diff --git a/SSU.cpp b/SSU.cpp index a316bddd..96c1e7ae 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -16,8 +16,8 @@ namespace transport { SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, - const i2p::data::RouterInfo * router, bool peerTest ): - m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_RemoteRouter (router), + const i2p::data::RouterInfo * router, bool peerTest ): TransportSession (router), + m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_Timer (m_Server.GetService ()), m_PeerTest (peerTest), m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0), m_Data (*this), m_NumSentBytes (0), m_NumReceivedBytes (0) @@ -232,10 +232,8 @@ namespace transport payload += 2; // size of identity fragment if (identitySize == i2p::data::DEFAULT_IDENTITY_SIZE) { - i2p::data::Identity ident; - ident.FromBuffer (payload, identitySize); - m_RemoteIdent = ident.Hash (); - m_Data.UpdatePacketSize (m_RemoteIdent); + m_RemoteIdentity.FromBuffer (payload, identitySize); + m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ()); } else LogPrint ("SSU unexpected identity size ", identitySize); diff --git a/SSU.h b/SSU.h index 7f1d2563..b9fb781e 100644 --- a/SSU.h +++ b/SSU.h @@ -72,7 +72,6 @@ namespace transport void WaitForIntroduction (); void Close (); boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; - const i2p::data::RouterInfo * GetRemoteRouter () const { return m_RemoteRouter; }; void SendI2NPMessage (I2NPMessage * msg); void SendPeerTest (); // Alice @@ -129,8 +128,6 @@ namespace transport friend class SSUData; // TODO: change in later SSUServer& m_Server; boost::asio::ip::udp::endpoint m_RemoteEndpoint; - const i2p::data::RouterInfo * m_RemoteRouter; - i2p::data::IdentHash m_RemoteIdent; // if m_RemoteRouter is null boost::asio::deadline_timer m_Timer; bool m_PeerTest; SessionState m_State; diff --git a/TransportSession.h b/TransportSession.h index 37b58fe8..0e993508 100644 --- a/TransportSession.h +++ b/TransportSession.h @@ -2,6 +2,8 @@ #define TRANSPORT_SESSION_H__ #include +#include "Identity.h" +#include "RouterInfo.h" namespace i2p { @@ -17,11 +19,22 @@ namespace transport { public: - TransportSession (): m_DHKeysPair (nullptr) {}; + TransportSession (const i2p::data::RouterInfo * in_RemoteRouter): + m_RemoteRouter (in_RemoteRouter), m_DHKeysPair (nullptr) + { + if (m_RemoteRouter) + m_RemoteIdentity = m_RemoteRouter->GetRouterIdentity (); + } + virtual ~TransportSession () { delete m_DHKeysPair; }; + const i2p::data::RouterInfo * GetRemoteRouter () { return m_RemoteRouter; }; + const i2p::data::IdentityEx& GetRemoteIdentity () { return m_RemoteIdentity; }; + protected: + const i2p::data::RouterInfo * m_RemoteRouter; + i2p::data::IdentityEx m_RemoteIdentity; DHKeysPair * m_DHKeysPair; // X - for client and Y - for server }; } From 2308f854b1099c652d9d482672a986a38ef83a92 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Oct 2014 21:51:55 -0400 Subject: [PATCH 25/35] verify signature through remore identity --- SSU.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index 96c1e7ae..27eb6c03 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -214,10 +214,7 @@ namespace transport m_SessionKeyDecryption.SetIV (((SSUHeader *)buf)->iv); m_SessionKeyDecryption.Decrypt (payload, 48, payload); // verify - CryptoPP::DSA::PublicKey pubKey; - pubKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_RemoteRouter->GetRouterIdentity ().signingKey, 128)); - CryptoPP::DSA::Verifier verifier (pubKey); - if (!verifier.VerifyMessage (signedData, 532, payload, 40)) + if (!m_RemoteIdentity.Verify (signedData, 532, payload)) LogPrint ("SSU signature verification failed"); SendSessionConfirmed (y, ourAddress); @@ -230,15 +227,15 @@ namespace transport payload++; // identity fragment info uint16_t identitySize = be16toh (*(uint16_t *)payload); payload += 2; // size of identity fragment - if (identitySize == i2p::data::DEFAULT_IDENTITY_SIZE) - { - m_RemoteIdentity.FromBuffer (payload, identitySize); - m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ()); - } - else - LogPrint ("SSU unexpected identity size ", identitySize); + m_RemoteIdentity.FromBuffer (payload, identitySize); + m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ()); payload += identitySize; // identity - // TODO: verify signature + payload += 4; // signed-on time + size_t paddingSize = (payload - buf) + m_RemoteIdentity.GetSignatureLen (); + paddingSize >>= 4; // %16 + if (paddingSize > 0) paddingSize = 16 - paddingSize; + payload += paddingSize; + // TODO: verify signature (need data from session request), payload points to signature SendI2NPMessage (CreateDeliveryStatusMsg (0)); Established (); } From 65c13f1758ea591ce9dcaf4e467c82f85f375c3a Mon Sep 17 00:00:00 2001 From: Cameron Norman Date: Sat, 25 Oct 2014 18:25:03 -0700 Subject: [PATCH 26/35] Decouple logging and daemonization --- Daemon.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index ea98378b..284466f2 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -84,18 +84,13 @@ namespace i2p // initialize log if (isLogging) { - if (isDaemon) - { - std::string logfile_path = IsService () ? "/var/log" : i2p::util::filesystem::GetDataDir().string(); + std::string logfile_path = IsService () ? "/var/log" : i2p::util::filesystem::GetDataDir().string(); #ifndef _WIN32 - logfile_path.append("/i2pd.log"); + logfile_path.append("/i2pd.log"); #else - logfile_path.append("\\i2pd.log"); + logfile_path.append("\\i2pd.log"); #endif - StartLog (logfile_path); - } - else - StartLog (""); // write to stdout + StartLog (logfile_path); } d.httpServer = new i2p::util::HTTPServer(i2p::util::config::GetArg("-httpport", 7070)); From 61932ff49fefbc6b8bdff9f4675c6197a78299a9 Mon Sep 17 00:00:00 2001 From: Cameron Norman Date: Sat, 25 Oct 2014 18:40:11 -0700 Subject: [PATCH 27/35] Rename init.d to i2pd.init --- debian/{init.d => i2pd.init} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename debian/{init.d => i2pd.init} (100%) diff --git a/debian/init.d b/debian/i2pd.init similarity index 100% rename from debian/init.d rename to debian/i2pd.init From ced41496796d93a3f407a420d81b721d2a913516 Mon Sep 17 00:00:00 2001 From: Cameron Norman Date: Sat, 25 Oct 2014 18:41:04 -0700 Subject: [PATCH 28/35] Implement reload in init script --- debian/i2pd.init | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/debian/i2pd.init b/debian/i2pd.init index 79dea50a..eda135c6 100644 --- a/debian/i2pd.init +++ b/debian/i2pd.init @@ -57,10 +57,10 @@ do_stop() } # Function that sends a SIGHUP to the daemon/service -#do_reload() { -# start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME -# return 0 -#} +do_reload() { + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} case "$1" in start) @@ -82,14 +82,12 @@ case "$1" in status) status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? ;; - #reload|force-reload) - #log_daemon_msg "Reloading $DESC" "$NAME" - #do_reload - #log_end_msg $? - #;; - restart|force-reload) - # If the "reload" option is implemented then remove the - # 'force-reload' alias + reload|force-reload) + log_daemon_msg "Reloading $DESC" "$NAME" + do_reload + log_end_msg $? + ;; + restart) log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in From e768e33ddd862bf988d09b7965867784b2db8596 Mon Sep 17 00:00:00 2001 From: Cameron Norman Date: Sat, 25 Oct 2014 18:42:35 -0700 Subject: [PATCH 29/35] Add Upstart job to debian packaging --- debian/i2pd.upstart | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 debian/i2pd.upstart diff --git a/debian/i2pd.upstart b/debian/i2pd.upstart new file mode 100644 index 00000000..0527935d --- /dev/null +++ b/debian/i2pd.upstart @@ -0,0 +1,10 @@ +description "i2p client daemon" + +start on runlevel [2345] +stop on runlevel [016] or unmounting-filesystem + +# these can be overridden in /etc/init/i2pd.override +env I2P_HOST="1.2.3.4" +env I2P_PORT="4567" + +exec /usr/sbin/i2pd --daemon=0 --log=1 --host=$I2P_HOST --port=$I2P_PORT From a20cc97fa308ebf2700cbeef258fd77d901e8c27 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 25 Oct 2014 22:11:31 -0400 Subject: [PATCH 30/35] Update Daemon.cpp rollback --- Daemon.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index 284466f2..ea98378b 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -84,13 +84,18 @@ namespace i2p // initialize log if (isLogging) { - std::string logfile_path = IsService () ? "/var/log" : i2p::util::filesystem::GetDataDir().string(); + if (isDaemon) + { + std::string logfile_path = IsService () ? "/var/log" : i2p::util::filesystem::GetDataDir().string(); #ifndef _WIN32 - logfile_path.append("/i2pd.log"); + logfile_path.append("/i2pd.log"); #else - logfile_path.append("\\i2pd.log"); + logfile_path.append("\\i2pd.log"); #endif - StartLog (logfile_path); + StartLog (logfile_path); + } + else + StartLog (""); // write to stdout } d.httpServer = new i2p::util::HTTPServer(i2p::util::config::GetArg("-httpport", 7070)); From 1408422da9da45405e271380d9842965a00ec78f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 25 Oct 2014 22:23:28 -0400 Subject: [PATCH 31/35] some cleanup --- RouterInfo.cpp | 12 +----------- RouterInfo.h | 8 +++----- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 0793e996..c88ae02c 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -59,7 +59,6 @@ namespace data { m_RouterIdentity = identity; m_IdentHash = m_RouterIdentity.Hash (); - UpdateIdentHashBase64 (); m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); } @@ -226,7 +225,6 @@ namespace data } CryptoPP::SHA256().CalculateDigest(m_IdentHash, (uint8_t *)&m_RouterIdentity, sizeof (m_RouterIdentity)); - UpdateIdentHashBase64 (); if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers)) SetUnreachable (true); @@ -279,14 +277,6 @@ namespace data SetProperty ("caps", caps.c_str ()); } - - void RouterInfo::UpdateIdentHashBase64 () - { - size_t l = i2p::data::ByteStreamToBase64 (m_IdentHash, 32, m_IdentHashBase64, 48); - m_IdentHashBase64[l] = 0; - memcpy (m_IdentHashAbbreviation, m_IdentHashBase64, 4); - m_IdentHashAbbreviation[4] = 0; - } void RouterInfo::WriteToStream (std::ostream& s) { @@ -409,7 +399,7 @@ namespace data if (!m_Buffer) { if (LoadFile ()) - LogPrint ("Buffer for ", m_IdentHashAbbreviation, " loaded from file"); + LogPrint ("Buffer for ", GetIdentHashAbbreviation (), " loaded from file"); } return m_Buffer; } diff --git a/RouterInfo.h b/RouterInfo.h index 669c85bd..a4ccb159 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -78,7 +78,7 @@ namespace data }; RouterInfo (const std::string& fullPath); - RouterInfo (): m_Buffer (nullptr) { m_IdentHashBase64[0] = 0; m_IdentHashAbbreviation[0] = 0; }; + RouterInfo (): m_Buffer (nullptr) { }; RouterInfo (const RouterInfo& ) = default; RouterInfo& operator=(const RouterInfo& ) = default; RouterInfo (const uint8_t * buf, int len); @@ -86,8 +86,8 @@ namespace data const Identity& GetRouterIdentity () const { return m_RouterIdentity; }; void SetRouterIdentity (const Identity& identity); - const char * GetIdentHashBase64 () const { return m_IdentHashBase64; }; - const char * GetIdentHashAbbreviation () const { return m_IdentHashAbbreviation; }; + std::string GetIdentHashBase64 () const { return m_IdentHash.ToBase64 (); }; + std::string GetIdentHashAbbreviation () const { return m_IdentHash.ToBase64 ().substr (0, 4); }; uint64_t GetTimestamp () const { return m_Timestamp; }; std::vector
& GetAddresses () { return m_Addresses; }; const Address * GetNTCPAddress (bool v4only = true) const; @@ -143,7 +143,6 @@ namespace data size_t ReadString (char * str, std::istream& s); void WriteString (const std::string& str, std::ostream& s); void ExtractCaps (const char * value); - void UpdateIdentHashBase64 (); const Address * GetAddress (TransportStyle s, bool v4only) const; void UpdateCapsProperty (); @@ -152,7 +151,6 @@ namespace data std::string m_FullPath; Identity m_RouterIdentity; IdentHash m_IdentHash; - char m_IdentHashBase64[48], m_IdentHashAbbreviation[5]; uint8_t * m_Buffer; int m_BufferLen; uint64_t m_Timestamp; From 7fb73415027ec2dbcadc3b495b292e474c1369ea Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 26 Oct 2014 21:32:06 -0400 Subject: [PATCH 32/35] support ipv6 for outgoing NTCP connections --- Daemon.cpp | 2 ++ RouterContext.cpp | 12 ++++++++++-- RouterContext.h | 4 +++- RouterInfo.cpp | 32 ++++++++++++++++++++++++++++++-- RouterInfo.h | 9 +++++++++ Transports.cpp | 2 +- 6 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index ea98378b..3836bd96 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -72,6 +72,8 @@ namespace i2p if (i2p::util::config::GetArg("-unreachable", 0)) i2p::context.SetUnreachable (); + i2p::context.SetSupportsV6 (i2p::util::config::GetArg("-v6", 0)); + LogPrint("CMD parameters:"); for (int i = 0; i < argc; ++i) LogPrint(i, " ", argv[i]); diff --git a/RouterContext.cpp b/RouterContext.cpp index 2560e6d4..8832e81e 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -78,7 +78,7 @@ namespace i2p auto newAddress = boost::asio::ip::address::from_string (host); for (auto& address : m_RouterInfo.GetAddresses ()) { - if (address.host != newAddress) + if (address.host != newAddress && address.IsCompatible (newAddress)) { address.host = newAddress; updated = true; @@ -130,7 +130,15 @@ namespace i2p // update UpdateRouterInfo (); } - + + void RouterContext::SetSupportsV6 (bool supportsV6) + { + if (supportsV6) + m_RouterInfo.EnableV6 (); + else + m_RouterInfo.DisableV6 (); + } + bool RouterContext::Load () { std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ofstream::in); diff --git a/RouterContext.h b/RouterContext.h index e10a4192..35f11e2d 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -32,7 +32,9 @@ namespace i2p void SetUnreachable (); bool AcceptsTunnels () const { return m_AcceptsTunnels; }; void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; - + bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; + void SetSupportsV6 (bool supportsV6); + // implements LocalDestination const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const uint8_t * GetEncryptionPrivateKey () const { return m_Keys.GetPrivateKey (); }; diff --git a/RouterInfo.cpp b/RouterInfo.cpp index c88ae02c..960db401 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -458,7 +458,7 @@ namespace data addr.cost = 2; addr.date = 0; m_Addresses.push_back(addr); - m_SupportedTransports |= eNTCPV4; + m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eNTCPV4; } void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key) @@ -471,7 +471,7 @@ namespace data addr.date = 0; memcpy (addr.key, key, 32); m_Addresses.push_back(addr); - m_SupportedTransports |= eSSUV4; + m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eSSUV4; m_Caps |= eSSUTesting; m_Caps |= eSSUIntroducer; } @@ -560,6 +560,34 @@ namespace data return m_SupportedTransports & (eSSUV4 | eSSUV6); } + bool RouterInfo::IsV6 () const + { + return m_SupportedTransports & (eNTCPV6 | eSSUV6); + } + + void RouterInfo::EnableV6 () + { + if (!IsV6 ()) + m_SupportedTransports |= eNTCPV6; + } + + void RouterInfo::DisableV6 () + { + if (IsV6 ()) + { + m_SupportedTransports &= ~eNTCPV6; + for (size_t i = 0; i < m_Addresses.size (); i++) + { + if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportNTCP && + m_Addresses[i].host.is_v6 ()) + { + m_Addresses.erase (m_Addresses.begin () + i); + break; + } + } + } + } + bool RouterInfo::UsesIntroducer () const { return m_Caps & Caps::eUnreachable; // non-reachable diff --git a/RouterInfo.h b/RouterInfo.h index a4ccb159..d5d775b1 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -75,6 +75,12 @@ namespace data // SSU only Tag<32> key; // intro key for SSU std::vector introducers; + + bool IsCompatible (const boost::asio::ip::address& other) const + { + return (host.is_v4 () && other.is_v4 ()) || + (host.is_v6 () && other.is_v6 ()); + } }; RouterInfo (const std::string& fullPath); @@ -102,6 +108,9 @@ namespace data bool IsFloodfill () const; bool IsNTCP (bool v4only = true) const; bool IsSSU (bool v4only = true) const; + bool IsV6 () const; + void EnableV6 (); + void DisableV6 (); bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; bool UsesIntroducer () const; bool IsIntroducer () const { return m_Caps & eSSUIntroducer; }; diff --git a/Transports.cpp b/Transports.cpp index b3a01aee..cfe368e7 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -253,7 +253,7 @@ namespace transport { // existing session not found. create new // try NTCP first if message size < 16K - auto address = r->GetNTCPAddress (); + auto address = r->GetNTCPAddress (!context.SupportsV6 ()); if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE) { auto s = new NTCPClient (m_Service, address->host, address->port, *r); From f2434d66fc2aae0555741fe8db5357c553f38470 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 27 Oct 2014 15:08:50 -0400 Subject: [PATCH 33/35] incoming ipv6 connections --- HTTPServer.cpp | 5 ++++- NTCPSession.cpp | 2 ++ README.md | 1 + RouterContext.cpp | 30 ++++++++++++++++++++++++++++++ RouterContext.h | 4 +++- Transports.cpp | 33 ++++++++++++++++++++++++++++++++- Transports.h | 3 ++- 7 files changed, 74 insertions(+), 4 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 35ef512c..57656334 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -644,7 +644,10 @@ namespace util switch (address.transportStyle) { case i2p::data::RouterInfo::eTransportNTCP: - s << "NTCP  "; + if (address.host.is_v6 ()) + s << "NTCP6  "; + else + s << "NTCP  "; break; case i2p::data::RouterInfo::eTransportSSU: s << "SSU     "; diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 8f6faa4b..c75755b3 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -623,6 +623,8 @@ namespace transport else { LogPrint ("Connected"); + if (GetSocket ().local_endpoint ().protocol () == boost::asio::ip::tcp::v6()) // ipv6 + context.UpdateV6Address (GetSocket ().local_endpoint ().address ().to_string ()); ClientLogin (); } } diff --git a/README.md b/README.md index b9da1f3e..395500c3 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Options * --daemon= - Enable or disable daemon mode. 1 for yes, 0 for no. * --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd). * --unreachable= - 1 if router is declared as unreachable and works through introducers. +* --v6= - 1 if supports communication through ipv6, off by default * --httpproxyport= - The port to listen on (HTTP Proxy) * --socksproxyport= - The port to listen on (SOCKS Proxy) * --ircport= - The local port of IRC tunnel to listen on. 6668 by default diff --git a/RouterContext.cpp b/RouterContext.cpp index 8832e81e..65905196 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -138,6 +138,36 @@ namespace i2p else m_RouterInfo.DisableV6 (); } + + void RouterContext::UpdateV6Address (const std::string& host) + { + bool updated = false, found = false; + int port = 0; + auto newAddress = boost::asio::ip::address::from_string (host); + auto& addresses = m_RouterInfo.GetAddresses (); + for (auto& addr : addresses) + { + if (addr.host.is_v6 ()) + { + if (addr.host != newAddress) + { + addr.host = newAddress; + updated = true; + } + found = true; + } + else + port = addr.port; + } + if (!found) + { + // create new address + m_RouterInfo.AddNTCPAddress (host.c_str (), port); + updated = true; + } + if (updated) + UpdateRouterInfo (); + } bool RouterContext::Load () { diff --git a/RouterContext.h b/RouterContext.h index 35f11e2d..e2e5b24e 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -2,6 +2,7 @@ #define ROUTER_CONTEXT_H__ #include +#include #include #include #include "Identity.h" @@ -34,7 +35,8 @@ namespace i2p void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; void SetSupportsV6 (bool supportsV6); - + void UpdateV6Address (const std::string& host); // called from NTCP session + // implements LocalDestination const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const uint8_t * GetEncryptionPrivateKey () const { return m_Keys.GetPrivateKey (); }; diff --git a/Transports.cpp b/Transports.cpp index cfe368e7..c0c7bfca 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -96,7 +96,7 @@ namespace transport Transports transports; Transports::Transports (): - m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr), + m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr), m_SSUServer (nullptr), m_DHKeysPairSupplier (5) // 5 pre-generated keys { } @@ -124,6 +124,17 @@ namespace transport auto conn = new NTCPServerConnection (m_Service); m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this, conn, boost::asio::placeholders::error)); + + if (context.SupportsV6 ()) + { + m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service, + boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address.port)); + + LogPrint ("Start listening V6 TCP port ", address.port); + auto conn = new NTCPServerConnection (m_Service); + m_NTCPV6Acceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAcceptV6, + this, conn, boost::asio::placeholders::error)); + } } else if (address.transportStyle == RouterInfo::eTransportSSU) { @@ -154,6 +165,8 @@ namespace transport m_NTCPSessions.clear (); delete m_NTCPAcceptor; m_NTCPAcceptor = nullptr; + delete m_NTCPV6Acceptor; + m_NTCPV6Acceptor = nullptr; m_DHKeysPairSupplier.Stop (); m_IsRunning = false; @@ -211,6 +224,24 @@ namespace transport } } + void Transports::HandleAcceptV6 (NTCPServerConnection * conn, const boost::system::error_code& error) + { + if (!error) + { + LogPrint ("Connected from ", conn->GetSocket ().remote_endpoint().address ().to_string ()); + conn->ServerLogin (); + } + else + delete conn; + + if (error != boost::asio::error::operation_aborted) + { + conn = new NTCPServerConnection (m_Service); + m_NTCPV6Acceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAcceptV6, this, + conn, boost::asio::placeholders::error)); + } + } + NTCPSession * Transports::GetNextNTCPSession () { for (auto session: m_NTCPSessions) diff --git a/Transports.h b/Transports.h index c795c2b4..d306de77 100644 --- a/Transports.h +++ b/Transports.h @@ -76,6 +76,7 @@ namespace transport void Run (); void HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error); + void HandleAcceptV6 (NTCPServerConnection * conn, const boost::system::error_code& error); void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer, const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); @@ -89,7 +90,7 @@ namespace transport std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::io_service::work m_Work; - boost::asio::ip::tcp::acceptor * m_NTCPAcceptor; + boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor; std::map m_NTCPSessions; SSUServer * m_SSUServer; From 35d4692f5fe24f835985355396014996f698eef2 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 27 Oct 2014 16:01:22 -0400 Subject: [PATCH 34/35] send datagram through destination's thread --- Datagram.cpp | 51 +++++++++++++++++++++++++++++++++------------------ Datagram.h | 4 +--- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index dc4a01f9..1f272693 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -15,41 +15,56 @@ namespace datagram DatagramDestination::DatagramDestination (i2p::client::ClientDestination& owner): m_Owner (owner) { - auto identityLen = m_Owner.GetIdentity ().ToBuffer (m_OutgoingBuffer, MAX_DATAGRAM_SIZE); - m_Signature = m_OutgoingBuffer + identityLen; - auto signatureLen = m_Owner.GetIdentity ().GetSignatureLen (); - m_Payload = m_Signature + signatureLen; - m_HeaderLen = identityLen + signatureLen; } void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote) + { + uint8_t buf[MAX_DATAGRAM_SIZE]; + auto identityLen = m_Owner.GetIdentity ().ToBuffer (buf, MAX_DATAGRAM_SIZE); + uint8_t * signature = buf + identityLen; + auto signatureLen = m_Owner.GetIdentity ().GetSignatureLen (); + uint8_t * buf1 = signature + signatureLen; + size_t headerLen = identityLen + signatureLen; + + memcpy (buf1, payload, len); + if (m_Owner.GetIdentity ().GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + CryptoPP::SHA256().CalculateDigest (hash, buf1, len); + m_Owner.Sign (hash, 32, signature); + } + else + m_Owner.Sign (buf1, len, signature); + + auto service = m_Owner.GetService (); + if (service) + service->post (boost::bind (&DatagramDestination::SendMsg, this, + CreateDataMessage (buf, len + headerLen), remote)); + else + LogPrint ("Failed to send datagram. Destination is not running"); + } + + void DatagramDestination::SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote) { auto leases = remote.GetNonExpiredLeases (); if (!leases.empty ()) { - memcpy (m_Payload, payload, len); - if (m_Owner.GetIdentity ().GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) - { - uint8_t hash[32]; - CryptoPP::SHA256().CalculateDigest (hash, m_Payload, len); - m_Owner.Sign (hash, 32, m_Signature); - } - else - m_Owner.Sign (m_Payload, len, m_Signature); - std::vector msgs; uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1); - auto msg = m_Owner.WrapMessage (remote, CreateDataMessage (m_OutgoingBuffer, len + m_HeaderLen), true); + auto garlic = m_Owner.WrapMessage (remote, msg, true); msgs.push_back (i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, leases[i].tunnelGateway, leases[i].tunnelID, - msg + garlic }); m_Owner.SendTunnelDataMsgs (msgs); } else - LogPrint ("Failed to send datagram. All leases expired"); + { + LogPrint ("Failed to send datagram. All leases expired"); + DeleteI2NPMessage (msg); + } } void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len) diff --git a/Datagram.h b/Datagram.h index 5d8f6f5b..efce2b17 100644 --- a/Datagram.h +++ b/Datagram.h @@ -27,13 +27,11 @@ namespace datagram private: I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); + void SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote); private: i2p::client::ClientDestination& m_Owner; - uint8_t m_OutgoingBuffer[MAX_DATAGRAM_SIZE]; - uint8_t * m_Signature, * m_Payload; - size_t m_HeaderLen; }; } } From 2dfd351e7a47f2dca498b7a5a1219d9b78a1bc45 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 27 Oct 2014 16:30:56 -0400 Subject: [PATCH 35/35] handle incoming datagramms --- Datagram.cpp | 27 ++++++++++++++++++++++++++- Datagram.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index 1f272693..a154fc5b 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -67,6 +67,31 @@ namespace datagram } } + void DatagramDestination::HandleDatagram (const uint8_t * buf, size_t len) + { + i2p::data::IdentityEx identity; + size_t identityLen = identity.FromBuffer (buf, len); + const uint8_t * signature = buf + identityLen; + size_t headerLen = identityLen + identity.GetSignatureLen (); + + bool verified = false; + if (identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + CryptoPP::SHA256().CalculateDigest (hash, buf + headerLen, len - headerLen); + verified = identity.Verify (hash, 32, signature); + } + else + verified = identity.Verify (buf + headerLen, len - headerLen, signature); + + if (verified) + { + // TODO: invoke datagram handler + } + else + LogPrint ("Datagram signature verification failed"); + } + void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len) { // unzip it @@ -78,7 +103,7 @@ namespace datagram if (uncompressedLen <= MAX_DATAGRAM_SIZE) { decompressor.Get (uncompressed, uncompressedLen); - //HandleNextPacket (uncompressed); + HandleDatagram (uncompressed, uncompressedLen); } else LogPrint ("Received datagram size ", uncompressedLen, " exceeds max size"); diff --git a/Datagram.h b/Datagram.h index efce2b17..fd4c3cc4 100644 --- a/Datagram.h +++ b/Datagram.h @@ -28,6 +28,7 @@ namespace datagram I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); void SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote); + void HandleDatagram (const uint8_t * buf, size_t len); private: