private void MessageRecieved(PeerMessage msg, PeerConnection connection) { // if msg == null, close the connection and remove it from the list if (msg == null) { // message handler's loop stops only when the program is closing // this means calling "Stop" on DownloadingFile, that means // sending "CloseConnection" message to the Pump for EVERY connection // so if it's stopped, the connection is waiting to be closed, and no more // messages can be received if (!messageHandler.isStopped) { messageHandler.AddTask(new CommandMessage(ControlMessageType.CloseConnection, this, connection)); } } else { if (!messageHandler.isStopped) { msg.targetConnection = connection; msg.targetFile = this; messageHandler.AddTask(msg); } } }
private void ConnectionTimeOut(PeerConnection connection) { if (!messageHandler.isStopped) { var msg = new PeerMessage(PeerMessageType.keepAlive); msg.targetConnection = connection; msg.targetFile = this; messageHandler.AddTask(new CommandMessage(ControlMessageType.SendInner, msg)); } }
private async Task ConnectToPeersAsync() { foreach (var peer in peersAddr) { if (connectionsCancellationToken.IsCancellationRequested) { break; } var connection = new PeerConnection(peer, MessageRecieved, pieces.Count, torrentContents.OriginalInfoHashBytes, ConnectionTimeOut); try { if (await connection.PeerHandshakeAsync(torrentContents.OriginalInfoHashBytes, ownerForm.myPeerID, connectionsCancellationToken).ConfigureAwait(false) == 0) { lock (connectedPeers) { connectedPeers.AddLast(connection); } if (downloaded == 0) { // nothing to send, so count it as sent connection.bitfieldSent = true; } else { PeerMessage message; lock (pieces) { // copy here for no race-conditions // peer will receive either a complete BitField or a subsequent "have"(-s) message = new PeerMessage(new BitArray(pieces)); } message.targetConnection = connection; message.targetFile = this; messageHandler.AddTask(new CommandMessage(ControlMessageType.SendInner, message)); } ownerForm.PeerConnectedDisconnectedEvent(this, connectedPeers.Count); connection.StartPeerMessageLoop(); } else { connection.CloseConnection(); } } catch { connection.CloseConnection(); } } connectionsSemaphore.Release(); }
public void SetBitField(PeerMessage message) { for (int i = message.rawBytesOffset; i < message.GetMsgContents().Length; i++) { byte mask = 0b10000000; byte curByte = message.GetMsgContents()[i]; for (int bit = 7; bit >= 0; bit--) { if ((i - message.rawBytesOffset) * 8 + (7 - bit) >= peersPieces.Count) { break; } peersPieces.Set((i - message.rawBytesOffset) * 8 + (7 - bit), (curByte & mask) != 0); mask >>= 1; } } }
private void SendBroadcastHave(int pieceIndex) { // copy the list here for not locking it for too long List <PeerConnection> localCopy; lock (connectedPeers) { localCopy = new List <PeerConnection>(connectedPeers); } for (int i = 0; i < localCopy.Count; i++) { var msg = new PeerMessage(pieceIndex); msg.targetFile = this; msg.targetConnection = localCopy[i]; messageHandler.AddTask(new CommandMessage(ControlMessageType.SendInner, msg)); } localCopy.Clear(); }
public async Task <int> PeerHandshakeAsync(byte[] infoHash, string peerID, CancellationTokenSource cancellationToken) { await connectionClient.ConnectAsync(endPoint.Address, endPoint.Port).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return(-1); } var handshakeMessage = new PeerMessage(infoHash, peerID); await connectionClient.GetStream().WriteAsync(handshakeMessage.GetMsgContents(), 0, handshakeMessage.GetMsgContents().Length, cancellationToken.Token).ConfigureAwait(false); var message = await RecieveHandshakeMessageAsync(cancellationToken).ConfigureAwait(false); if (message == null || message.messageType != PeerMessageType.handshake) { return(-1); } // setting the timer for two minutes activityTimer = new Timer(TimerCallback, null, TIMEOUT * 1000, TIMEOUT * 1000); return(0); }
public void SendPeerMessage(PeerMessage message) { ResetTimer(); connectionClient.GetStream().Write(message.GetMsgContents(), 0, message.GetMsgContents().Length); }
private void ConnectionStateChanged(PeerMessage message) { bool interestingPieces = message.targetFile.PeerHasInterestingPieces(message.targetConnection); if (message.targetConnection.connectionState.HasFlag(CONNSTATES.PEER_CHOKING)) { if (message.targetConnection.connectionState.HasFlag(CONNSTATES.AM_INTERESTED)) { if (!interestingPieces) { try { message.targetConnection.SendPeerMessage(new PeerMessage(PeerMessageType.notInterested)); message.targetConnection.SetAmNotInterested(); } catch { message.targetConnection.CloseConnection(); message.targetFile.RemoveConnection(message.targetConnection); } } } else { if (interestingPieces) { try { message.targetConnection.SendPeerMessage(new PeerMessage(PeerMessageType.interested)); message.targetConnection.SetAmInterested(); } catch { message.targetConnection.CloseConnection(); message.targetFile.RemoveConnection(message.targetConnection); } } } } else { if (!interestingPieces && message.targetConnection.outgoingRequestsCount == 0) { try { message.targetConnection.SendPeerMessage(new PeerMessage(PeerMessageType.notInterested)); message.targetConnection.SetAmNotInterested(); } catch { message.targetConnection.CloseConnection(); message.targetFile.RemoveConnection(message.targetConnection); } } else if (interestingPieces && message.targetConnection.outgoingRequestsCount < message.targetConnection.maxPendingOutgoingRequestsCount) { Tuple <int, int, int> nextRequest = message.targetFile.FindNextRequest(message.targetConnection); // <= because last ++ (if nextRequest is not null) occured in FindNextRequest, so we need to send // this newly added request while (nextRequest != null && message.targetConnection.outgoingRequestsCount <= message.targetConnection.maxPendingOutgoingRequestsCount) { try { message.targetConnection.AddOutgoingRequest(nextRequest.Item1, nextRequest.Item2); message.targetConnection.SendPeerMessage(new PeerMessage(PeerMessageType.request, nextRequest.Item1, nextRequest.Item2, nextRequest.Item3)); } catch { message.targetConnection.CloseConnection(); message.targetFile.RemoveConnection(message.targetConnection); break; } if (message.targetConnection.outgoingRequestsCount < message.targetConnection.maxPendingOutgoingRequestsCount) { nextRequest = message.targetFile.FindNextRequest(message.targetConnection); } else { nextRequest = null; } } } } }