/// <summary> /// Checks the send queue of the peer to see if there are any outstanding pieces which they requested /// and rejects them as necessary /// </summary> /// <param name="peer"></param> private void RejectPendingRequests(PeerId peer) { var length = peer.QueueLength; for (var i = 0; i < length; i++) { var message = peer.Dequeue(); if (!(message is PieceMessage)) { peer.Enqueue(message); continue; } var pieceMessage = (PieceMessage)message; // If the peer doesn't support fast peer, then we will never requeue the message if (!(peer.SupportsFastPeer && ClientEngine.SupportsFastPeer)) { peer.IsRequestingPiecesCount--; continue; } // If the peer supports fast peer, queue the message if it is an AllowedFast piece // Otherwise send a reject message for the piece if (peer.AmAllowedFastPieces.Contains(pieceMessage.PieceIndex)) { peer.Enqueue(pieceMessage); } else { peer.IsRequestingPiecesCount--; peer.Enqueue(new RejectRequestMessage(pieceMessage)); } } }
protected virtual void HandleRequestMessage (PeerId id, RequestMessage message) { // If we are not on the last piece and the user requested a stupidly big/small amount of data // we will close the connection if (Manager.Torrent.Pieces.Count != (message.PieceIndex + 1)) if (message.RequestLength > RequestMessage.MaxSize || message.RequestLength < RequestMessage.MinSize) throw new MessageException ( $"Illegal piece request received. Peer requested {message.RequestLength} byte"); var m = new PieceMessage (message.PieceIndex, message.StartOffset, message.RequestLength); // If we're not choking the peer, enqueue the message right away if (!id.AmChoking) { id.IsRequestingPiecesCount++; id.Enqueue (m); } // If the peer supports fast peer and the requested piece is one of the allowed pieces, enqueue it // otherwise send back a reject request message else if (id.SupportsFastPeer && ClientEngine.SupportsFastPeer) { if (id.AmAllowedFastPieces.Contains (message.PieceIndex)) { id.IsRequestingPiecesCount++; id.Enqueue (m); } else id.Enqueue (new RejectRequestMessage (m)); } }
internal void AddPieceRequests(PeerId id) { PeerMessage msg; var maxRequests = id.MaxPendingRequests; if (id.AmRequestingPiecesCount >= maxRequests) { return; } var count = 1; if (id.Connection is HttpConnection) { // How many whole pieces fit into 2MB count = (2 * 1024 * 1024) / id.TorrentManager.Torrent.PieceLength; // Make sure we have at least one whole piece count = Math.Max(count, 1); count *= id.TorrentManager.Torrent.PieceLength / Piece.BlockSize; } if (!id.IsChoking || id.SupportsFastPeer) { while (id.AmRequestingPiecesCount < maxRequests) { msg = Picker.ContinueExistingRequest(id); if (msg != null) { id.Enqueue(msg); } else { break; } } } if (!id.IsChoking || (id.SupportsFastPeer && id.IsAllowedFastPieces.Count > 0)) { while (id.AmRequestingPiecesCount < maxRequests) { msg = Picker.PickPiece(id, id.TorrentManager.Peers.ConnectedPeers, count); if (msg != null) { id.Enqueue(msg); } else { break; } } } }
protected virtual void SetAmInterestedStatus (PeerId id, bool interesting) { if (interesting && !id.AmInterested) { id.AmInterested = true; id.Enqueue (new InterestedMessage ()); // He's interesting, so attempt to queue up any FastPieces (if that's possible) Manager.PieceManager.AddPieceRequests (id); } else if (!interesting && id.AmInterested) { id.AmInterested = false; id.Enqueue (new NotInterestedMessage ()); } }
protected virtual void HandleLtMetadataMessage(PeerId id, LTMetadata message) { if (message.MetadataMessageType == LTMetadata.eMessageType.Request) { if (Manager.HasMetadata) { id.Enqueue(new LTMetadata(id, LTMetadata.eMessageType.Data, message.Piece, Manager.Torrent.Metadata)); } else { id.Enqueue(new LTMetadata(id, LTMetadata.eMessageType.Reject, message.Piece)); } } }
public virtual void Unchoke(PeerId peerToUnchoke) { peerToUnchoke.AmChoking = false; peerToUnchoke.TorrentManager.UploadingTo++; peerToUnchoke.Enqueue(new UnchokeMessage()); peerToUnchoke.LastUnchoked = DateTime.Now; }
protected virtual void HandleCancelMessage (PeerId id, CancelMessage message) { PeerMessage msg; for (int i = 0; i < id.QueueLength; i++) { msg = id.Dequeue (); if (!(msg is PieceMessage)) { id.Enqueue (msg); continue; } var piece = msg as PieceMessage; if (!(piece.PieceIndex == message.PieceIndex && piece.StartOffset == message.StartOffset && piece.RequestLength == message.RequestLength)) { id.Enqueue (msg); } else { id.IsRequestingPiecesCount--; } } }
public virtual void HandlePeerConnected(PeerId id, Direction direction) { var bundle = new MessageBundle(); AppendBitfieldMessage(id, bundle); AppendExtendedHandshake(id, bundle); AppendFastPieces(id, bundle); id.Enqueue(bundle); }
void RequestNextNeededPiece(PeerId id) { int index = bitField.FirstFalse(); if (index == -1) { return;//throw exception or switch to regular? } var m = new LTMetadata(id, LTMetadata.eMessageType.Request, index); id.Enqueue(m); requestTimeout = DateTime.Now.Add(timeout); }
protected virtual void HandleCancelMessage(PeerId id, CancelMessage message) { for (var i = 0; i < id.QueueLength; i++) { var msg = id.Dequeue(); if (!(msg is PieceMessage)) { id.Enqueue(msg); continue; } var piece = msg as PieceMessage; if ( !(piece.PieceIndex == message.PieceIndex && piece.StartOffset == message.StartOffset && piece.RequestLength == message.RequestLength)) { id.Enqueue(msg); } else { id.IsRequestingPiecesCount--; } } for (var i = 0; i < id.PieceReads.Count; i++) { if (id.PieceReads[i].PieceIndex == message.PieceIndex && id.PieceReads[i].StartOffset == message.StartOffset && id.PieceReads[i].RequestLength == message.RequestLength) { id.IsRequestingPiecesCount--; id.PieceReads.RemoveAt(i); break; } } }
public virtual void HandlePeerConnected(PeerId id) { if (CanAcceptConnections) { var bundle = new MessageBundle(); AppendBitfieldMessage(id, bundle); AppendExtendedHandshake(id, bundle); AppendFastPieces(id, bundle); id.Enqueue(bundle); } else { ConnectionManager.CleanupSocket(Manager, id); } }
internal void OnTick() { if (!_id.TorrentManager.Settings.EnablePeerExchange) { return; } var len = (_addedPeers.Count <= MaxPeers) ? _addedPeers.Count : MaxPeers; var added = new byte[len * 6]; var addedDotF = new byte[len]; for (var i = 0; i < len; i++) { _addedPeers[i].CompactPeer(added, i * 6); if ((_addedPeers[i].Encryption & (EncryptionTypes.RC4Full | EncryptionTypes.RC4Header)) != EncryptionTypes.None) { addedDotF[i] = 0x01; } else { addedDotF[i] = 0x00; } addedDotF[i] |= (byte)(_addedPeers[i].IsSeeder ? 0x02 : 0x00); } _addedPeers.RemoveRange(0, len); len = Math.Min(MaxPeers - len, _droppedPeers.Count); var dropped = new byte[len * 6]; for (var i = 0; i < len; i++) { _droppedPeers[i].CompactPeer(dropped, i * 6); } _droppedPeers.RemoveRange(0, len); _id.Enqueue(new PeerExchangeMessage(_id, added, addedDotF, dropped)); }
/// <summary> /// Performs any necessary actions required to process the message /// </summary> /// <param name="id">The Peer who's message will be handled</param> internal override void Handle(PeerId id) { PeerMessage msg; for (int i = 0; i < id.QueueLength; i++) { msg = id.Dequeue(); if (!(msg is PieceMessage)) { id.Enqueue(msg); continue; } PieceMessage piece = msg as PieceMessage; if (!(piece.PieceIndex == this.pieceIndex && piece.StartOffset == this.startOffset && piece.RequestLength == this.requestLength)) { id.Enqueue(msg); } else { id.IsRequestingPiecesCount--; } } }
public virtual void Choke(PeerId id) { id.AmChoking = true; id.TorrentManager.UploadingTo--; id.Enqueue(new ChokeMessage()); }