Browse Source

Merge pull request #146 from klondi/i2pservice

I2pservice
pull/147/head
orignal 10 years ago
parent
commit
d67db32015
  1. 36
      HTTPProxy.cpp
  2. 26
      HTTPProxy.h
  3. 44
      I2PService.cpp
  4. 31
      I2PService.h
  5. 105
      I2PTunnel.cpp
  6. 17
      I2PTunnel.h
  7. 36
      SOCKS.cpp
  8. 26
      SOCKS.h

36
HTTPProxy.cpp

@ -231,41 +231,9 @@ namespace proxy
} }
} }
void HTTPProxyServer::Start () std::shared_ptr<i2p::client::I2PServiceHandler> HTTPProxyServer::CreateHandler(boost::asio::ip::tcp::socket * socket)
{ {
m_Acceptor.listen (); return std::make_shared<HTTPProxyHandler> (this, socket);
Accept ();
}
void HTTPProxyServer::Stop ()
{
m_Acceptor.close();
m_Timer.cancel ();
ClearHandlers();
}
void HTTPProxyServer::Accept ()
{
auto newSocket = new boost::asio::ip::tcp::socket (GetService ());
m_Acceptor.async_accept (*newSocket, std::bind (&HTTPProxyServer::HandleAccept, this,
std::placeholders::_1, newSocket));
}
void HTTPProxyServer::HandleAccept (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket)
{
if (!ecode)
{
LogPrint(eLogDebug,"--- HTTP Proxy accepted");
auto handler = std::make_shared<HTTPProxyHandler> (this, socket);
AddHandler(handler);
handler->Handle();
Accept();
}
else
{
LogPrint (eLogError,"--- HTTP Proxy Closing socket on accept because: ", ecode.message ());
delete socket;
}
} }
} }

26
HTTPProxy.h

@ -11,28 +11,16 @@ namespace i2p
{ {
namespace proxy namespace proxy
{ {
class HTTPProxyHandler; class HTTPProxyServer: public i2p::client::TCPIPAcceptor
class HTTPProxyServer: public i2p::client::I2PService
{ {
private: protected:
std::set<std::shared_ptr<HTTPProxyHandler> > m_Handlers; // Implements TCPIPAcceptor
boost::asio::ip::tcp::acceptor m_Acceptor; std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(boost::asio::ip::tcp::socket * socket);
boost::asio::deadline_timer m_Timer; const char* GetName() { return "HTTP Proxy"; }
std::mutex m_HandlersMutex;
private:
void Accept();
void HandleAccept(const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket);
public: public:
HTTPProxyServer(int port) : I2PService(i2p::data::SIGNING_KEY_TYPE_DSA_SHA1), HTTPProxyServer(int port) : TCPIPAcceptor(port, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) {}
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)), ~HTTPProxyServer() {}
m_Timer (GetService ()) {};
~HTTPProxyServer() { Stop(); }
void Start ();
void Stop ();
}; };
typedef HTTPProxyServer HTTPProxy; typedef HTTPProxyServer HTTPProxy;

44
I2PService.cpp

@ -32,5 +32,49 @@ namespace client
streamRequestComplete (nullptr); streamRequestComplete (nullptr);
} }
} }
void TCPIPAcceptor::Start ()
{
m_Acceptor.listen ();
Accept ();
}
void TCPIPAcceptor::Stop ()
{
m_Acceptor.close();
m_Timer.cancel ();
ClearHandlers();
}
void TCPIPAcceptor::Accept ()
{
auto newSocket = new boost::asio::ip::tcp::socket (GetService ());
m_Acceptor.async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this,
std::placeholders::_1, newSocket));
}
void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket)
{
if (!ecode)
{
LogPrint(eLogDebug,"--- ",GetName()," accepted");
auto handler = CreateHandler(socket);
if (handler) {
AddHandler(handler);
handler->Handle();
} else {
socket->close();
delete socket;
}
Accept();
}
else
{
if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogError,"--- ",GetName()," Closing socket on accept because: ", ecode.message ());
delete socket;
}
}
} }
} }

31
I2PService.h

