mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-02 11:04:00 +01:00
add tunnel test message
This commit is contained in:
parent
d6d440ba8a
commit
3d03732555
|
@ -367,9 +367,11 @@ namespace client
|
||||||
HandleDataMessage (payload, len);
|
HandleDataMessage (payload, len);
|
||||||
break;
|
break;
|
||||||
case eI2NPDeliveryStatus:
|
case eI2NPDeliveryStatus:
|
||||||
// try tunnel test first
|
HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET));
|
||||||
if (!m_Pool || !m_Pool->ProcessDeliveryStatus (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET), bufbe64toh (payload + DELIVERY_STATUS_TIMESTAMP_OFFSET)))
|
break;
|
||||||
HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET));
|
case eI2NPTunnelTest:
|
||||||
|
if (m_Pool)
|
||||||
|
m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET));
|
||||||
break;
|
break;
|
||||||
case eI2NPDatabaseStore:
|
case eI2NPDatabaseStore:
|
||||||
HandleDatabaseStoreMessage (payload, len);
|
HandleDatabaseStoreMessage (payload, len);
|
||||||
|
|
|
@ -115,6 +115,17 @@ namespace i2p
|
||||||
return newMsg;
|
return newMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<I2NPMessage> CreateTunnelTestMsg (uint32_t msgID)
|
||||||
|
{
|
||||||
|
auto m = NewI2NPShortMessage ();
|
||||||
|
uint8_t * buf = m->GetPayload ();
|
||||||
|
htobe32buf (buf + TUNNEL_TEST_MSGID_OFFSET, msgID);
|
||||||
|
htobe64buf (buf + TUNNEL_TEST_TIMESTAMP_OFFSET, i2p::util::GetSteadyMicroseconds ());
|
||||||
|
m->len += TUNNEL_TEST_SIZE;
|
||||||
|
m->FillI2NPMessageHeader (eI2NPTunnelTest);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
|
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
|
||||||
{
|
{
|
||||||
auto m = NewI2NPShortMessage ();
|
auto m = NewI2NPShortMessage ();
|
||||||
|
@ -870,6 +881,10 @@ namespace i2p
|
||||||
i2p::context.ProcessDeliveryStatusMessage (msg);
|
i2p::context.ProcessDeliveryStatusMessage (msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case eI2NPTunnelTest:
|
||||||
|
if (msg->from && msg->from->GetTunnelPool ())
|
||||||
|
msg->from->GetTunnelPool ()->ProcessTunnelTest (msg);
|
||||||
|
break;
|
||||||
case eI2NPVariableTunnelBuild:
|
case eI2NPVariableTunnelBuild:
|
||||||
case eI2NPTunnelBuild:
|
case eI2NPTunnelBuild:
|
||||||
case eI2NPShortTunnelBuild:
|
case eI2NPShortTunnelBuild:
|
||||||
|
|
|
@ -48,6 +48,11 @@ namespace i2p
|
||||||
const size_t DELIVERY_STATUS_TIMESTAMP_OFFSET = DELIVERY_STATUS_MSGID_OFFSET + 4;
|
const size_t DELIVERY_STATUS_TIMESTAMP_OFFSET = DELIVERY_STATUS_MSGID_OFFSET + 4;
|
||||||
const size_t DELIVERY_STATUS_SIZE = DELIVERY_STATUS_TIMESTAMP_OFFSET + 8;
|
const size_t DELIVERY_STATUS_SIZE = DELIVERY_STATUS_TIMESTAMP_OFFSET + 8;
|
||||||
|
|
||||||
|
// TunnelTest
|
||||||
|
const size_t TUNNEL_TEST_MSGID_OFFSET = 0;
|
||||||
|
const size_t TUNNEL_TEST_TIMESTAMP_OFFSET = TUNNEL_TEST_MSGID_OFFSET + 4;
|
||||||
|
const size_t TUNNEL_TEST_SIZE = TUNNEL_TEST_TIMESTAMP_OFFSET + 8;
|
||||||
|
|
||||||
// DatabaseStore
|
// DatabaseStore
|
||||||
const size_t DATABASE_STORE_KEY_OFFSET = 0;
|
const size_t DATABASE_STORE_KEY_OFFSET = 0;
|
||||||
const size_t DATABASE_STORE_TYPE_OFFSET = DATABASE_STORE_KEY_OFFSET + 32;
|
const size_t DATABASE_STORE_TYPE_OFFSET = DATABASE_STORE_KEY_OFFSET + 32;
|
||||||
|
@ -116,7 +121,8 @@ namespace i2p
|
||||||
eI2NPVariableTunnelBuild = 23,
|
eI2NPVariableTunnelBuild = 23,
|
||||||
eI2NPVariableTunnelBuildReply = 24,
|
eI2NPVariableTunnelBuildReply = 24,
|
||||||
eI2NPShortTunnelBuild = 25,
|
eI2NPShortTunnelBuild = 25,
|
||||||
eI2NPShortTunnelBuildReply = 26
|
eI2NPShortTunnelBuildReply = 26,
|
||||||
|
eI2NPTunnelTest = 231
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t TUNNEL_BUILD_RECORD_GATEWAY_FLAG = 0x80;
|
const uint8_t TUNNEL_BUILD_RECORD_GATEWAY_FLAG = 0x80;
|
||||||
|
@ -279,6 +285,7 @@ namespace tunnel
|
||||||
std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from = nullptr);
|
std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from = nullptr);
|
||||||
std::shared_ptr<I2NPMessage> CopyI2NPMessage (std::shared_ptr<I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> CopyI2NPMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
|
||||||
|
std::shared_ptr<I2NPMessage> CreateTunnelTestMsg (uint32_t msgID);
|
||||||
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID);
|
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID);
|
||||||
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
||||||
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
||||||
|
|
|
@ -1152,13 +1152,13 @@ namespace i2p
|
||||||
|
|
||||||
bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID)
|
bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID)
|
||||||
{
|
{
|
||||||
if (typeID == eI2NPDeliveryStatus)
|
if (typeID == eI2NPTunnelTest)
|
||||||
{
|
{
|
||||||
// try tunnel test
|
// try tunnel test
|
||||||
auto pool = GetTunnelPool ();
|
auto pool = GetTunnelPool ();
|
||||||
if (pool && pool->ProcessDeliveryStatus (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET), bufbe64toh (payload + DELIVERY_STATUS_TIMESTAMP_OFFSET)))
|
if (pool && pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET)))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto msg = CreateI2NPMessage (typeID, payload, len, msgID);
|
auto msg = CreateI2NPMessage (typeID, payload, len, msgID);
|
||||||
if (!msg) return false;
|
if (!msg) return false;
|
||||||
i2p::HandleI2NPMessage (msg);
|
i2p::HandleI2NPMessage (msg);
|
||||||
|
|
|
@ -232,6 +232,12 @@ namespace util
|
||||||
return GetLocalHoursSinceEpoch () + g_TimeOffset/3600;
|
return GetLocalHoursSinceEpoch () + g_TimeOffset/3600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t GetSteadyMicroseconds()
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<std::chrono::microseconds>(
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
||||||
void GetCurrentDate (char * date)
|
void GetCurrentDate (char * date)
|
||||||
{
|
{
|
||||||
GetDateString (GetSecondsSinceEpoch (), date);
|
GetDateString (GetSecondsSinceEpoch (), date);
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace util
|
||||||
uint32_t GetMinutesSinceEpoch ();
|
uint32_t GetMinutesSinceEpoch ();
|
||||||
uint32_t GetHoursSinceEpoch ();
|
uint32_t GetHoursSinceEpoch ();
|
||||||
|
|
||||||
|
uint64_t GetSteadyMicroseconds();
|
||||||
|
|
||||||
void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes
|
void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes
|
||||||
void GetDateString (uint64_t timestamp, char * date); // timestamp is seconds since epoch, returns date as YYYYMMDD string, 9 bytes
|
void GetDateString (uint64_t timestamp, char * date); // timestamp is seconds since epoch, returns date as YYYYMMDD string, 9 bytes
|
||||||
void AdjustTimeOffset (int64_t offset); // in seconds from current
|
void AdjustTimeOffset (int64_t offset); // in seconds from current
|
||||||
|
|
|
@ -109,9 +109,9 @@ namespace tunnel
|
||||||
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out) override;
|
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out) override;
|
||||||
|
|
||||||
/** @brief add latency sample */
|
/** @brief add latency sample */
|
||||||
void AddLatencySample(const int ms) { m_Latency = LatencyIsKnown() ? (m_Latency + ms) >> 1 : ms; }
|
void AddLatencySample(const int us) { m_Latency = LatencyIsKnown() ? (m_Latency + us) >> 1 : us; }
|
||||||
/** @brief get this tunnel's estimated latency */
|
/** @brief get this tunnel's estimated latency */
|
||||||
int GetMeanLatency() const { return m_Latency; }
|
int GetMeanLatency() const { return (m_Latency + 500) / 1000; }
|
||||||
/** @brief return true if this tunnel's latency fits in range [lowerbound, upperbound] */
|
/** @brief return true if this tunnel's latency fits in range [lowerbound, upperbound] */
|
||||||
bool LatencyFitsRange(int lowerbound, int upperbound) const;
|
bool LatencyFitsRange(int lowerbound, int upperbound) const;
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ namespace tunnel
|
||||||
TunnelState m_State;
|
TunnelState m_State;
|
||||||
i2p::data::RouterInfo::CompatibleTransports m_FarEndTransports;
|
i2p::data::RouterInfo::CompatibleTransports m_FarEndTransports;
|
||||||
bool m_IsRecreated; // if tunnel is replaced by new, or new tunnel requested to replace
|
bool m_IsRecreated; // if tunnel is replaced by new, or new tunnel requested to replace
|
||||||
int m_Latency; // in milliseconds
|
int m_Latency; // in microseconds
|
||||||
};
|
};
|
||||||
|
|
||||||
class OutboundTunnel: public Tunnel
|
class OutboundTunnel: public Tunnel
|
||||||
|
|
|
@ -399,7 +399,7 @@ namespace tunnel
|
||||||
std::unique_lock<std::mutex> l(m_TestsMutex);
|
std::unique_lock<std::mutex> l(m_TestsMutex);
|
||||||
m_Tests[msgID] = it;
|
m_Tests[msgID] = it;
|
||||||
}
|
}
|
||||||
auto msg = CreateDeliveryStatusMsg (msgID);
|
auto msg = CreateTunnelTestMsg (msgID);
|
||||||
auto outbound = it.first;
|
auto outbound = it.first;
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
msg->onDrop = [msgID, outbound, s]()
|
msg->onDrop = [msgID, outbound, s]()
|
||||||
|
@ -452,16 +452,23 @@ namespace tunnel
|
||||||
buf += 4;
|
buf += 4;
|
||||||
uint64_t timestamp = bufbe64toh (buf);
|
uint64_t timestamp = bufbe64toh (buf);
|
||||||
|
|
||||||
if (!ProcessDeliveryStatus (msgID, timestamp))
|
if (m_LocalDestination)
|
||||||
{
|
m_LocalDestination->ProcessDeliveryStatusMessage (msg);
|
||||||
if (m_LocalDestination)
|
else
|
||||||
m_LocalDestination->ProcessDeliveryStatusMessage (msg);
|
LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped");
|
||||||
else
|
|
||||||
LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TunnelPool::ProcessDeliveryStatus (uint32_t msgID, uint64_t timestamp)
|
void TunnelPool::ProcessTunnelTest (std::shared_ptr<I2NPMessage> msg)
|
||||||
|
{
|
||||||
|
const uint8_t * buf = msg->GetPayload ();
|
||||||
|
uint32_t msgID = bufbe32toh (buf);
|
||||||
|
buf += 4;
|
||||||
|
uint64_t timestamp = bufbe64toh (buf);
|
||||||
|
|
||||||
|
ProcessTunnelTest (msgID, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TunnelPool::ProcessTunnelTest (uint32_t msgID, uint64_t timestamp)
|
||||||
{
|
{
|
||||||
decltype(m_Tests)::mapped_type test;
|
decltype(m_Tests)::mapped_type test;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -477,9 +484,9 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
int dlt = (int)((int64_t)i2p::util::GetMillisecondsSinceEpoch () - (int64_t)timestamp);
|
int dlt = (int)((int64_t)i2p::util::GetSteadyMicroseconds () - (int64_t)timestamp);
|
||||||
LogPrint (eLogDebug, "Tunnels: Test of ", msgID, " successful. ", dlt, " milliseconds");
|
LogPrint (eLogDebug, "Tunnels: Test of ", msgID, " successful. ", dlt, " microseconds");
|
||||||
if (dlt < 0)
|
if (dlt < 0) // should not happen
|
||||||
dlt = 0;
|
dlt = 0;
|
||||||
int numHops = 0;
|
int numHops = 0;
|
||||||
if (test.first) numHops += test.first->GetNumHops ();
|
if (test.first) numHops += test.first->GetNumHops ();
|
||||||
|
@ -493,7 +500,7 @@ namespace tunnel
|
||||||
int latency = 0;
|
int latency = 0;
|
||||||
if (numHops) latency = dlt*test.first->GetNumHops ()/numHops;
|
if (numHops) latency = dlt*test.first->GetNumHops ()/numHops;
|
||||||
if (!latency) latency = dlt/2;
|
if (!latency) latency = dlt/2;
|
||||||
test.first->AddLatencySample(latency);
|
test.first->AddLatencySample (latency);
|
||||||
}
|
}
|
||||||
if (test.second)
|
if (test.second)
|
||||||
{
|
{
|
||||||
|
@ -503,7 +510,7 @@ namespace tunnel
|
||||||
int latency = 0;
|
int latency = 0;
|
||||||
if (numHops) latency = dlt*test.second->GetNumHops ()/numHops;
|
if (numHops) latency = dlt*test.second->GetNumHops ()/numHops;
|
||||||
if (!latency) latency = dlt/2;
|
if (!latency) latency = dlt/2;
|
||||||
test.second->AddLatencySample(latency);
|
test.second->AddLatencySample (latency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
|
|
|
@ -85,7 +85,8 @@ namespace tunnel
|
||||||
void ManageTunnels (uint64_t ts);
|
void ManageTunnels (uint64_t ts);
|
||||||
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
void ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg);
|
void ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg);
|
||||||
bool ProcessDeliveryStatus (uint32_t msgID, uint64_t timestamp);
|
void ProcessTunnelTest (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
bool ProcessTunnelTest (uint32_t msgID, uint64_t timestamp);
|
||||||
|
|
||||||
bool IsExploratory () const;
|
bool IsExploratory () const;
|
||||||
bool IsActive () const { return m_IsActive; };
|
bool IsActive () const { return m_IsActive; };
|
||||||
|
|
Loading…
Reference in a new issue