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