private static void AddTunnelMessage(List <TunnelMessage> result, TunnelDataFragment initialfragment, byte[] buf) { switch (initialfragment.Delivery) { case TunnelMessage.DeliveryTypes.Local: result.Add(new TunnelMessageLocal(I2NPMessage.ReadHeader16(new BufRef(buf)))); break; case TunnelMessage.DeliveryTypes.Router: result.Add(new TunnelMessageRouter(I2NPMessage.ReadHeader16(new BufRef(buf)), new I2PIdentHash((BufRefLen)initialfragment.ToHash))); break; case TunnelMessage.DeliveryTypes.Tunnel: result.Add(new TunnelMessageTunnel(I2NPMessage.ReadHeader16(new BufRef(buf)), new I2PIdentHash((BufRefLen)initialfragment.ToHash), initialfragment.Tunnel)); break; } }
public IEnumerable <TunnelMessage> Process(IEnumerable <TunnelDataMessage> tdmsgs) { var result = new List <TunnelMessage>(); RemoveUnmatchedFragments.Do(() => { lock ( MessageFragments ) { var remove = MessageFragments.Where(p => p.Value.Created.DeltaToNow.ToMinutes > RememberUnmatchedFragmentsForMinutes). Select(p => p.Key).ToArray(); foreach (var key in remove) { Logging.LogDebug("TunnelDataFragmentReassembly: Removing old unmatched fragment for " + key.ToString()); MessageFragments.Remove(key); } } }); foreach (var msg in tdmsgs) { var hash = I2PHashSHA256.GetHash(msg.TunnelDataPayload, msg.IV); var eq = BufUtils.Equal(msg.Checksum.PeekB(0, 4), 0, hash, 0, 4); if (!eq) { // Do not stop processing, just throw away faulty data // throw new SignatureCheckFailureException( "TunnelDataFragmentReassembly: SHA256 check failed in TunnelData" ); Logging.LogDebug("TunnelDataFragmentReassembly: SHA256 check failed in TunnelData"); continue; } var reader = (BufRefLen)msg.TunnelDataPayload; while (reader.Length > 0) { var frag = new TunnelDataFragment(reader); if (frag.FollowOnFragment) { List <TunnelDataFragment> fragments; if (!MessageFragments.ContainsKey(frag.MessageId)) { fragments = new List <TunnelDataFragment>(); MessageFragments[frag.MessageId] = new TunnelDataFragmentList(fragments); } else { fragments = MessageFragments[frag.MessageId].List; } if (fragments.Count <= frag.FragmentNumber) { fragments.AddRange(new TunnelDataFragment[frag.FragmentNumber - fragments.Count + 1]); } fragments[frag.FragmentNumber] = frag; CheckForAllFragmentsFound(result, frag.MessageId, fragments); } else { if (frag.Fragmented) { List <TunnelDataFragment> fragments; if (!MessageFragments.ContainsKey(frag.MessageId)) { fragments = new List <TunnelDataFragment>(); MessageFragments[frag.MessageId] = new TunnelDataFragmentList(fragments); } else { fragments = MessageFragments[frag.MessageId].List; } if (fragments.Count == 0) { fragments.AddRange(new TunnelDataFragment[1]); } fragments[0] = frag; CheckForAllFragmentsFound(result, frag.MessageId, fragments); } else { AddTunnelMessage(result, frag, frag.Payload.ToByteArray()); } } } } return(result); }