Пример #1
0
        public Peer(MetainfoFile infofile, DownloadFile downloadFile,
                    Sockets.Socket socket, Sockets.NetworkStream netStream, PeerInformation peerInformation)
        {
            this.infofile        = infofile;
            this.downloadFile    = downloadFile;
            this.socket          = socket;
            this.netStream       = netStream;
            this.peerInformation = peerInformation;

            this.piecesDownloaded = new BitField(this.infofile.PieceCount);
            this.peerProtocol.UpThrottle.Start();
            this.peerProtocol.DownThrottle.Start();
        }
Пример #2
0
        /// <summary>
        /// Helper thread method to start the connection to peers
        /// </summary>
        /// <param name="state"></param>
        private void StartPeerConnectionThread(System.IAsyncResult result)
        {
            object[]        objs = (object[])result.AsyncState;
            Sockets.Socket  socket = (Sockets.Socket)objs[0];
            PeerInformation peerinfo = (PeerInformation)objs[1];
            ByteField20     infoDigest = new ByteField20(), peerId = new ByteField20();

            Sockets.NetworkStream netStream;

            try
            {
                socket.EndConnect(result);

                netStream = new Sockets.NetworkStream(socket, true);

                // send handshake info
                PeerProtocol.SendHandshake(netStream, this.infofile.InfoDigest);
                PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);
                PeerProtocol.SendPeerId(netStream, this.mSession.LocalPeerID);

                if (!PeerProtocol.ReceivePeerId(netStream, ref peerId))
                {                 // NAT check
                    socket.Close();
                    return;
                }

                // check info digest matches and we are not attempting to connect to ourself
                if (infoDigest.Equals(this.infofile.InfoDigest) && !peerId.Equals(this.mSession.LocalPeerID))
                {
                    peerinfo.ID = peerId;
                    this.AddPeer(socket, netStream, peerinfo);
                }
                else                 // info digest doesn't match, close the connection
                {
                    socket.Close();
                }
            }
            catch (System.Exception e)
            {
                Config.LogException(e);
                // die if the connection failed
                if (socket != null)
                {
                    socket.Close();
                }
                return;
            }
        }
Пример #3
0
        private void OnAccept(System.IAsyncResult result)
        {
            Sockets.Socket socket;

            try
            {
                // Accept connections from other peers, find the appropriate torrent and add the peer to it
                socket = this.mListener.EndAccept(result);
            }
            catch (System.Exception)
            {
                if (this.mListener != null)
                {
                    this.mListener.Close();
                }
                this.mListener = null;
                return;
            }

            try
            {
                ByteField20           infoDigest = new ByteField20(), peerId = new ByteField20();
                Sockets.NetworkStream netStream = new Sockets.NetworkStream(socket, true);

                PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);

                Torrent torrent = this.FindTorrent(infoDigest);

                if (torrent != null)
                {
                    // found it, finish handshaking and add the peer to the list
                    PeerProtocol.SendHandshake(netStream, torrent.Metainfo.InfoDigest);
                    PeerProtocol.SendPeerId(netStream, mLocalPeerId);

                    if (!PeerProtocol.ReceivePeerId(netStream, ref peerId))
                    {                     // NAT check, discard
                        socket.Close();
                    }
                    else
                    {
                        if (!peerId.Equals(mLocalPeerId))                             // make sure we aren't connecting to ourselves
                        {
                            Net.IPEndPoint  endPoint        = (Net.IPEndPoint)socket.RemoteEndPoint;
                            PeerInformation peerInformation = new PeerInformation(endPoint.Address.ToString(), endPoint.Port, peerId);

                            // add the peer to the torrent
                            torrent.AddPeer(socket, netStream, peerInformation);
                        }
                        else
                        {
                            socket.Close();
                        }
                    }
                }
                else
                {
                    socket.Close();
                }
            }
            catch (System.Exception e)
            {
                Config.LogException(e);
                socket.Close();
            }

            this.mListener.BeginAccept(new System.AsyncCallback(OnAccept), null);
        }
