diff --git a/HTTPServer.cpp b/HTTPServer.cpp index a66a394f..5dd349dd 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -332,6 +332,7 @@ namespace util void HTTPConnection::HandleDestinationRequest (const std::string& address, const std::string& method, const std::string& data, const std::string& uri) { + const i2p::data::LeaseSet * leaseSet = nullptr; i2p::data::IdentHash destination; std::string fullAddress; if (address.find(".b32.i2p") != std::string::npos) @@ -360,17 +361,29 @@ namespace util } else { - if (i2p::data::Base32ToByteStream(address.c_str(), address.length(), (uint8_t *)destination, 32) != 32) + if (address == "local") { - LogPrint("Invalid Base32 address ", address); - SendReply("" + itoopieImage + "
Invalid Base32 address", 400); - return; + // TODO: remove later + fullAddress = "local.i2p"; + auto destination = i2p::stream::GetSharedLocalDestination (); + leaseSet = destination->GetLeaseSet (); + EepAccept (destination); } - fullAddress = address + ".b32.i2p"; + else + { + if (i2p::data::Base32ToByteStream(address.c_str(), address.length(), (uint8_t *)destination, 32) != 32) + { + LogPrint("Invalid Base32 address ", address); + SendReply("" + itoopieImage + "
Invalid Base32 address", 400); + return; + } + fullAddress = address + ".b32.i2p"; + } } } - auto leaseSet = i2p::data::netdb.FindLeaseSet (destination); + if (!leaseSet) + leaseSet = i2p::data::netdb.FindLeaseSet (destination); if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) { i2p::data::netdb.Subscribe(destination); @@ -495,6 +508,47 @@ namespace util new HTTPConnection (m_NewSocket); } +// eepSite. TODO: move away + + void HTTPConnection::EepAccept (i2p::stream::StreamingDestination * destination) + { + if (destination) + destination->SetAcceptor (std::bind (&HTTPConnection::HandleEepAccept, this, std::placeholders::_1)); + } + + void HTTPConnection::HandleEepAccept (i2p::stream::Stream * stream) + { + if (stream) + { + auto conn = new EepSiteDummyConnection (stream); + conn->AsyncStreamReceive (); + } + } + + void EepSiteDummyConnection::AsyncStreamReceive () + { + if (m_Stream) + m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, 8192), + boost::bind (&EepSiteDummyConnection::HandleStreamReceive, this, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred), + 60); // 60 seconds timeout + } + + void EepSiteDummyConnection::HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) + { + if (ecode) + { + LogPrint ("eepSite error: ", ecode.message ()); + DeleteStream (m_Stream); + } + else + { + std::string response ("HTTP/1.0 200 OK\r\n"); + m_Stream->Send ((uint8_t *)response.c_str (), response.length (), 30); + } + delete this; + } + } } diff --git a/HTTPServer.h b/HTTPServer.h index 39c61070..bef69bdf 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -59,6 +59,10 @@ namespace util void FillContent (std::stringstream& s); std::string ExtractAddress (); + // for eepsite + void EepAccept (i2p::stream::StreamingDestination * destination); + void HandleEepAccept (i2p::stream::Stream * stream); + protected: boost::asio::ip::tcp::socket * m_Socket; @@ -94,7 +98,7 @@ namespace util void Run (); void Accept (); void HandleAccept(const boost::system::error_code& ecode); - + private: std::thread * m_Thread; @@ -106,6 +110,24 @@ namespace util protected: virtual void CreateConnection(boost::asio::ip::tcp::socket * m_NewSocket); }; + + // TODO: move away + class EepSiteDummyConnection + { + public: + + EepSiteDummyConnection (i2p::stream::Stream * stream): m_Stream (stream) {}; + void AsyncStreamReceive (); + + private: + + void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); + + private: + + i2p::stream::Stream * m_Stream; + char m_StreamBuffer[8192]; + }; } } diff --git a/Streaming.cpp b/Streaming.cpp index e4ce6d5e..c12c4f53 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -127,8 +127,9 @@ namespace stream if (!m_RemoteLeaseSet) { i2p::data::Identity * identity = (i2p::data::Identity *)optionData; + LogPrint ("Incoming stream from ", identity->Hash ().ToBase64 ()); m_RemoteLeaseSet = i2p::data::netdb.FindLeaseSet (identity->Hash ()); - if (!m_RemoteLeaseSet) + if (!m_RemoteLeaseSet) LogPrint ("LeaseSet ", identity->Hash ().ToBase64 (), " not found"); } optionData += sizeof (i2p::data::Identity); @@ -410,6 +411,8 @@ namespace stream else // new incoming stream { auto incomingStream = CreateNewIncomingStream (); + if (m_Acceptor != nullptr) + m_Acceptor (incomingStream); incomingStream->HandleNextPacket (packet); } } @@ -438,6 +441,11 @@ namespace stream } I2NPMessage * StreamingDestination::GetLeaseSetMsg () + { + return CreateDatabaseStoreMsg (GetLeaseSet ()); + } + + const i2p::data::LeaseSet * StreamingDestination::GetLeaseSet () { if (!m_Pool) return nullptr; if (!m_LeaseSet || m_LeaseSet->HasExpiredLeases ()) @@ -450,9 +458,9 @@ namespace stream for (auto it: m_Streams) it.second->SetLeaseSetUpdated (); } - return CreateDatabaseStoreMsg (m_LeaseSet); + return m_LeaseSet; } - + void StreamingDestination::Sign (const uint8_t * buf, int len, uint8_t * signature) const { CryptoPP::DSA::Signer signer (m_SigningPrivateKey); @@ -524,15 +532,20 @@ namespace stream if (!m_SharedLocalDestination) return nullptr; return m_SharedLocalDestination->CreateNewOutgoingStream (remote); } - - void StreamingDestinations::DeleteClientStream (Stream * stream) + + void StreamingDestinations::DeleteStream (Stream * stream) { - if (m_SharedLocalDestination) - m_SharedLocalDestination->DeleteStream (stream); - else - delete stream; + if (stream) + { + m_Service.post ( + [=](void) + { + stream->GetLocalDestination ()->DeleteStream (stream); + } + ); + } } - + void StreamingDestinations::HandleNextPacket (i2p::data::IdentHash destination, Packet * packet) { m_Service.post (boost::bind (&StreamingDestinations::PostNextPacket, this, destination, packet)); @@ -557,7 +570,7 @@ namespace stream void DeleteStream (Stream * stream) { - destinations.DeleteClientStream (stream); + destinations.DeleteStream (stream); } void StartStreaming () @@ -569,6 +582,11 @@ namespace stream { destinations.Stop (); } + + StreamingDestination * GetSharedLocalDestination () + { + return destinations.GetSharedLocalDestination (); + } void HandleDataMessage (i2p::data::IdentHash destination, const uint8_t * buf, size_t len) { diff --git a/Streaming.h b/Streaming.h index 39b15ced..a348c641 100644 --- a/Streaming.h +++ b/Streaming.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,7 @@ namespace stream const i2p::data::LeaseSet * GetRemoteLeaseSet () const { return m_RemoteLeaseSet; }; bool IsOpen () const { return m_IsOpen; }; bool IsEstablished () const { return m_SendStreamID; }; + StreamingDestination * GetLocalDestination () { return m_LocalDestination; }; void HandleNextPacket (Packet * packet); size_t Send (const uint8_t * buf, size_t len, int timeout); // timeout in seconds @@ -127,10 +129,12 @@ namespace stream const i2p::data::PrivateKeys& GetKeys () const { return m_Keys; }; I2NPMessage * GetLeaseSetMsg (); + const i2p::data::LeaseSet * GetLeaseSet (); i2p::tunnel::TunnelPool * GetTunnelPool () const { return m_Pool; }; Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote); - void DeleteStream (Stream * stream); + void DeleteStream (Stream * stream); + void SetAcceptor (const std::function& acceptor) { m_Acceptor = acceptor; }; void HandleNextPacket (Packet * packet); // implements LocalDestination @@ -156,6 +160,7 @@ namespace stream i2p::data::LeaseSet * m_LeaseSet; CryptoPP::DSA::PrivateKey m_SigningPrivateKey; + std::function m_Acceptor; }; class StreamingDestinations @@ -172,7 +177,8 @@ namespace stream void HandleNextPacket (i2p::data::IdentHash destination, Packet * packet); Stream * CreateClientStream (const i2p::data::LeaseSet& remote); - void DeleteClientStream (Stream * stream); + void DeleteStream (Stream * stream); + StreamingDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; }; private: @@ -195,6 +201,7 @@ namespace stream void DeleteStream (Stream * stream); void StartStreaming (); void StopStreaming (); + StreamingDestination * GetSharedLocalDestination (); // assuming data is I2CP message void HandleDataMessage (i2p::data::IdentHash destination, const uint8_t * buf, size_t len);