@ -46,6 +46,7 @@ namespace client
virtual void Start () = 0; virtual void Start () = 0;
virtual void Stop () = 0; virtual void Stop () = 0;
virtual const char* GetName() { return "Generic I2P Service"; }
private: private:
ClientDestination * m_LocalDestination; ClientDestination * m_LocalDestination;
@ -59,6 +60,8 @@ namespace client
public: public:
I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { } I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { }
virtual ~I2PServiceHandler() { } virtual ~I2PServiceHandler() { }
//If you override this make sure you call it from the children
virtual void Handle() {}; //Start handling the socket
protected: protected:
// Call when terminating or handing over to avoid race conditions // Call when terminating or handing over to avoid race conditions
inline bool Kill () { return m_Dead.exchange(true); } inline bool Kill () { return m_Dead.exchange(true); }
@ -72,6 +75,34 @@ namespace client
I2PService *m_Service; I2PService *m_Service;
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
}; };
/* TODO: support IPv6 too */
//This is a service that listens for connections on the IP network and interacts with I2P
class TCPIPAcceptor: public I2PService
{
public:
TCPIPAcceptor (int port, ClientDestination * localDestination = nullptr) :
I2PService(localDestination),
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)),
m_Timer (GetService ()) {}
TCPIPAcceptor (int port, i2p::data::SigningKeyType kt) :
I2PService(kt),
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)),
m_Timer (GetService ()) {}
virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); }
//If you override this make sure you call it from the children
void Start ();
//If you override this make sure you call it from the children
void Stop ();
protected:
virtual std::shared_ptr<I2PServiceHandler> CreateHandler(boost::asio::ip::tcp::socket * socket) = 0;
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
private:
void Accept();
void HandleAccept(const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket);
boost::asio::ip::tcp::acceptor m_Acceptor;
boost::asio::deadline_timer m_Timer;
};
} }
} }

105
I2PTunnel.cpp

@ -151,30 +151,69 @@ namespace client
} }
} }
I2PClientTunnel::I2PClientTunnel (const std::string& destination, int port, ClientDestination * localDestination): /* This handler tries to stablish a connection with the desired server and dies if it fails to do so */
I2PService (localDestination), class I2PClientTunnelHandler: public I2PServiceHandler, public std::enable_shared_from_this<I2PClientTunnelHandler>
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)), {
m_Timer (GetService ()), m_Destination (destination), m_DestinationIdentHash (nullptr) public:
I2PClientTunnelHandler (I2PClientTunnel * parent, i2p::data::IdentHash destination,
boost::asio::ip::tcp::socket * socket):
I2PServiceHandler(parent), m_DestinationIdentHash(destination), m_Socket(socket) {}
void Handle();
void Terminate();
private:
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream);
i2p::data::IdentHash m_DestinationIdentHash;
boost::asio::ip::tcp::socket * m_Socket;
};
void I2PClientTunnelHandler::Handle()
{ {
GetOwner()->GetLocalDestination ()->CreateStream (std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete,
shared_from_this(), std::placeholders::_1), m_DestinationIdentHash);
} }
I2PClientTunnel::~I2PClientTunnel () void I2PClientTunnelHandler::HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream)
{
if (stream)
{ {
Stop (); if (Kill()) return;
LogPrint (eLogInfo,"New I2PTunnel connection");
auto connection = std::make_shared<I2PTunnelConnection>(GetOwner(), m_Socket, stream);
GetOwner()->AddHandler (connection);
connection->I2PConnect ();
Done(shared_from_this());
}
else
{
LogPrint (eLogError,"I2P Client Tunnel Issue when creating the stream, check the previous warnings for more info.");
Terminate();
}
} }
void I2PClientTunnelHandler::Terminate()
{
if (Kill()) return;
if (m_Socket)
{
m_Socket->close();
delete m_Socket;
m_Socket = nullptr;
}
Done(shared_from_this());
}
I2PClientTunnel::I2PClientTunnel (const std::string& destination, int port, ClientDestination * localDestination):
TCPIPAcceptor (port,localDestination), m_Destination (destination), m_DestinationIdentHash (nullptr)
{}
void I2PClientTunnel::Start () void I2PClientTunnel::Start ()
{ {
GetIdentHash(); GetIdentHash();
m_Acceptor.listen ();
Accept ();
} }
void I2PClientTunnel::Stop () void I2PClientTunnel::Stop ()
{ {
m_Acceptor.close(); TCPIPAcceptor::Stop();
m_Timer.cancel ();
ClearHandlers ();
auto *originalIdentHash = m_DestinationIdentHash; auto *originalIdentHash = m_DestinationIdentHash;
m_DestinationIdentHash = nullptr; m_DestinationIdentHash = nullptr;
delete originalIdentHash; delete originalIdentHash;
@ -194,51 +233,13 @@ namespace client
return m_DestinationIdentHash; return m_DestinationIdentHash;
} }
std::shared_ptr<I2PServiceHandler> I2PClientTunnel::CreateHandler(boost::asio::ip::tcp::socket * socket)
void I2PClientTunnel::Accept ()
{
auto newSocket = new boost::asio::ip::tcp::socket (GetService ());
m_Acceptor.async_accept (*newSocket, std::bind (&I2PClientTunnel::HandleAccept, this,
std::placeholders::_1, newSocket));
}
void I2PClientTunnel::HandleAccept (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket)
{
if (!ecode)
{ {
const i2p::data::IdentHash *identHash = GetIdentHash(); const i2p::data::IdentHash *identHash = GetIdentHash();
if (identHash) if (identHash)
GetLocalDestination ()->CreateStream ( return std::make_shared<I2PClientTunnelHandler>(this, *identHash, socket);
std::bind (&I2PClientTunnel::HandleStreamRequestComplete,
this, std::placeholders::_1, socket), *identHash);
else else
{ return nullptr;
LogPrint (eLogError,"Closing socket");
delete socket;
}
Accept ();
}
else
{
LogPrint (eLogError,"Closing socket on accept because: ", ecode.message ());
delete socket;
}
}
void I2PClientTunnel::HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream, boost::asio::ip::tcp::socket * socket)
{
if (stream)
{
LogPrint (eLogInfo,"New I2PTunnel connection");
auto connection = std::make_shared<I2PTunnelConnection>(this, socket, stream);
AddHandler (connection);
connection->I2PConnect ();
}
else
{
LogPrint (eLogError,"Issue when creating the stream, check the previous warnings for more info.");
delete socket;
}
} }
I2PServerTunnel::I2PServerTunnel (const std::string& address, int port, ClientDestination * localDestination): I2PServerTunnel::I2PServerTunnel (const std::string& address, int port, ClientDestination * localDestination):