Пример #4
0
		public Peer(MetainfoFile infofile, DownloadFile downloadFile,
			Sockets.Socket socket, Sockets.NetworkStream netStream, PeerInformation peerInformation)
		{
			this.infofile = infofile;
			this.downloadFile = downloadFile;
			this.socket = socket;
			this.netStream = netStream;
			this.peerInformation = peerInformation;

			this.piecesDownloaded = new BitField(this.infofile.PieceCount);
			this.peerProtocol.UpThrottle.Start();
			this.peerProtocol.DownThrottle.Start();
		}
Пример #5
0
        // Called by the Session class for peers connecting through the server and in StartPeerConnectionThread() method for peers
        // connected to directly
        private void AddPeerPrivate(Sockets.Socket socket, Sockets.NetworkStream netStream, PeerInformation peerInformation)
        {
            try
            {
                if (Config.ActiveConfig.MaxPeersConnected < this.mPeers.Count)
                {
                    socket.Close();
                    return;
                }

                bool connect = true;

                if (Config.ActiveConfig.OnlyOneConnectionFromEachIP)
                {
                    foreach (Peer connectedPeer in this.mPeers)
                    {
                        if (connectedPeer.Information.IP.Equals(peerInformation.IP))
                        {
                            connect = false;
                            break;
                        }
                    }
                }

                if (!connect)
                {
                    socket.Close();
                    return;
                }

                if (!this.downloadFile.Bitfield.AllFalse)
                {
                    PeerProtocol.SendBitfieldMessage(netStream, this.downloadFile);
                }

                Peer peer = new Peer(this.infofile, this.downloadFile, socket, netStream, peerInformation);
                peer.Disconnected += new PeerDisconnectedCallback(peer_Disconnected);

                Config.LogDebugMessage("Connection accepted from: " + peer.ToString());

                // add to download and upload manager
                this.mDownloadStrategy.HookPeerEvents(peer);
                this.uploadManager.AddPeer(peer);
                this.peerManager.AddPeer(peer);

                if (this.PeerConnected != null)
                {
                    this.PeerConnected(this, peer, true);
                }

                this.mPeers.Add(peer);
            }
            catch (System.Exception e)
            {
                Config.LogException(e);
            }
        }
Пример #6
0
 // Called by the Session class for peers connecting through the server, adds it to a list which can then be added when
 // ProcessWaitingData() is called so we keep it on one thread
 internal void AddPeer(Sockets.Socket socket, Sockets.NetworkStream netStream, PeerInformation peerInformation)
 {
     lock (mWaitingPeers.SyncRoot)
     {
         mWaitingPeers.Add(new object[] { socket, netStream, peerInformation });
     }
 }
Пример #7
0
		private void OnAccept(System.IAsyncResult result)
		{
			Sockets.Socket socket;

			try
			{
				// Accept connections from other peers, find the appropriate torrent and add the peer to it
				socket = this.mListener.EndAccept(result);
			}
			catch (System.Exception)
			{
				if (this.mListener != null)
					this.mListener.Close();
				this.mListener = null;
				return;
			}

			try
			{
				ByteField20 infoDigest = new ByteField20(), peerId = new ByteField20();
				Sockets.NetworkStream netStream = new Sockets.NetworkStream(socket, true);
				
				PeerProtocol.ReceiveHandshake(netStream, ref infoDigest);

				Torrent torrent = this.FindTorrent(infoDigest);

				if (torrent != null)
				{
					// found it, finish handshaking and add the peer to the list
					PeerProtocol.SendHandshake(netStream, torrent.Metainfo.InfoDigest);
					PeerProtocol.SendPeerId(netStream, mLocalPeerId );

					if ( !PeerProtocol.ReceivePeerId( netStream, ref peerId ))
					{ // NAT check, discard
						socket.Close();
					}
					else
					{
						if ( !peerId.Equals( mLocalPeerId ) ) // make sure we aren't connecting to ourselves
						{
							Net.IPEndPoint endPoint = (Net.IPEndPoint)socket.RemoteEndPoint;
							PeerInformation peerInformation = new PeerInformation( endPoint.Address.ToString(), endPoint.Port, peerId );

							// add the peer to the torrent
							torrent.AddPeer( socket, netStream, peerInformation );
						}
						else
							socket.Close();
					}
				}
				else
					socket.Close();
			}
			catch (System.Exception e)
			{
				Config.LogException( e );
				socket.Close();
			}

			this.mListener.BeginAccept(new System.AsyncCallback(OnAccept), null);
		}
