Browse Source

Merge pull request #18 from orignal/master

Merge pull request from orignal/master
pull/49/head
chertov 10 years ago
parent
commit
d44cfc73b8
  1. 26
      Garlic.cpp
  2. 3
      Garlic.h
  3. 4
      HTTPServer.cpp
  4. 6
      LeaseSet.cpp
  5. 3
      LeaseSet.h
  6. 34
      NetDb.cpp
  7. 3
      NetDb.h
  8. 118
      Streaming.cpp
  9. 43
      Streaming.h
  10. 29
      Tunnel.cpp
  11. 5
      Tunnel.h
  12. 43
      TunnelPool.cpp

26
Garlic.cpp

@ -16,7 +16,7 @@ namespace garlic @@ -16,7 +16,7 @@ namespace garlic
{
GarlicRoutingSession::GarlicRoutingSession (const i2p::data::RoutingDestination& destination, int numTags):
m_Destination (destination), m_FirstMsgID (0), m_IsAcknowledged (false),
m_NumTags (numTags), m_NextTag (-1), m_SessionTags (0)
m_NumTags (numTags), m_NextTag (-1), m_SessionTags (0), m_TagsCreationTime (0)
{
// create new session tags and session key
m_Rnd.GenerateBlock (m_SessionKey, 32);
@ -40,6 +40,8 @@ namespace garlic @@ -40,6 +40,8 @@ namespace garlic
{
for (int i = 0; i < m_NumTags; i++)
m_Rnd.GenerateBlock (m_SessionTags + i*32, 32);
m_TagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
SetAcknowledged (false);
}
}
@ -48,6 +50,24 @@ namespace garlic @@ -48,6 +50,24 @@ namespace garlic
I2NPMessage * m = NewI2NPMessage ();
size_t len = 0;
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
// take care about tags
if (m_NumTags > 0)
{
if (i2p::util::GetSecondsSinceEpoch () >= m_TagsCreationTime + TAGS_EXPIRATION_TIMEOUT)
{
// old tags expired create new set
LogPrint ("Garlic tags expired");
GenerateSessionTags ();
m_NextTag = -1;
}
else if (!m_IsAcknowledged) // new set of tags was not acknowledged
{
LogPrint ("Previous garlic tags was not acknowledged. Use ElGamal");
m_NextTag = -1; // have to use ElGamal
}
}
// create message
if (m_NextTag < 0 || !m_NumTags) // new session
{
// create ElGamal block
@ -253,7 +273,7 @@ namespace garlic @@ -253,7 +273,7 @@ namespace garlic
session = it->second;
if (!session)
{
session = new GarlicRoutingSession (destination, 4); // TODO: change it later
session = new GarlicRoutingSession (destination, 32);
m_Sessions[destination.GetIdentHash ()] = session;
}
@ -372,7 +392,7 @@ namespace garlic @@ -372,7 +392,7 @@ namespace garlic
// later on we should let destination decide
I2NPHeader * header = (I2NPHeader *)buf;
if (header->typeID == eI2NPData)
i2p::stream::HandleDataMessage (&destination, buf + sizeof (I2NPHeader), be16toh (header->size));
i2p::stream::HandleDataMessage (destination, buf + sizeof (I2NPHeader), be16toh (header->size));
else
LogPrint ("Unexpected I2NP garlic message ", (int)header->typeID);
break;

3
Garlic.h

@ -35,7 +35,7 @@ namespace garlic @@ -35,7 +35,7 @@ namespace garlic
};
#pragma pack()
const int TAGS_EXPIRATION_TIMEOUT = 900; // 15 minutes
class GarlicRoutingSession
{
public:
@ -66,6 +66,7 @@ namespace garlic @@ -66,6 +66,7 @@ namespace garlic
bool m_IsAcknowledged;
int m_NumTags, m_NextTag;
uint8_t * m_SessionTags; // m_NumTags*32 bytes
uint32_t m_TagsCreationTime; // seconds since epoch
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
CryptoPP::AutoSeededRandomPool m_Rnd;

4
HTTPServer.cpp

@ -141,6 +141,8 @@ namespace util @@ -141,6 +141,8 @@ namespace util
it->GetTunnelConfig ()->Print (s);
if (it->GetTunnelPool ())
s << " " << "Pool";
if (it->IsFailed ())
s << " " << "Failed";
s << " " << (int)it->GetNumSentBytes () << "<BR>";
}
@ -149,6 +151,8 @@ namespace util @@ -149,6 +151,8 @@ namespace util
it.second->GetTunnelConfig ()->Print (s);
if (it.second->GetTunnelPool ())
s << " " << "Pool";
if (it.second->IsFailed ())
s << " " << "Failed";
s << " " << (int)it.second->GetNumReceivedBytes () << "<BR>";
}