17
I2PTunnel.h

@ -55,12 +55,18 @@ namespace client
bool m_IsQuiet; // don't send destination bool m_IsQuiet; // don't send destination
}; };
class I2PClientTunnel: public I2PService class I2PClientTunnel: public TCPIPAcceptor
{ {
protected:
// Implements TCPIPAcceptor
std::shared_ptr<I2PServiceHandler> CreateHandler(boost::asio::ip::tcp::socket * socket);
const char* GetName() { return "I2P Client Tunnel"; }
public: public:
I2PClientTunnel (const std::string& destination, int port, ClientDestination * localDestination = nullptr); I2PClientTunnel (const std::string& destination, int port, ClientDestination * localDestination = nullptr);
~I2PClientTunnel (); ~I2PClientTunnel () {}
void Start (); void Start ();
void Stop (); void Stop ();
@ -68,14 +74,7 @@ namespace client
private: private:
const i2p::data::IdentHash * GetIdentHash (); const i2p::data::IdentHash * GetIdentHash ();
void Accept ();
void HandleAccept (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket);
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream, boost::asio::ip::tcp::socket * socket);
private:
boost::asio::ip::tcp::acceptor m_Acceptor;
boost::asio::deadline_timer m_Timer;
std::string m_Destination; std::string m_Destination;
const i2p::data::IdentHash * m_DestinationIdentHash; const i2p::data::IdentHash * m_DestinationIdentHash;
}; };

36
SOCKS.cpp

@ -514,41 +514,9 @@ namespace proxy
} }
} }
void SOCKSServer::Start () std::shared_ptr<i2p::client::I2PServiceHandler> SOCKSServer::CreateHandler(boost::asio::ip::tcp::socket * socket)
{ {
m_Acceptor.listen (); return std::make_shared<SOCKSHandler> (this, socket);
Accept ();
}
void SOCKSServer::Stop ()
{
m_Acceptor.close();
m_Timer.cancel ();
ClearHandlers();
}
void SOCKSServer::Accept ()
{
auto newSocket = new boost::asio::ip::tcp::socket (GetService ());
m_Acceptor.async_accept (*newSocket, std::bind (&SOCKSServer::HandleAccept, this,
std::placeholders::_1, newSocket));
}
void SOCKSServer::HandleAccept (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket)
{
if (!ecode)
{
LogPrint(eLogDebug,"--- SOCKS accepted");
auto handle = std::make_shared<SOCKSHandler> (this, socket);
AddHandler(handle);
handle->Handle();
Accept();
}
else
{
LogPrint (eLogError,"--- SOCKS Closing socket on accept because: ", ecode.message ());
delete socket;
}
} }
} }

26
SOCKS.h

@ -11,28 +11,16 @@ namespace i2p
{ {
namespace proxy namespace proxy
{ {
class SOCKSHandler; class SOCKSServer: public i2p::client::TCPIPAcceptor
class SOCKSServer: public i2p::client::I2PService
{ {
private: protected:
std::set<std::shared_ptr<SOCKSHandler> > m_Handlers; // Implements TCPIPAcceptor
boost::asio::ip::tcp::acceptor m_Acceptor; std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(boost::asio::ip::tcp::socket * socket);
boost::asio::deadline_timer m_Timer; const char* GetName() { return "SOCKS"; }
std::mutex m_HandlersMutex;
private:
void Accept();
void HandleAccept(const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket);
public: public:
SOCKSServer(int port) : I2PService(nullptr), SOCKSServer(int port) : TCPIPAcceptor(port) {}
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)), ~SOCKSServer() {}
m_Timer (GetService ()) {};
~SOCKSServer() { Stop(); }
void Start ();
void Stop ();
}; };
typedef SOCKSServer SOCKSProxy; typedef SOCKSServer SOCKSProxy;

Loading…
Cancel
Save