Пример #8
0
		// Called by the Session class for peers connecting through the server and in StartPeerConnectionThread() method for peers
		// connected to directly
		private void AddPeerPrivate(Sockets.Socket socket, Sockets.NetworkStream netStream, PeerInformation peerInformation)
		{
			try
			{
				if ( Config.ActiveConfig.MaxPeersConnected < this.mPeers.Count )
				{
					socket.Close();
					return;
				}

				bool connect = true;

				if (Config.ActiveConfig.OnlyOneConnectionFromEachIP)
				{
					foreach ( Peer connectedPeer in this.mPeers )
					{
						if (connectedPeer.Information.IP.Equals(peerInformation.IP))
						{
							connect = false;
							break;
						}
					}
				}

				if (!connect)
				{
					socket.Close();
					return;
				}

				if (!this.downloadFile.Bitfield.AllFalse)
					PeerProtocol.SendBitfieldMessage(netStream, this.downloadFile);

				Peer peer = new Peer(this.infofile, this.downloadFile, socket, netStream, peerInformation);
				peer.Disconnected += new PeerDisconnectedCallback(peer_Disconnected);

				Config.LogDebugMessage("Connection accepted from: " + peer.ToString());

				// add to download and upload manager
				this.mDownloadStrategy.HookPeerEvents(peer);
				this.uploadManager.AddPeer(peer);
				this.peerManager.AddPeer(peer);

				if (this.PeerConnected != null)
					this.PeerConnected(this, peer, true);

				this.mPeers.Add( peer );
			}
			catch ( System.Exception e )
			{
				Config.LogException( e );
			}
		}
Пример #9
0
		// Called by the Session class for peers connecting through the server, adds it to a list which can then be added when
		// ProcessWaitingData() is called so we keep it on one thread
		internal void AddPeer( Sockets.Socket socket, Sockets.NetworkStream netStream, PeerInformation peerInformation )
		{
			lock ( mWaitingPeers.SyncRoot )
			{
				mWaitingPeers.Add( new object[] { socket, netStream, peerInformation } );
			}
		}
Пример #10
0
		/// <summary>
		/// Parses the response from the tracker, and updates the peer list
		/// </summary>
		/// <param name="stream">IO stream from response</param>
		private void ParseTrackerResponse(IO.Stream stream)
		{
			this.peerList.Clear();
/*
			// because the response stream does not support seeking, we copy the contents to a memorystream
			// to send to the bencoder. This shouldnt cause too much of a performance penalty as it shouldnt
			// be too large anyway.
			byte[] data = new byte[ 1024 ];
			IO.MemoryStream responseStream = new IO.MemoryStream();
			int dataRead = 0;

			while ((dataRead = stream.Read(data, 0, data.Length)) > 0)
			{
				responseStream.Write(data, 0, dataRead);
			}

			responseStream.Seek(0, IO.SeekOrigin.Begin);
*/
			///

			BEncode.Dictionary dic = BEncode.NextDictionary(stream);

			// note: sometimes IPs can be duplicated in quick disconnection, so there is a check for any duplications
			
			if (dic.Contains("failure reason"))
			{
				throw new IO.IOException("Tracker connection failed: " + dic.GetString("failure reason"));
			}
			else
			{
				this.updateInterval = dic.GetInteger("interval");

				BEncode.Element peers = dic["peers"];

				if (peers is BEncode.List)
				{
					// peer list comes as a list of dictionaries
					BEncode.List dicList = (BEncode.List)peers;

					foreach (BEncode.Dictionary dicPeer in dicList)
					{
						ByteField20 peerId = new ByteField20(dicPeer.GetBytes("peer id"));
						string peerIp = dicPeer.GetString("ip");
						int port = dicPeer.GetInteger("port");
						PeerInformation peerinfo = new PeerInformation(peerIp, port, peerId);

						if (!this.peerList.Contains(peerinfo))
							this.peerList.Add(peerinfo);
					}
				}
				else if (peers is BEncode.String)
				{
					// else its compressed (this is pretty common)
					byte[] compactPeers = ((BEncode.String)peers).Data;

					for (int i=0; i<compactPeers.Length; i += 6)
					{
						int	ip1 = 0xFF & compactPeers[i];
						int	ip2 = 0xFF & compactPeers[i+1];
						int	ip3 = 0xFF & compactPeers[i+2];
						int	ip4 = 0xFF & compactPeers[i+3];
						int	po1 = 0xFF & compactPeers[i+4];
						int	po2 = 0xFF & compactPeers[i+5];

						string peerIp = ip1 + "." + ip2 + "." + ip3 + "." + ip4;
						int	port = (po1 * 256) + po2;
						PeerInformation peerinfo = new PeerInformation(peerIp, port);

						if (!this.peerList.Contains(peerinfo))
							this.peerList.Add(peerinfo);
					}
				}
				else
					throw new TrackerException("Unexcepted error");
			}
		}
