NTCPSession.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #ifndef NTCP_SESSION_H__
  2. #define NTCP_SESSION_H__
  3. #include <inttypes.h>
  4. #include <map>
  5. #include <memory>
  6. #include <thread>
  7. #include <mutex>
  8. #include <boost/asio.hpp>
  9. #include "Crypto.h"
  10. #include "Identity.h"
  11. #include "RouterInfo.h"
  12. #include "I2NPProtocol.h"
  13. #include "TransportSession.h"
  14. #include "CryptoWorker.h"
  15. namespace i2p
  16. {
  17. namespace transport
  18. {
  19. struct NTCPPhase1
  20. {
  21. uint8_t pubKey[256];
  22. uint8_t HXxorHI[32];
  23. };
  24. struct NTCPPhase2
  25. {
  26. uint8_t pubKey[256];
  27. struct
  28. {
  29. uint8_t hxy[32];
  30. uint8_t timestamp[4];
  31. uint8_t filler[12];
  32. } encrypted;
  33. };
  34. struct NTCPWork;
  35. const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
  36. const size_t NTCP_BUFFER_SIZE = 1028; // fits 1 tunnel data message
  37. const int NTCP_CONNECT_TIMEOUT = 5; // 5 seconds
  38. const int NTCP_ESTABLISH_TIMEOUT = 10; // 10 seconds
  39. const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
  40. const int NTCP_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
  41. const size_t NTCP_DEFAULT_PHASE3_SIZE = 2/*size*/ + i2p::data::DEFAULT_IDENTITY_SIZE/*387*/ + 4/*ts*/ + 15/*padding*/ + 40/*signature*/; // 448
  42. const int NTCP_CLOCK_SKEW = 60; // in seconds
  43. const int NTCP_MAX_OUTGOING_QUEUE_SIZE = 200; // how many messages we can queue up
  44. class NTCPServer;
  45. class NTCPSession: public TransportSession, public std::enable_shared_from_this<NTCPSession>
  46. {
  47. public:
  48. NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
  49. ~NTCPSession ();
  50. void Terminate ();
  51. void Done ();
  52. boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
  53. boost::asio::io_service & GetService();
  54. bool IsEstablished () const { return m_IsEstablished; };
  55. bool IsTerminated () const { return m_IsTerminated; };
  56. void ClientLogin ();
  57. void ServerLogin ();
  58. void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
  59. private:
  60. void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
  61. void Connected ();
  62. void SendTimeSyncMessage ();
  63. void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
  64. void CreateAESKey (uint8_t * pubKey);
  65. // client
  66. void SendPhase3 ();
  67. void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  68. void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  69. void HandlePhase2 (NTCPWork * work=nullptr);
  70. void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
  71. void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
  72. //server
  73. void SendPhase2 (NTCPWork * work=nullptr);
  74. void SendPhase4 (uint32_t tsA, uint32_t tsB);
  75. void HandlePhase1Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  76. void HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB);
  77. void HandlePhase3Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB);
  78. void HandlePhase3ExtraReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB, size_t paddingLen);
  79. void HandlePhase3 (uint32_t tsB, size_t paddingLen);
  80. void HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  81. // common
  82. void Receive ();
  83. void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  84. bool DecryptNextBlock (const uint8_t * encrypted);
  85. void Send (std::shared_ptr<i2p::I2NPMessage> msg);
  86. boost::asio::const_buffers_1 CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg);
  87. void Send (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
  88. void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs);
  89. private:
  90. NTCPServer& m_Server;
  91. boost::asio::ip::tcp::socket m_Socket;
  92. bool m_IsEstablished, m_IsTerminated;
  93. i2p::crypto::CBCDecryption m_Decryption;
  94. i2p::crypto::CBCEncryption m_Encryption;
  95. struct Establisher
  96. {
  97. NTCPPhase1 phase1;
  98. NTCPPhase2 phase2;
  99. } * m_Establisher;
  100. i2p::crypto::AESAlignedBuffer<NTCP_BUFFER_SIZE + 16> m_ReceiveBuffer;
  101. i2p::crypto::AESAlignedBuffer<16> m_TimeSyncBuffer;
  102. int m_ReceiveBufferOffset;
  103. std::shared_ptr<I2NPMessage> m_NextMessage;
  104. size_t m_NextMessageOffset;
  105. i2p::I2NPMessagesHandler m_Handler;
  106. bool m_IsSending;
  107. std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
  108. };
  109. // TODO: move to NTCP.h/.cpp
  110. class NTCPServer
  111. {
  112. public:
  113. typedef i2p::worker::ThreadPool<NTCPSession> Pool;
  114. enum RemoteAddressType
  115. {
  116. eIP4Address,
  117. eIP6Address,
  118. eHostname
  119. };
  120. enum ProxyType
  121. {
  122. eNoProxy,
  123. eSocksProxy,
  124. eHTTPProxy
  125. };
  126. NTCPServer (int workers=4);
  127. ~NTCPServer ();
  128. void Start ();
  129. void Stop ();
  130. bool AddNTCPSession (std::shared_ptr<NTCPSession> session);
  131. void RemoveNTCPSession (std::shared_ptr<NTCPSession> session);
  132. std::shared_ptr<NTCPSession> FindNTCPSession (const i2p::data::IdentHash& ident);
  133. void ConnectWithProxy (const std::string& addr, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCPSession> conn);
  134. void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCPSession> conn);
  135. bool IsBoundV4() const { return m_NTCPAcceptor != nullptr; };
  136. bool IsBoundV6() const { return m_NTCPV6Acceptor != nullptr; };
  137. bool NetworkIsReady() const { return IsBoundV4() || IsBoundV6() || UsingProxy(); };
  138. bool UsingProxy() const { return m_ProxyType != eNoProxy; };
  139. void UseProxy(ProxyType proxy, const std::string & address, uint16_t port);
  140. boost::asio::io_service& GetService () { return m_Service; };
  141. void SetSessionLimits(uint16_t softLimit, uint16_t hardLimit) { m_SoftLimit = softLimit; m_HardLimit = hardLimit; }
  142. bool ShouldLimit() const { return ShouldHardLimit() || ShouldSoftLimit(); }
  143. void Work(std::shared_ptr<NTCPSession> conn, Pool::WorkFunc work)
  144. {
  145. m_CryptoPool->Offer({conn, work});
  146. }
  147. private:
  148. /** @brief return true for hard limit */
  149. bool ShouldHardLimit() const { return m_HardLimit && m_NTCPSessions.size() >= m_HardLimit; }
  150. /** @brief return true for probabalistic soft backoff */
  151. bool ShouldSoftLimit() const
  152. {
  153. auto sessions = m_NTCPSessions.size();
  154. return sessions && m_SoftLimit && m_SoftLimit < sessions && ( rand() % sessions ) <= m_SoftLimit;
  155. }
  156. void Run ();
  157. void HandleAccept (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
  158. void HandleAcceptV6 (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
  159. void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
  160. void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
  161. void AfterSocksHandshake(std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
  162. // timer
  163. void ScheduleTermination ();
  164. void HandleTerminationTimer (const boost::system::error_code& ecode);
  165. private:
  166. bool m_IsRunning;
  167. std::thread * m_Thread;
  168. boost::asio::io_service m_Service;
  169. boost::asio::io_service::work m_Work;
  170. boost::asio::deadline_timer m_TerminationTimer;
  171. boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor;
  172. std::map<i2p::data::IdentHash, std::shared_ptr<NTCPSession> > m_NTCPSessions; // access from m_Thread only
  173. std::list<std::shared_ptr<NTCPSession> > m_PendingIncomingSessions;
  174. ProxyType m_ProxyType;
  175. std::string m_ProxyAddress;
  176. uint16_t m_ProxyPort;
  177. boost::asio::ip::tcp::resolver m_Resolver;
  178. boost::asio::ip::tcp::endpoint * m_ProxyEndpoint;
  179. std::shared_ptr<Pool> m_CryptoPool;
  180. uint16_t m_SoftLimit, m_HardLimit;
  181. public:
  182. // for HTTP/I2PControl
  183. const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; };
  184. };
  185. }
  186. }
  187. #endif