mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-08-26 10:10:24 +01:00
extract and check VERSION
This commit is contained in:
parent
d496b15249
commit
7dd174d32c
2 changed files with 83 additions and 80 deletions
|
@ -26,9 +26,9 @@ namespace client
|
|||
{
|
||||
SAMSocket::SAMSocket (SAMBridge& owner):
|
||||
m_Owner (owner), m_Socket(owner.GetService()), m_Timer (m_Owner.GetService ()),
|
||||
m_BufferOffset (0),
|
||||
m_SocketType (SAMSocketType::eSAMSocketTypeUnknown), m_IsSilent (false),
|
||||
m_IsAccepting (false), m_IsReceiving (false)
|
||||
m_BufferOffset (0), m_SocketType (SAMSocketType::eSAMSocketTypeUnknown),
|
||||
m_IsSilent (false), m_IsAccepting (false), m_IsReceiving (false),
|
||||
m_Version (MIN_SAM_VERSION)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -81,19 +81,24 @@ namespace client
|
|||
std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
static bool SAMVersionAcceptable(const std::string & ver)
|
||||
static int ExtractVersion (std::string_view ver)
|
||||
{
|
||||
return ver == "3.0" || ver == "3.1";
|
||||
int version = 0;
|
||||
for (auto ch: ver)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
{
|
||||
version *= 10;
|
||||
version += (ch - '0');
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
static bool SAMVersionTooLow(const std::string & ver)
|
||||
static std::string CreateVersion (int ver)
|
||||
{
|
||||
return ver.size() && ver[0] < '3';
|
||||
}
|
||||
|
||||
static bool SAMVersionTooHigh(const std::string & ver)
|
||||
{
|
||||
return ver.size() && ver > "3.1";
|
||||
auto d = div (ver, 10);
|
||||
return std::to_string (d.quot) + "." + std::to_string (d.rem);
|
||||
}
|
||||
|
||||
void SAMSocket::HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||
|
@ -121,8 +126,7 @@ namespace client
|
|||
|
||||
if (!strcmp (m_Buffer, SAM_HANDSHAKE))
|
||||
{
|
||||
std::string maxver("3.1");
|
||||
std::string minver("3.0");
|
||||
int minVer = 0, maxVer = 0;
|
||||
// try to find MIN and MAX, 3.0 if not found
|
||||
if (separator)
|
||||
{
|
||||
|
@ -130,40 +134,34 @@ namespace client
|
|||
auto params = ExtractParams (separator);
|
||||
auto it = params.find (SAM_PARAM_MAX);
|
||||
if (it != params.end ())
|
||||
maxver = it->second;
|
||||
maxVer = ExtractVersion (it->second);
|
||||
it = params.find(SAM_PARAM_MIN);
|
||||
if (it != params.end ())
|
||||
minver = it->second;
|
||||
minVer = ExtractVersion (it->second);
|
||||
}
|
||||
// version negotiation
|
||||
std::string version;
|
||||
if (SAMVersionAcceptable(maxver))
|
||||
if (maxVer && maxVer <= MAX_SAM_VERSION)
|
||||
m_Version = maxVer;
|
||||
else if (minVer && minVer >= MIN_SAM_VERSION && minVer <= MAX_SAM_VERSION)
|
||||
m_Version = minVer;
|
||||
else if (!maxVer && !minVer)
|
||||
m_Version = MIN_SAM_VERSION;
|
||||
else
|
||||
{
|
||||
version = maxver;
|
||||
LogPrint (eLogError, "SAM: Handshake version mismatch ", minVer, " ", maxVer);
|
||||
SendMessageReply (SAM_HANDSHAKE_NOVERSION, true);
|
||||
return;
|
||||
}
|
||||
else if (SAMVersionAcceptable(minver))
|
||||
{
|
||||
version = minver;
|
||||
}
|
||||
else if (SAMVersionTooLow(minver) && SAMVersionTooHigh(maxver))
|
||||
{
|
||||
version = "3.0";
|
||||
}
|
||||
|
||||
if (SAMVersionAcceptable(version))
|
||||
{
|
||||
// send reply
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, CreateVersion (m_Version).c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, CreateVersion (m_Version).c_str ());
|
||||
#endif
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (),
|
||||
std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_HANDSHAKE_NOVERSION, strlen (SAM_HANDSHAKE_NOVERSION), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SAM: Handshake mismatch");
|
||||
|
@ -193,12 +191,12 @@ namespace client
|
|||
}
|
||||
}
|
||||
|
||||
void SAMSocket::SendMessageReply (const char * msg, size_t len, bool close)
|
||||
void SAMSocket::SendMessageReply (std::string_view msg, bool close)
|
||||
{
|
||||
LogPrint (eLogDebug, "SAMSocket::SendMessageReply, close=",close?"true":"false", " reason: ", msg);
|
||||
|
||||
if (!m_IsSilent || m_SocketType == SAMSocketType::eSAMSocketTypeForward)
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (),
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (msg.data (), msg.size ()), boost::asio::transfer_all (),
|
||||
std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (),
|
||||
std::placeholders::_1, std::placeholders::_2, close));
|
||||
else
|
||||
|
@ -341,14 +339,14 @@ namespace client
|
|||
if(!IsAcceptableSessionName(id))
|
||||
{
|
||||
// invalid session id
|
||||
SendMessageReply (SAM_SESSION_CREATE_INVALID_ID, strlen(SAM_SESSION_CREATE_INVALID_ID), true);
|
||||
SendMessageReply (SAM_SESSION_CREATE_INVALID_ID, true);
|
||||
return;
|
||||
}
|
||||
m_ID = id;
|
||||
if (m_Owner.FindSession (id))
|
||||
{
|
||||
// session exists
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), true);
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -412,7 +410,7 @@ namespace client
|
|||
//ensure we actually received a destination
|
||||
if (destination.empty())
|
||||
{
|
||||
SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
||||
SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -422,7 +420,7 @@ namespace client
|
|||
i2p::data::PrivateKeys keys;
|
||||
if (!keys.FromBase64(destination))
|
||||
{
|
||||
SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
||||
SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +463,7 @@ namespace client
|
|||
}
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_DEST, strlen(SAM_SESSION_CREATE_DUPLICATED_DEST), true);
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_DEST, true);
|
||||
}
|
||||
|
||||
void SAMSocket::HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode)
|
||||
|
@ -503,7 +501,7 @@ namespace client
|
|||
#else
|
||||
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv.c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l2, false);
|
||||
SendMessageReply ({m_Buffer, l2}, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,10 +569,10 @@ namespace client
|
|||
shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_KEY, strlen(SAM_STREAM_STATUS_INVALID_KEY), true);
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_KEY, true);
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true);
|
||||
}
|
||||
|
||||
void SAMSocket::Connect (std::shared_ptr<const i2p::data::LeaseSet> remote, std::shared_ptr<SAMSession> session)
|
||||
|
@ -591,16 +589,16 @@ namespace client
|
|||
m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send
|
||||
m_BufferOffset = 0;
|
||||
I2PReceive ();
|
||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||
SendMessageReply (SAM_STREAM_STATUS_OK, false);
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true);
|
||||
}
|
||||
else
|
||||
SendStreamCantReachPeer ("Incompatible crypto");
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true);
|
||||
}
|
||||
|
||||
void SAMSocket::HandleConnectLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||
|
@ -634,7 +632,7 @@ namespace client
|
|||
if (!session->GetLocalDestination ()->IsAcceptingStreams ())
|
||||
{
|
||||
m_IsAccepting = true;
|
||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||
SendMessageReply (SAM_STREAM_STATUS_OK, false);
|
||||
session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1));
|
||||
}
|
||||
else
|
||||
|
@ -650,7 +648,7 @@ namespace client
|
|||
if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE)
|
||||
{
|
||||
// already accepting, queue up
|
||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||
SendMessageReply (SAM_STREAM_STATUS_OK, false);
|
||||
session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts));
|
||||
}
|
||||
else
|
||||
|
@ -661,7 +659,7 @@ namespace client
|
|||
}
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true);
|
||||
}
|
||||
|
||||
void SAMSocket::ProcessStreamForward (std::string_view buf)
|
||||
|
@ -680,7 +678,7 @@ namespace client
|
|||
auto session = m_Owner.FindSession(id);
|
||||
if (!session)
|
||||
{
|
||||
SendMessageReply(SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||
SendMessageReply(SAM_STREAM_STATUS_INVALID_ID, true);
|
||||
return;
|
||||
}
|
||||
if (session->GetLocalDestination()->IsAcceptingStreams())
|
||||
|
@ -748,7 +746,7 @@ namespace client
|
|||
session->GetLocalDestination()->AcceptStreams(
|
||||
std::bind(&SAMSocket::HandleI2PForward, shared_from_this(), std::placeholders::_1, ep));
|
||||
|
||||
SendMessageReply(SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||
SendMessageReply(SAM_STREAM_STATUS_OK, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -823,7 +821,7 @@ namespace client
|
|||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l, false);
|
||||
SendMessageReply ({m_Buffer, l}, false);
|
||||
}
|
||||
|
||||
void SAMSocket::ProcessNamingLookup (std::string_view buf)
|
||||
|
@ -864,7 +862,7 @@ namespace client
|
|||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, false);
|
||||
SendMessageReply ({m_Buffer, len}, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -880,7 +878,7 @@ namespace client
|
|||
if (masterSession->subsessions.count (id) > 1)
|
||||
{
|
||||
// session exists
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false);
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, false);
|
||||
return;
|
||||
}
|
||||
std::string_view style = params[SAM_PARAM_STYLE];
|
||||
|
@ -912,7 +910,7 @@ namespace client
|
|||
SendSessionCreateReplyOk ();
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false);
|
||||
SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, false);
|
||||
}
|
||||
else
|
||||
SendSessionI2PError ("Wrong session type");
|
||||
|
@ -929,7 +927,7 @@ namespace client
|
|||
std::string id(params[SAM_PARAM_ID]);
|
||||
if (!masterSession->subsessions.erase (id))
|
||||
{
|
||||
SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), false);
|
||||
SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, false);
|
||||
return;
|
||||
}
|
||||
m_Owner.CloseSession (id);
|
||||
|
@ -946,7 +944,7 @@ namespace client
|
|||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, true);
|
||||
SendMessageReply ({m_Buffer, len}, true);
|
||||
}
|
||||
|
||||
void SAMSocket::SendSessionI2PError(const std::string & msg)
|
||||
|
@ -981,7 +979,7 @@ namespace client
|
|||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, false);
|
||||
SendMessageReply ({m_Buffer, len}, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -993,7 +991,7 @@ namespace client
|
|||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l, false);
|
||||
SendMessageReply ({m_Buffer, l}, false);
|
||||
}
|
||||
|
||||
const std::map<std::string_view, std::string_view> SAMSocket::ExtractParams (std::string_view buf)
|
||||
|
|
|
@ -39,21 +39,21 @@ namespace client
|
|||
|
||||
const char SAM_HANDSHAKE[] = "HELLO VERSION";
|
||||
const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n";
|
||||
const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n";
|
||||
constexpr std::string_view SAM_HANDSHAKE_NOVERSION { "HELLO REPLY RESULT=NOVERSION\n" };
|
||||
const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n";
|
||||
const char SAM_SESSION_CREATE[] = "SESSION CREATE";
|
||||
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
|
||||
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
|
||||
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
|
||||
const char SAM_SESSION_CREATE_INVALID_ID[] = "SESSION STATUS RESULT=INVALID_ID\n";
|
||||
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
|
||||
constexpr std::string_view SAM_SESSION_CREATE_DUPLICATED_ID { "SESSION STATUS RESULT=DUPLICATED_ID\n" };
|
||||
constexpr std::string_view SAM_SESSION_CREATE_DUPLICATED_DEST { "SESSION STATUS RESULT=DUPLICATED_DEST\n" };
|
||||
constexpr std::string_view SAM_SESSION_CREATE_INVALID_ID { "SESSION STATUS RESULT=INVALID_ID\n" };
|
||||
constexpr std::string_view SAM_SESSION_STATUS_INVALID_KEY { "SESSION STATUS RESULT=INVALID_KEY\n" };
|
||||
const char SAM_SESSION_STATUS_I2P_ERROR[] = "SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n";
|
||||
const char SAM_SESSION_ADD[] = "SESSION ADD";
|
||||
const char SAM_SESSION_REMOVE[] = "SESSION REMOVE";
|
||||
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
|
||||
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
|
||||
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
|
||||
const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n";
|
||||
constexpr std::string_view SAM_STREAM_STATUS_OK { "STREAM STATUS RESULT=OK\n" };
|
||||
constexpr std::string_view SAM_STREAM_STATUS_INVALID_ID { "STREAM STATUS RESULT=INVALID_ID\n" };
|
||||
constexpr std::string_view SAM_STREAM_STATUS_INVALID_KEY { "STREAM STATUS RESULT=INVALID_KEY\n" };
|
||||
const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"%s\"\n";
|
||||
const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n";
|
||||
const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT";
|
||||
|
@ -91,6 +91,10 @@ namespace client
|
|||
constexpr std::string_view SAM_VALUE_RAW { "RAW" };
|
||||
constexpr std::string_view SAM_VALUE_MASTER { "MASTER" };
|
||||
|
||||
constexpr int MAKE_SAM_VERSION_NUMBER (int major, int minor) { return major*10 + minor; }
|
||||
constexpr int MIN_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 0);
|
||||
constexpr int MAX_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 3);
|
||||
|
||||
enum class SAMSocketType
|
||||
{
|
||||
eSAMSocketTypeUnknown,
|
||||
|
@ -127,7 +131,7 @@ namespace client
|
|||
void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void SendMessageReply (const char * msg, size_t len, bool close);
|
||||
void SendMessageReply (std::string_view msg, bool close);
|
||||
void HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close);
|
||||
void Receive ();
|
||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
|
@ -182,6 +186,7 @@ namespace client
|
|||
bool m_IsAccepting; // for eSAMSocketTypeAcceptor only
|
||||
bool m_IsReceiving; // for eSAMSocketTypeStream only
|
||||
std::shared_ptr<i2p::stream::Stream> m_Stream;
|
||||
int m_Version;
|
||||
};
|
||||
|
||||
enum class SAMSessionType
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue