/// <summary> /// Generates the AnnounceParameters from PeerEntry /// </summary> private AnnounceParameters GenerateAnnounceParameters(byte[] infoHash, PeerEntry entry) { NameValueCollection c = new NameValueCollection(); // "info_hash", "peer_id", "port", "uploaded(bytes)", "downloaded", "left", "compact" // InfoHash here should be just like what's in HttpRequests c.Add("info_hash", System.Web.HttpUtility.UrlEncode(infoHash)); c.Add("peer_id", entry.PeerID); c.Add("port", entry.PeerPort.ToString()); // Fake the mandatory fields, these are solely used to compute the upload/download speed c.Add("uploaded", "0"); c.Add("downloaded", "0"); c.Add("left", "1000"); c.Add("compact", "1"); // Optional but needs to set for monotorrent tracker if (entry.PeerState != MonoTorrent.Common.TorrentEvent.None) { c.Add("event", entry.PeerEventAsRequestKey); } // NOTE: "ip" is optional and we don't supply it. // AnnounceParameters will set entry.PeerIP as its ClientAddress. AnnounceParameters par = new AnnounceParameters(c, IPAddress.Parse(entry.PeerIP)); return(par); }
/// <summary> /// Announces Peer to DHT with AnnounceParameters infomation. /// </summary> /// <returns>True if successful</returns> public void AnnouncePeer(byte[] infoHash, AnnounceParameters pars) { PeerEntry entry = new PeerEntry(pars); Logger.WriteLineIf(LogLevel.Verbose, _log_props, string.Format("Peer to be announced to DHT:\n{0}", entry.ToString())); AnnouncePeer(infoHash, entry); }
/// <summary> /// Annouces Peer to DHT. /// </summary> public void AnnouncePeer(byte[] infoHash, PeerEntry peer) { // Firing DHT Put byte[] peer_bytes = peer.SerializeTo(); byte[] dictKey = ServiceUtil.GetUrlCompatibleBytes(infoHash); try { _dictSvc.Put(dictKey, peer_bytes); } catch (Exception ex) { Logger.WriteLineIf(LogLevel.Error, _log_props, string.Format("Unable to announce peer to DHT. We can try next time. \n{0}", ex)); return; } Logger.WriteLineIf(LogLevel.Info, _log_props, string.Format("Successfully announced peer to DHT")); }
/// <summary> /// Gets peers from DHT. /// </summary> /// <param name="infoHash">The infoHash of the torrent, used as the name in Dht</param> /// <returns> /// A List of PeerEntries which could have duplicated peers with different /// states. Empty List if no peers for this infoHash or the network communication /// is temporarily down. /// </returns> public IEnumerable <PeerEntry> GetPeers(byte[] infoHash) { Logger.WriteLineIf(LogLevel.Verbose, _log_props, string.Format("Getting peers for infoHash: {0}", ServiceUtil.GetUrlCompatibleString(infoHash))); ICollection <PeerEntry> peers = new List <PeerEntry>(); // Fire DHT Get DictionaryServiceData results; try { byte[] key = ServiceUtil.GetUrlCompatibleBytes(infoHash); results = _dictSvc.Get(key); } catch (DictionaryServiceException ex) { Logger.WriteLineIf(LogLevel.Error, _log_props, string.Format( "Exception caught when retrieving peers. Returning empty peers collection.\n{0}", ex)); // No big deal. We simply wait until the next time to query again. // Return empty collection. return(peers); } Logger.WriteLineIf(LogLevel.Info, _log_props, string.Format("{0} peer(s) retrieved from DHT", results.DataEntries.Length)); int index = 0; foreach (var r in results.DataEntries) { try { PeerEntry entry = (PeerEntry)DictionaryData.CreateDictionaryData(r.Value); Logger.WriteLineIf(LogLevel.Verbose, _log_props, string.Format("Peer entry #{0} built:\n{1}", index++, entry.ToString())); peers.Add(entry); } catch (Exception ex) { Logger.WriteLineIf(LogLevel.Error, _log_props, string.Format( "Error occurred when deserializing result from DHT. Continue to parse next.\n{0}", ex)); // Ignore this entry and continue to parse others. continue; } } return(peers); }
/// <summary> /// Generates the AnnounceParameters from PeerEntry /// </summary> private AnnounceParameters GenerateAnnounceParameters(byte[] infoHash, PeerEntry entry) { NameValueCollection c = new NameValueCollection(); // "info_hash", "peer_id", "port", "uploaded(bytes)", "downloaded", "left", "compact" // InfoHash here should be just like what's in HttpRequests c.Add("info_hash", System.Web.HttpUtility.UrlEncode(infoHash)); c.Add("peer_id", entry.PeerID); c.Add("port", entry.PeerPort.ToString()); // Fake the mandatory fields, these are solely used to compute the upload/download speed c.Add("uploaded", "0"); c.Add("downloaded", "0"); c.Add("left", "1000"); c.Add("compact", "1"); // Optional but needs to set for monotorrent tracker if (entry.PeerState != MonoTorrent.Common.TorrentEvent.None) { c.Add("event", entry.PeerEventAsRequestKey); } // NOTE: "ip" is optional and we don't supply it. // AnnounceParameters will set entry.PeerIP as its ClientAddress. AnnounceParameters par = new AnnounceParameters(c, IPAddress.Parse(entry.PeerIP)); return par; }