/// <summary> /// Perform an HTTP announce request to tracker and return any response. /// </summary> /// <param name="tracker"></param> /// <returns>Announce response.</returns> public AnnounceResponse Announce(Tracker tracker) { Tracker.LogAnnouce(tracker); AnnounceResponse response = new AnnounceResponse(); try { _web.SetURL(BuildAnnouceURL(tracker)); if (_web.Get()) { DecodeAnnounceResponse(tracker, _web.ResponseData, ref response); } else { throw new BitTorrentException(_web.StatusDescription); } } catch (Exception ex) { Log.Logger.Error(ex); throw; } return(response); }
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++; } }