/// <summary> /// Process any piece requests in buffer and send to remote peer. /// </summary> /// <param name="cancelTask"></param> /// <returns></returns> private void PieceRequestProcessing(CancellationToken cancelTask) { try { Log.Logger.Info("Piece request processing task started..."); while (true) { Peer remotePeer = null; PieceRequest request = pieceRequestQueue.Take(cancelTask); try { Log.Logger.Info($"Piece Reqeuest {request.pieceNumber} {request.blockOffset} {request.blockSize}."); if (_manager.GetPeer(request.infoHash, request.ip, out remotePeer)) { PieceBuffer requestBuffer = GetPieceFromTorrent(remotePeer, request.pieceNumber); byte[] requestBlock = new byte[request.blockSize]; Array.Copy(requestBuffer.Buffer, (Int32)request.blockOffset, requestBlock, 0, (Int32)request.blockSize); PWP.Piece(remotePeer, request.pieceNumber, request.blockOffset, requestBlock); remotePeer.Tc.TotalBytesUploaded += request.blockSize; } } catch (Exception ex) { Log.Logger.Error(ex); // Remote peer most probably closed socket so close connection remotePeer?.Close(); } } } catch (Exception ex) { Log.Logger.Debug(ex); } Log.Logger.Info("Piece request processing task terminated."); }
/// <summary> /// Request piece blocks from passed in peer list. /// </summary> /// <param name="tc"></param> /// <param name="pieceNumber"></param> /// <param name="remotePeers"></param> /// <param name="stopwatch"></param> private bool GetMoreBlocks(TorrentContext tc, UInt32 pieceNumber, Peer[] remotePeers) { bool success = true; tc.assemblyData.guardMutex.WaitOne(); try { UInt32 blockOffset = 0; int currentPeer = 0; tc.assemblyData.currentBlockRequests = 0; foreach (var blockThere in tc.assemblyData.pieceBuffer.BlocksPresent) { if (!blockThere) { PWP.Request(remotePeers[currentPeer], pieceNumber, blockOffset, Math.Min(Constants.BlockSize, tc.GetPieceLength(pieceNumber) - blockOffset)); remotePeers[currentPeer].OutstandingRequestsCount++; if (++tc.assemblyData.currentBlockRequests == _maximumBlockRequests) { break; } currentPeer = (currentPeer + 1) % (int)remotePeers.Length; } blockOffset += Constants.BlockSize; } } catch (Exception ex) { Log.Logger.Error(ex); success = false; } tc.assemblyData.guardMutex.ReleaseMutex(); return(success); }
/// <summary> /// Perform intial handsake with remote peer. /// </summary> /// <param name="manager"></param> public void Handshake(Manager manager) { if (manager is null) { throw new ArgumentNullException(nameof(manager)); } RemotePeerID = PWP.Handshake(this, manager); Connected = true; _network.StartReads(this); PWP.Bitfield(this, Tc.Bitfield); }
private readonly int _maximumBlockRequests; // Maximum requests at a time /// <summary> /// Signal to all peers in swarm that we now have the piece local so /// that they can request it if they need. /// </summary> /// <param name="tc"></param> /// <param name="pieceNumber"></param> private void SignalHaveToSwarm(TorrentContext tc, UInt32 pieceNumber) { foreach (var remotePeer in tc.peerSwarm.Values) { try { PWP.Have(remotePeer, pieceNumber); } catch (Exception ex) { Log.Logger.Error(ex); remotePeer.Close(); } } }
/// <summary> // Wait and process remote peer requests until cancelled. /// </summary> /// <param name="tc"></param> /// <param name="cancelTask"></param> private void ProcessRemotePeerRequests(TorrentContext tc, CancellationToken cancelAssemblerTask) { WaitHandle[] waitHandles = new WaitHandle[] { cancelAssemblerTask.WaitHandle }; foreach (var remotePeer in tc.peerSwarm.Values) { try { PWP.Uninterested(remotePeer); PWP.Unchoke(remotePeer); } catch (Exception ex) { Log.Logger.Error(ex); remotePeer.Close(); } } WaitHandle.WaitAll(waitHandles); }