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(); }
/// <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; } }
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); }
// 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); } }
// 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 }); } }
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); }
// 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 ); } }
// 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 } ); } }
/// <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"); } }
/// <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"); } } }