/* * 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() { 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); } } }
private void HandleTunnelData(List <TunnelDataMessage> msgs) { DecryptTunnelMessages(msgs); var newmsgs = Reassembler.Process(msgs); foreach (var one in newmsgs) { if (one.GetType() == typeof(TunnelMessageLocal)) { DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Local :\r\n" + one.Header.ToString()); MessageReceived(((TunnelMessageLocal)one).Header); } else if (one.GetType() == typeof(TunnelMessageRouter)) { DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Router :\r\n" + one.Header.ToString()); TransportProvider.Send(((TunnelMessageRouter)one).Destination, one.Header.Message); } else if (one.GetType() == typeof(TunnelMessageTunnel)) { var tone = (TunnelMessageTunnel)one; DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Tunnel :\r\n" + one.Header.ToString()); var gwmsg = new TunnelGatewayMessage(tone.Header, tone.Tunnel); TransportProvider.Send(tone.Destination, gwmsg); } else { DebugUtils.LogWarning("InboundTunnel " + TunnelDebugTrace + " TunnelData without routing rules:\r\n" + one.Header.ToString()); } } }
private bool HandleTunnelData(IEnumerable <TunnelDataMessage> msgs) { EncryptTunnelMessages(msgs); #if LOG_ALL_TUNNEL_TRANSFER LogDataSent.Log(() => "PassthroughTunnel " + Destination.Id32Short + " TunnelData sent."); #endif var dropped = 0; foreach (var one in msgs) { if (Limiter.DropMessage()) { ++dropped; continue; } one.TunnelId = SendTunnelId; Bandwidth.DataSent(one.Payload.Length); TransportProvider.Send(Destination, one); } #if LOG_ALL_TUNNEL_TRANSFER if (dropped > 0) { DebugUtils.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth)); } #endif return(true); }
private void HandleGatewayTunnelRequest( II2NPHeader msg, IEnumerable <AesEGBuildRequestRecord> records, EGBuildRequestRecord myrec, BuildRequestRecord drec) { var tunnel = new GatewayTunnel(drec); var replykey = drec.ReplyKey.Key.Clone(); var replyiv = drec.ReplyIV.Clone(); tunnel.EstablishedTime.SetNow(); var doaccept = AcceptingTunnels(drec); var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply; Logging.LogDebug(() => string.Format("HandleGatewayTunnelRequest {3}: {0} Gateway tunnel request: {1} for tunnel id {2}.", tunnel.Destination.Id32Short, response, tunnel.ReceiveTunnelId, tunnel.TunnelDebugTrace)); TunnelProvider.UpdateTunnelBuildReply(records, myrec, replykey, replyiv, response); if (response == BuildResponseRecord.RequestResponse.Accept) { AddTunnel(tunnel); TunnelMgr.AddExternalTunnel(tunnel); AcceptedTunnelBuildRequest(drec); } TransportProvider.Send(tunnel.Destination, msg.Message); }
private void HandleEndpointTunnelRequest( II2NPHeader msg, IEnumerable <AesEGBuildRequestRecord> records, EGBuildRequestRecord myrec, BuildRequestRecord drec) { var tunnel = new EndpointTunnel(drec); var replykey = drec.ReplyKey.Key.Clone(); var replyiv = drec.ReplyIV.Clone(); tunnel.EstablishedTime.SetNow(); var doaccept = AcceptingTunnels(drec); var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply; DebugUtils.LogDebug(() => string.Format("HandleEndpointTunnelRequest {3}: {0} Endpoint tunnel request: {1} for tunnel id {2}.", tunnel.Destination.Id32Short, response, tunnel.ReceiveTunnelId, tunnel.TunnelDebugTrace)); TunnelProvider.UpdateTunnelBuildReply(records, myrec, replykey, replyiv, response); var responsemessage = new VariableTunnelBuildReplyMessage(records.Select(r => new BuildResponseRecord(r))); var buildreplymsg = new TunnelGatewayMessage(responsemessage.GetHeader16(tunnel.ResponseMessageId), tunnel.ResponseTunnelId); if (response == BuildResponseRecord.RequestResponse.Accept) { AddTunnel(tunnel); TunnelMgr.AddExternalTunnel(tunnel); AcceptedTunnelBuildRequest(drec); } TransportProvider.Send(tunnel.Destination, buildreplymsg); }
private bool HandleReceiveQueue() { II2NPHeader16[] messages = null; lock ( ReceiveQueue ) { if (ReceiveQueue.Count == 0) { return(true); } var msgs = new List <II2NPHeader16>(); int dropped = 0; foreach (var msg in ReceiveQueue) { if (Limiter.DropMessage()) { ++dropped; continue; } msgs.Add((II2NPHeader16)msg); } messages = msgs.ToArray(); #if LOG_ALL_TUNNEL_TRANSFER if (dropped > 0) { if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x63e9))) { Logging.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth)); } } #endif } if (messages == null || messages.Length == 0) { return(true); } var tdata = TunnelDataMessage.MakeFragments(messages.Select(msg => (TunnelMessage)(new TunnelMessageLocal(msg))), SendTunnelId); EncryptTunnelMessages(tdata); #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x17f3))) { Logging.Log("GatewayTunnel " + Destination.Id32Short + ": TunnelData sent."); } #endif foreach (var tdmsg in tdata) { Bandwidth.DataSent(tdmsg.Payload.Length); TransportProvider.Send(Destination, tdmsg); } return(true); }
public ResultPromise <TransportResponse> Send(TransportRequest request) { #region Contracts if (request == null) { throw new ArgumentNullException(); } #endregion // Send return(_provider.Send(request)); }
private void SendUpdate(I2PIdentHash ff, uint token) { // If greater than zero, a DeliveryStatusMessage // is requested with the Message ID set to the value of the Reply Token. // A floodfill router is also expected to flood the data to the closest floodfill peers // if the token is greater than zero. // https://geti2p.net/spec/i2np#databasestore var ds = new DatabaseStoreMessage( RouterContext.Inst.MyRouterInfo, token, RouterContext.Inst.MyRouterInfo.Identity.IdentHash, 0); TransportProvider.Send(ff, ds); }
private void HandleEndpointTunnelRequest( II2NPHeader msg, TunnelBuildRequestDecrypt decrypt) { var config = new TunnelConfig( TunnelConfig.TunnelDirection.Inbound, TunnelConfig.TunnelPool.External, new TunnelInfo(new List <HopInfo> { new HopInfo( RouterContext.Inst.MyRouterIdentity, new I2PTunnelId()) } )); var tunnel = new EndpointTunnel(this, config, decrypt.Decrypted); tunnel.EstablishedTime.SetNow(); var doaccept = AcceptingTunnels(decrypt.Decrypted); var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply; Logging.LogDebug($"HandleEndpointTunnelRequest {tunnel.TunnelDebugTrace}: " + $"{tunnel.Destination.Id32Short} Endpoint tunnel request: {response} " + $"for tunnel id {tunnel.ReceiveTunnelId}."); var newrecords = decrypt.CreateTunnelBuildReplyRecords(response); var responsemessage = new VariableTunnelBuildReplyMessage( newrecords.Select(r => new BuildResponseRecord(r)), tunnel.ResponseMessageId); var buildreplymsg = new TunnelGatewayMessage( responsemessage, tunnel.ResponseTunnelId); if (response == BuildResponseRecord.RequestResponse.Accept) { RunningEndpointTunnels[tunnel] = 1; TunnelMgr.AddTunnel(tunnel); AcceptedTunnelBuildRequest(decrypt.Decrypted); } TransportProvider.Send(tunnel.Destination, buildreplymsg); }
internal static void HandleDatabaseStore(DatabaseStoreMessage ds) { if (ds.RouterInfo == null && ds.LeaseSet == null) { throw new ArgumentException("DatabaseStore without Router or Lease info!"); } if (ds.RouterInfo != null) { #if LOG_ALL_TUNNEL_TRANSFER //Logging.Log( "HandleDatabaseStore: DatabaseStore RouterInfo" + ds.ToString() ); #endif NetDb.Inst.AddRouterInfo(ds.RouterInfo); } else { #if LOG_ALL_TUNNEL_TRANSFER //Logging.Log( "HandleDatabaseStore: DatabaseStore LeaseSet" + ds.ToString() ); #endif NetDb.Inst.AddLeaseSet(ds.LeaseSet); } if (ds.ReplyToken != 0) { if (ds.ReplyTunnelId != 0) { var outtunnel = TunnelProvider.Inst.GetEstablishedOutboundTunnel(true); if (outtunnel != null) { outtunnel.Send(new TunnelMessageRouter( (new TunnelGatewayMessage( new DeliveryStatusMessage(ds.ReplyToken), ds.ReplyTunnelId)), ds.ReplyGateway)); } } else { TransportProvider.Send(ds.ReplyGateway, new DeliveryStatusMessage(ds.ReplyToken)); } } }
private void SendUpdateTunnelReply(I2PIdentHash ff, uint token) { // If greater than zero, a DeliveryStatusMessage // is requested with the Message ID set to the value of the Reply Token. // A floodfill router is also expected to flood the data to the closest floodfill peers // if the token is greater than zero. // https://geti2p.net/spec/i2np#databasestore var replytunnel = TunnelProvider.Inst.GetInboundTunnel(true); var ds = new DatabaseStoreMessage(RouterContext.Inst.MyRouterInfo, token, replytunnel.Destination, replytunnel.ReceiveTunnelId); lock ( OutstandingRequests ) { OutstandingRequests[token] = new FFUpdateRequestInfo(ff); } TransportProvider.Send(ff, ds); }
private void SendRIDatabaseLookup(I2PIdentHash ident, IdentUpdateRequestInfo info) { var ff = NetDb.Inst.GetClosestFloodfill( ident, 10 + 3 * info.Retries, info.AlreadyQueried, false); if (!ff.Any()) { Logging.Log($"IdentResolver: failed to find a floodfill router to lookup ({ident}): "); return; } ff.Shuffle(); ff = ff.Take(DatabaseLookupSelectFloodfillCount).ToArray(); foreach (var oneff in ff) { try { var msg = new DatabaseLookupMessage( ident, RouterContext.Inst.MyRouterIdentity.IdentHash, DatabaseLookupMessage.LookupTypes.RouterInfo); TransportProvider.Send(oneff, msg); #if LOG_ALL_IDENT_LOOKUPS Logging.Log($"IdentResolver: RouterInfo query {msg.Key.Id32Short} sent to {oneff.Id32Short}"); #endif } catch (Exception ex) { Logging.Log("SendRIDatabaseLookup", ex); } } foreach (var f in ff) { info.AlreadyQueried.Add(f); } }
public virtual ResultPromise <TransportResponse> Send(TransportRequest request) { #region Contracts if (request == null) { throw new ArgumentNullException(); } #endregion // Require if (_provider == null) { throw new InvalidOperationException(); } // Send return(_provider.Send(request)); }
private bool CreateTunnelMessageFragments(IEnumerable <TunnelMessage> messages) { var data = TunnelDataMessage.MakeFragments(messages, SendTunnelId); var encr = OutboundGatewayDecrypt(data); foreach (var msg in encr) { #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup((int)msg.MessageType, 0x4272))) { Logging.LogDebug($"OutboundTunnel: Send {NextHop.Id32Short} : {msg}"); } #endif Bandwidth.DataSent(msg.Payload.Length); TransportProvider.Send(NextHop, msg); } return(true); }
private void HandleTunnelData(List <TunnelDataMessage> msgs) { DecryptTunnelMessages(msgs); var newmsgs = Reassembler.Process(msgs); foreach (var one in newmsgs) { if (one.GetType() == typeof(TunnelMessageLocal)) { #if LOG_ALL_TUNNEL_TRANSFER Logging.Log($"InboundTunnel {TunnelDebugTrace} TunnelData distributed Local :\r\n{one.Header}"); #endif MessageReceived(((TunnelMessageLocal)one).Header); } else if (one.GetType() == typeof(TunnelMessageRouter)) { #if LOG_ALL_TUNNEL_TRANSFER Logging.Log($"InboundTunnel {TunnelDebugTrace} TunnelData distributed Router :\r\n{one.Header}"); #endif TransportProvider.Send(((TunnelMessageRouter)one).Destination, one.Header.Message); } else if (one.GetType() == typeof(TunnelMessageTunnel)) { var tone = (TunnelMessageTunnel)one; #if LOG_ALL_TUNNEL_TRANSFER Logging.Log($"InboundTunnel {TunnelDebugTrace} TunnelData distributed Tunnel :\r\n{one.Header}"); #endif var gwmsg = new TunnelGatewayMessage(tone.Header, tone.Tunnel); TransportProvider.Send(tone.Destination, gwmsg); } else { Logging.LogWarning($"InboundTunnel {TunnelDebugTrace} TunnelData without routing rules:\r\n{one.Header}"); } } }
public override void Distribute(Tunnel tunnel) { #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x2317))) { Logging.LogDebug($"EndpointTunnel {Destination.Id32Short} TunnelData Router :\r\n{one.Header.MessageType}"); } #endif try { tunnel.Bandwidth.DataSent(Message.Payload.Length); TransportProvider.Send(Destination, Message); } catch (Exception ex) { Logging.LogWarning($"{this}", ex); if (++tunnel.AggregateErrors > 5) { throw; } } }
private void SendRIDatabaseLookup(I2PIdentHash ident, IdentUpdateRequestInfo info) { var ff = NetDb.Inst.GetClosestFloodfill(ident, 10, info.AlreadyQueried, false).ToArray(); if (ff == null || ff.Length == 0) { DebugUtils.Log("IdentResolver: failed to find a floodfill router to lookup (" + ident.ToString() + "): "); return; } ff.Shuffle(); ff = ff.Take(DatabaseLookupSelectFloodfillCount).ToArray(); foreach (var oneff in ff) { try { var msg = new DatabaseLookupMessage( ident, RouterContext.Inst.MyRouterIdentity.IdentHash, DatabaseLookupMessage.LookupTypes.RouterInfo); TransportProvider.Send(oneff, msg); #if LOG_ALL_IDENT_LOOKUPS DebugUtils.Log("IdentResolver: RouterInfo query " + msg.Key.Id32Short + " sent to " + oneff.Id32Short); #endif } catch (Exception ex) { DebugUtils.Log("SendRIDatabaseLookup", ex); } } lock (info.AlreadyQueried) { info.AlreadyQueried.AddRange(ff); } }
private bool HandleSendQueue() { I2NPMessage[] rawdata; lock ( SendRawQueue ) { rawdata = SendRawQueue.ToArray(); SendRawQueue.Clear(); } foreach (var msg in rawdata) { #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup((int)msg.MessageType, 0x1701))) { Logging.LogDebug($"OutboundTunnel: Send raw {NextHop.Id32Short} : {msg}"); } #endif Bandwidth.DataSent(msg.Payload.Length); TransportProvider.Send(NextHop, msg); } if (SendQueue.Count == 0) { return(true); } IEnumerable <TunnelMessage> messages; lock ( SendQueue ) { messages = SendQueue.ToArray(); SendQueue.Clear(); } return(CreateTunnelMessageFragments(messages)); }
void InboundTunnel_GarlicMessageReceived(GarlicMessage msg) { try { var decr = IncommingSessions.DecryptMessage(msg.Garlic); if (decr == null) { return; } #if LOG_ALL_TUNNEL_TRANSFER DebugUtils.LogDebug("ClientDestination: GarlicMessageReceived: " + decr.ToString()); #endif foreach (var clove in decr.Cloves) { try { switch (clove.Delivery.Delivery) { case GarlicCloveDelivery.DeliveryMethod.Local: #if LOG_ALL_TUNNEL_TRANSFER DebugUtils.LogDebug(() => string.Format( "ClientDestination: GarlicMessageReceived: Delivered Local: {0}", clove.Message)); #endif TunnelProvider.Inst.DistributeIncomingMessage(null, clove.Message.Header16); break; case GarlicCloveDelivery.DeliveryMethod.Router: var dest = ((GarlicCloveDeliveryRouter)clove.Delivery).Destination; #if LOG_ALL_TUNNEL_TRANSFER DebugUtils.LogDebug(() => string.Format( "ClientDestination: GarlicMessageReceived: Delivered Router: {0} {1}", dest.Id32Short, clove.Message)); #endif TransportProvider.Send(dest, clove.Message); break; case GarlicCloveDelivery.DeliveryMethod.Tunnel: var tone = (GarlicCloveDeliveryTunnel)clove.Delivery; #if LOG_ALL_TUNNEL_TRANSFER DebugUtils.LogDebug(() => string.Format( "ClientDestination: GarlicMessageReceived: Delivered Tunnel: {0} TunnelId: {1} {2}", tone.Destination.Id32Short, tone.Tunnel, clove.Message)); #endif TransportProvider.Send(tone.Destination, new TunnelGatewayMessage(clove.Message.Header16, tone.Tunnel)); break; case GarlicCloveDelivery.DeliveryMethod.Destination: #if LOG_ALL_TUNNEL_TRANSFER DebugUtils.LogDebug(() => string.Format( "ClientDestination: GarlicMessageReceived: Delivered Destination: {0}", clove.Message)); #endif DestinationMessageReceived(clove.Message); break; } } catch (Exception ex) { DebugUtils.Log("ClientDestination GarlicDecrypt Clove", ex); } } } catch (Exception ex) { DebugUtils.Log("ClientDestination GarlicDecrypt", ex); } }
private bool HandleTunnelData(IEnumerable <TunnelDataMessage> msgs) { EncryptTunnelMessages(msgs); var newmsgs = Reassembler.Process(msgs); var dropped = 0; foreach (var one in newmsgs) { if (Limiter.DropMessage()) { ++dropped; continue; } try { if (one.GetType() == typeof(TunnelMessageLocal)) { MessageReceived(((TunnelMessageLocal)one).Header); DebugUtils.Log("EndpointTunnel " + Destination.Id32Short + " TunnelData destination Local. Dropped.\r\n" + one.Header.ToString()); } else if (one.GetType() == typeof(TunnelMessageRouter)) { #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x2317))) { DebugUtils.LogDebug("EndpointTunnel " + Destination.Id32Short + " TunnelData Router :\r\n" + one.Header.MessageType.ToString()); } #endif var msg = one.Header.Message; Bandwidth.DataSent(msg.Payload.Length); TransportProvider.Send(((TunnelMessageRouter)one).Destination, msg); } else if (one.GetType() == typeof(TunnelMessageTunnel)) { var tone = (TunnelMessageTunnel)one; #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x6375))) { DebugUtils.LogDebug("EndpointTunnel " + Destination.Id32Short + " TunnelData Tunnel :\r\n" + one.Header.MessageType.ToString()); } #endif var gwmsg = new TunnelGatewayMessage(tone.Header, tone.Tunnel); Bandwidth.DataSent(gwmsg.Payload.Length); TransportProvider.Send(tone.Destination, gwmsg); } else { DebugUtils.LogDebug("EndpointTunnel " + Destination.Id32Short + " TunnelData of unexpected type: " + one.Header.ToString()); } } catch (Exception ex) { DebugUtils.Log("EndpointTunnel", ex); throw; // Kill tunnel is strange things happen } } #if LOG_ALL_TUNNEL_TRANSFER if (dropped > 0) { DebugUtils.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth)); } #endif return(true); }
private void SendLSDatabaseLookup(I2PIdentHash ident, IdentUpdateRequestInfo info) { /* * var replytunnel = TunnelProvider.Inst.GetInboundTunnel(); * if ( replytunnel == null ) return; */ var ff = NetDb.Inst.GetClosestFloodfill(ident, DatabaseLookupSelectFloodfillCount * 2, info.AlreadyQueried, false).ToArray(); #if LOG_ALL_IDENT_LOOKUPS StringBuilder foundrouters = new StringBuilder(); StringBuilder foundrouterskeys = new StringBuilder(); foreach (var router in ff) { foundrouters.AppendFormat("{0}{1}{2}", (foundrouters.Length != 0 ? ", " : ""), router.Id32Short, FreenetBase64.Encode(router.Hash)); foundrouterskeys.AppendFormat("{0}{1}{2}", (foundrouterskeys.Length != 0 ? ", " : ""), router.Id32Short, FreenetBase64.Encode(router.RoutingKey.Hash)); } var st = foundrouters.ToString(); var st2 = foundrouterskeys.ToString(); #endif if (ff == null || ff.Length == 0) { DebugUtils.Log("IdentResolver failed to find a floodfill router to lookup (" + ident.ToString() + "): "); return; } ff.Shuffle(); ff = ff.Take(DatabaseLookupSelectFloodfillCount).ToArray(); foreach (var oneff in ff) { try { var msg = new DatabaseLookupMessage( ident, RouterContext.Inst.MyRouterIdentity.IdentHash, DatabaseLookupMessage.LookupTypes.LeaseSet); /* * var msg = new DatabaseLookupMessage( * ident, * replytunnel.Destination, replytunnel.GatewayTunnelId, * DatabaseLookupMessage.LookupTypes.LeaseSet, null ); */ //TunnelProvider.Inst.SendEncrypted( oneff.Identity, false, msg ); TransportProvider.Send(oneff, msg); #if LOG_ALL_IDENT_LOOKUPS DebugUtils.Log(string.Format("IdentResolver: LeaseSet query {0} sent to {1}. Dist: {2}", msg.Key.Id32Short, oneff.Id32Short, oneff ^ msg.Key.RoutingKey)); #endif } catch (Exception ex) { DebugUtils.Log("SendLSDatabaseLookup", ex); } } lock (info.AlreadyQueried) { info.AlreadyQueried.AddRange(ff); } }