diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 21e1fdfa..0ba9d696 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -87,7 +87,7 @@ namespace client auto itr = m_ReadyCallbacks.begin(); while(itr != m_ReadyCallbacks.end()) { - if(itr->second >= now) + if(itr->second <= now) { itr->first(boost::asio::error::timed_out); itr = m_ReadyCallbacks.erase(itr); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 1f4d04db..05943981 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -107,6 +107,21 @@ namespace client std::placeholders::_1, std::placeholders::_2)); } + static bool SAMVersionAcceptable(const std::string & ver) + { + return ver == "3.0" || ver == "3.1"; + } + + static bool SAMVersionTooLow(const std::string & ver) + { + return ver.size() && ver[0] < '3'; + } + + static bool SAMVersionTooHigh(const std::string & ver) + { + return ver.size() && ver > "3.1"; + } + void SAMSocket::HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -132,19 +147,37 @@ namespace client if (!strcmp (m_Buffer, SAM_HANDSHAKE)) { - std::string version("3.0"); + std::string maxver("3.1"); + std::string minver("3.0"); // try to find MIN and MAX, 3.0 if not found if (separator) { separator++; std::map params; ExtractParams (separator, params); - //auto it = params.find (SAM_PARAM_MAX); - // TODO: check MIN as well - //if (it != params.end ()) - // version = it->second; + auto it = params.find (SAM_PARAM_MAX); + if (it != params.end ()) + maxver = it->second; + it = params.find(SAM_PARAM_MIN); + if (it != params.end ()) + minver = it->second; + } + // version negotiation + std::string version; + if (SAMVersionAcceptable(maxver)) + { + version = maxver; + } + else if (SAMVersionAcceptable(minver)) + { + version = minver; + } + else if (SAMVersionTooLow(minver) && SAMVersionTooHigh(maxver)) + { + version = "3.0"; } - if (version[0] == '3') // we support v3 (3.0 and 3.1) only + + if (SAMVersionAcceptable(version)) { #ifdef _MSC_VER size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ()); @@ -156,7 +189,7 @@ namespace client std::placeholders::_1, std::placeholders::_2)); } else - SendMessageReply (SAM_HANDSHAKE_I2P_ERROR, strlen (SAM_HANDSHAKE_I2P_ERROR), true); + SendMessageReply (SAM_HANDSHAKE_NOVERSION, strlen (SAM_HANDSHAKE_NOVERSION), true); } else { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 5f0ee69b..6ecd14a4 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -23,6 +23,7 @@ namespace client const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds 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"; 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";