Пример #11
0
        /// <summary>
        /// Parses the response from the tracker, and updates the peer list
        /// </summary>
        /// <param name="stream">IO stream from response</param>
        private void ParseTrackerResponse(IO.Stream stream)
        {
            this.peerList.Clear();

/*
 *                      // because the response stream does not support seeking, we copy the contents to a memorystream
 *                      // to send to the bencoder. This shouldnt cause too much of a performance penalty as it shouldnt
 *                      // be too large anyway.
 *                      byte[] data = new byte[ 1024 ];
 *                      IO.MemoryStream responseStream = new IO.MemoryStream();
 *                      int dataRead = 0;
 *
 *                      while ((dataRead = stream.Read(data, 0, data.Length)) > 0)
 *                      {
 *                              responseStream.Write(data, 0, dataRead);
 *                      }
 *
 *                      responseStream.Seek(0, IO.SeekOrigin.Begin);
 */
            ///

            BEncode.Dictionary dic = BEncode.NextDictionary(stream);

            // note: sometimes IPs can be duplicated in quick disconnection, so there is a check for any duplications

            if (dic.Contains("failure reason"))
            {
                throw new IO.IOException("Tracker connection failed: " + dic.GetString("failure reason"));
            }
            else
            {
                this.updateInterval = dic.GetInteger("interval");

                BEncode.Element peers = dic["peers"];

                if (peers is BEncode.List)
                {
                    // peer list comes as a list of dictionaries
                    BEncode.List dicList = (BEncode.List)peers;

                    foreach (BEncode.Dictionary dicPeer in dicList)
                    {
                        ByteField20     peerId   = new ByteField20(dicPeer.GetBytes("peer id"));
                        string          peerIp   = dicPeer.GetString("ip");
                        int             port     = dicPeer.GetInteger("port");
                        PeerInformation peerinfo = new PeerInformation(peerIp, port, peerId);

                        if (!this.peerList.Contains(peerinfo))
                        {
                            this.peerList.Add(peerinfo);
                        }
                    }
                }
                else if (peers is BEncode.String)
                {
                    // else its compressed (this is pretty common)
                    byte[] compactPeers = ((BEncode.String)peers).Data;

                    for (int i = 0; i < compactPeers.Length; i += 6)
                    {
                        int ip1 = 0xFF & compactPeers[i];
                        int ip2 = 0xFF & compactPeers[i + 1];
                        int ip3 = 0xFF & compactPeers[i + 2];
                        int ip4 = 0xFF & compactPeers[i + 3];
                        int po1 = 0xFF & compactPeers[i + 4];
                        int po2 = 0xFF & compactPeers[i + 5];

                        string          peerIp   = ip1 + "." + ip2 + "." + ip3 + "." + ip4;
                        int             port     = (po1 * 256) + po2;
                        PeerInformation peerinfo = new PeerInformation(peerIp, port);

                        if (!this.peerList.Contains(peerinfo))
                        {
                            this.peerList.Add(peerinfo);
                        }
                    }
                }
                else
                {
                    throw new TrackerException("Unexcepted error");
                }
            }
        }