public void AddConnection(TorrentConnection connection, TorrentManager manager)
        {
            string remoteId = String.Empty;

            LoggingService.LogDebug("AddConnection(): Start");

            if (!connection.IsIncoming) {
                // Send my identity.
                // XXX: This absolutely needs to be signed.
                connection.Transport.SendMessage(System.Text.Encoding.ASCII.GetBytes(Core.MyNodeID));

                // Get other end's identity.
                byte[] message = connection.Transport.ReceiveMessage();
                remoteId = System.Text.Encoding.ASCII.GetString(message);

            } else {
                // Get other end's identity.
                byte[] message = connection.Transport.ReceiveMessage();
                remoteId = System.Text.Encoding.ASCII.GetString(message);

                // Send my identity.
                // XXX: This absolutely needs to be signed.
                connection.Transport.SendMessage(System.Text.Encoding.ASCII.GetBytes(Core.MyNodeID));
            }

            LoggingService.LogDebug("Pushing connection to engine: {0} - {1}", connection.IsIncoming ? "Incoming" : "Outgoing",
                              ((Meshwork.Transport.TcpTransport)connection.Transport).RemoteEndPoint.ToString());

            Peer p = new Peer("", new Uri(String.Format("meshwork:{0}", remoteId)), EncryptionTypes.PlainText);
            RaiseConnectionReceived(p, connection, manager);

            LoggingService.LogDebug("AddConnection(): End");
        }
 /// <summary>
 ///     Create new instance of PeerConnectionFailedEventArgs for peer from given torrent.
 /// </summary>
 /// <param name="manager"></param>
 /// <param name="peer"></param>
 /// <param name="direction">Which direction the connection attempt was</param>
 /// <param name="message">Message associated with the failure</param>
 public PeerConnectionFailedEventArgs(TorrentManager manager, Peer peer, Direction direction, string message)
     : base(manager)
 {
     Peer = peer;
     ConnectionDirection = direction;
     Message = message;
 }
예제 #3
0
 public AsyncConnectState(TorrentManager manager, Peer peer, IConnection connection, AsyncConnect callback)
 {
     Manager = manager;
     Peer = peer;
     Connection = connection;
     Callback = callback;
 }
 /// <summary>
 ///     Create new instance of PeerConnectionFailedEventArgs for peer from given torrent.
 /// </summary>
 /// <param name="manager"></param>
 /// <param name="peer"></param>
 /// <param name="direction">Which direction the connection attempt was</param>
 /// <param name="message">Message associated with the failure</param>
 public PeerConnectionFailedEventArgs(TorrentManager manager, Peer peer, Direction direction, String message)
     : base(manager)
 {
     this.peer = peer;
     connectionDirection = direction;
     this.message = message;
 }
        private void OnReceiveCallBack(IAsyncResult ar)
        {
            var u = (UdpClient) ar.AsyncState;
            var e = new IPEndPoint(IPAddress.Any, 0);
            try
            {
                var receiveBytes = u.EndReceive(ar, ref e);
                var receiveString = Encoding.ASCII.GetString(receiveBytes);

                var exp =
                    new Regex(
                        "BT-SEARCH \\* HTTP/1.1\\r\\nHost: 239.192.152.143:6771\\r\\nPort: (?<port>[^@]+)\\r\\nInfohash: (?<hash>[^@]+)\\r\\n\\r\\n\\r\\n");
                var match = exp.Match(receiveString);

                if (!match.Success)
                    return;

                var portcheck = Convert.ToInt32(match.Groups["port"].Value);
                if (portcheck < 0 || portcheck > 65535)
                    return;

                TorrentManager manager = null;
                var matchHash = InfoHash.FromHex(match.Groups["hash"].Value);
                for (var i = 0; manager == null && i < engine.Torrents.Count; i ++)
                    if (engine.Torrents[i].InfoHash == matchHash)
                        manager = engine.Torrents[i];

                if (manager == null)
                    return;

                var uri = new Uri("tcp://" + e.Address + ':' + match.Groups["port"].Value);
                var peer = new Peer("", uri, EncryptionTypes.All);

                // Add new peer to matched Torrent
                if (!manager.HasMetadata || !manager.Torrent.IsPrivate)
                {
                    ClientEngine.MainLoop.Queue(delegate
                    {
                        var count = manager.AddPeersCore(peer);
                        manager.RaisePeersFound(new LocalPeersAdded(manager, count, 1));
                    });
                }
            }
            catch
            {
                // Failed to receive data, ignore
            }
            finally
            {
                try
                {
                    u.BeginReceive(OnReceiveCallBack, ar.AsyncState);
                }
                catch
                {
                    // It's closed
                }
            }
        }
 public void AddFailedPeer(Peer p)
 {
     var id = new TrackerConnectionID(this, true, TorrentEvent.None, null);
     var e = new AnnounceResponseEventArgs(this, null, true);
     e.Peers.Add(p);
     e.Successful = false;
     RaiseAnnounceComplete(e);
 }
 public void AddFailedPeer(Peer p)
 {
     var id = new TrackerConnectionID(this, true, TorrentEvent.None, new ManualResetEvent(false));
     var e = new AnnounceResponseEventArgs(this, id, false);
     e.Peers.Add(p);
     RaiseAnnounceComplete(e);
     Assert.True(id.WaitHandle.WaitOne(1000, true), "#2 Tracker never raised the AnnounceComplete event");
 }