6
LeaseSet.cpp

@ -57,13 +57,13 @@ namespace data @@ -57,13 +57,13 @@ namespace data
LogPrint ("LeaseSet verification failed");
}
std::set<Lease> LeaseSet::GetNonExpiredLeases () const
const std::vector<Lease> LeaseSet::GetNonExpiredLeases () const
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
std::set<Lease> leases;
std::vector<Lease> leases;
for (auto& it: m_Leases)
if (ts < it.endDate)
leases.insert (it);
leases.push_back (it);
return leases;
}

3
LeaseSet.h

@ -4,7 +4,6 @@ @@ -4,7 +4,6 @@
#include <inttypes.h>
#include <string.h>
#include <vector>
#include <set>
#include "Identity.h"
namespace i2p
@ -43,7 +42,7 @@ namespace data @@ -43,7 +42,7 @@ namespace data
const Identity& GetIdentity () const { return m_Identity; };
const IdentHash& GetIdentHash () const { return m_IdentHash; };
const std::vector<Lease>& GetLeases () const { return m_Leases; };
std::set<Lease> GetNonExpiredLeases () const;
const std::vector<Lease> GetNonExpiredLeases () const;
bool HasExpiredLeases () const;
bool HasNonExpiredLeases () const;
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; };

34
NetDb.cpp

@ -42,6 +42,11 @@ namespace data @@ -42,6 +42,11 @@ namespace data
return msg;
}
void RequestedDestination::ClearExcludedPeers ()
{
m_ExcludedPeers.clear ();
}
#ifndef _WIN32
const char NetDb::m_NetDbPath[] = "/netDb";
#else
@ -335,19 +340,26 @@ namespace data @@ -335,19 +340,26 @@ namespace data
if (inbound)
{
RequestedDestination * dest = CreateRequestedDestination (destination, isLeaseSet);
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
if (floodfill)
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
// request 3 closests floodfills
for (int i = 0; i < 3; i++)
{
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
// DatabaseLookup message
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
if (floodfill)
{
// DatabaseLookup message
msgs.push_back (i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeRouter,
floodfill->GetIdentHash (), 0,
dest->CreateRequestMessage (floodfill, inbound)
});
}
}
if (msgs.size () > 0)
{
dest->ClearExcludedPeers ();
dest->SetLastOutboundTunnel (outbound);
msgs.push_back (i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeRouter,
floodfill->GetIdentHash (), 0,
dest->CreateRequestMessage (floodfill, inbound)
});
outbound->SendTunnelDataMsg (msgs);
}
else

3
NetDb.h

@ -30,7 +30,8 @@ namespace data @@ -30,7 +30,8 @@ namespace data
const IdentHash& GetDestination () const { return m_Destination; };
int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); };
const std::set<IdentHash>& GetExcludedPeers () { return m_ExcludedPeers; };
const RouterInfo * GetLastRouter () const { return m_LastRouter; };
void ClearExcludedPeers ();
const RouterInfo * GetLastRouter () const { return m_LastRouter; };
const i2p::tunnel::InboundTunnel * GetLastReplyTunnel () const { return m_LastReplyTunnel; };
bool IsExploratory () const { return m_IsExploratory; };
bool IsLeaseSet () const { return m_IsLeaseSet; };

