diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp index d36949c3..3f9226d1 100644 --- a/Win32/DaemonWin32.cpp +++ b/Win32/DaemonWin32.cpp @@ -6,7 +6,6 @@ #include "Log.h" #ifdef _WIN32 - #include "Win32/Win32Service.h" #ifdef WIN32_APP #include "Win32/Win32App.h" @@ -109,4 +108,4 @@ namespace util } } } -#endif +#endif //_WIN32 diff --git a/Win32/Win32Service.cpp b/Win32/Win32Service.cpp index d3785999..4a0058ac 100644 --- a/Win32/Win32Service.cpp +++ b/Win32/Win32Service.cpp @@ -15,7 +15,6 @@ I2PService *I2PService::s_service = NULL; BOOL I2PService::isService() { BOOL bIsService = FALSE; - HWINSTA hWinStation = GetProcessWindowStation(); if (hWinStation != NULL) { @@ -31,28 +30,23 @@ BOOL I2PService::isService() BOOL I2PService::Run(I2PService &service) { s_service = &service; - SERVICE_TABLE_ENTRY serviceTable[] = { { service.m_name, ServiceMain }, { NULL, NULL } }; - return StartServiceCtrlDispatcher(serviceTable); } - void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv) { assert(s_service != NULL); - s_service->m_statusHandle = RegisterServiceCtrlHandler( s_service->m_name, ServiceCtrlHandler); if (s_service->m_statusHandle == NULL) { throw GetLastError(); } - s_service->Start(dwArgc, pszArgv); } @@ -61,12 +55,12 @@ void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl) { switch (dwCtrl) { - case SERVICE_CONTROL_STOP: s_service->Stop(); break; - case SERVICE_CONTROL_PAUSE: s_service->Pause(); break; - case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break; - case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break; - case SERVICE_CONTROL_INTERROGATE: break; - default: break; + case SERVICE_CONTROL_STOP: s_service->Stop(); break; + case SERVICE_CONTROL_PAUSE: s_service->Pause(); break; + case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break; + case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break; + case SERVICE_CONTROL_INTERROGATE: break; + default: break; } } @@ -76,11 +70,8 @@ I2PService::I2PService(PSTR pszServiceName, BOOL fCanPauseContinue) { m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName; - m_statusHandle = NULL; - m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - m_status.dwCurrentState = SERVICE_START_PENDING; DWORD dwControlsAccepted = 0; @@ -90,15 +81,13 @@ I2PService::I2PService(PSTR pszServiceName, dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN; if (fCanPauseContinue) dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; - m_status.dwControlsAccepted = dwControlsAccepted; + m_status.dwControlsAccepted = dwControlsAccepted; m_status.dwWin32ExitCode = NO_ERROR; m_status.dwServiceSpecificExitCode = 0; m_status.dwCheckPoint = 0; m_status.dwWaitHint = 0; - m_fStopping = FALSE; - // Create a manual-reset event that is not signaled at first to indicate // the stopped signal of the service. m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -108,7 +97,6 @@ I2PService::I2PService(PSTR pszServiceName, } } - I2PService::~I2PService(void) { if (m_hStoppedEvent) @@ -118,92 +106,73 @@ I2PService::~I2PService(void) } } - void I2PService::Start(DWORD dwArgc, PSTR *pszArgv) { try { SetServiceStatus(SERVICE_START_PENDING); - OnStart(dwArgc, pszArgv); - SetServiceStatus(SERVICE_RUNNING); } catch (DWORD dwError) { LogPrint(eLogError, "Win32Service Start", dwError); - SetServiceStatus(SERVICE_STOPPED, dwError); } catch (...) { LogPrint(eLogError, "Win32Service failed to start.", EVENTLOG_ERROR_TYPE); - SetServiceStatus(SERVICE_STOPPED); } } - void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv) { LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE); - Daemon.start(); - //i2p::util::config::OptionParser(dwArgc, pszArgv); //i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); //i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), // i2p::util::config::GetArg("-port", 17070)); - _worker = new std::thread(std::bind(&I2PService::WorkerThread, this)); } - void I2PService::WorkerThread() { while (!m_fStopping) { ::Sleep(1000); // Simulate some lengthy operations. } - // Signal the stopped event. SetEvent(m_hStoppedEvent); } - void I2PService::Stop() { DWORD dwOriginalState = m_status.dwCurrentState; try { SetServiceStatus(SERVICE_STOP_PENDING); - OnStop(); - SetServiceStatus(SERVICE_STOPPED); } catch (DWORD dwError) { LogPrint(eLogInfo, "Win32Service Stop", dwError); - SetServiceStatus(dwOriginalState); } catch (...) { LogPrint(eLogError, "Win32Service failed to stop.", EVENTLOG_ERROR_TYPE); - SetServiceStatus(dwOriginalState); } } - void I2PService::OnStop() { // Log a service stop message to the Application log. LogPrint(eLogInfo, "Win32Service in OnStop", EVENTLOG_INFORMATION_TYPE); - Daemon.stop(); - m_fStopping = TRUE; if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0) { @@ -213,57 +182,46 @@ void I2PService::OnStop() delete _worker; } - void I2PService::Pause() { try { SetServiceStatus(SERVICE_PAUSE_PENDING); - OnPause(); - SetServiceStatus(SERVICE_PAUSED); } catch (DWORD dwError) { LogPrint(eLogError, "Win32Service Pause", dwError); - SetServiceStatus(SERVICE_RUNNING); } catch (...) { LogPrint(eLogError, "Win32Service failed to pause.", EVENTLOG_ERROR_TYPE); - SetServiceStatus(SERVICE_RUNNING); } } - void I2PService::OnPause() { } - void I2PService::Continue() { try { SetServiceStatus(SERVICE_CONTINUE_PENDING); - OnContinue(); - SetServiceStatus(SERVICE_RUNNING); } catch (DWORD dwError) { LogPrint(eLogError, "Win32Service Continue", dwError); - SetServiceStatus(SERVICE_PAUSED); } catch (...) { LogPrint(eLogError, "Win32Service failed to resume.", EVENTLOG_ERROR_TYPE); - SetServiceStatus(SERVICE_PAUSED); } } @@ -277,7 +235,6 @@ void I2PService::Shutdown() try { OnShutdown(); - SetServiceStatus(SERVICE_STOPPED); } catch (DWORD dwError) @@ -299,11 +256,9 @@ void I2PService::SetServiceStatus(DWORD dwCurrentState, DWORD dwWaitHint) { static DWORD dwCheckPoint = 1; - m_status.dwCurrentState = dwCurrentState; m_status.dwWin32ExitCode = dwWin32ExitCode; m_status.dwWaitHint = dwWaitHint; - m_status.dwCheckPoint = ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) ? @@ -328,7 +283,7 @@ void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService) } } -void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType, PSTR pszDependencies, PSTR pszAccount, PSTR pszPassword) +void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartType, PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword) { printf("Try to install Win32Service (%s).\n", pszServiceName); @@ -383,7 +338,7 @@ void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType, FreeHandles(schSCManager, schService); } -void UninstallService(PSTR pszServiceName) +void UninstallService(PCSTR pszServiceName) { printf("Try to uninstall Win32Service (%s).\n", pszServiceName); diff --git a/Win32/Win32Service.h b/Win32/Win32Service.h index 95cad3b5..2830d237 100644 --- a/Win32/Win32Service.h +++ b/Win32/Win32Service.h @@ -4,7 +4,6 @@ #include #include - #ifdef _WIN32 // Internal name of the service #define SERVICE_NAME "i2pdService" @@ -25,7 +24,6 @@ #define SERVICE_PASSWORD NULL #endif - class I2PService { public: @@ -72,13 +70,15 @@ private: std::thread* _worker; }; -void InstallService(PSTR pszServiceName, - PSTR pszDisplayName, +void InstallService( + PCSTR pszServiceName, + PCSTR pszDisplayName, DWORD dwStartType, - PSTR pszDependencies, - PSTR pszAccount, - PSTR pszPassword); + PCSTR pszDependencies, + PCSTR pszAccount, + PCSTR pszPassword + ); -void UninstallService(PSTR pszServiceName); +void UninstallService(PCSTR pszServiceName); #endif // WIN_32_SERVICE_H__ \ No newline at end of file diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index a90cf3d4..6fd5d763 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -13,8 +13,8 @@ namespace client I2PService::I2PService (std::shared_ptr localDestination): m_LocalDestination (localDestination ? localDestination : i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), - m_ReadyTimer(m_LocalDestination->GetService()), - m_ConnectTimeout(0), + m_ReadyTimer(m_LocalDestination->GetService()), + m_ConnectTimeout(0), isUpdated (true) { m_LocalDestination->Acquire (); @@ -49,7 +49,7 @@ namespace client { if(timeout && !m_ConnectTimeout) { - TriggerReadyCheckTimer(); + TriggerReadyCheckTimer(); } else if (m_ConnectTimeout && !timeout) { @@ -104,9 +104,7 @@ namespace client assert(streamRequestComplete); i2p::data::IdentHash identHash; if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash)) - { CreateStream(streamRequestComplete, identHash, port); - } else { LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest); @@ -158,16 +156,16 @@ namespace client void TCPIPPipe::Terminate() { if(Kill()) return; - if (m_up) { - if (m_up->is_open()) { + if (m_up) + { + if (m_up->is_open()) m_up->close(); - } m_up = nullptr; } - if (m_down) { - if (m_down->is_open()) { + if (m_down) + { + if (m_down->is_open()) m_down->close(); - } m_down = nullptr; } Done(shared_from_this()); @@ -175,103 +173,106 @@ namespace client void TCPIPPipe::AsyncReceiveUpstream() { - if (m_up) { + if (m_up) + { m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE), - std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - } else { - LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket"); + std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); } + else + LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket"); } void TCPIPPipe::AsyncReceiveDownstream() { if (m_down) { m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE), - std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - } else { - LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket"); + std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); } + else + LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket"); } void TCPIPPipe::UpstreamWrite(size_t len) { - if (m_up) { + if (m_up) + { LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), - boost::asio::transfer_all(), - std::bind(&TCPIPPipe::HandleUpstreamWrite, - shared_from_this(), - std::placeholders::_1) - ); - } else { - LogPrint(eLogError, "TCPIPPipe: upstream write: no socket"); + boost::asio::transfer_all(), + std::bind(&TCPIPPipe::HandleUpstreamWrite, + shared_from_this(), + std::placeholders::_1)); } + else + LogPrint(eLogError, "TCPIPPipe: upstream write: no socket"); } void TCPIPPipe::DownstreamWrite(size_t len) { - if (m_down) { + if (m_down) + { LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), - boost::asio::transfer_all(), - std::bind(&TCPIPPipe::HandleDownstreamWrite, - shared_from_this(), - std::placeholders::_1) - ); - } else { - LogPrint(eLogError, "TCPIPPipe: downstream write: no socket"); + boost::asio::transfer_all(), + std::bind(&TCPIPPipe::HandleDownstreamWrite, + shared_from_this(), + std::placeholders::_1)); } + else + LogPrint(eLogError, "TCPIPPipe: downstream write: no socket"); } void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received"); - if (ecode) { + if (ecode) + { LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); } else { - if (bytes_transfered > 0 ) { + if (bytes_transfered > 0 ) memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); - } UpstreamWrite(bytes_transfered); } } void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { - if (ecode) { + if (ecode) + { LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); - } else { - AsyncReceiveUpstream(); } + else + AsyncReceiveUpstream(); } void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { - if (ecode) { + if (ecode) + { LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); - } else { - AsyncReceiveDownstream(); } + else + AsyncReceiveDownstream(); } void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received"); - if (ecode) { + if (ecode) + { LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); } else { - if (bytes_transfered > 0 ) { + if (bytes_transfered > 0 ) memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); - } DownstreamWrite(bytes_transfered); } } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index 60fd29ee..fd5e8999 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -16,8 +16,9 @@ namespace client class I2PServiceHandler; class I2PService : std::enable_shared_from_this { - public: - typedef std::function ReadyCallback; + public: + typedef std::function ReadyCallback; + public: I2PService (std::shared_ptr localDestination = nullptr); I2PService (i2p::data::SigningKeyType kt); @@ -35,9 +36,9 @@ namespace client } void ClearHandlers (); - void SetConnectTimeout(uint32_t timeout); + void SetConnectTimeout(uint32_t timeout); - void AddReadyCallback(ReadyCallback cb); + void AddReadyCallback(ReadyCallback cb); inline std::shared_ptr GetLocalDestination () { return m_LocalDestination; } inline std::shared_ptr GetLocalDestination () const { return m_LocalDestination; } @@ -48,7 +49,7 @@ namespace client m_LocalDestination = dest; } void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); - void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port); + void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port); inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); } virtual void Start () = 0; @@ -56,18 +57,17 @@ namespace client virtual const char* GetName() { return "Generic I2P Service"; } - private: - void TriggerReadyCheckTimer(); - void HandleReadyCheckTimer(const boost::system::error_code & ec); - private: + void TriggerReadyCheckTimer(); + void HandleReadyCheckTimer(const boost::system::error_code & ec); + private: std::shared_ptr m_LocalDestination; std::unordered_set > m_Handlers; std::mutex m_HandlersMutex; - std::vector > m_ReadyCallbacks; - boost::asio::deadline_timer m_ReadyTimer; - uint32_t m_ConnectTimeout; + std::vector > m_ReadyCallbacks; + boost::asio::deadline_timer m_ReadyTimer; + uint32_t m_ConnectTimeout; public: bool isUpdated; // transient, used during reload only @@ -93,6 +93,7 @@ namespace client 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 @@ -101,25 +102,28 @@ namespace client const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8; // bidirectional pipe for 2 tcp/ip sockets - class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this { - public: - TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); - ~TCPIPPipe(); - void Start(); - protected: - void Terminate(); - void AsyncReceiveUpstream(); - void AsyncReceiveDownstream(); - void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); - void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); - void HandleUpstreamWrite(const boost::system::error_code & ecode); - void HandleDownstreamWrite(const boost::system::error_code & ecode); - void UpstreamWrite(size_t len); - void DownstreamWrite(size_t len); - private: - uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; - uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; - std::shared_ptr m_up, m_down; + class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this + { + public: + TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); + ~TCPIPPipe(); + void Start(); + + protected: + void Terminate(); + void AsyncReceiveUpstream(); + void AsyncReceiveDownstream(); + void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); + void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); + void HandleUpstreamWrite(const boost::system::error_code & ecode); + void HandleDownstreamWrite(const boost::system::error_code & ecode); + void UpstreamWrite(size_t len); + void DownstreamWrite(size_t len); + + private: + uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; + uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; + std::shared_ptr m_up, m_down; }; /* TODO: support IPv6 too */ @@ -143,10 +147,11 @@ namespace client const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; - virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } + virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } protected: virtual std::shared_ptr CreateHandler(std::shared_ptr socket) = 0; + private: void Accept(); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 8d559aee..da5dbfee 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -29,14 +29,14 @@ namespace client } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, - std::shared_ptr socket, std::shared_ptr stream): + std::shared_ptr socket, std::shared_ptr stream): I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, bool quiet): + std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, bool quiet): I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), m_RemoteEndpoint (target), m_IsQuiet (quiet) { @@ -137,7 +137,7 @@ namespace client auto s = shared_from_this (); m_Stream->AsyncSend (m_Buffer, bytes_transferred, [s](const boost::system::error_code& ecode) - { + { if (!ecode) s->Receive (); else @@ -164,7 +164,7 @@ namespace client if (m_Stream) { if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || - m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular + m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular { m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), @@ -207,7 +207,7 @@ namespace client void I2PTunnelConnection::Write (const uint8_t * buf, size_t len) { boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (), - std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1)); + std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1)); } void I2PTunnelConnection::HandleConnect (const boost::system::error_code& ecode) @@ -339,48 +339,48 @@ namespace client } I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, - const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass): - I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()), - m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass) - { - } - - void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) - { + std::shared_ptr socket, + const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass): + I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()), + m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass) + { + } + + void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) + { m_OutPacket.str (""); - if (m_NeedsWebIrc) + if (m_NeedsWebIrc) { - m_NeedsWebIrc = false; - m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl; - } + m_NeedsWebIrc = false; + m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl; + } - m_InPacket.clear (); - m_InPacket.write ((const char *)buf, len); + m_InPacket.clear (); + m_InPacket.write ((const char *)buf, len); - while (!m_InPacket.eof () && !m_InPacket.fail ()) - { + while (!m_InPacket.eof () && !m_InPacket.fail ()) + { std::string line; - std::getline (m_InPacket, line); - if (line.length () == 0 && m_InPacket.eof ()) - m_InPacket.str (""); - auto pos = line.find ("USER"); - if (!pos) // start of line - { - pos = line.find (" "); - pos++; - pos = line.find (" ", pos); - pos++; - auto nextpos = line.find (" ", pos); - m_OutPacket << line.substr (0, pos); - m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()); - m_OutPacket << line.substr (nextpos) << '\n'; - } + std::getline (m_InPacket, line); + if (line.length () == 0 && m_InPacket.eof ()) + m_InPacket.str (""); + auto pos = line.find ("USER"); + if (!pos) // start of line + { + pos = line.find (" "); + pos++; + pos = line.find (" ", pos); + pos++; + auto nextpos = line.find (" ", pos); + m_OutPacket << line.substr (0, pos); + m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()); + m_OutPacket << line.substr (nextpos) << '\n'; + } else - m_OutPacket << line << '\n'; - } - I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); - } + m_OutPacket << line << '\n'; + } + I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); + } /* This handler tries to stablish a connection with the desired server and dies if it fails to do so */ @@ -437,7 +437,7 @@ namespace client } I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination, - const std::string& address, int port, std::shared_ptr localDestination, int destinationPort): + const std::string& address, int port, std::shared_ptr localDestination, int destinationPort): TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination), m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort) { @@ -481,7 +481,7 @@ namespace client } I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, int inport, bool gzip): + int port, std::shared_ptr localDestination, int inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip); @@ -573,8 +573,8 @@ namespace client } I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, - const std::string& host, int inport, bool gzip): + int port, std::shared_ptr localDestination, + const std::string& host, int inport, bool gzip): I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_Host (host) { @@ -586,30 +586,30 @@ namespace client std::make_shared (GetService ()), GetEndpoint (), m_Host); } - I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, - const std::string& webircpass, int inport, bool gzip): - I2PServerTunnel (name, address, port, localDestination, inport, gzip), - m_WebircPass (webircpass) - { - } - - std::shared_ptr I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr stream) - { - return std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), this->m_WebircPass); - } - - void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) - { - std::lock_guard lock(m_SessionsMutex); - auto session = ObtainUDPSession(from, toPort, fromPort); - session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); - session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - } - - void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { - std::lock_guard lock(m_SessionsMutex); - uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); + I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, + int port, std::shared_ptr localDestination, + const std::string& webircpass, int inport, bool gzip): + I2PServerTunnel (name, address, port, localDestination, inport, gzip), + m_WebircPass (webircpass) + { + } + + std::shared_ptr I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr stream) + { + return std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), this->m_WebircPass); + } + + void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + std::lock_guard lock(m_SessionsMutex); + auto session = ObtainUDPSession(from, toPort, fromPort); + session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); + session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + } + + void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { + std::lock_guard lock(m_SessionsMutex); + uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); auto itr = m_Sessions.begin(); while(itr != m_Sessions.end()) { if(now - (*itr)->LastActivity >= delta ) @@ -617,11 +617,11 @@ namespace client else ++itr; } - } + } void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) { std::lock_guard lock(m_SessionsMutex); - uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); + uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); std::vector removePorts; for (const auto & s : m_Sessions) { if (now - s.second.second >= delta) @@ -630,20 +630,20 @@ namespace client for(auto port : removePorts) { m_Sessions.erase(port); } - } + } UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) - { - auto ih = from.GetIdentHash(); - for (auto & s : m_Sessions ) - { - if ( s->Identity == ih) - { - /** found existing session */ - LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); - return s; - } - } + { + auto ih = from.GetIdentHash(); + for (auto & s : m_Sessions ) + { + if ( s->Identity == ih) + { + /** found existing session */ + LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); + return s; + } + } boost::asio::ip::address addr; /** create new udp session */ if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) @@ -654,16 +654,16 @@ namespace client else addr = m_LocalAddress; boost::asio::ip::udp::endpoint ep(addr, 0); - m_Sessions.push_back(std::make_shared(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort)); + m_Sessions.push_back(std::make_shared(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort)); auto & back = m_Sessions.back(); return back; - } + } - UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, - const std::shared_ptr & localDestination, - boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to, - uint16_t ourPort, uint16_t theirPort) : - m_Destination(localDestination->GetDatagramDestination()), + UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, + const std::shared_ptr & localDestination, + boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to, + uint16_t ourPort, uint16_t theirPort) : + m_Destination(localDestination->GetDatagramDestination()), IPSocket(localDestination->GetService(), localEndpoint), SendEndpoint(endpoint), LastActivity(i2p::util::GetMillisecondsSinceEpoch()), @@ -674,7 +674,6 @@ namespace client Receive(); } - void UDPSession::Receive() { LogPrint(eLogDebug, "UDPSession: Receive"); IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), @@ -694,8 +693,6 @@ namespace client } } - - I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : m_IsUniqueLocal(true), @@ -759,13 +756,11 @@ namespace client { auto dgram = m_LocalDest->CreateDatagramDestination(); dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5)); + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, + std::placeholders::_5)); } - - void I2PUDPClientTunnel::Start() { m_LocalDest->Start(); if (m_ResolveThread == nullptr) @@ -850,7 +845,6 @@ namespace client } else LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); - } I2PUDPClientTunnel::~I2PUDPClientTunnel() { diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index dd78d0fe..1bdf8bb5 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -29,7 +29,6 @@ namespace client class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this { public: - I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr leaseSet, int port = 0); // to I2P I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, @@ -41,7 +40,6 @@ namespace client void Connect (bool isUniqueLocal = true); protected: - void Terminate (); void Receive (); @@ -56,7 +54,6 @@ namespace client std::shared_ptr GetSocket () const { return m_Socket; }; private: - uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; std::shared_ptr m_Socket; std::shared_ptr m_Stream; @@ -67,18 +64,15 @@ namespace client class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection { public: - I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr socket, std::shared_ptr stream): I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false), m_ConnectionSent (false), m_ProxyConnectionSent (false) {}; protected: - void Write (const uint8_t * buf, size_t len); private: - std::stringstream m_InHeader, m_OutHeader; bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent; }; @@ -86,17 +80,14 @@ namespace client class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection { public: - I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& host); protected: - void Write (const uint8_t * buf, size_t len); private: - std::string m_Host; std::stringstream m_InHeader, m_OutHeader; bool m_HeaderSent; @@ -104,35 +95,30 @@ namespace client }; class I2PTunnelConnectionIRC: public I2PTunnelConnection - { - public: - - I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, - const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); - - protected: - - void Write (const uint8_t * buf, size_t len); + { + public: + I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, + std::shared_ptr socket, + const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); - private: + protected: + void Write (const uint8_t * buf, size_t len); - std::shared_ptr m_From; - std::stringstream m_OutPacket, m_InPacket; + private: + std::shared_ptr m_From; + std::stringstream m_OutPacket, m_InPacket; bool m_NeedsWebIrc; - std::string m_WebircPass; - }; + std::string m_WebircPass; + }; class I2PClientTunnel: public TCPIPAcceptor { protected: - // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); public: - I2PClientTunnel (const std::string& name, const std::string& destination, const std::string& address, int port, std::shared_ptr localDestination, int destinationPort = 0); ~I2PClientTunnel () {} @@ -143,11 +129,9 @@ namespace client const char* GetName() { return m_Name.c_str (); } private: - const i2p::data::IdentHash * GetIdentHash (); private: - std::string m_Name, m_Destination; const i2p::data::IdentHash * m_DestinationIdentHash; int m_DestinationPort; @@ -208,11 +192,11 @@ namespace client /** server side udp tunnel, many i2p inbound to 1 ip outbound */ class I2PUDPServerTunnel - { + { public: I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, - boost::asio::ip::address localAddress, + boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port); ~I2PUDPServerTunnel(); /** expire stale udp conversations */ @@ -225,7 +209,6 @@ namespace client void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } private: - void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); @@ -256,22 +239,22 @@ namespace client void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); private: - typedef std::pair UDPConvo; - void RecvFromLocal(); - void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); + typedef std::pair UDPConvo; + void RecvFromLocal(); + void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void TryResolving(); const std::string m_Name; - std::mutex m_SessionsMutex; - std::map m_Sessions; // maps i2p port -> local udp convo + std::mutex m_SessionsMutex; + std::map m_Sessions; // maps i2p port -> local udp convo const std::string m_RemoteDest; std::shared_ptr m_LocalDest; const boost::asio::ip::udp::endpoint m_LocalEndpoint; i2p::data::IdentHash * m_RemoteIdent; std::thread * m_ResolveThread; - boost::asio::ip::udp::socket m_LocalSocket; - boost::asio::ip::udp::endpoint m_RecvEndpoint; - uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; + boost::asio::ip::udp::socket m_LocalSocket; + boost::asio::ip::udp::endpoint m_RecvEndpoint; + uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; uint16_t RemotePort; bool m_cancel_resolve; }; @@ -279,7 +262,6 @@ namespace client class I2PServerTunnel: public I2PService { public: - I2PServerTunnel (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, int inport = 0, bool gzip = true); @@ -298,10 +280,9 @@ namespace client const char* GetName() { return m_Name.c_str (); } - void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); } - - private: + void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); } + private: void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, std::shared_ptr resolver); @@ -310,7 +291,6 @@ namespace client virtual std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: - bool m_IsUniqueLocal; std::string m_Name, m_Address; int m_Port; @@ -323,37 +303,30 @@ namespace client class I2PServerTunnelHTTP: public I2PServerTunnel { public: - I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, const std::string& host, - int inport = 0, bool gzip = true); + int inport = 0, bool gzip = true); private: - std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: - std::string m_Host; }; - class I2PServerTunnelIRC: public I2PServerTunnel - { - public: - - I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, - std::shared_ptr localDestination, const std::string& webircpass, - int inport = 0, bool gzip = true); - - private: - - std::shared_ptr CreateI2PConnection (std::shared_ptr stream); - - private: + class I2PServerTunnelIRC: public I2PServerTunnel + { + public: + I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, + std::shared_ptr localDestination, const std::string& webircpass, + int inport = 0, bool gzip = true); - std::string m_WebircPass; - }; + private: + std::shared_ptr CreateI2PConnection (std::shared_ptr stream); + private: + std::string m_WebircPass; + }; } }