예제 #8
0
 public void CompactPeerTest()
 {
     var peerId = "12345abcde12345abcde";
     var uri = new Uri("tcp://192.168.0.5:12345");
     var p = new Peer(peerId, uri);
     var compact = p.CompactPeer();
     var peer = Peer.Decode(compact)[0];
     Assert.Equal(p.ConnectionUri, peer.ConnectionUri);
 }
        public NewConnectionEventArgs(Peer peer, IConnection connection, TorrentManager manager)
            : base(manager)
        {
            if (!connection.IsIncoming && manager == null)
                throw new InvalidOperationException("An outgoing connection must specify the torrent manager it belongs to");

            this.connection = connection;
            this.peer = peer;
        }
예제 #10
0
 public void CompactPeerTest()
 {
     string peerId = "12345abcde12345abcde";
     Uri uri = new Uri("tcp://192.168.0.5:12345");
     Peer p = new Peer(peerId, uri);
     byte[] compact = p.CompactPeer();
     Peer peer = Peer.Decode((BEncoding.BEncodedString)compact)[0];
     Assert.AreEqual(p.ConnectionUri, peer.ConnectionUri);
 }
예제 #11
0
        public bool Equals(Peer other)
        {
            if (other == null)
                return false;

            // FIXME: Don't compare the port, just compare the IP
            if (string.IsNullOrEmpty(PeerId) && string.IsNullOrEmpty(other.PeerId))
                return ConnectionUri.Host.Equals(other.ConnectionUri.Host);

            return PeerId == other.PeerId;
        }
예제 #12
0
        private void EndAccept(IAsyncResult result)
        {
            Socket peerSocket = null;
            try
            {
                Socket listener = (Socket)result.AsyncState;
                peerSocket = listener.EndAccept(result);

                IPEndPoint endpoint = (IPEndPoint)peerSocket.RemoteEndPoint;
                Uri uri = new Uri("tcp://" + endpoint.Address.ToString() + ':' + endpoint.Port);
                Peer peer = new Peer("", uri, EncryptionTypes.All);
                IConnection connection = null;
                if (peerSocket.AddressFamily == AddressFamily.InterNetwork)
                    connection = new IPV4Connection(peerSocket, true);
                else
                    connection = new IPV6Connection(peerSocket, true);


                RaiseConnectionReceived(peer, connection, null);
            }
            catch (SocketException)
            {
                // Just dump the connection
                if (peerSocket != null)
                    peerSocket.Close();
            }
            catch (ObjectDisposedException)
            {
                // We've stopped listening
            }
            finally
            {
                try
                {
                    if (Status == ListenerStatus.Listening)
                        listener.BeginAccept(endAcceptCallback, listener);
                }
                catch (ObjectDisposedException)
                {

                }
            }
        }
예제 #13
0
        internal PeerId(Peer peer, TorrentManager manager)
        {
            if (peer == null)
                throw new ArgumentNullException("peer");

            SuggestedPieces = new MonoTorrentCollection<int>();
            AmChoking = true;
            IsChoking = true;

            IsAllowedFastPieces = new MonoTorrentCollection<int>();
            AmAllowedFastPieces = new MonoTorrentCollection<int>();
            LastMessageReceived = DateTime.Now;
            LastMessageSent = DateTime.Now;
            Peer = peer;
            MaxPendingRequests = 2;
            MaxSupportedPendingRequests = 50;
            Monitor = new ConnectionMonitor();
            sendQueue = new MonoTorrentCollection<PeerMessage>(12);
            ExtensionSupports = new ExtensionSupports();
            TorrentManager = manager;
            InitializeTyrant();
        }
