Beispiel #1
0
void TunnelPool::TestTunnels() {
  for (auto it : m_Tests) {
    LogPrint("Tunnel test ", static_cast<int>(it.first), " failed");
    // if test failed again with another tunnel we consider it failed
    if (it.second.first) {
      if (it.second.first->GetState() == e_TunnelStateTestFailed) {
        it.second.first->SetState(e_TunnelStateFailed);
        std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
        m_OutboundTunnels.erase(it.second.first);
      } else {
        it.second.first->SetState(e_TunnelStateTestFailed);
      }
    }
    if (it.second.second) {
      if (it.second.second->GetState() == e_TunnelStateTestFailed) {
        it.second.second->SetState(e_TunnelStateFailed);
        {
          std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
          m_InboundTunnels.erase(it.second.second);
        }
        if (m_LocalDestination)
          m_LocalDestination->SetLeaseSetUpdated();
      } else {
        it.second.second->SetState(e_TunnelStateTestFailed);
      }
    }
  }
  m_Tests.clear();
  // new tests
  auto it1 = m_OutboundTunnels.begin();
  auto it2 = m_InboundTunnels.begin();
  while (it1 != m_OutboundTunnels.end() && it2 != m_InboundTunnels.end()) {
    bool failed = false;
    if ((*it1)->IsFailed()) {
      failed = true;
      it1++;
    }
    if ((*it2)->IsFailed()) {
      failed = true;
      it2++;
    }
    if (!failed) {
      uint32_t msgID = i2p::crypto::Rand<uint32_t>();
      m_Tests[msgID] = std::make_pair(*it1, *it2);
      (*it1)->SendTunnelDataMsg(
          (*it2)->GetNextIdentHash(),
          (*it2)->GetNextTunnelID(),
          CreateDeliveryStatusMsg(msgID));
      it1++;
      it2++;
    }
  }
}
Beispiel #2
0
	size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID)
	{
		size_t size = 0;
		if (m_Owner)
		{
			auto inboundTunnel = m_Owner->GetTunnelPool ()->GetNextInboundTunnel ();
			if (inboundTunnel)
			{
				buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel
				size++;
				// hash and tunnelID sequence is reversed for Garlic
				memcpy (buf + size, inboundTunnel->GetNextIdentHash (), 32); // To Hash
				size += 32;
				htobe32buf (buf + size, inboundTunnel->GetNextTunnelID ()); // tunnelID
				size += 4;
				// create msg
				auto msg = CreateDeliveryStatusMsg (msgID);
				if (m_Owner)
				{
					//encrypt
					uint8_t key[32], tag[32];
					RAND_bytes (key, 32); // random session key
					RAND_bytes (tag, 32); // random session tag
					m_Owner->SubmitSessionKey (key, tag);
					GarlicRoutingSession garlic (key, tag);
					msg = garlic.WrapSingleMessage (msg);
				}
				memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
				size += msg->GetLength ();
				// fill clove
				uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
				uint32_t cloveID;
				RAND_bytes ((uint8_t *)&cloveID, 4);
				htobe32buf (buf + size, cloveID); // CloveID
				size += 4;
				htobe64buf (buf + size, ts); // Expiration of clove
				size += 8;
				memset (buf + size, 0, 3); // certificate of clove
				size += 3;
			}
			else
				LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus");
		}
		else
			LogPrint (eLogWarning, "Garlic: Missing local LeaseSet");

		return size;
	}
Beispiel #3
0
	void TunnelPool::TestTunnels ()
	{
		auto& rnd = i2p::context.GetRandomNumberGenerator ();
		for (auto it: m_Tests)
		{
			LogPrint ("Tunnel test ", (int)it.first, " failed"); 
			// both outbound and inbound tunnels considered as invalid
			if (it.second.first)
			{	
				it.second.first->SetFailed (true);
				m_OutboundTunnels.erase (it.second.first);
			}	
			if (it.second.second)
			{
				it.second.second->SetFailed (true);
				m_InboundTunnels.erase (it.second.second);
			}	
		}
		m_Tests.clear ();	
		auto it1 = m_OutboundTunnels.begin ();
		auto it2 = m_InboundTunnels.begin ();
		while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ())
		{
			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++;
			}	
		}
	}