public RouterStatistics(BufRef buf) { Id = new I2PIdentHash(buf); LastSeen = new I2PDate(buf); Created = new I2PDate(buf); buf.Seek(52); // Reserved space var mapping = new I2PMapping(buf); SuccessfulConnects = TryGet(mapping, "SuccessfulConnects"); FailedConnects = TryGet(mapping, "FailedConnects"); InformationFaulty = TryGet(mapping, "InformationFaulty"); SuccessfulTunnelMember = TryGet(mapping, "SuccessfulTunnelMember"); DeclinedTunnelMember = TryGet(mapping, "DeclinedTunnelMember"); SlowHandshakeConnect = TryGet(mapping, "SlowHandshakeConnect"); MaxBandwidthSeen = TryGetFloat(mapping, "MaxBandwidthSeen"); TunnelBuildTimeout = TryGet(mapping, "TunnelBuildTimeout"); TunnelBuildTimeMsPerHop = TryGet(mapping, "TunnelBuildTimeMsPerHop", DefaultTunnelBuildTimeMsPerHop); FloodfillUpdateTimeout = TryGet(mapping, "FloodfillUpdateTimeout"); FloodfillUpdateSuccess = TryGet(mapping, "FloodfillUpdateSuccess"); SuccessfulTunnelTest = TryGet(mapping, "SuccessfulTunnelTest"); FailedTunnelTest = TryGet(mapping, "FailedTunnelTest"); IsFirewalled = TryGet(mapping, "IsFirewalled") != 0; }
public IEnumerable <I2PIdentHash> GetClosestFloodfill( I2PIdentHash dest, int count, ConcurrentBag <I2PIdentHash> exclude, bool nextset) { var minfit = RouletteFloodFill.AverageFit - Math.Max(4.0, RouletteFloodFill.AbsDevFit * 0.8); var subset = (exclude != null && exclude.Any()) ? FloodfillInfos.Where(inf => !exclude.Contains(inf.Key)) : FloodfillInfos; var refkey = nextset ? dest.NextRoutingKey : dest.RoutingKey; var qlist = subset .Select(ri => new { Id = ri.Key, Q = ri.Value.CachedStatistics }) .Where(inf => (inf.Q?.Score ?? 0f) > minfit); return(qlist .Select(p => new { p.Id, Dist = p.Id ^ refkey }) .OrderBy(p => p.Dist) .Take(count) .Select(p => p.Id) .ToArray()); }
/* * Exploration * * Exploration is a special form of netdb lookup, where a router attempts to learn about new routers. * It does this by sending a floodfill router a I2NP DatabaseLookupMessage, looking for a random key. * As this lookup will fail, the floodfill would normally respond with a I2NP DatabaseSearchReplyMessage * containing hashes of floodfill routers close to the key. This would not be helpful, as the requesting * router probably already knows those floodfills, and it would be impractical to add ALL floodfill * routers to the "don't include" field of the lookup. For an exploration query, the requesting router * adds a router hash of all zeros to the "don't include" field of the DatabaseLookupMessage. * * The floodfill will then respond only with non-floodfill routers close to the requested key. * * https://geti2p.net/en/docs/how/network-database * * 11 => exploration lookup, return DatabaseSearchReplyMessage * containing non-floodfill routers only (replaces an * excludedPeer of all zeroes) * https://geti2p.net/spec/i2np#databaselookup */ void ExplorationRouterLookup() { if (NetDb.Inst.RouterCount > 1000 && ExploreNewRouters.Frequency < TickSpan.Minutes(1)) { ExploreNewRouters.Frequency = TickSpan.Minutes(5); } I2PIdentHash ident = new I2PIdentHash(true); var ff = NetDb.Inst.GetClosestFloodfill(ident, 10, null, false) .Shuffle() .Take(DatabaseLookupSelectFloodfillCount) .ToArray(); foreach (var oneff in ff) { var msg = new DatabaseLookupMessage( ident, RouterContext.Inst.MyRouterIdentity.IdentHash, DatabaseLookupMessage.LookupTypes.Exploration, new I2PIdentHash[] { new I2PIdentHash(false) }); #if LOG_ALL_IDENT_LOOKUPS Logging.Log("IdentResolver: Random router lookup " + ident.Id32Short + " sent to " + oneff.Id32Short); #endif try { TransportProvider.Send(oneff, msg); } catch (Exception ex) { Logging.Log(ex); } } }
public InboundTunnel(TunnelConfig config, int outtunnelhops) : base(config) { if (config != null) { Fake0HopTunnel = false; TunnelSetup = config.Info; OutTunnelHops = outtunnelhops; var gw = TunnelSetup.Hops[0]; RemoteGateway = gw.Peer.IdentHash; GatewayTunnelId = gw.TunnelId; ReceiveTunnelId = TunnelSetup.Hops.Last().TunnelId; DebugUtils.LogDebug("InboundTunnel: Tunnel " + Destination.Id32Short + " created."); } else { Fake0HopTunnel = true; var hops = new List <HopInfo>(); hops.Add(new HopInfo(RouterContext.Inst.MyRouterIdentity, new I2PTunnelId())); TunnelSetup = new TunnelInfo(hops); Config = new TunnelConfig( TunnelConfig.TunnelDirection.Inbound, TunnelConfig.TunnelPool.Exploratory, TunnelSetup); ReceiveTunnelId = TunnelSetup.Hops.Last().TunnelId; RemoteGateway = RouterContext.Inst.MyRouterIdentity.IdentHash; GatewayTunnelId = ReceiveTunnelId; DebugUtils.LogDebug("InboundTunnel " + TunnelDebugTrace + ": 0-hop tunnel " + Destination.Id32Short + " created."); } }
static void LookupResult(I2PIdentHash hash, I2PLeaseSet ls) { LS = ls; }
public IEnumerable <I2PRouterInfo> GetClosestFloodfillInfo(I2PIdentHash reference, int count, List <I2PIdentHash> exclude, bool nextset) { return(Find(GetClosestFloodfill(reference, count, exclude, nextset))); }
public void FloodfillUpdateTimeout(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.FloodfillUpdateTimeout), false); }
public DestinationStatistics(I2PIdentHash id) { Id = id; LastSeen = new I2PDate(DateTime.UtcNow); UpdateScore(); }
public void FailedTunnelTest(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.FailedTunnelTest), false); }
private static bool Send(I2PIdentHash dest, I2NPMessage data, int reclvl) { ITransport transp = null; try { if (dest == RouterContext.Inst.MyRouterIdentity.IdentHash) { Logging.LogTransport($"TransportProvider: Loopback {data}"); TransportProvider.Inst.DistributeIncomingMessage(null, data.CreateHeader16); return(true); } lock ( TransportSelectionLock ) { if (TransportProvider.Inst.CurrentlyUnknownRouters.Contains(dest)) { TransportProvider.Inst.CurrentlyUnknownRouters.Add(dest, data); return(true); } transp = TransportProvider.Inst.GetEstablishedTransport(dest, false); if (transp != null) { transp.Send(data); return(true); } if (NetDb.Inst.Contains(dest)) { transp = TransportProvider.Inst.GetTransport(dest); if (transp == null) { throw new FailedToConnectException($"Unable to contact {dest}"); } transp.Send(data); } else { if (TransportProvider.Inst.CurrentlyUnresolvableRouters.Contains(dest)) { throw new ArgumentException($"Unable to resolve {dest}"); } TransportProvider.Inst.CurrentlyUnknownRouters.Add(dest, data); } } } catch (FailedToConnectException ex) { if (transp != null) { TransportProvider.Inst.Remove(transp); } if (dest != null && NetDb.Inst != null) { NetDb.Inst.Statistics.FailedToConnect(dest); } Logging.LogTransport($"TransportProvider.Send: {( transp == null ? "<>" : transp.DebugId )}" + $" Exception {ex.GetType()}"); return(false); } catch (EndOfStreamEncounteredException ex) { TransportProvider.Inst.Remove(transp); Logging.LogTransport($"TransportProvider.Send: Connection {( transp == null ? "<>" : transp.DebugId )}" + $" closed exception: {ex.GetType()}"); if (reclvl > 1 || !Send(dest, data, reclvl + 1)) { Logging.LogTransport($"TransportProvider.Send: Recconnection failed to {dest.Id32Short}, reclvl: {reclvl}."); throw; } } catch (RouterUnresolvableException ex) { if (dest != null) { NetDb.Inst.Statistics.DestinationInformationFaulty(dest); } Logging.LogTransport($"TransportProvider.Send: Unresolvable router: {ex.Message}"); return(false); } catch (Exception ex) { if (transp != null) { TransportProvider.Inst.Remove(transp); } if (dest != null) { NetDb.Inst.Statistics.DestinationInformationFaulty(dest); } Logging.LogTransport($"TransportProvider.Send: Exception {ex.GetType()}, {ex.Message}"); throw; } return(true); }
public void FailedToConnect(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.FailedConnects), false); }
public ITransport GetTransport(I2PIdentHash dest) { return(GetEstablishedTransport(dest, true)); }
public static bool Send(I2PIdentHash dest, I2NPMessage data) { return(Send(dest, data, 0)); }
internal void Remove(I2PIdentHash d) { Subscribers.TryRemove(d, out var _); }
public LookupDestination(I2PIdentHash dest) { Destination = dest; }
public static VariableTunnelBuildMessage BuildOutboundTunnel( TunnelInfo setup, I2PIdentHash replyaddr, I2PTunnelId replytunnel, uint replymessageid) { byte usehops = (byte)(setup.Hops.Count > 5 ? 8 : 5); //byte usehops = 7; // 8 makes the response "TunnelBuildReply" var result = new VariableTunnelBuildMessage(usehops); // Hop sort order var requests = new List <BuildRequestRecord>(); for (int i = 0; i < setup.Hops.Count; ++i) { // Hop order: Our out dest -> Endpoint var endpoint = i == setup.Hops.Count - 1; var gateway = i == 0; var rec = new BuildRequestRecord(); rec.Data.Randomize(); rec.Flag = 0; var hop = setup.Hops[i]; rec.OurIdent = hop.Peer.IdentHash; rec.ReceiveTunnel = hop.TunnelId; if (!endpoint) { var nexthop = setup.Hops[i + 1]; rec.NextIdent = nexthop.Peer.IdentHash; rec.NextTunnel = nexthop.TunnelId; } else { rec.SendMessageId = replymessageid; rec.NextIdent = replyaddr; rec.NextTunnel = replytunnel; } rec.RequestTime = DateTime.UtcNow; rec.ToAnyone = endpoint; hop.LayerKey = new I2PSessionKey(rec.LayerKey.Clone()); hop.IVKey = new I2PSessionKey(rec.IVKey.Clone()); requests.Add(rec); #if LOG_ALL_TUNNEL_TRANSFER Logging.Log(rec.ToString()); #endif } // Physical record sort order var order = new List <AesEGBuildRequestRecord>(result.Records); order.Shuffle(); // Scramble the rest for (int i = setup.Hops.Count; i < usehops; ++i) { order[i].Data.Randomize(); } // ElGamal encrypt all of the non random records // and place them in shuffled order. for (int i = 0; i < setup.Hops.Count; ++i) { var hop = setup.Hops[i]; var egrec = new EGBuildRequestRecord(order[i].Data, requests[i], hop.Peer.IdentHash, hop.Peer.PublicKey); } var cipher = new CbcBlockCipher(new AesEngine()); // Dont Aes the first destination for (int i = setup.Hops.Count - 2; i >= 0; --i) { var prevhop = requests[i]; cipher.Init(false, prevhop.ReplyKeyBuf.ToParametersWithIV(prevhop.ReplyIV)); for (int j = i + 1; j < setup.Hops.Count; ++j) { cipher.Reset(); cipher.ProcessBytes(order[j].Data); } } for (int i = 0; i < setup.Hops.Count; ++i) { setup.Hops[i].ReplyProcessing = new ReplyProcessingInfo() { BuildRequestIndex = result.Records.IndexOf(order[i]), ReplyIV = requests[i].ReplyIV.Clone(), ReplyKey = new I2PSessionKey(requests[i].ReplyKeyBuf.Clone()) }; } return(result); }
static void Main(string[] args) { PeriodicAction LsLookup = new PeriodicAction(TickSpan.Minutes(5)); DebugUtils.LogToConsole = true; DebugUtils.LogToFile("i2p.log"); DebugUtils.LogInformation("Me: " + RouterContext.Inst.MyRouterIdentity.IdentHash.Id32); for (int i = 0; i < args.Length; ++i) { switch (args[i]) { case "--addr": if (args.Length > i) { RouterContext.Inst.DefaultExtAddress = IPAddress.Parse(args[++i]); } break; case "--port": if (args.Length > i) { var port = int.Parse(args[++i]); RouterContext.Inst.DefaultTCPPort = port; RouterContext.Inst.DefaultUDPPort = port; } break; case "--nofw": RouterContext.Inst.IsFirewalled = false; break; default: Console.WriteLine("Usage: I2P.exe --addr 12.34.56.78 --port 8081 --nofw"); break; } } RouterContext.Inst.ApplyNewSettings(); var pnp = new UPnp(); Thread.Sleep(5000); // Give UPnp a chance Router.Start(); while (true) { try { Connected = true; var dest = new I2PDestinationInfo(I2PSigningKey.SigningKeyTypes.EdDSA_SHA512_Ed25519); var mydest = Router.CreateDestination(dest, false); mydest.DataReceived += new ClientDestination.DestinationDataReceived(mydest_DataReceived); var hashes = new I2PIdentHash[] { new I2PIdentHash("udhdrtrcetjm5sxaskjyr5ztseszydbh4dpl3pl4utgqqw2v4jna.b32.i2p"), new I2PIdentHash("7tbay5p4kzemkxvyvbf6v7eau3zemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p"), new I2PIdentHash("ukeu3k5oycga3uneqgtnvselmt4yemvoilkln7jpvafvfx7dnkdq.b32.i2p") }; while (Connected) { Thread.Sleep(20000); /* * if ( LS != null ) * { * mydest.Send( LS, BufUtils.Random( 200 ), false ); * }*/ LsLookup.Do(() => mydest.LookupDestination(hashes.Random(), new ClientDestination.DestinationLookupResult(LookupResult))); } } catch (SocketException ex) { DebugUtils.Log(ex); } catch (IOException ex) { DebugUtils.Log(ex); } catch (Exception ex) { DebugUtils.Log(ex); } } }
public void SlowHandshakeConnect(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.SlowHandshakeConnect), false); }
public void SuccessfulConnect(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.SuccessfulConnects), true); }
public void DeclinedTunnelMember(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.DeclinedTunnelMember), false); }
public void DestinationInformationFaulty(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.InformationFaulty), false); }
public TunnelMessageTunnel(I2NPMessage message, I2PIdentHash destination, I2PTunnelId tunnel) : base(message, destination, DeliveryTypes.Tunnel) { Tunnel = tunnel; }
public void MaxBandwidth(I2PIdentHash hash, Bandwidth bw) { Update(hash, ds => ds.MaxBandwidthSeen = Math.Max(ds.MaxBandwidthSeen, bw.BitrateMax), false); }
public bool IsDestination(I2PIdentHash comp) { return(comp.Hash16 == Data); }
public void SuccessfulTunnelTest(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.SuccessfulTunnelTest), true); }
public RouterInfoMeta(I2PIdentHash id) { Id = id; StoreIx = -1; }
// Not answering a build request is wose than declining public void TunnelBuildTimeout(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.TunnelBuildTimeout), false); }
public EGBuildRequestRecord(BuildRequestRecord src, I2PIdentHash topeer, I2PPublicKey key) : this(new BufLen(new byte[Length]), src, topeer, key) { }
public void FloodfillUpdateSuccess(I2PIdentHash hash) { Update(hash, ds => Interlocked.Increment(ref ds.FloodfillUpdateSuccess), false); }
public I2PLeaseSet FindLeaseSet(I2PIdentHash dest) { return(LeaseSets[dest]); }