예제 #14
0
파일: Mode.cs 프로젝트: Ilyatk/monotorrent
        void DownloadLogic(int counter)
        {
            // FIXME: Hardcoded 15kB/sec - is this ok?
            if ((DateTime.Now - manager.StartTime) > TimeSpan.FromSeconds(20))
            {
                foreach (string s in manager.Torrent.GetRightHttpSeeds)
                {
                    string peerId = "-WebSeed-";
                    peerId = peerId + (webseedCount++).ToString().PadLeft(20 - peerId.Length, '0');

                    Uri uri = new Uri(s);
                    // HACK: Don't want to add more than 10 same webseed (sometimes webseeds stuck)
                    if (manager.Peers.ConnectedPeers.FindAll(p => p.Uri.Host.Equals(uri.Host)).Count > 9)
                    {
                        continue;
                    }

                    // Dont' want to add more than 2 same webseed if current webseeds is active (speed more than 5Kbs.
                    if (manager.Peers.ConnectedPeers.FindAll(p => p.Uri.Host.Equals(uri.Host)
                                                            && p.Monitor.DownloadSpeed > 5 * 1024
                                                            ).Count > 1
                        )
                    {
                        continue;
                    }

                    Peer peer = new Peer(peerId, uri);
                    PeerId id = new PeerId(peer, manager);
                    HttpConnection connection = new HttpConnection(new Uri(s));
                    connection.Manager = this.manager;
                    peer.IsSeeder = true;
                    id.BitField.SetAll(true);
                    id.Encryptor = new PlainTextEncryption();
                    id.Decryptor = new PlainTextEncryption();
                    id.IsChoking = false;
                    id.AmInterested = !manager.Complete;
                    id.Connection = connection;
                    id.ClientApp = new Software(id.PeerID);
                    manager.Peers.ConnectedPeers.Add(id);
                    manager.RaisePeerConnected(new PeerConnectionEventArgs(manager, id, Direction.Outgoing));
                    PeerIO.EnqueueReceiveMessage (id.Connection, id.Decryptor, Manager.DownloadLimiter, id.Monitor, id.TorrentManager, id.ConnectionManager.messageReceivedCallback, id);
                }

            }

            // Remove inactive peers we haven't heard from if we're downloading
            if (manager.State == TorrentState.Downloading && manager.lastCalledInactivePeerManager + TimeSpan.FromSeconds(5) < DateTime.Now)
            {
                manager.InactivePeerManager.TimePassed();
                manager.lastCalledInactivePeerManager = DateTime.Now;
            }

            // Now choke/unchoke peers; first instantiate the choke/unchoke manager if we haven't done so already
            if (manager.chokeUnchoker == null)
                manager.chokeUnchoker = new ChokeUnchokeManager(manager, manager.Settings.MinimumTimeBetweenReviews, manager.Settings.PercentOfMaxRateToSkipReview);
            manager.chokeUnchoker.UnchokeReview();
        }
