} // Torrent file name /// <summary> /// Get a list of dictionaries from metainfo file that have been come under the main level dictionary /// key of "files". The output being a entry in the internal dictionary that contains a comma /// separated string of the fields (name, length, md5sum) for each list entry (file). Each file found is /// stored under the numeric key value representing the number of the dictionary within the list /// (ie. "0", "1"..... "N"). /// </summary> /// <param name="bNodeRoot">BNode root of list.</param> /// <param name="field">Field.</param> private void GetListOfDictionarys(BNodeBase bNodeRoot, string field) { BNodeBase fieldBytes = _Bencode.GetDictionaryEntry(bNodeRoot, field); if (fieldBytes is BNodeList bNodeList) { int fileNo = 0; foreach (var listItem in (bNodeList).list) { if (listItem is BNodeDictionary bNodeDictionary) { BNodeBase fileDictionaryItem = (bNodeDictionary); BNodeBase fileField = null; string fileEntry = String.Empty; fileField = _Bencode.GetDictionaryEntry(fileDictionaryItem, "path"); if (fileField != null) { string path = string.Empty; foreach (var file in ((BNodeList)(fileField)).list) { path += $"{Path.DirectorySeparatorChar}" + Encoding.ASCII.GetString(((BitTorrentLibrary.BNodeString)file).str); } fileEntry = path; } fileEntry += ","; fileEntry += _Bencode.GetDictionaryEntryString(fileDictionaryItem, "length"); fileEntry += ","; fileEntry += _Bencode.GetDictionaryEntryString(fileDictionaryItem, "md5string"); metaInfoDict[fileNo.ToString()] = Encoding.ASCII.GetBytes(fileEntry); fileNo++; } } } }
private readonly Bencode _Bencode; // Bencode encode/decode /// <summary> /// Decodes the announce request BEncoded response recieved from a tracker. /// </summary> /// <param name="announceResponse">Announce response.</param> /// <param name="decodedResponse">Response.</param> private void DecodeAnnounceResponse(Tracker tracker, byte[] announceResponse, ref AnnounceResponse decodedResponse) { if (announceResponse.Length != 0) { BNodeBase decodedAnnounce = _Bencode.Decode(announceResponse); decodedResponse.statusMessage = _Bencode.GetDictionaryEntryString(decodedAnnounce, "failure reason"); if (decodedResponse.statusMessage != "") { decodedResponse.failure = true; return; // If failure present then ignore rest of reply. } int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "complete"), out decodedResponse.complete); int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "incomplete"), out decodedResponse.incomplete); BNodeBase field = _Bencode.GetDictionaryEntry(decodedAnnounce, "peers"); if (field != null) { decodedResponse.peerList = new List <PeerDetails>(); if (field is BNodeString bNodeString) // Compact peer list reply { decodedResponse.peerList = tracker.GetCompactPeerList((bNodeString).str, 0); } else if (field is BNodeList bNodeList) // Non-compact peer list reply { foreach (var listItem in (bNodeList).list) { if (listItem is BNodeDictionary bNodeDictionary) { PeerDetails peer = new PeerDetails { infoHash = tracker.InfoHash }; BNodeBase peerDictionaryItem = (bNodeDictionary); BNodeBase peerField = _Bencode.GetDictionaryEntry(peerDictionaryItem, "ip"); if (peerField != null) { peer.ip = Encoding.ASCII.GetString(((BitTorrentLibrary.BNodeString)peerField).str); } if (peer.ip.Contains(":")) { peer.ip = peer.ip.Substring(peer.ip.LastIndexOf(":", StringComparison.Ordinal) + 1); } peerField = _Bencode.GetDictionaryEntry(peerDictionaryItem, "port"); if (peerField != null) { peer.port = int.Parse(Encoding.ASCII.GetString(((BitTorrentLibrary.BNodeNumber)peerField).number)); } if (peer.ip != tracker.Ip) // Ignore self in peers list { Log.Logger.Trace($"(Tracker) Peer {peer.ip} Port {peer.port} found."); decodedResponse.peerList.Add(peer); } } } } } int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "interval"), out decodedResponse.interval); int.TryParse(_Bencode.GetDictionaryEntryString(decodedAnnounce, "min interval"), out decodedResponse.minInterval); decodedResponse.trackerID = _Bencode.GetDictionaryEntryString(decodedAnnounce, "tracker id"); decodedResponse.statusMessage = _Bencode.GetDictionaryEntryString(decodedAnnounce, "warning message"); decodedResponse.announceCount++; } }