118
Streaming.cpp

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
#include <fstream>
#include <algorithm>
#include <boost/bind.hpp>
#include <cryptopp/gzip.h>
#include "Log.h"
#include "RouterInfo.h"
@ -14,12 +15,14 @@ namespace i2p @@ -14,12 +15,14 @@ namespace i2p
{
namespace stream
{
Stream::Stream (StreamingDestination * local, const i2p::data::LeaseSet& remote):
m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (0),
m_IsOpen (false), m_LeaseSetUpdated (true), m_LocalDestination (local),
m_RemoteLeaseSet (remote), m_OutboundTunnel (nullptr)
Stream::Stream (boost::asio::io_service& service, StreamingDestination * local,
const i2p::data::LeaseSet& remote): m_Service (service), m_SendStreamID (0),
m_SequenceNumber (0), m_LastReceivedSequenceNumber (0), m_IsOpen (false),
m_LeaseSetUpdated (true), m_LocalDestination (local), m_RemoteLeaseSet (remote),
m_OutboundTunnel (nullptr)
{
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
UpdateCurrentRemoteLease ();
}
Stream::~Stream ()
@ -62,6 +65,7 @@ namespace stream @@ -62,6 +65,7 @@ namespace stream
{
// we have received duplicate. Most likely our outbound tunnel is dead
LogPrint ("Duplicate message ", receivedSeqn, " received");
UpdateCurrentRemoteLease (); // pick another lease
m_OutboundTunnel = i2p::tunnel::tunnels.GetNextOutboundTunnel (); // pick another tunnel
if (m_OutboundTunnel)
SendQuickAck (); // resend ack for previous message again
@ -276,11 +280,12 @@ namespace stream @@ -276,11 +280,12 @@ namespace stream
m_OutboundTunnel = m_LocalDestination->GetTunnelPool ()->GetNextOutboundTunnel ();
if (m_OutboundTunnel)
{
auto leases = m_RemoteLeaseSet.GetNonExpiredLeases ();
if (!leases.empty ())
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
if (ts >= m_CurrentRemoteLease.endDate)
UpdateCurrentRemoteLease ();
if (ts < m_CurrentRemoteLease.endDate)
{
auto& lease = *leases.begin (); // TODO:
m_OutboundTunnel->SendTunnelDataMsg (lease.tunnelGateway, lease.tunnelID, msg);
m_OutboundTunnel->SendTunnelDataMsg (m_CurrentRemoteLease.tunnelGateway, m_CurrentRemoteLease.tunnelID, msg);
return true;
}
else
@ -296,8 +301,19 @@ namespace stream @@ -296,8 +301,19 @@ namespace stream
}
return false;
}
void Stream::UpdateCurrentRemoteLease ()
{
auto leases = m_RemoteLeaseSet.GetNonExpiredLeases ();
if (!leases.empty ())
{
uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1);
m_CurrentRemoteLease = leases[i];
}
else
m_CurrentRemoteLease.endDate = 0;
}
StreamingDestination * sharedLocalDestination = nullptr;
StreamingDestination::StreamingDestination (): m_LeaseSet (nullptr)
{
@ -339,9 +355,10 @@ namespace stream @@ -339,9 +355,10 @@ namespace stream
}
}
Stream * StreamingDestination::CreateNewStream (const i2p::data::LeaseSet& remote)
Stream * StreamingDestination::CreateNewStream (boost::asio::io_service& service,
const i2p::data::LeaseSet& remote)
{
Stream * s = new Stream (this, remote);
Stream * s = new Stream (service, this, remote);
m_Streams[s->GetRecvStreamID ()] = s;
return s;
}
@ -402,14 +419,14 @@ namespace stream @@ -402,14 +419,14 @@ namespace stream
size += 32; // tunnel_gw
*(uint32_t *)(buf + size) = htobe32 (tunnel->GetNextTunnelID ());
size += 4; // tunnel_id
uint64_t ts = tunnel->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT;
uint64_t ts = tunnel->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - 60; // 1 minute before expiration
ts *= 1000; // in milliseconds
*(uint64_t *)(buf + size) = htobe64 (ts);
size += 8; // end_date
}
Sign (buf, size, buf+ size);
size += 40; // signature
LogPrint ("Local LeaseSet of ", tunnels.size (), " leases created");
m->len += size + sizeof (I2NPDatabaseStoreMsg);
FillI2NPMessageHeader (m, eI2NPDatabaseStore);
return m;
@ -420,32 +437,83 @@ namespace stream @@ -420,32 +437,83 @@ namespace stream
CryptoPP::DSA::Signer signer (m_SigningPrivateKey);
signer.SignMessage (i2p::context.GetRandomNumberGenerator (), buf, len, signature);
}
StreamingDestinations destinations;
void StreamingDestinations::Start ()
{
if (!m_SharedLocalDestination)
m_SharedLocalDestination = new StreamingDestination ();
m_IsRunning = true;
m_Thread = new std::thread (std::bind (&StreamingDestinations::Run, this));
}
void StreamingDestinations::Stop ()
{
delete m_SharedLocalDestination;
m_IsRunning = false;
m_Service.stop ();
if (m_Thread)
{
m_Thread->join ();
delete m_Thread;
m_Thread = 0;
}
}
void StreamingDestinations::Run ()
{
m_Service.run ();
}
Stream * StreamingDestinations::CreateClientStream (const i2p::data::LeaseSet& remote)
{
if (!m_SharedLocalDestination) return nullptr;
return m_SharedLocalDestination->CreateNewStream (m_Service, remote);
}
void StreamingDestinations::DeleteClientStream (Stream * stream)
{
if (m_SharedLocalDestination)
m_SharedLocalDestination->DeleteStream (stream);
else
delete stream;
}
void StreamingDestinations::HandleNextPacket (i2p::data::IdentHash destination, Packet * packet)
{
m_Service.post (boost::bind (&StreamingDestinations::PostNextPacket, this, destination, packet));
}
void StreamingDestinations::PostNextPacket (i2p::data::IdentHash destination, Packet * packet)
{
// TODO: we have onle one destination, might be more
if (m_SharedLocalDestination)
m_SharedLocalDestination->HandleNextPacket (packet);
}
Stream * CreateStream (const i2p::data::LeaseSet& remote)
{
if (!sharedLocalDestination)
sharedLocalDestination = new StreamingDestination ();
return sharedLocalDestination->CreateNewStream (remote);
return destinations.CreateClientStream (remote);
}
void DeleteStream (Stream * stream)
{
if (sharedLocalDestination)
sharedLocalDestination->DeleteStream (stream);
destinations.DeleteClientStream (stream);
}
void StartStreaming ()
{
if (!sharedLocalDestination)
sharedLocalDestination = new StreamingDestination ();
destinations.Start ();
}
void StopStreaming ()
{
delete sharedLocalDestination;
destinations.Stop ();
}
void HandleDataMessage (i2p::data::IdentHash * destination, const uint8_t * buf, size_t len)
void HandleDataMessage (i2p::data::IdentHash destination, const uint8_t * buf, size_t len)
{
uint32_t length = be32toh (*(uint32_t *)buf);
buf += 4;
@ -465,10 +533,8 @@ namespace stream @@ -465,10 +533,8 @@ namespace stream
uncompressed->len = MAX_PACKET_SIZE;
}
decompressor.Get (uncompressed->buf, uncompressed->len);
// then forward to streaming engine
// TODO: we have onle one destination, might be more
if (sharedLocalDestination)
sharedLocalDestination->HandleNextPacket (uncompressed);
// then forward to streaming engine thread
destinations.HandleNextPacket (destination, uncompressed);
}
else
LogPrint ("Data: protocol ", buf[9], " is not supported");