예제 #15
0
        private void DownloadLogic(int counter)
        {
            // This timer thing is retarded. We should be checking if we're already downloading from the webseed.
            if ((DateTime.Now - manager.StartTime) > TimeSpan.FromSeconds(1))
            {
                foreach (string s in manager.Torrent.GetRightHttpSeeds)
                {
                    //if we don't have a webseed, insert it
                    if (!manager.Peers.ConnectedPeers.Any(a => a.Peer.ConnectionUri.Equals(new Uri(s))))
                    {
                        string peerId = "-WebSeed-";
                        peerId = peerId + (webseedCount++).ToString().PadLeft(20 - peerId.Length, '0');

                        var uri = new Uri(s);
                        var peer = new Peer(peerId, uri);
                        var id = new PeerId(peer, manager);
                        var connection = new HttpConnection(new Uri(s));
                        connection.Manager = manager;
                        peer.IsSeeder = true;
                        id.BitField.SetAll(true);
                        id.Encryptor = new PlainTextEncryption();
                        id.Decryptor = new PlainTextEncryption();
                        id.IsChoking = false;
                        id.AmInterested = !manager.Complete;
                        id.Connection = connection;
                        id.ClientApp = new Software(id.PeerID);
                        manager.Peers.ConnectedPeers.Add(id);
                        manager.RaisePeerConnected(new PeerConnectionEventArgs(manager, id, Direction.Outgoing));
                        PeerIO.EnqueueReceiveMessage(id.Connection, id.Decryptor, Manager.DownloadLimiter, id.Monitor, id.TorrentManager,
                            id.ConnectionManager.messageReceivedCallback, id);
                    }
                }
            }

            // Remove inactive peers we haven't heard from if we're downloading
            if (manager.State == TorrentState.Downloading &&
                manager.lastCalledInactivePeerManager + TimeSpan.FromSeconds(5) < DateTime.Now)
            {
                manager.InactivePeerManager.TimePassed();
                manager.lastCalledInactivePeerManager = DateTime.Now;
            }

            // Now choke/unchoke peers; first instantiate the choke/unchoke manager if we haven't done so already
            if (manager.chokeUnchoker == null)
                manager.chokeUnchoker = new ChokeUnchokeManager(manager, manager.Settings.MinimumTimeBetweenReviews,
                    manager.Settings.PercentOfMaxRateToSkipReview);
            manager.chokeUnchoker.UnchokeReview();
        }
예제 #16
0
파일: Mode.cs 프로젝트: remy33/monotorrent
 public virtual bool ShouldConnect(Peer peer)
 {
     return(true);
 }
예제 #17
0
        internal PeerId(Peer peer, TorrentManager manager)
        {
            LastReviewUploadRate = 0;
            LastReviewDownloadRate = 0;
            BytesUploadedAtLastReview = 0;
            BytesDownloadedAtLastReview = 0;
            if (peer == null)
                throw new ArgumentNullException("peer");

            suggestedPieces = new MonoTorrentCollection<int>();
            amChoking = true;
            isChoking = true;

            IsAllowedFastPieces = new MonoTorrentCollection<int>();
            AmAllowedFastPieces = new MonoTorrentCollection<int>();
            lastMessageReceived = DateTime.Now;
            lastMessageSent = DateTime.Now;
            this.peer = peer;
            MaxPendingRequests = 2;
            MaxSupportedPendingRequests = 50;
            monitor = new ConnectionMonitor();
            sendQueue = new MonoTorrentCollection<PeerMessage>(12);
            ExtensionSupports = new ExtensionSupports();
            TorrentManager = manager;
            InitializeTyrant();
        }
예제 #18
0
 public override bool ShouldConnect(Peer peer)
 {
     return !(peer.IsSeeder && Manager.HasMetadata && Manager.Complete);
 }
예제 #19
0
파일: Mode.cs 프로젝트: Cyarix/monotorrent
		public virtual bool ShouldConnect(Peer peer)
        {
            return true;
        }
        internal void ConnectToPeer(TorrentManager manager, Peer peer)
        {
            // Connect to the peer.
            IConnection connection = ConnectionFactory.Create(peer.ConnectionUri);
            if (connection == null)
                return;

            logger.Info("Connecting to {0}", peer);

            peer.LastConnectionAttempt = DateTime.Now;
            AsyncConnectState c = new AsyncConnectState(manager, peer, connection);
            pendingConnects.Add(c);

            manager.Peers.ConnectingToPeers.Add(peer);
            NetworkIO.EnqueueConnect(connection, endCreateConnectionCallback, c);
        }
