2014-12-02 23:47:44 +03:00
|
|
|
#include <string.h>
|
2014-12-03 05:45:01 +03:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2014-12-02 19:42:35 +03:00
|
|
|
#include "Log.h"
|
2014-12-03 22:48:41 +03:00
|
|
|
#include "NetDb.h"
|
2014-12-03 05:45:01 +03:00
|
|
|
#include "ClientContext.h"
|
2014-12-02 18:34:02 +03:00
|
|
|
#include "BOB.h"
|
|
|
|
|
|
|
|
namespace i2p
|
|
|
|
{
|
|
|
|
namespace client
|
|
|
|
{
|
2014-12-03 22:48:41 +03:00
|
|
|
BOBI2PInboundTunnel::BOBI2PInboundTunnel (boost::asio::io_service& service, int port, ClientDestination * localDestination):
|
2014-12-06 06:25:31 +03:00
|
|
|
BOBI2PTunnel (service, localDestination),
|
2014-12-03 22:48:41 +03:00
|
|
|
m_Acceptor (service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)),
|
2014-12-04 04:37:20 +03:00
|
|
|
m_Timer (service), m_ReceivedData (nullptr), m_ReceivedDataLen (0)
|
2014-12-03 22:48:41 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BOBI2PInboundTunnel::~BOBI2PInboundTunnel ()
|
|
|
|
{
|
2014-12-05 03:29:20 +03:00
|
|
|
Stop ();
|
2014-12-03 22:48:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::Start ()
|
|
|
|
{
|
|
|
|
m_Acceptor.listen ();
|
|
|
|
Accept ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::Stop ()
|
|
|
|
{
|
|
|
|
m_Acceptor.close();
|
|
|
|
ClearConnections ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::Accept ()
|
|
|
|
{
|
|
|
|
auto newSocket = new boost::asio::ip::tcp::socket (GetService ());
|
|
|
|
m_Acceptor.async_accept (*newSocket, std::bind (&BOBI2PInboundTunnel::HandleAccept, this,
|
|
|
|
std::placeholders::_1, newSocket));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::HandleAccept (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket)
|
|
|
|
{
|
|
|
|
if (!ecode)
|
|
|
|
{
|
|
|
|
Accept ();
|
|
|
|
ReceiveAddress (socket);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
delete socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::ReceiveAddress (boost::asio::ip::tcp::socket * socket)
|
|
|
|
{
|
|
|
|
socket->async_read_some (boost::asio::buffer(m_ReceiveBuffer, BOB_COMMAND_BUFFER_SIZE),
|
|
|
|
std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this,
|
|
|
|
std::placeholders::_1, std::placeholders::_2, socket));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
|
|
|
boost::asio::ip::tcp::socket * socket)
|
|
|
|
{
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
LogPrint ("BOB inbound tunnel read error: ", ecode.message ());
|
|
|
|
delete socket;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_ReceiveBuffer[bytes_transferred] = 0;
|
|
|
|
char * eol = strchr (m_ReceiveBuffer, '\n');
|
|
|
|
if (eol)
|
|
|
|
{
|
|
|
|
*eol = 0;
|
2014-12-04 04:37:20 +03:00
|
|
|
|
|
|
|
m_ReceivedData = (uint8_t *)eol + 1;
|
|
|
|
m_ReceivedDataLen = bytes_transferred - (eol - m_ReceiveBuffer + 1);
|
2014-12-03 22:48:41 +03:00
|
|
|
i2p::data::IdentHash ident;
|
2014-12-04 22:16:33 +03:00
|
|
|
if (!context.GetAddressBook ().GetIdentHash (m_ReceiveBuffer, ident))
|
|
|
|
{
|
|
|
|
LogPrint (eLogError, "BOB address ", m_ReceiveBuffer, " not found");
|
|
|
|
delete socket;
|
|
|
|
return;
|
|
|
|
}
|
2014-12-03 22:48:41 +03:00
|
|
|
auto leaseSet = GetLocalDestination ()->FindLeaseSet (ident);
|
|
|
|
if (leaseSet)
|
|
|
|
CreateConnection (socket, leaseSet);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i2p::data::netdb.RequestDestination (ident, true, GetLocalDestination ()->GetTunnelPool ());
|
|
|
|
m_Timer.expires_from_now (boost::posix_time::seconds (I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT));
|
|
|
|
m_Timer.async_wait (std::bind (&BOBI2PInboundTunnel::HandleDestinationRequestTimer,
|
|
|
|
this, std::placeholders::_1, socket, ident));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-12-06 06:25:31 +03:00
|
|
|
LogPrint ("BOB missing inbound address ", bytes_transferred);
|
2014-12-03 22:48:41 +03:00
|
|
|
delete socket;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::HandleDestinationRequestTimer (const boost::system::error_code& ecode, boost::asio::ip::tcp::socket * socket, i2p::data::IdentHash ident)
|
|
|
|
{
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
{
|
|
|
|
auto leaseSet = GetLocalDestination ()->FindLeaseSet (ident);
|
|
|
|
if (leaseSet)
|
|
|
|
{
|
|
|
|
CreateConnection (socket, leaseSet);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
LogPrint ("LeaseSet for BOB inbound destination not found");
|
|
|
|
}
|
|
|
|
delete socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2PInboundTunnel::CreateConnection (boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet)
|
|
|
|
{
|
|
|
|
LogPrint ("New BOB inbound connection");
|
|
|
|
auto connection = std::make_shared<I2PTunnelConnection>(this, socket, leaseSet);
|
|
|
|
AddConnection (connection);
|
2014-12-04 04:37:20 +03:00
|
|
|
connection->I2PConnect (m_ReceivedData, m_ReceivedDataLen);
|
2014-12-03 22:48:41 +03:00
|
|
|
}
|
|
|
|
|
2014-12-05 22:13:16 +03:00
|
|
|
BOBI2POutboundTunnel::BOBI2POutboundTunnel (boost::asio::io_service& service, const std::string& address, int port,
|
2014-12-06 06:25:31 +03:00
|
|
|
ClientDestination * localDestination, bool quiet): BOBI2PTunnel (service, localDestination),
|
2014-12-05 22:13:16 +03:00
|
|
|
m_Endpoint (boost::asio::ip::address::from_string (address), port), m_IsQuiet (quiet)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2POutboundTunnel::Start ()
|
|
|
|
{
|
|
|
|
Accept ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2POutboundTunnel::Stop ()
|
|
|
|
{
|
|
|
|
ClearConnections ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2POutboundTunnel::Accept ()
|
|
|
|
{
|
|
|
|
auto localDestination = GetLocalDestination ();
|
|
|
|
if (localDestination)
|
|
|
|
localDestination->AcceptStreams (std::bind (&BOBI2POutboundTunnel::HandleAccept, this, std::placeholders::_1));
|
|
|
|
else
|
|
|
|
LogPrint ("Local destination not set for server tunnel");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBI2POutboundTunnel::HandleAccept (std::shared_ptr<i2p::stream::Stream> stream)
|
|
|
|
{
|
|
|
|
if (stream)
|
|
|
|
{
|
2014-12-05 22:46:59 +03:00
|
|
|
auto conn = std::make_shared<I2PTunnelConnection> (this, stream, new boost::asio::ip::tcp::socket (GetService ()), m_Endpoint, m_IsQuiet);
|
2014-12-05 22:13:16 +03:00
|
|
|
AddConnection (conn);
|
|
|
|
conn->Connect ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-02 23:47:44 +03:00
|
|
|
BOBCommandSession::BOBCommandSession (BOBCommandChannel& owner):
|
|
|
|
m_Owner (owner), m_Socket (m_Owner.GetService ()), m_ReceiveBufferOffset (0),
|
2014-12-05 22:13:16 +03:00
|
|
|
m_IsOpen (true), m_IsOutbound (false), m_IsQuiet (false), m_Port (0)
|
2014-12-02 19:42:35 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-12-02 23:47:44 +03:00
|
|
|
BOBCommandSession::~BOBCommandSession ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-12-03 00:45:51 +03:00
|
|
|
void BOBCommandSession::Terminate ()
|
|
|
|
{
|
|
|
|
m_Socket.close ();
|
|
|
|
m_IsOpen = false;
|
|
|
|
}
|
|
|
|
|
2014-12-02 23:47:44 +03:00
|
|
|
void BOBCommandSession::Receive ()
|
|
|
|
{
|
|
|
|
m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, BOB_COMMAND_BUFFER_SIZE - m_ReceiveBufferOffset),
|
|
|
|
std::bind(&BOBCommandSession::HandleReceived, shared_from_this (),
|
|
|
|
std::placeholders::_1, std::placeholders::_2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
|
|
|
{
|
|
|
|
if (ecode)
|
2014-12-03 00:45:51 +03:00
|
|
|
{
|
2014-12-02 23:47:44 +03:00
|
|
|
LogPrint ("BOB command channel read error: ", ecode.message ());
|
2014-12-05 03:29:20 +03:00
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
2014-12-03 00:45:51 +03:00
|
|
|
}
|
2014-12-02 23:47:44 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
size_t size = m_ReceiveBufferOffset + bytes_transferred;
|
|
|
|
m_ReceiveBuffer[size] = 0;
|
|
|
|
char * eol = strchr (m_ReceiveBuffer, '\n');
|
|
|
|
if (eol)
|
|
|
|
{
|
|
|
|
*eol = 0;
|
|
|
|
char * operand = strchr (m_ReceiveBuffer, ' ');
|
2014-12-03 05:45:01 +03:00
|
|
|
if (operand)
|
|
|
|
{
|
|
|
|
*operand = 0;
|
|
|
|
operand++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
operand = eol;
|
2014-12-02 23:47:44 +03:00
|
|
|
// process command
|
2014-12-03 05:45:01 +03:00
|
|
|
auto& handlers = m_Owner.GetCommandHandlers ();
|
2014-12-02 23:47:44 +03:00
|
|
|
auto it = handlers.find (m_ReceiveBuffer);
|
|
|
|
if (it != handlers.end ())
|
2014-12-03 05:45:01 +03:00
|
|
|
(this->*(it->second))(operand, eol - operand);
|
|
|
|
else
|
2014-12-05 18:59:37 +03:00
|
|
|
{
|
2014-12-03 05:45:01 +03:00
|
|
|
LogPrint (eLogError, "BOB unknown command ", m_ReceiveBuffer);
|
2014-12-05 18:59:37 +03:00
|
|
|
SendReplyError ("unknown command");
|
|
|
|
}
|
2014-12-02 23:47:44 +03:00
|
|
|
|
|
|
|
m_ReceiveBufferOffset = size - (eol - m_ReceiveBuffer) - 1;
|
|
|
|
memmove (m_ReceiveBuffer, eol + 1, m_ReceiveBufferOffset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (size < BOB_COMMAND_BUFFER_SIZE)
|
|
|
|
m_ReceiveBufferOffset = size;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LogPrint (eLogError, "Malformed input of the BOB command channel");
|
2014-12-03 00:45:51 +03:00
|
|
|
Terminate ();
|
2014-12-02 23:47:44 +03:00
|
|
|
}
|
|
|
|
}
|
2014-12-03 00:45:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::Send (size_t len)
|
|
|
|
{
|
|
|
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SendBuffer, len),
|
|
|
|
boost::asio::transfer_all (),
|
|
|
|
std::bind(&BOBCommandSession::HandleSent, shared_from_this (),
|
|
|
|
std::placeholders::_1, std::placeholders::_2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
|
|
|
{
|
|
|
|
if (ecode)
|
|
|
|
{
|
|
|
|
LogPrint ("BOB command channel send error: ", ecode.message ());
|
2014-12-05 03:29:20 +03:00
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Terminate ();
|
2014-12-03 00:45:51 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-12-02 23:47:44 +03:00
|
|
|
if (m_IsOpen)
|
|
|
|
Receive ();
|
2014-12-03 00:45:51 +03:00
|
|
|
else
|
|
|
|
Terminate ();
|
2014-12-02 23:47:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-03 00:45:51 +03:00
|
|
|
void BOBCommandSession::SendReplyOK (const char * msg)
|
|
|
|
{
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg);
|
|
|
|
#else
|
|
|
|
size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg);
|
|
|
|
#endif
|
|
|
|
Send (len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::SendReplyError (const char * msg)
|
|
|
|
{
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg);
|
|
|
|
#else
|
|
|
|
size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg);
|
|
|
|
#endif
|
|
|
|
Send (len);
|
|
|
|
}
|
2014-12-06 06:25:31 +03:00
|
|
|
|
2014-12-06 00:03:43 +03:00
|
|
|
void BOBCommandSession::SendVersion ()
|
|
|
|
{
|
|
|
|
size_t len = strlen (BOB_VERSION);
|
|
|
|
memcpy (m_SendBuffer, BOB_VERSION, len);
|
|
|
|
Send (len);
|
|
|
|
}
|
|
|
|
|
2014-12-06 06:25:31 +03:00
|
|
|
void BOBCommandSession::SendData (const char * nickname)
|
|
|
|
{
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_DATA, nickname);
|
|
|
|
#else
|
|
|
|
size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_DATA, nickname);
|
|
|
|
#endif
|
|
|
|
Send (len);
|
|
|
|
}
|
|
|
|
|
2014-12-02 23:47:44 +03:00
|
|
|
void BOBCommandSession::ZapCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: zap");
|
2014-12-03 00:45:51 +03:00
|
|
|
Terminate ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::QuitCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: quit");
|
2014-12-02 23:47:44 +03:00
|
|
|
m_IsOpen = false;
|
2014-12-03 00:45:51 +03:00
|
|
|
SendReplyOK ("Bye!");
|
2014-12-02 23:47:44 +03:00
|
|
|
}
|
|
|
|
|
2014-12-03 05:45:01 +03:00
|
|
|
void BOBCommandSession::StartCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: start ", m_Nickname);
|
2014-12-03 23:02:19 +03:00
|
|
|
auto dest = context.CreateNewLocalDestination (m_Keys, true);
|
2014-12-06 06:25:31 +03:00
|
|
|
BOBI2PTunnel * tunnel = nullptr;
|
2014-12-03 23:02:19 +03:00
|
|
|
if (m_IsOutbound)
|
2014-12-05 22:13:16 +03:00
|
|
|
tunnel = new BOBI2POutboundTunnel (m_Owner.GetService (), m_Address, m_Port, dest, m_IsQuiet);
|
2014-12-03 23:02:19 +03:00
|
|
|
else
|
|
|
|
tunnel = new BOBI2PInboundTunnel (m_Owner.GetService (), m_Port, dest);
|
|
|
|
if (tunnel)
|
|
|
|
{
|
2014-12-03 05:45:01 +03:00
|
|
|
m_Owner.AddTunnel (m_Nickname, tunnel);
|
2014-12-03 23:02:19 +03:00
|
|
|
tunnel->Start ();
|
2014-12-03 05:45:01 +03:00
|
|
|
SendReplyOK ("tunnel starting");
|
|
|
|
}
|
|
|
|
else
|
2014-12-03 23:02:19 +03:00
|
|
|
SendReplyError ("failed to create tunnel");
|
2014-12-03 05:45:01 +03:00
|
|
|
}
|
2014-12-03 23:24:30 +03:00
|
|
|
|
|
|
|
void BOBCommandSession::StopCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
auto tunnel = m_Owner.FindTunnel (m_Nickname);
|
|
|
|
if (tunnel)
|
|
|
|
{
|
|
|
|
tunnel->Stop ();
|
2014-12-05 03:29:20 +03:00
|
|
|
tunnel->GetLocalDestination ()->Stop ();
|
2014-12-03 23:24:30 +03:00
|
|
|
SendReplyOK ("tunnel stopping");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SendReplyError ("tunnel not found");
|
|
|
|
}
|
|
|
|
|
2014-12-03 05:45:01 +03:00
|
|
|
void BOBCommandSession::SetNickCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: setnick");
|
|
|
|
m_Nickname = operand;
|
2014-12-05 03:29:20 +03:00
|
|
|
std::string msg ("Nickname set to ");
|
2014-12-03 05:45:01 +03:00
|
|
|
msg += operand;
|
|
|
|
SendReplyOK (msg.c_str ());
|
|
|
|
}
|
|
|
|
|
2014-12-03 23:24:30 +03:00
|
|
|
void BOBCommandSession::GetNickCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: getnick");
|
2014-12-05 03:29:20 +03:00
|
|
|
auto tunnel = m_Owner.FindTunnel (operand);
|
|
|
|
if (tunnel)
|
2014-12-03 23:24:30 +03:00
|
|
|
{
|
2014-12-05 03:29:20 +03:00
|
|
|
m_Keys = tunnel->GetLocalDestination ()->GetPrivateKeys ();
|
2014-12-03 23:24:30 +03:00
|
|
|
m_Nickname = operand;
|
2014-12-05 03:29:20 +03:00
|
|
|
std::string msg ("Nickname set to ");
|
2014-12-03 23:24:30 +03:00
|
|
|
msg += operand;
|
|
|
|
SendReplyOK (msg.c_str ());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SendReplyError ("tunnel not found");
|
|
|
|
}
|
|
|
|
|
2014-12-03 05:45:01 +03:00
|
|
|
void BOBCommandSession::NewkeysCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: newkeys");
|
|
|
|
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys ();
|
2014-12-03 05:55:30 +03:00
|
|
|
SendReplyOK (m_Keys.GetPublic ().ToBase64 ().c_str ());
|
2014-12-03 05:45:01 +03:00
|
|
|
}
|
|
|
|
|
2014-12-04 05:01:40 +03:00
|
|
|
void BOBCommandSession::SetkeysCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: setkeys");
|
|
|
|
m_Keys.FromBase64 (operand);
|
|
|
|
SendReplyOK ("keys set");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::GetkeysCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: getkeys");
|
|
|
|
SendReplyOK (m_Keys.ToBase64 ().c_str ());
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::GetdestCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: getdest");
|
|
|
|
SendReplyOK (m_Keys.GetPublic ().ToBase64 ().c_str ());
|
|
|
|
}
|
|
|
|
|
2014-12-03 05:45:01 +03:00
|
|
|
void BOBCommandSession::OuthostCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: outhost");
|
2014-12-03 23:02:19 +03:00
|
|
|
m_IsOutbound = true;
|
2014-12-03 05:45:01 +03:00
|
|
|
m_Address = operand;
|
|
|
|
SendReplyOK ("outhost set");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::OutportCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: outport");
|
2014-12-03 23:02:19 +03:00
|
|
|
m_IsOutbound = true;
|
2014-12-03 05:45:01 +03:00
|
|
|
m_Port = boost::lexical_cast<int>(operand);
|
|
|
|
SendReplyOK ("outbound port set");
|
|
|
|
}
|
2014-12-03 23:02:19 +03:00
|
|
|
|
|
|
|
void BOBCommandSession::InhostCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: inhost");
|
|
|
|
m_IsOutbound = false;
|
|
|
|
m_Address = operand;
|
|
|
|
SendReplyOK ("inhost set");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::InportCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: inport");
|
|
|
|
m_IsOutbound = false;
|
|
|
|
m_Port = boost::lexical_cast<int>(operand);
|
|
|
|
SendReplyOK ("inbound port set");
|
|
|
|
}
|
2014-12-05 22:13:16 +03:00
|
|
|
|
|
|
|
void BOBCommandSession::QuietCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: quiet");
|
|
|
|
m_IsQuiet = true;
|
|
|
|
SendReplyOK ("quiet");
|
|
|
|
}
|
|
|
|
|
2014-12-06 00:03:43 +03:00
|
|
|
void BOBCommandSession::LookupCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: lookup");
|
|
|
|
i2p::data::IdentityEx addr;
|
|
|
|
if (!context.GetAddressBook ().GetAddress (operand, addr))
|
|
|
|
{
|
|
|
|
SendReplyError ("Address Not found");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SendReplyOK (addr.ToBase64 ().c_str ());
|
|
|
|
}
|
|
|
|
|
2014-12-06 03:16:54 +03:00
|
|
|
void BOBCommandSession::ClearCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: clear");
|
|
|
|
// TODO
|
|
|
|
SendReplyOK ("cleared");
|
|
|
|
}
|
2014-12-06 00:03:43 +03:00
|
|
|
|
2014-12-06 06:25:31 +03:00
|
|
|
void BOBCommandSession::ListCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: list");
|
|
|
|
auto& tunnels = m_Owner.GetTunnels ();
|
|
|
|
for (auto it: tunnels)
|
|
|
|
SendData (it.first.c_str ());
|
|
|
|
SendReplyOK ("Listing done");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandSession::OptionCommandHandler (const char * operand, size_t len)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "BOB: option ", operand);
|
|
|
|
SendReplyOK ("option");
|
|
|
|
}
|
|
|
|
|
2014-12-02 19:42:35 +03:00
|
|
|
BOBCommandChannel::BOBCommandChannel (int port):
|
|
|
|
m_IsRunning (false), m_Thread (nullptr),
|
|
|
|
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
|
2014-12-02 18:34:02 +03:00
|
|
|
{
|
2014-12-03 05:45:01 +03:00
|
|
|
// command -> handler
|
2014-12-02 23:47:44 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_ZAP] = &BOBCommandSession::ZapCommandHandler;
|
2014-12-03 00:45:51 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_QUIT] = &BOBCommandSession::QuitCommandHandler;
|
2014-12-03 05:45:01 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_START] = &BOBCommandSession::StartCommandHandler;
|
2014-12-03 23:24:30 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_STOP] = &BOBCommandSession::StopCommandHandler;
|
2014-12-03 05:45:01 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_SETNICK] = &BOBCommandSession::SetNickCommandHandler;
|
2014-12-03 23:24:30 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_GETNICK] = &BOBCommandSession::GetNickCommandHandler;
|
2014-12-03 05:45:01 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_NEWKEYS] = &BOBCommandSession::NewkeysCommandHandler;
|
2014-12-04 05:01:40 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_GETKEYS] = &BOBCommandSession::GetkeysCommandHandler;
|
|
|
|
m_CommandHandlers[BOB_COMMAND_SETKEYS] = &BOBCommandSession::SetkeysCommandHandler;
|
|
|
|
m_CommandHandlers[BOB_COMMAND_GETDEST] = &BOBCommandSession::GetdestCommandHandler;
|
2014-12-03 05:45:01 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_OUTHOST] = &BOBCommandSession::OuthostCommandHandler;
|
|
|
|
m_CommandHandlers[BOB_COMMAND_OUTPORT] = &BOBCommandSession::OutportCommandHandler;
|
2014-12-03 23:02:19 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_INHOST] = &BOBCommandSession::InhostCommandHandler;
|
|
|
|
m_CommandHandlers[BOB_COMMAND_INPORT] = &BOBCommandSession::InportCommandHandler;
|
2014-12-05 22:13:16 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_QUIET] = &BOBCommandSession::QuietCommandHandler;
|
2014-12-06 00:03:43 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_LOOKUP] = &BOBCommandSession::LookupCommandHandler;
|
2014-12-06 03:16:54 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_CLEAR] = &BOBCommandSession::ClearCommandHandler;
|
2014-12-06 06:25:31 +03:00
|
|
|
m_CommandHandlers[BOB_COMMAND_LIST] = &BOBCommandSession::ListCommandHandler;
|
|
|
|
m_CommandHandlers[BOB_COMMAND_OPTION] = &BOBCommandSession::OptionCommandHandler;
|
2014-12-02 18:34:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
BOBCommandChannel::~BOBCommandChannel ()
|
|
|
|
{
|
2014-12-02 19:42:35 +03:00
|
|
|
Stop ();
|
2014-12-03 23:24:30 +03:00
|
|
|
for (auto it: m_Tunnels)
|
|
|
|
delete it.second;
|
2014-12-02 19:42:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandChannel::Start ()
|
|
|
|
{
|
|
|
|
Accept ();
|
|
|
|
m_IsRunning = true;
|
|
|
|
m_Thread = new std::thread (std::bind (&BOBCommandChannel::Run, this));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandChannel::Stop ()
|
|
|
|
{
|
2014-12-02 23:47:44 +03:00
|
|
|
for (auto it: m_Tunnels)
|
2014-12-03 23:24:30 +03:00
|
|
|
it.second->Stop ();
|
2014-12-02 19:42:35 +03:00
|
|
|
m_IsRunning = false;
|
|
|
|
m_Service.stop ();
|
|
|
|
if (m_Thread)
|
|
|
|
{
|
|
|
|
m_Thread->join ();
|
|
|
|
delete m_Thread;
|
|
|
|
m_Thread = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BOBCommandChannel::Run ()
|
|
|
|
{
|
|
|
|
while (m_IsRunning)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
m_Service.run ();
|
|
|
|
}
|
|
|
|
catch (std::exception& ex)
|
|
|
|
{
|
|
|
|
LogPrint (eLogError, "BOB: ", ex.what ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-06 06:25:31 +03:00
|
|
|
void BOBCommandChannel::AddTunnel (const std::string& name, BOBI2PTunnel * tunnel)
|
2014-12-03 05:45:01 +03:00
|
|
|
{
|
|
|
|
m_Tunnels[name] = tunnel;
|
|
|
|
}
|
2014-12-03 23:24:30 +03:00
|
|
|
|
2014-12-06 06:25:31 +03:00
|
|
|
BOBI2PTunnel * BOBCommandChannel::FindTunnel (const std::string& name)
|
2014-12-03 23:24:30 +03:00
|
|
|
{
|
|
|
|
auto it = m_Tunnels.find (name);
|
|
|
|
if (it != m_Tunnels.end ())
|
|
|
|
return it->second;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-12-03 05:45:01 +03:00
|
|
|
|
2014-12-02 19:42:35 +03:00
|
|
|
void BOBCommandChannel::Accept ()
|
|
|
|
{
|
2014-12-02 23:47:44 +03:00
|
|
|
auto newSession = std::make_shared<BOBCommandSession> (*this);
|
|
|
|
m_Acceptor.async_accept (newSession->GetSocket (), std::bind (&BOBCommandChannel::HandleAccept, this,
|
|
|
|
std::placeholders::_1, newSession));
|
2014-12-02 19:42:35 +03:00
|
|
|
}
|
|
|
|
|
2014-12-02 23:47:44 +03:00
|
|
|
void BOBCommandChannel::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<BOBCommandSession> session)
|
2014-12-02 19:42:35 +03:00
|
|
|
{
|
|
|
|
if (ecode != boost::asio::error::operation_aborted)
|
|
|
|
Accept ();
|
|
|
|
|
|
|
|
if (!ecode)
|
|
|
|
{
|
2014-12-02 23:47:44 +03:00
|
|
|
LogPrint (eLogInfo, "New BOB command connection from ", session->GetSocket ().remote_endpoint ());
|
2014-12-06 00:03:43 +03:00
|
|
|
session->SendVersion ();
|
2014-12-02 19:42:35 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
LogPrint (eLogError, "BOB accept error: ", ecode.message ());
|
2014-12-02 18:34:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|