/// <summary> /// Updates the peer in the tracker database based on the announce parameters /// </summary> /// <param name="par"></param> internal void Update(AnnounceParameters par) { Peer peer; object peerKey = comparer.GetKey(par); if (!peers.TryGetValue(peerKey, out peer)) { peer = new Peer(par, peerKey); Add(peer); } else { Debug.WriteLine(string.Format("Updating: {0} with key {1}", peer.ClientAddress, peerKey)); peer.Update(par); } if (par.Event == TorrentEvent.Completed) { System.Threading.Interlocked.Increment(ref downloaded.number); } else if (par.Event == TorrentEvent.Stopped) { Remove(peer); } tracker.RaisePeerAnnounced(new AnnounceEventArgs(peer, this)); UpdateCounts(); }
public override bool Equals(object obj) { AnnounceParameters other = obj as AnnounceParameters; return(other == null ? false : other.clientAddress.Equals(clientAddress) && other.Port.Equals(Port)); }
/// <summary> /// Gets the peers from DHT and generates AnnounceParameters of a list of /// peers and puts the peer info of this announcing peer to DHT /// </summary> /// <param name="parameters"> /// AnnounceParameters from the requesting client. It's modified in method. /// </param> internal void HandleAnnounceRequest(AnnounceParameters parameters) { IEnumerable<PeerEntry> entries = _proxy.GetPeers(parameters.InfoHash.ToArray()); foreach (PeerEntry entry in entries) { AnnounceParameters par = GenerateAnnounceParameters( parameters.InfoHash.ToArray(), entry); if (par.IsValid) { // Tracker will write to the par.Response but we don't use it // ListenerBase.Handle use par.ClientAddress to generate // AnnounceParameters again. Handle(par.Parameters, par.ClientAddress.Address, false); } else { Logger.WriteLineIf(LogLevel.Error, _log_props, string.Format( "Parameters invalid!")); continue; } //Logger.WriteLineIf(LogLevel.Verbose, _log_props, // string.Format("Tracker's response for this peer {0} from DHT: {1}", // par.ClientAddress, par.Response.ToString())); } // Got all I need, now announce myself to DHT. try { _proxy.AnnouncePeer(parameters.InfoHash.ToArray(), parameters); } catch (Exception ex) { // It is OK to temporarily unable to announce to Dht. We can try the next time. Logger.WriteLineIf(LogLevel.Error, _log_props, string.Format( "Unable to reach Dht. We can try the next time.\n{0}", ex)); } Logger.WriteLineIf(LogLevel.Info, _log_props, string.Format("DhtListener finished handling annoucement from {0}", parameters.RemoteAddress)); }
private void ListenerReceivedAnnounce(object sender, AnnounceParameters e) { if (disposed) { e.Response.Add(RequestParameters.FailureKey, (BEncodedString)"The tracker has been shut down"); return; } monitor.AnnounceReceived(); SimpleTorrentManager manager; // Check to see if we're monitoring the requested torrent lock (torrents) { if (!torrents.TryGetValue(e.InfoHash, out manager)) { if (AllowUnregisteredTorrents) { Add(new InfoHashTrackable(BitConverter.ToString(e.InfoHash.Hash), e.InfoHash)); manager = torrents[e.InfoHash]; } else { e.Response.Add(RequestParameters.FailureKey, (BEncodedString)"The requested torrent is not registered with this tracker"); return; } } } // If a non-compact response is expected and we do not allow non-compact responses // bail out if (!AllowNonCompact && !e.HasRequestedCompact) { e.Response.Add(RequestParameters.FailureKey, (BEncodedString)"This tracker does not support non-compact responses"); return; } lock (manager) { // Update the tracker with the peers information. This adds the peer to the tracker, // updates it's information or removes it depending on the context manager.Update(e); // Clear any peers who haven't announced within the allowed timespan and may be inactive manager.ClearZombiePeers(DateTime.Now.Add(-TimeoutInterval)); // Fulfill the announce request manager.GetPeers(e.Response, e.NumberWanted, e.HasRequestedCompact); } e.Response.Add(Tracker.IntervalKey, new BEncodedNumber((int)AnnounceInterval.TotalSeconds)); e.Response.Add(Tracker.MinIntervalKey, new BEncodedNumber((int)MinAnnounceInterval.TotalSeconds)); e.Response.Add(Tracker.TrackerIdKey, trackerId); // FIXME: Is this right? e.Response.Add(Tracker.CompleteKey, new BEncodedNumber(manager.Complete)); e.Response.Add(Tracker.Incomplete, new BEncodedNumber(manager.Incomplete)); //FIXME is this the right behaivour //if (par.TrackerId == null) // par.TrackerId = "monotorrent-tracker"; }
/// <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); }
/** * This initializes the PeerEntry to be stored in Dht * @param pars */ public PeerEntry(AnnounceParameters pars) { /* * The ClientAddress here could be ["ip"] in the args of GET request * or, if it is null, the remote endpoint IP of the request. * Don't use pars.RemoteAddress */ this._peer_endpoint = pars.ClientAddress; this._peer_id = pars.PeerId; this._event = pars.Event; }
public async Task MultipleAnnounce() { Random r = new Random(); for (int i = 0; i < 20; i++) { InfoHash infoHash = new InfoHash(new byte[20]); r.NextBytes(infoHash.Hash); TrackerTier tier = new TrackerTier(new[] { uri.ToString() }); var parameters = new AnnounceParameters(0, 0, 0, TorrentEvent.Started, infoHash, false, new string ('1', 20), "", 1411, false); await tier.Trackers[0].AnnounceAsync(parameters); } }
internal void Update(AnnounceParameters parameters) { DateTime now = DateTime.Now; double elapsedTime = (now - lastAnnounceTime).TotalSeconds; if (elapsedTime < 1) { elapsedTime = 1; } clientAddress = parameters.ClientAddress; downloadSpeed = (int)((parameters.Downloaded - downloaded) / elapsedTime); uploadSpeed = (int)((parameters.Uploaded - uploaded) / elapsedTime); downloaded = parameters.Downloaded; uploaded = parameters.Uploaded; left = parameters.Left; peerId = parameters.PeerId; lastAnnounceTime = now; }
/// <summary> /// Updates the peer in the tracker database based on the announce parameters /// </summary> /// <param name="par"></param> internal void Update(AnnounceParameters par) { Peer peer; object peerKey = comparer.GetKey(par); if (!peers.TryGetValue(peerKey, out peer)) { peer = new Peer(par, peerKey); Add(peer); } else { Debug.WriteLine(string.Format("Updating: {0} with key {1}", peer.ClientAddress, peerKey)); peer.Update(par); } if (par.Event == TorrentEvent.Completed) System.Threading.Interlocked.Increment(ref downloaded.number); else if (par.Event == TorrentEvent.Stopped) Remove(peer); tracker.RaisePeerAnnounced(new AnnounceEventArgs(peer, this)); UpdateCounts(); }
/// <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> /// Listens to event fired by HttpListener and delegates the handling /// process to DhtListener where a list of peers are retrieved. /// </summary> private void OnAnnounceReceived(object sender, AnnounceParameters e) { Logger.WriteLineIf(LogLevel.Verbose, _log_props, string.Format("Annoucement received from {0}", e.RemoteAddress)); try { _dictListener.HandleAnnounceRequest(e); } catch (Exception ex) { Logger.WriteLineIf(LogLevel.Error, _log_props, string.Format("Exception caught while processing announce request. {0}", ex)); throw; } }
public object GetKey(AnnounceParameters parameters) { return parameters.Uploaded; }
public object GetKey(AnnounceParameters parameters) { return(parameters.Uploaded); }
public object GetKey(AnnounceParameters parameters) { return(parameters.ClientAddress); }
internal Peer(AnnounceParameters par, object dictionaryKey) { this.dictionaryKey = dictionaryKey; Update(par); }
public object GetKey(AnnounceParameters parameters) { return parameters.ClientAddress.Address; }