/// <summary> /// Decode Bencoded torrent file and load internal dictionary from its contents /// for later retrieval by other modules. /// </summary> public void Parse() { try { BNodeBase bNodeRoot = _Bencode.Decode(_metaInfoData); GetStringOrNumeric(bNodeRoot, "announce"); GetListOfStrings(bNodeRoot, "announce-list"); GetStringOrNumeric(bNodeRoot, "comment"); GetStringOrNumeric(bNodeRoot, "created by"); GetStringOrNumeric(bNodeRoot, "creation date"); GetStringOrNumeric(bNodeRoot, "name"); GetStringOrNumeric(bNodeRoot, "piece length"); GetStringOrNumeric(bNodeRoot, "pieces"); GetStringOrNumeric(bNodeRoot, "private"); GetStringOrNumeric(bNodeRoot, "url-list"); if (_Bencode.GetDictionaryEntry(bNodeRoot, "files") == null) { GetStringOrNumeric(bNodeRoot, "length"); GetStringOrNumeric(bNodeRoot, "md5sum"); } else { GetListOfDictionarys(bNodeRoot, "files"); } CalculateInfoHash(bNodeRoot); foreach (var key in metaInfoDict.Keys) { if ((key != "pieces") && (key != "info") && (key != "info hash")) { Log.Logger.Error($"{key}={Encoding.ASCII.GetString(metaInfoDict[key])}"); } } } catch (Exception ex) { Log.Logger.Error(ex); throw new BitTorrentException(ex.Message); } }
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++; } }