internal FastResume(BEncodedDictionary dict) { CheckVersion(dict); CheckContent(dict, InfoHashKey); CheckContent(dict, BitfieldKey); CheckContent(dict, BitfieldLengthKey); // BEP52: Support backwards/forwards compatibility var infoHash = InfoHash.FromMemory(((BEncodedString)dict[InfoHashKey]).AsMemory()); if (infoHash.Span.Length == 20) { InfoHashes = InfoHashes.FromV1(infoHash); } else { InfoHashes = InfoHashes.FromV2(infoHash); } var data = ((BEncodedString)dict[BitfieldKey]).Span; Bitfield = new ReadOnlyBitField(data, (int)((BEncodedNumber)dict[BitfieldLengthKey]).Number); // If we're loading up an older version of the FastResume data then we if (dict.ContainsKey(UnhashedPiecesKey)) { data = ((BEncodedString)dict[UnhashedPiecesKey]).Span; UnhashedPieces = new ReadOnlyBitField(data, Bitfield.Length); } else { UnhashedPieces = new ReadOnlyBitField(Bitfield.Length); } }
public override void Decode(ReadOnlySpan <byte> buffer) { ConnectionId = ReadLong(ref buffer); if (Action != ReadInt(ref buffer)) { throw new MessageException("Udp message decoded incorrectly"); } TransactionId = ReadInt(ref buffer); while (buffer.Length >= 20) { InfoHashes.Add(InfoHash.FromMemory(ReadBytes(ref buffer, 20))); } }
public void ScrapeMessageTest() { List <InfoHash> hashes = new List <InfoHash> (); Random r = new Random(); byte[] hash1 = new byte[20]; byte[] hash2 = new byte[20]; byte[] hash3 = new byte[20]; r.NextBytes(hash1); r.NextBytes(hash2); r.NextBytes(hash3); hashes.Add(InfoHash.FromMemory(hash1)); hashes.Add(InfoHash.FromMemory(hash2)); hashes.Add(InfoHash.FromMemory(hash3)); ScrapeMessage m = new ScrapeMessage(12345, 123, hashes); ScrapeMessage d = (ScrapeMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), MessageType.Request); Check(m, MessageType.Request); Assert.AreEqual(2, m.Action); Assert.AreEqual(m.Action, d.Action); Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode())); }
public override void Decode(ReadOnlySpan <byte> buffer) { ProtocolStringLength = ReadByte(ref buffer); // First byte is length // #warning Fix this hack - is there a better way of verifying the protocol string? Hack if (ProtocolStringLength != Constants.ProtocolStringV100.Length) { ProtocolStringLength = Constants.ProtocolStringV100.Length; } ProtocolString = ReadString(ref buffer, ProtocolStringLength); CheckForSupports(ref buffer); InfoHash = InfoHash.FromMemory(ReadBytes(ref buffer, 20)); PeerId = BEncodedString.FromMemory(ReadBytes(ref buffer, 20)); }
public override void Decode(ReadOnlySpan <byte> buffer) { ConnectionId = ReadLong(ref buffer); if (Action != ReadInt(ref buffer)) { ThrowInvalidActionException(); } TransactionId = ReadInt(ref buffer); InfoHash = InfoHash.FromMemory(ReadBytes(ref buffer, 20)); PeerId = ReadBytes(ref buffer, 20); Downloaded = ReadLong(ref buffer); Left = ReadLong(ref buffer); Uploaded = ReadLong(ref buffer); TorrentEvent = (TorrentEvent)ReadInt(ref buffer); IP = ReadUInt(ref buffer); Key = ReadUInt(ref buffer); NumWanted = ReadInt(ref buffer); Port = ReadUShort(ref buffer); }
internal FastResume(BEncodedDictionary dict) { CheckVersion(dict); CheckContent(dict, InfoHashKey); CheckContent(dict, BitfieldKey); CheckContent(dict, BitfieldLengthKey); Infohash = InfoHash.FromMemory(((BEncodedString)dict[InfoHashKey]).AsMemory()); var data = ((BEncodedString)dict[BitfieldKey]).Span; Bitfield = new BitField(data, (int)((BEncodedNumber)dict[BitfieldLengthKey]).Number); // If we're loading up an older version of the FastResume data then we if (dict.ContainsKey(UnhashedPiecesKey)) { data = ((BEncodedString)dict[UnhashedPiecesKey]).Span; UnhashedPieces = new BitField(data, Bitfield.Length); } else { UnhashedPieces = new BitField(Bitfield.Length); } }
protected override void HandleLtMetadataMessage(PeerId id, LTMetadata message) { base.HandleLtMetadataMessage(id, message); switch (message.MetadataMessageType) { case LTMetadata.MessageType.Data: // If we've already received everything successfully, do nothing! if (bitField.AllTrue) { return; } if (Stream == null) { throw new Exception("Need extention handshake before ut_metadata message."); } Stream.Seek(message.Piece * LTMetadata.BlockSize, SeekOrigin.Begin); Stream.Write(message.MetadataPiece, 0, message.MetadataPiece.Length); bitField[message.Piece] = true; if (bitField.AllTrue) { InfoHash hash; Stream.Position = 0; using (SHA1 hasher = Manager.Engine.Factories.CreateSHA1()) hash = InfoHash.FromMemory(hasher.ComputeHash(Stream)); if (Manager.InfoHash != hash) { bitField.SetAll(false); } else { Stream.Position = 0; BEncodedDictionary dict = new BEncodedDictionary(); dict.Add("info", BEncodedValue.Decode(Stream)); if (Manager.TrackerManager.Tiers != null && Manager.TrackerManager.Tiers.Count > 0) { BEncodedList announceTrackers = new BEncodedList(); foreach (var tier in Manager.TrackerManager.Tiers) { BEncodedList announceUrls = new BEncodedList(); foreach (var tracker in tier.Trackers) { announceUrls.Add(new BEncodedString(tracker.Uri.OriginalString)); } announceTrackers.Add(announceUrls); } dict.Add("announce-list", announceTrackers); } var rawData = dict.Encode(); if (Torrent.TryLoad(rawData, out Torrent t)) { if (stopWhenDone) { Manager.RaiseMetadataReceived(rawData); return; } try { if (this.Settings.AutoSaveLoadMagnetLinkMetadata) { if (!Directory.Exists(Path.GetDirectoryName(savePath))) { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); } File.Delete(savePath); File.WriteAllBytes(savePath, dict.Encode()); } } catch (Exception ex) { logger.ExceptionFormated(ex, "Cannot write metadata to path '{0}'", savePath); Manager.TrySetError(Reason.WriteFailure, ex); return; } Manager.SetMetadata(t); _ = Manager.StartAsync(); Manager.RaiseMetadataReceived(rawData); } else { bitField.SetAll(false); } } } RequestNextNeededPiece(id); break; case LTMetadata.MessageType.Reject: //TODO //Think to what we do in this situation //for moment nothing ;) //reject or flood? break; case LTMetadata.MessageType.Request: //ever done in base class but needed to avoid default break; default: throw new MessageException($"Invalid messagetype in LTMetadata: {message.MetadataMessageType}"); } }
internal void RaisePeersFound(NodeId infoHash, IList <PeerInfo> peers) { PeersFound?.Invoke(this, new PeersFoundEventArgs(InfoHash.FromMemory(infoHash.AsMemory()), peers)); }