From 114022d18a1947217b02351a3be1686bb89d79c6 Mon Sep 17 00:00:00 2001 From: "Francisco Blas (klondike) Izquierdo Riera" Date: Thu, 8 Jan 2015 01:31:31 +0100 Subject: [PATCH] Add the TCPIPAcceptor class for handling TCP/IP services on clearnet --- I2PService.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ I2PService.h | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/I2PService.cpp b/I2PService.cpp index 568d03eb..69cee2bc 100644 --- a/I2PService.cpp +++ b/I2PService.cpp @@ -32,5 +32,49 @@ namespace client 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; + } + } + } } diff --git a/I2PService.h b/I2PService.h index 6d9e878f..636a9780 100644 --- a/I2PService.h +++ b/I2PService.h @@ -46,6 +46,7 @@ namespace client virtual void Start () = 0; virtual void Stop () = 0; + virtual const char* GetName() { return "Generic I2P Service"; } private: ClientDestination * m_LocalDestination; @@ -59,19 +60,48 @@ namespace client public: I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { } virtual ~I2PServiceHandler() { } + //If you override this make sure you call it from the children + virtual void Handle() {}; //Start handling the socket protected: // 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); } // Call to know if the handler is dead - inline bool Dead() { return m_Dead; } + inline bool Dead () { return m_Dead; } // Call when done to clean up (make sure Kill is called first) - inline void Done(std::shared_ptr me) { if(m_Service) m_Service->RemoveHandler(me); } + inline void Done (std::shared_ptr me) { if(m_Service) m_Service->RemoveHandler(me); } // Call to talk with the owner inline I2PService * GetOwner() { return m_Service; } private: I2PService *m_Service; std::atomic m_Dead; //To avoid cleaning up multiple times }; + + //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 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; + }; } }