예제 #21
0
        private void OnReceiveCallBack(IAsyncResult ar)
        {
            UdpClient  u = (UdpClient)ar.AsyncState;
            IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);

            try
            {
                byte[] receiveBytes  = u.EndReceive(ar, ref e);
                string receiveString = Encoding.ASCII.GetString(receiveBytes);

                Regex exp   = new Regex("BT-SEARCH \\* HTTP/1.1\\r\\nHost: 239.192.152.143:6771\\r\\nPort: (?<port>[^@]+)\\r\\nInfohash: (?<hash>[^@]+)\\r\\n\\r\\n\\r\\n");
                Match match = exp.Match(receiveString);

                if (!match.Success)
                {
                    return;
                }

                int portcheck = Convert.ToInt32(match.Groups["port"].Value);
                if (portcheck < 0 || portcheck > 65535)
                {
                    return;
                }

                TorrentManager manager   = null;
                InfoHash       matchHash = InfoHash.FromHex(match.Groups["hash"].Value);
                for (int i = 0; manager == null && i < engine.Torrents.Count; i++)
                {
                    if (engine.Torrents[i].InfoHash == matchHash)
                    {
                        manager = engine.Torrents[i];
                    }
                }

                if (manager == null)
                {
                    return;
                }

                Uri  uri  = new Uri("tcp://" + e.Address.ToString() + ':' + match.Groups["port"].Value);
                Peer peer = new Peer("", uri, EncryptionTypes.All);

                // Add new peer to matched Torrent
                if (!manager.HasMetadata || !manager.Torrent.IsPrivate)
                {
                    ClientEngine.MainLoop.Queue(delegate
                    {
                        int count = manager.AddPeersCore(peer);
                        manager.RaisePeersFound(new LocalPeersAdded(manager, count, 1));
                    });
                }
            }
            catch
            {
                // Failed to receive data, ignore
            }
            finally
            {
                try
                {
                    u.BeginReceive(OnReceiveCallBack, ar.AsyncState);
                }
                catch
                {
                    // It's closed
                }
            }
        }
예제 #22
0
 public AsyncConnectState(TorrentManager manager, Peer peer, IConnection connection)
 {
     Manager = manager;
     Peer = peer;
     Connection = connection;
 }
예제 #23
0
 public void AddPeer(Peer peer)
 {
     peers.Add(peer);
 }
 public AttemptConnectionEventArgs(Peer peer)
 {
     this.peer = peer;
 }
예제 #25
0
 public void Add(TorrentManager manager, IConnection connection)
 {
     MonoTorrent.Client.Peer p = new MonoTorrent.Client.Peer("", new Uri("tcp://12.123.123.1:2342"), EncryptionTypes.All);
     base.RaiseConnectionReceived(p, connection, manager);
 }
예제 #26
0
        internal void ConnectToPeer(TorrentManager manager, Peer peer)
        {
            // Connect to the peer.
            IConnection connection = ConnectionFactory.Create(peer.ConnectionUri);
            if (connection == null)
                return;

            peer.LastConnectionAttempt = DateTime.Now;
            AsyncConnectState c = new AsyncConnectState(manager, peer, connection, endCreateConnectionCallback);

            manager.Peers.ConnectingToPeers.Add(peer);
            NetworkIO.EnqueueConnect(c);

            // Try to connect to another peer
            TryConnect();
        }
예제 #27
0
        public void Add(TorrentManager manager, IConnection connection)
        {
            var p = new Peer("", new Uri("ipv4://12.123.123.1:2342"), EncryptionTypes.All);

            ConnectionReceived?.Invoke(this, new NewConnectionEventArgs(p, connection, manager));
        }
예제 #28
0
        internal PeerId(Peer peer, TorrentManager manager)
        {
            if (peer == null)
                throw new ArgumentNullException("peer");

            this.suggestedPieces = new MonoTorrentCollection<int>();
            this.amChoking = true;
            this.isChoking = true;

            this.isAllowedFastPieces = new MonoTorrentCollection<int>();
            this.amAllowedFastPieces = new MonoTorrentCollection<int>();
            this.lastMessageReceived = DateTime.Now;
            this.lastMessageSent = DateTime.Now;
            this.peer = peer;
            this.monitor = new ConnectionMonitor();
            this.sendQueue = new MonoTorrentCollection<PeerMessage>(12);
            TorrentManager = manager;
            InitializeTyrant();
        }
예제 #29
0
 public void Add(TorrentManager manager, IConnection connection)
 {
     MonoTorrent.Client.Peer p = new MonoTorrent.Client.Peer("", new Uri("tcp://12.123.123.1:2342"), EncryptionTypes.All);
     base.RaiseConnectionReceived(p, connection, manager);
 }
예제 #30
0
 public PeerId CreatePeer(bool processingQueue, bool supportsFastPeer)
 {
     var sb = new StringBuilder();
     for (var i = 0; i < 20; i++)
         sb.Append((char) Random.Next('a', 'z'));
     var peer = new Peer(sb.ToString(), new Uri("tcp://127.0.0.1:" + port++));
     var id = new PeerId(peer, Manager);
     id.SupportsFastPeer = supportsFastPeer;
     id.ProcessingQueue = processingQueue;
     return id;
 }
