void DatagramDestination::SendMsg( I2NPMessage* msg, std::shared_ptr<const i2p::data::LeaseSet> remote) { auto outboundTunnel = m_Owner.GetTunnelPool()->GetNextOutboundTunnel(); auto leases = remote->GetNonExpiredLeases(); if (!leases.empty() && outboundTunnel) { std::vector<i2p::tunnel::TunnelMessageBlock> msgs; uint32_t i = i2p::crypto::RandInRange<uint32_t>(0, leases.size() - 1); auto garlic = m_Owner.WrapMessage(remote, ToSharedI2NPMessage(msg), true); msgs.push_back( i2p::tunnel::TunnelMessageBlock { i2p::tunnel::e_DeliveryTypeTunnel, leases[i].tunnel_gateway, leases[i].tunnel_ID, garlic}); outboundTunnel->SendTunnelDataMsg(msgs); } else { if (outboundTunnel) LogPrint(eLogWarn, "DatagramDestination: failed to send datagram: all leases expired"); else LogPrint(eLogWarn, "DatagramDestination: failed to send datagram: no outbound tunnels"); DeleteI2NPMessage(msg); } }
void DatagramDestination::SendMsg (I2NPMessage * msg, std::shared_ptr<const i2p::data::LeaseSet> remote) { auto outboundTunnel = m_Owner.GetTunnelPool ()->GetNextOutboundTunnel (); auto leases = remote->GetNonExpiredLeases (); if (!leases.empty () && outboundTunnel) { std::vector<i2p::tunnel::TunnelMessageBlock> msgs; uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1); auto garlic = m_Owner.WrapMessage (remote, ToSharedI2NPMessage (msg), true); msgs.push_back (i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, leases[i].tunnelGateway, leases[i].tunnelID, garlic }); outboundTunnel->SendTunnelDataMsg (msgs); } else { if (outboundTunnel) LogPrint (eLogWarning, "Failed to send datagram. All leases expired"); else LogPrint (eLogWarning, "Failed to send datagram. No outbound tunnels"); DeleteI2NPMessage (msg); } }
void NetDbRequests::ManageRequests() { uint64_t ts = i2p::util::GetSecondsSinceEpoch(); std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex); for (auto it = m_RequestedDestinations.begin(); it != m_RequestedDestinations.end();) { auto& dest = it->second; bool done = false; // request is worthless after 1 minute if (ts < dest->GetCreationTime() + 60) { // no response for 5 seconds if (ts > dest->GetCreationTime() + 5) { auto count = dest->GetExcludedPeers().size(); std::size_t attempts(7); if (!dest->IsExploratory() && count < attempts) { auto pool = i2p::tunnel::tunnels.GetExploratoryPool(); auto outbound = pool->GetNextOutboundTunnel(); auto inbound = pool->GetNextInboundTunnel(); auto nextFloodfill = netdb.GetClosestFloodfill( dest->GetDestination(), dest->GetExcludedPeers()); if (nextFloodfill && outbound && inbound) { outbound->SendTunnelDataMsg( nextFloodfill->GetIdentHash(), 0, dest->CreateRequestMessage( nextFloodfill, inbound)); } else { done = true; if (!inbound) LogPrint(eLogWarn, "NetDbRequests: no inbound tunnels"); if (!outbound) LogPrint(eLogWarn, "NetDbRequests: no outbound tunnels"); if (!nextFloodfill) LogPrint(eLogWarn, "NetDbRequests: no more floodfills"); } } else { if (!dest->IsExploratory()) LogPrint(eLogWarn, "NetDbRequests: ", dest->GetDestination().ToBase64(), " not found after ", attempts, " attempts"); done = true; } } } else { // delete obsolete request done = true; } if (done) it = m_RequestedDestinations.erase(it); else it++; } }