|
|
|
@@ -116,7 +116,7 @@ namespace transport
|
|
|
|
m_Establisher->phase1.HXxorHI[i] ^= ident[i];
|
|
|
|
m_Establisher->phase1.HXxorHI[i] ^= ident[i];
|
|
|
|
|
|
|
|
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (),
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (),
|
|
|
|
std::bind(&NTCPSession::HandlePhase1Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
|
|
|
std::bind(&NTCPSession::HandlePhase1Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPSession::ServerLogin ()
|
|
|
|
void NTCPSession::ServerLogin ()
|
|
|
|
@@ -132,7 +132,7 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) bytes_transferred;
|
|
|
|
(void) bytes_transferred;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: couldn't send Phase 1 message: ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: couldn't send Phase 1 message: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -149,7 +149,7 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) bytes_transferred;
|
|
|
|
(void) bytes_transferred;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: phase 1 read error: ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: phase 1 read error: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -210,7 +210,7 @@ namespace transport
|
|
|
|
|
|
|
|
|
|
|
|
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
|
|
|
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase2, sizeof (NTCPPhase2)), boost::asio::transfer_all (),
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase2, sizeof (NTCPPhase2)), boost::asio::transfer_all (),
|
|
|
|
std::bind(&NTCPSession::HandlePhase2Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, tsB));
|
|
|
|
std::bind(&NTCPSession::HandlePhase2Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, tsB));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -218,7 +218,7 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) bytes_transferred;
|
|
|
|
(void) bytes_transferred;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: Couldn't send Phase 2 message: ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: Couldn't send Phase 2 message: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -235,7 +235,7 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) bytes_transferred;
|
|
|
|
(void) bytes_transferred;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: Phase 2 read error: ", ecode.message (), ". Wrong ident assumed");
|
|
|
|
LogPrint (eLogInfo, "NTCP: Phase 2 read error: ", ecode.message (), ". Wrong ident assumed");
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -318,20 +318,20 @@ namespace transport
|
|
|
|
s.Insert (m_Establisher->phase1.pubKey, 256); // x
|
|
|
|
s.Insert (m_Establisher->phase1.pubKey, 256); // x
|
|
|
|
s.Insert (m_Establisher->phase2.pubKey, 256); // y
|
|
|
|
s.Insert (m_Establisher->phase2.pubKey, 256); // y
|
|
|
|
s.Insert (m_RemoteIdentity->GetIdentHash (), 32); // ident
|
|
|
|
s.Insert (m_RemoteIdentity->GetIdentHash (), 32); // ident
|
|
|
|
s.Insert (tsA); // tsA
|
|
|
|
s.Insert (tsA); // tsA
|
|
|
|
s.Insert (m_Establisher->phase2.encrypted.timestamp, 4); // tsB
|
|
|
|
s.Insert (m_Establisher->phase2.encrypted.timestamp, 4); // tsB
|
|
|
|
s.Sign (keys, buf);
|
|
|
|
s.Sign (keys, buf);
|
|
|
|
|
|
|
|
|
|
|
|
m_Encryption.Encrypt(m_ReceiveBuffer, len, m_ReceiveBuffer);
|
|
|
|
m_Encryption.Encrypt(m_ReceiveBuffer, len, m_ReceiveBuffer);
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_ReceiveBuffer, len), boost::asio::transfer_all (),
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_ReceiveBuffer, len), boost::asio::transfer_all (),
|
|
|
|
std::bind(&NTCPSession::HandlePhase3Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, tsA));
|
|
|
|
std::bind(&NTCPSession::HandlePhase3Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, tsA));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPSession::HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA)
|
|
|
|
void NTCPSession::HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) bytes_transferred;
|
|
|
|
(void) bytes_transferred;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: Couldn't send Phase 3 message: ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: Couldn't send Phase 3 message: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -351,7 +351,7 @@ namespace transport
|
|
|
|
void NTCPSession::HandlePhase3Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB)
|
|
|
|
void NTCPSession::HandlePhase3Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: Phase 3 read error: ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: Phase 3 read error: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -389,7 +389,7 @@ namespace transport
|
|
|
|
void NTCPSession::HandlePhase3ExtraReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB, size_t paddingLen)
|
|
|
|
void NTCPSession::HandlePhase3ExtraReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB, size_t paddingLen)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: Phase 3 extra read error: ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: Phase 3 extra read error: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -444,21 +444,21 @@ namespace transport
|
|
|
|
s.Insert (tsA); // tsA
|
|
|
|
s.Insert (tsA); // tsA
|
|
|
|
s.Insert (tsB); // tsB
|
|
|
|
s.Insert (tsB); // tsB
|
|
|
|
auto& keys = i2p::context.GetPrivateKeys ();
|
|
|
|
auto& keys = i2p::context.GetPrivateKeys ();
|
|
|
|
auto signatureLen = keys.GetPublic ()->GetSignatureLen ();
|
|
|
|
auto signatureLen = keys.GetPublic ()->GetSignatureLen ();
|
|
|
|
s.Sign (keys, m_ReceiveBuffer);
|
|
|
|
s.Sign (keys, m_ReceiveBuffer);
|
|
|
|
size_t paddingSize = signatureLen & 0x0F; // %16
|
|
|
|
size_t paddingSize = signatureLen & 0x0F; // %16
|
|
|
|
if (paddingSize > 0) signatureLen += (16 - paddingSize);
|
|
|
|
if (paddingSize > 0) signatureLen += (16 - paddingSize);
|
|
|
|
m_Encryption.Encrypt (m_ReceiveBuffer, signatureLen, m_ReceiveBuffer);
|
|
|
|
m_Encryption.Encrypt (m_ReceiveBuffer, signatureLen, m_ReceiveBuffer);
|
|
|
|
|
|
|
|
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_ReceiveBuffer, signatureLen), boost::asio::transfer_all (),
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_ReceiveBuffer, signatureLen), boost::asio::transfer_all (),
|
|
|
|
std::bind(&NTCPSession::HandlePhase4Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
|
|
|
std::bind(&NTCPSession::HandlePhase4Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPSession::HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
|
|
|
void NTCPSession::HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) bytes_transferred;
|
|
|
|
(void) bytes_transferred;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogWarning, "NTCP: Couldn't send Phase 4 message: ", ecode.message ());
|
|
|
|
LogPrint (eLogWarning, "NTCP: Couldn't send Phase 4 message: ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
|
|
|
Terminate ();
|
|
|
|
@@ -478,7 +478,7 @@ namespace transport
|
|
|
|
void NTCPSession::HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA)
|
|
|
|
void NTCPSession::HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
|
|
|
|
LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -673,13 +673,13 @@ namespace transport
|
|
|
|
m_NextMessage = nullptr;
|
|
|
|
m_NextMessage = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPSession::Send (std::shared_ptr<i2p::I2NPMessage> msg)
|
|
|
|
void NTCPSession::Send (std::shared_ptr<i2p::I2NPMessage> msg)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_IsSending = true;
|
|
|
|
m_IsSending = true;
|
|
|
|
boost::asio::async_write (m_Socket, CreateMsgBuffer (msg), boost::asio::transfer_all (),
|
|
|
|
boost::asio::async_write (m_Socket, CreateMsgBuffer (msg), boost::asio::transfer_all (),
|
|
|
|
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::vector<std::shared_ptr<I2NPMessage> >{ msg }));
|
|
|
|
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::vector<std::shared_ptr<I2NPMessage> >{ msg }));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boost::asio::const_buffers_1 NTCPSession::CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg)
|
|
|
|
boost::asio::const_buffers_1 NTCPSession::CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg)
|
|
|
|
@@ -726,7 +726,7 @@ namespace transport
|
|
|
|
for (const auto& it: msgs)
|
|
|
|
for (const auto& it: msgs)
|
|
|
|
bufs.push_back (CreateMsgBuffer (it));
|
|
|
|
bufs.push_back (CreateMsgBuffer (it));
|
|
|
|
boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (),
|
|
|
|
boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (),
|
|
|
|
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs));
|
|
|
|
std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs)
|
|
|
|
void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs)
|
|
|
|
@@ -734,7 +734,7 @@ namespace transport
|
|
|
|
(void) msgs;
|
|
|
|
(void) msgs;
|
|
|
|
m_IsSending = false;
|
|
|
|
m_IsSending = false;
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogWarning, "NTCP: Couldn't send msgs: ", ecode.message ());
|
|
|
|
LogPrint (eLogWarning, "NTCP: Couldn't send msgs: ", ecode.message ());
|
|
|
|
// we shouldn't call Terminate () here, because HandleReceive takes care
|
|
|
|
// we shouldn't call Terminate () here, because HandleReceive takes care
|
|
|
|
// TODO: 'delete this' statement in Terminate () must be eliminated later
|
|
|
|
// TODO: 'delete this' statement in Terminate () must be eliminated later
|
|
|
|
@@ -788,7 +788,8 @@ namespace transport
|
|
|
|
//-----------------------------------------
|
|
|
|
//-----------------------------------------
|
|
|
|
NTCPServer::NTCPServer ():
|
|
|
|
NTCPServer::NTCPServer ():
|
|
|
|
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
|
|
|
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
|
|
|
m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr)
|
|
|
|
m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
|
|
|
|
|
|
|
|
m_UseSocks(false), m_Resolver(m_Service), m_SocksEndpoint(nullptr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -803,48 +804,62 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_IsRunning = true;
|
|
|
|
m_IsRunning = true;
|
|
|
|
m_Thread = new std::thread (std::bind (&NTCPServer::Run, this));
|
|
|
|
m_Thread = new std::thread (std::bind (&NTCPServer::Run, this));
|
|
|
|
// create acceptors
|
|
|
|
// we are using a socks proxy, don't create any acceptors
|
|
|
|
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
|
|
|
if(m_UseSocks)
|
|
|
|
for (const auto& address: addresses)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!address) continue;
|
|
|
|
boost::asio::ip::tcp::resolver::query q(m_SocksAddress, std::to_string(m_SocksPort));
|
|
|
|
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
|
|
|
boost::system::error_code e;
|
|
|
|
|
|
|
|
auto itr = m_Resolver.resolve(q, e);
|
|
|
|
|
|
|
|
if(e)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (address->host.is_v4())
|
|
|
|
LogPrint(eLogError, "NTCP: Failed to resolve proxy ", e.message());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_SocksEndpoint = new boost::asio::ip::tcp::endpoint(*itr);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// create acceptors
|
|
|
|
|
|
|
|
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
|
|
|
|
|
|
|
for (const auto& address: addresses)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!address) continue;
|
|
|
|
|
|
|
|
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
try
|
|
|
|
if (address->host.is_v4())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service,
|
|
|
|
try
|
|
|
|
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
|
|
|
{
|
|
|
|
} catch ( std::exception & ex ) {
|
|
|
|
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
|
|
|
/** fail to bind ip4 */
|
|
|
|
} catch ( std::exception & ex ) {
|
|
|
|
LogPrint(eLogError, "NTCP: Failed to bind to ip4 port ",address->port, ex.what());
|
|
|
|
/** fail to bind ip4 */
|
|
|
|
continue;
|
|
|
|
LogPrint(eLogError, "NTCP: Failed to bind to ip4 port ",address->port, ex.what());
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LogPrint (eLogInfo, "NTCP: Start listening TCP port ", address->port);
|
|
|
|
|
|
|
|
auto conn = std::make_shared<NTCPSession>(*this);
|
|
|
|
|
|
|
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this, conn, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (address->host.is_v6() && context.SupportsV6 ())
|
|
|
|
LogPrint (eLogInfo, "NTCP: Start listening TCP port ", address->port);
|
|
|
|
|
|
|
|
auto conn = std::make_shared<NTCPSession>(*this);
|
|
|
|
|
|
|
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this,
|
|
|
|
|
|
|
|
conn, std::placeholders::_1));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (address->host.is_v6() && context.SupportsV6 ())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
|
|
|
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
|
|
|
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor->listen ();
|
|
|
|
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
|
|
|
LogPrint (eLogInfo, "NTCP: Start listening V6 TCP port ", address->port);
|
|
|
|
m_NTCPV6Acceptor->listen ();
|
|
|
|
auto conn = std::make_shared<NTCPSession> (*this);
|
|
|
|
|
|
|
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this, conn, std::placeholders::_1));
|
|
|
|
LogPrint (eLogInfo, "NTCP: Start listening V6 TCP port ", address->port);
|
|
|
|
} catch ( std::exception & ex ) {
|
|
|
|
auto conn = std::make_shared<NTCPSession> (*this);
|
|
|
|
LogPrint(eLogError, "NTCP: failed to bind to ip6 port ", address->port);
|
|
|
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6,
|
|
|
|
continue;
|
|
|
|
this, conn, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
} catch ( std::exception & ex ) {
|
|
|
|
|
|
|
|
LogPrint(eLogError, "NTCP: failed to bind to ip6 port ", address->port);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -869,14 +884,14 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_IsRunning = false;
|
|
|
|
m_IsRunning = false;
|
|
|
|
m_TerminationTimer.cancel ();
|
|
|
|
m_TerminationTimer.cancel ();
|
|
|
|
if (m_NTCPAcceptor)
|
|
|
|
if (m_NTCPAcceptor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
delete m_NTCPAcceptor;
|
|
|
|
delete m_NTCPAcceptor;
|
|
|
|
m_NTCPAcceptor = nullptr;
|
|
|
|
m_NTCPAcceptor = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_NTCPV6Acceptor)
|
|
|
|
if (m_NTCPV6Acceptor)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
delete m_NTCPV6Acceptor;
|
|
|
|
delete m_NTCPV6Acceptor;
|
|
|
|
m_NTCPV6Acceptor = nullptr;
|
|
|
|
m_NTCPV6Acceptor = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Service.stop ();
|
|
|
|
m_Service.stop ();
|
|
|
|
@@ -886,6 +901,11 @@ namespace transport
|
|
|
|
delete m_Thread;
|
|
|
|
delete m_Thread;
|
|
|
|
m_Thread = nullptr;
|
|
|
|
m_Thread = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_SocksEndpoint)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
delete m_SocksEndpoint;
|
|
|
|
|
|
|
|
m_SocksEndpoint = nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -956,7 +976,7 @@ namespace transport
|
|
|
|
|
|
|
|
|
|
|
|
if (error != boost::asio::error::operation_aborted)
|
|
|
|
if (error != boost::asio::error::operation_aborted)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
conn = std::make_shared<NTCPSession> (*this);
|
|
|
|
conn = std::make_shared<NTCPSession> (*this);
|
|
|
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this,
|
|
|
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this,
|
|
|
|
conn, std::placeholders::_1));
|
|
|
|
conn, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -983,31 +1003,56 @@ namespace transport
|
|
|
|
|
|
|
|
|
|
|
|
if (error != boost::asio::error::operation_aborted)
|
|
|
|
if (error != boost::asio::error::operation_aborted)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
conn = std::make_shared<NTCPSession> (*this);
|
|
|
|
conn = std::make_shared<NTCPSession> (*this);
|
|
|
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this,
|
|
|
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this,
|
|
|
|
conn, std::placeholders::_1));
|
|
|
|
conn, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPServer::Connect (const boost::asio::ip::address& address, int port, std::shared_ptr<NTCPSession> conn)
|
|
|
|
void NTCPServer::Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCPSession> conn)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "NTCP: Connecting to ", address ,":", port);
|
|
|
|
LogPrint (eLogDebug, "NTCP: Connecting to ", address ,":", port);
|
|
|
|
m_Service.post([=]()
|
|
|
|
m_Service.post([&]() {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (this->AddNTCPSession (conn))
|
|
|
|
if (this->AddNTCPSession (conn))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
auto timer = std::make_shared<boost::asio::deadline_timer>(m_Service);
|
|
|
|
auto timer = std::make_shared<boost::asio::deadline_timer>(m_Service);
|
|
|
|
timer->expires_from_now (boost::posix_time::seconds(NTCP_CONNECT_TIMEOUT));
|
|
|
|
timer->expires_from_now (boost::posix_time::seconds(NTCP_CONNECT_TIMEOUT));
|
|
|
|
timer->async_wait ([conn](const boost::system::error_code& ecode)
|
|
|
|
timer->async_wait ([conn](const boost::system::error_code& ecode) {
|
|
|
|
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
LogPrint (eLogInfo, "NTCP: Not connected in ", NTCP_CONNECT_TIMEOUT, " seconds");
|
|
|
|
{
|
|
|
|
conn->Terminate ();
|
|
|
|
LogPrint (eLogInfo, "NTCP: Not connected in ", NTCP_CONNECT_TIMEOUT, " seconds");
|
|
|
|
}
|
|
|
|
conn->Terminate ();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
conn->GetSocket ().async_connect (boost::asio::ip::tcp::endpoint (address, port), std::bind (&NTCPServer::HandleConnect, this, std::placeholders::_1, conn, timer));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
conn->GetSocket ().async_connect (boost::asio::ip::tcp::endpoint (address, port),
|
|
|
|
});
|
|
|
|
std::bind (&NTCPServer::HandleConnect, this, std::placeholders::_1, conn, timer));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPServer::ConnectSocks (const std::string& host, uint16_t port, std::shared_ptr<NTCPSession> conn)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(m_SocksEndpoint == nullptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
LogPrint (eLogDebug, "NTCP: Connecting to ", host ,":", port, " Via socks proxy");
|
|
|
|
|
|
|
|
m_Service.post([=]() {
|
|
|
|
|
|
|
|
if (this->AddNTCPSession (conn))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto timer = std::make_shared<boost::asio::deadline_timer>(m_Service);
|
|
|
|
|
|
|
|
auto timeout = NTCP_CONNECT_TIMEOUT * 2;
|
|
|
|
|
|
|
|
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
|
|
|
|
|
|
|
timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) {
|
|
|
|
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogPrint (eLogInfo, "NTCP: Not connected in ", timeout, " seconds");
|
|
|
|
|
|
|
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
|
|
|
|
|
|
|
conn->Terminate ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
conn->GetSocket ().async_connect (*m_SocksEndpoint, std::bind (&NTCPServer::HandleSocksConnect, this, std::placeholders::_1, conn, timer, host, port));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -1016,7 +1061,7 @@ namespace transport
|
|
|
|
{
|
|
|
|
{
|
|
|
|
timer->cancel ();
|
|
|
|
timer->cancel ();
|
|
|
|
if (ecode)
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogPrint (eLogInfo, "NTCP: Connect error ", ecode.message ());
|
|
|
|
LogPrint (eLogInfo, "NTCP: Connect error ", ecode.message ());
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
|
|
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
|
|
|
@@ -1031,6 +1076,66 @@ namespace transport
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPServer::UseSocksProxy(const std::string & addr, uint16_t port)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_UseSocks = true;
|
|
|
|
|
|
|
|
m_SocksAddress = addr;
|
|
|
|
|
|
|
|
m_SocksPort = port;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPServer::HandleSocksConnect(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)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(ecode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogPrint(eLogInfo, "NTCP: Socks Proxy connect error ", ecode.message());
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
LogPrint(eLogDebug, "NTCP: connecting via socks proxy to ",host, ":", port);
|
|
|
|
|
|
|
|
uint8_t readbuff[8];
|
|
|
|
|
|
|
|
// build socks4a request
|
|
|
|
|
|
|
|
size_t addrsz = host.size();
|
|
|
|
|
|
|
|
size_t sz = 8 + 1 + 4 + addrsz + 1;
|
|
|
|
|
|
|
|
uint8_t buff[256];
|
|
|
|
|
|
|
|
if(sz > 256)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// hostname too big
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
buff[0] = 4;
|
|
|
|
|
|
|
|
buff[1] = 1;
|
|
|
|
|
|
|
|
htobe16buf(buff+2, port);
|
|
|
|
|
|
|
|
buff[4] = 0;
|
|
|
|
|
|
|
|
buff[5] = 0;
|
|
|
|
|
|
|
|
buff[6] = 0;
|
|
|
|
|
|
|
|
buff[7] = 1;
|
|
|
|
|
|
|
|
buff[8] = 105; // i
|
|
|
|
|
|
|
|
buff[9] = 50; // 2
|
|
|
|
|
|
|
|
buff[10] = 112; // p
|
|
|
|
|
|
|
|
buff[11] = 100; // d
|
|
|
|
|
|
|
|
buff[12] = 0;
|
|
|
|
|
|
|
|
memcpy(buff+12, host.c_str(), addrsz);
|
|
|
|
|
|
|
|
buff[12+addrsz] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, sz), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t written) {
|
|
|
|
|
|
|
|
if(ec)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogPrint(eLogError, "NTCP: failed to write handshake to socks proxy ", ec.message());
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 8), [&](const boost::system::error_code & e, std::size_t transferred) {
|
|
|
|
|
|
|
|
if(transferred == 8 && readbuff[1] == 0x5a)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
timer->cancel();
|
|
|
|
|
|
|
|
conn->ClientLogin();
|
|
|
|
|
|
|
|
LogPrint(eLogDebug, "NTCP: connected via socks");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
LogPrint(eLogDebug, "NTCP: connection via socks failed");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void NTCPServer::ScheduleTermination ()
|
|
|
|
void NTCPServer::ScheduleTermination ()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_TerminationTimer.expires_from_now (boost::posix_time::seconds(NTCP_TERMINATION_CHECK_TIMEOUT));
|
|
|
|
m_TerminationTimer.expires_from_now (boost::posix_time::seconds(NTCP_TERMINATION_CHECK_TIMEOUT));
|
|
|
|
@@ -1045,15 +1150,14 @@ namespace transport
|
|
|
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
|
|
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
|
|
|
// established
|
|
|
|
// established
|
|
|
|
for (auto& it: m_NTCPSessions)
|
|
|
|
for (auto& it: m_NTCPSessions)
|
|
|
|
if (it.second->IsTerminationTimeoutExpired (ts))
|
|
|
|
if (it.second->IsTerminationTimeoutExpired (ts))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto session = it.second;
|
|
|
|
auto session = it.second;
|
|
|
|
// Termniate modifies m_NTCPSession, so we postpone it
|
|
|
|
// Termniate modifies m_NTCPSession, so we postpone it
|
|
|
|
m_Service.post ([session]
|
|
|
|
m_Service.post ([session] {
|
|
|
|
{
|
|
|
|
|
|
|
|
LogPrint (eLogDebug, "NTCP: No activity for ", session->GetTerminationTimeout (), " seconds");
|
|
|
|
LogPrint (eLogDebug, "NTCP: No activity for ", session->GetTerminationTimeout (), " seconds");
|
|
|
|
session->Terminate ();
|
|
|
|
session->Terminate ();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// pending
|
|
|
|
// pending
|
|
|
|
for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();)
|
|
|
|
for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();)
|
|
|
|
|