43
Streaming.h

@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
#include <string>
#include <map>
#include <set>
#include <thread>
#include <boost/asio.hpp>
#include <cryptopp/dsa.h>
#include "I2PEndian.h"
#include "Queue.h"
@ -67,7 +69,7 @@ namespace stream @@ -67,7 +69,7 @@ namespace stream
{
public:
Stream (StreamingDestination * local, const i2p::data::LeaseSet& remote);
Stream (boost::asio::io_service& service, StreamingDestination * local, const i2p::data::LeaseSet& remote);
~Stream ();
uint32_t GetSendStreamID () const { return m_SendStreamID; };
uint32_t GetRecvStreamID () const { return m_RecvStreamID; };
@ -90,13 +92,17 @@ namespace stream @@ -90,13 +92,17 @@ namespace stream
void SavePacket (Packet * packet);
void ProcessPacket (Packet * packet);
void UpdateCurrentRemoteLease ();
private:
boost::asio::io_service& m_Service;
uint32_t m_SendStreamID, m_RecvStreamID, m_SequenceNumber, m_LastReceivedSequenceNumber;
bool m_IsOpen, m_LeaseSetUpdated;
StreamingDestination * m_LocalDestination;
const i2p::data::LeaseSet& m_RemoteLeaseSet;
i2p::data::Lease m_CurrentRemoteLease;
i2p::util::Queue<Packet> m_ReceiveQueue;
std::set<Packet *, PacketCmp> m_SavedPackets;
i2p::tunnel::OutboundTunnel * m_OutboundTunnel;
@ -116,7 +122,7 @@ namespace stream @@ -116,7 +122,7 @@ namespace stream
i2p::tunnel::TunnelPool * GetTunnelPool () const { return m_Pool; };
void Sign (uint8_t * buf, int len, uint8_t * signature) const;
Stream * CreateNewStream (const i2p::data::LeaseSet& remote);
Stream * CreateNewStream (boost::asio::io_service& service, const i2p::data::LeaseSet& remote);
void DeleteStream (Stream * stream);
void HandleNextPacket (Packet * packet);
@ -139,13 +145,44 @@ namespace stream @@ -139,13 +145,44 @@ namespace stream
CryptoPP::DSA::PrivateKey m_SigningPrivateKey;
};
class StreamingDestinations
{
public:
StreamingDestinations (): m_IsRunning (false), m_Thread (nullptr),
m_Work (m_Service), m_SharedLocalDestination (nullptr) {};
~StreamingDestinations () {};
void Start ();
void Stop ();
void HandleNextPacket (i2p::data::IdentHash destination, Packet * packet);
Stream * CreateClientStream (const i2p::data::LeaseSet& remote);
void DeleteClientStream (Stream * stream);
private:
void Run ();
void PostNextPacket (i2p::data::IdentHash destination, Packet * packet);
private:
bool m_IsRunning;
std::thread * m_Thread;
boost::asio::io_service m_Service;
boost::asio::io_service::work m_Work;
StreamingDestination * m_SharedLocalDestination;
};
Stream * CreateStream (const i2p::data::LeaseSet& remote);
void DeleteStream (Stream * stream);
void StartStreaming ();
void StopStreaming ();
// assuming data is I2CP message
void HandleDataMessage (i2p::data::IdentHash * destination, const uint8_t * buf, size_t len);
void HandleDataMessage (i2p::data::IdentHash destination, const uint8_t * buf, size_t len);
I2NPMessage * CreateDataMessage (Stream * s, uint8_t * payload, size_t len);
}
}