예제 #31
0
 public override bool ShouldConnect(Peer peer)
 {
     return(!(peer.IsSeeder && Manager.HasMetadata && Manager.Complete));
 }
예제 #32
0
파일: Mode.cs 프로젝트: Cyarix/monotorrent
        void DownloadLogic(int counter)
        {
            // FIXME: Hardcoded 15kB/sec - is this ok?
            if ((DateTime.Now - manager.StartTime) > TimeSpan.FromMinutes(1) && manager.Monitor.DownloadSpeed < 15 * 1024)
            {
                foreach (string s in manager.Torrent.GetRightHttpSeeds)
                {
                    string peerId = "-WebSeed-";
                    peerId = peerId + (webseedCount++).ToString().PadLeft(20 - peerId.Length, '0');

                    Uri uri = new Uri(s);
                    Peer peer = new Peer(peerId, uri);
                    PeerId id = new PeerId(peer, manager);
                    HttpConnection connection = new HttpConnection(new Uri(s));
                    connection.Manager = this.manager;
                    peer.IsSeeder = true;
                    id.BitField.SetAll(true);
                    id.Encryptor = new PlainTextEncryption();
                    id.Decryptor = new PlainTextEncryption();
                    id.IsChoking = false;
					id.AmInterested = !manager.Complete;
                    id.Connection = connection;
					id.ClientApp = new Software(id.PeerID);
                    manager.Peers.ConnectedPeers.Add(id);
					manager.RaisePeerConnected(new PeerConnectionEventArgs(manager, id, Direction.Outgoing));
                    PeerIO.EnqueueReceiveMessage (id.Connection, id.Decryptor, Manager.DownloadLimiter, id.Monitor, id.TorrentManager, id.ConnectionManager.messageReceivedCallback, id);
                }

                // FIXME: In future, don't clear out this list. It may be useful to keep the list of HTTP seeds
                // Add a boolean or something so that we don't add them twice.
                manager.Torrent.GetRightHttpSeeds.Clear();
            }

            // Remove inactive peers we haven't heard from if we're downloading
            if (manager.State == TorrentState.Downloading && manager.lastCalledInactivePeerManager + TimeSpan.FromSeconds(5) < DateTime.Now)
            {
                manager.InactivePeerManager.TimePassed();
                manager.lastCalledInactivePeerManager = DateTime.Now;
            }

            // Now choke/unchoke peers; first instantiate the choke/unchoke manager if we haven't done so already
            if (manager.chokeUnchoker == null)
                manager.chokeUnchoker = new ChokeUnchokeManager(manager, manager.Settings.MinimumTimeBetweenReviews, manager.Settings.PercentOfMaxRateToSkipReview);
            manager.chokeUnchoker.UnchokeReview();
        }
예제 #33
0
파일: Peer.cs 프로젝트: proff/ProffTorrent
        public bool Equals(Peer other)
        {
            if (other == null)
                return false;

            // FIXME: Don't compare the port, just compare the IP
            if (string.IsNullOrEmpty(peerId) && string.IsNullOrEmpty(other.peerId))
                return this.connectionUri.Equals(other.connectionUri);

            return peerId == other.peerId;
        }
        internal bool ShouldBanPeer(Peer peer)
        {
            if (BanPeer == null)
                return false;

            AttemptConnectionEventArgs e = new AttemptConnectionEventArgs(peer);
            BanPeer(this, e);
            return e.BanPeer;
        }
예제 #35
0
 protected virtual void RaiseConnectionReceived(Peer peer, IConnection connection, TorrentManager manager)
 {
     if (ConnectionReceived != null)
         Toolbox.RaiseAsyncEvent(ConnectionReceived, this, new NewConnectionEventArgs(peer, connection, manager));
 }
예제 #36
0
        internal bool Contains(Peer peer)
        {
            foreach (Peer other in AllPeers())
                if (peer.Equals(other))
                    return true;

            return false;
        }
예제 #37
0
 /// <summary>
 /// Creates a new PeersAddedEventArgs
 /// </summary>
 /// <param name="peersAdded">The number of peers just added</param>
 public PeerAddedEventArgs(TorrentManager manager, Peer peerAdded)
     : base(manager)
 {
     this.peer = peerAdded;
 }