/// <summary> /// Start requesting pieces /// </summary> public void Start(bool stopAfterFinish = true) { AnnounceManager.Start(); if (stopAfterFinish) { PiecePicker.Finished += Stop; } PiecePicker.Start(); }
/// <summary> /// Gracefully shutdown the client /// </summary> public void Stop() { AnnounceManager.Stop(); PiecePicker.Stop(); PieceStorage.Dispose(); }
/// <summary> /// Creates new BtClient /// </summary> /// <param name="meta">Torrent metainfo</param> /// <param name="clientEndPoint">Client's external network endpoint. Must be accessible by other peers</param> /// <param name="defaultEncoding">Message text encoding</param> /// <param name="output">Output stream. If torrent contains multiple files </param> /// <param name="blockLen">Piece block length in bytes. 10^14 bytes if not specified</param> /// <param name="fileName">File name to download. If not specified all files will be downloaded</param> /// <param name="dhtEndPoint">Mainline DHT's client endpoint. DHT will not be used if parameter is null</param> /// <param name="storage">Storage for caching pieces. If not specified MemCachedPieceStorage will be used</param> /// <param name="cancelToken">Requesting cancel on this CancellationToken causes forcefull shutdown of client</param> public BtClient(Metainfo meta, IPEndPoint clientEndPoint, Encoding defaultEncoding, Stream output, int blockLen = 16384, string fileName = null, PiecePickStrategy piecePickStrategy = PiecePickStrategy.RarestFirst, IPEndPoint dhtEndPoint = null, IPieceStorage storage = null, CancellationToken?cancelToken = null) { Metainfo = meta; _endPoint = clientEndPoint; DefaultEncoding = defaultEncoding; _peerId = GeneratePeerId(); Handshake = CalcHandshake(); BlockLength = blockLen; BlocksInPieceCount = Metainfo.PieceLength / BlockLength; AnnounceManager = new AnnounceManager(this, Metainfo.Announces); IResourcePool <Peers.Peer> peersPool = AnnounceManager; if (dhtEndPoint != null) { MainlineManager = new MainlineManagerExt(clientEndPoint, dhtEndPoint, meta.InfoHash); peersPool = new MergedPool <Peer>(new IResourcePool <Peer>[] { AnnounceManager, MainlineManager }); } if (storage == null) { storage = new FileStorage(Metainfo, BlockLength); } PieceStorage = storage; BitField piecesHave = PieceStorage.GetValidPieces(); IRequestStrategy rqStrat = null; switch (piecePickStrategy) { case PiecePickStrategy.RarestFirst: RarestFirstRqStrategy rarestFirstRqStrategy = new RarestFirstRqStrategy(Metainfo.PiecesCount, piecesHave); rqStrat = rarestFirstRqStrategy; PeerStateCache = new PeerStateCache(rarestFirstRqStrategy); break; case PiecePickStrategy.Random: rqStrat = new RandomPieceRqStrategy(Metainfo.PiecesCount, piecesHave); break; case PiecePickStrategy.Sequential: rqStrat = new SequentialPieceRqStrategy(Metainfo.PiecesCount); break; case PiecePickStrategy.SequentialOneFile: if (string.IsNullOrEmpty(fileName)) { throw new ArgumentException("fileName"); } rqStrat = new SequentialPieceRqStrategyOneFile(Metainfo, fileName); break; default: break; } if (PeerStateCache == null) { PeerStateCache = new PeerStateCache(); } ConnectionManager = new ConnectionHub(this, clientEndPoint, peersPool, PeerStateCache); HandlerExchange = new HandlerExchange(ConnectionManager, PeerStateCache); PiecePicker = new PiecePicker(this, HandlerExchange, rqStrat, BlockLength, cancelToken); }
private void StartActions() { stop = false; stopping = false; Running = true; tracker = new TrackerClient(Data.Announces); statsReportTimer = new Timer(o => OnStatsReport()); //таймер за отчитане на състоянието monitor = new TransferMonitor(Data.InfoHash, Data.TotalLength); AnnounceManager = new AnnounceManager(Data.Announces, monitor, Data); AnnounceManager.PeersReceived += (sender, args) => { if (Mode != null) Mode.AddEndpoints(args.Value); }; }