29
Tunnel.cpp

@ -14,7 +14,8 @@ namespace i2p @@ -14,7 +14,8 @@ namespace i2p
namespace tunnel
{
Tunnel::Tunnel (TunnelConfig * config): m_Config (config), m_Pool (nullptr), m_IsEstablished (false)
Tunnel::Tunnel (TunnelConfig * config): m_Config (config), m_Pool (nullptr),
m_IsEstablished (false), m_IsFailed (false)
{
}
@ -130,6 +131,7 @@ namespace tunnel @@ -130,6 +131,7 @@ namespace tunnel
void InboundTunnel::HandleTunnelDataMsg (I2NPMessage * msg)
{
if (IsFailed ()) SetFailed (false); // incoming messages means a tunnel is alive
msg->from = this;
EncryptTunnelMsg (msg);
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
@ -225,11 +227,14 @@ namespace tunnel @@ -225,11 +227,14 @@ namespace tunnel
InboundTunnel * tunnel = nullptr;
size_t minReceived = 0;
for (auto it : m_InboundTunnels)
{
if (it.second->IsFailed ()) continue;
if (!tunnel || it.second->GetNumReceivedBytes () < minReceived)
{
tunnel = it.second;
minReceived = it.second->GetNumReceivedBytes ();
}
}
}
return tunnel;
}
@ -240,7 +245,7 @@ namespace tunnel @@ -240,7 +245,7 @@ namespace tunnel
for (auto it : m_InboundTunnels)
{
if (i >= num) break;
if (it.second->GetNextIdentHash () != i2p::context.GetRouterInfo ().GetIdentHash ())
if (!it.second->IsFailed () && it.second->GetNextIdentHash () != i2p::context.GetRouterInfo ().GetIdentHash ())
{
// exclude one hop tunnels
v.push_back (it.second);
@ -254,23 +259,17 @@ namespace tunnel @@ -254,23 +259,17 @@ namespace tunnel
{
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
uint32_t ind = rnd.GenerateWord32 (0, m_OutboundTunnels.size () - 1), i = 0;
OutboundTunnel * tunnel = nullptr;
for (auto it: m_OutboundTunnels)
{
if (i >= ind) return it;
else i++;
}
return nullptr;
// TODO: implement it base on profiling
/*OutboundTunnel * tunnel = nullptr;
size_t minSent = 0;
for (auto it : m_OutboundTunnels)
if (!tunnel || it->GetNumSentBytes () < minSent)
if (!it->IsFailed ())
{
tunnel = it;
minSent = it->GetNumSentBytes ();
}
return tunnel;*/
i++;
}
}
return tunnel;
}
TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination * localDestination)

5
Tunnel.h

@ -37,6 +37,9 @@ namespace tunnel @@ -37,6 +37,9 @@ namespace tunnel
TunnelConfig * GetTunnelConfig () const { return m_Config; }
bool IsEstablished () const { return m_IsEstablished; };
bool IsFailed () const { return m_IsFailed; };
void SetFailed (bool failed) { m_IsFailed = failed; }
TunnelPool * GetTunnelPool () const { return m_Pool; };
void SetTunnelPool (TunnelPool * pool) { m_Pool = pool; };
@ -57,7 +60,7 @@ namespace tunnel @@ -57,7 +60,7 @@ namespace tunnel
TunnelConfig * m_Config;
TunnelPool * m_Pool; // pool, tunnel belongs to, or null
bool m_IsEstablished;
bool m_IsEstablished, m_IsFailed;
CryptoPP::ECB_Mode<CryptoPP::AES>::Decryption m_ECBDecryption;
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_CBCDecryption;

43
TunnelPool.cpp

@ -31,8 +31,6 @@ namespace tunnel @@ -31,8 +31,6 @@ namespace tunnel
void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel)
{
m_InboundTunnels.insert (createdTunnel);
if (m_LocalDestination)
m_LocalDestination->UpdateLeaseSet ();
}
void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel)
@ -54,10 +52,10 @@ namespace tunnel @@ -54,10 +52,10 @@ namespace tunnel
void TunnelPool::TunnelExpired (OutboundTunnel * expiredTunnel)
{
if (expiredTunnel)
{
{
expiredTunnel->SetTunnelPool (nullptr);
m_OutboundTunnels.erase (expiredTunnel);
}
}
if (expiredTunnel == m_LastOutboundTunnel)
m_LastOutboundTunnel = nullptr;
}
@ -69,8 +67,11 @@ namespace tunnel @@ -69,8 +67,11 @@ namespace tunnel
for (auto it : m_InboundTunnels)
{
if (i >= num) break;
v.push_back (it);
i++;
if (!it->IsFailed ())
{
v.push_back (it);
i++;
}
}
return v;
}
@ -82,7 +83,7 @@ namespace tunnel @@ -82,7 +83,7 @@ namespace tunnel
if (m_LastOutboundTunnel && tunnel == m_LastOutboundTunnel)
{
for (auto it: m_OutboundTunnels)
if (it != m_LastOutboundTunnel)
if (it != m_LastOutboundTunnel && !it->IsFailed ())
{
tunnel = it;
break;
@ -109,19 +110,33 @@ namespace tunnel @@ -109,19 +110,33 @@ namespace tunnel
{
LogPrint ("Tunnel test ", (int)it.first, " failed");
// both outbound and inbound tunnels considered as invalid
TunnelExpired (it.second.first);
TunnelExpired (it.second.second);
it.second.first->SetFailed (true);
it.second.second->SetFailed (true);
}
m_Tests.clear ();
auto it1 = m_OutboundTunnels.begin ();
auto it2 = m_InboundTunnels.begin ();
while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ())
{
uint32_t msgID = rnd.GenerateWord32 ();
m_Tests[msgID] = std::make_pair (*it1, *it2);
(*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
CreateDeliveryStatusMsg (msgID));
it1++; it2++;
bool failed = false;
if ((*it1)->IsFailed ())
{
failed = true;
it1++;
}
if ((*it2)->IsFailed ())
{
failed = true;
it2++;
}
if (!failed)
{
uint32_t msgID = rnd.GenerateWord32 ();
m_Tests[msgID] = std::make_pair (*it1, *it2);
(*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
CreateDeliveryStatusMsg (msgID));
it1++; it2++;
}
}
}

Loading…
Cancel
Save