private bool ParseBitfield(PeerEventData peerEventData) { var byteBitsList = peerEventData.Payload.Select(b => new BitArray(new byte[] { b })); if (byteBitsList.Count() * 8 < PieceAmount - 1) { return(false); } long pieceIndex = 0; foreach (var byteBits in byteBitsList) { for (int byteIndex = 7; byteIndex >= 0; byteIndex--) { if (pieceIndex >= PieceAmount && byteBits[byteIndex]) //Extra bits must be 0 { return(false); } if (byteBits[byteIndex]) { PieceIndexes.Add(pieceIndex); } pieceIndex++; } } return(true); }
private void HandlePeerEvent(PeerEventData peerEventData) { if (peerEventData.EventStatus == PeerEventStatus.Partial) { return; } if (peerEventData.EventType == PeerEventType.Choke) { PeerChocking = true; } if (peerEventData.EventType == PeerEventType.Unchoke) { PeerChocking = false; } if (peerEventData.EventType == PeerEventType.Piece) { PieceRequestComplete(); } if (peerEventData.EventType == PeerEventType.Bitfield && !ParseBitfield(peerEventData)) { HandleDisconnect("Invalid bitfield sent"); return; } var eventArgs = new PeerEventArgs(peerEventData); PeerEventHandler(this, eventArgs); }
private void HandleDisconnect(string exceptionMessage = null) { var peerEventData = new PeerEventData(PeerEventStatus.Error, PeerEventType.ConnectionClosed, 0, null, exceptionMessage); var eventArgs = new PeerEventArgs(peerEventData); PeerEventHandler(this, eventArgs); }
public PeerEventDataWrapper TryParsePeerEventDataFromByteArray(byte[] byteContent) { if (byteContent.Length == 0) { var peerEventData = new PeerEventData(PeerEventStatus.Error, PeerEventType.ConnectionClosed, 0, null, "0 bytes sent, closed"); return(new PeerEventDataWrapper(peerEventData, new byte[0])); } if (byteContent.Length < 4) { var peerEventData = new PeerEventData(PeerEventStatus.Partial, PeerEventType.Unknown, 0, null); return(new PeerEventDataWrapper(peerEventData, byteContent)); //everything sent is leftover, because it cannot be parsed yet } var length = ParseLength(byteContent); if (length == 0) { var leftovers = byteContent.Skip(4); var peerEventData = new PeerEventData(PeerEventStatus.Ok, PeerEventType.KeepAlive, 0, null); return(new PeerEventDataWrapper(peerEventData, leftovers.ToArray())); //No leftovers } if (byteContent.Length == 4) { var peerEventData = new PeerEventData(PeerEventStatus.Partial, PeerEventType.Unknown, length, null); return(new PeerEventDataWrapper(peerEventData, byteContent)); //everything sent is leftover, because it cannot be parsed yet } var eventType = ParseEventType(byteContent); //Single byte for message ID var payloadBytes = byteContent.Skip(5).ToArray(); if (!Enum.IsDefined(typeof(PeerEventType), eventType)) { //Event types are predefined and known in advance. If message id is not in the known event types //That could mean this implamentation might not support it, some packets might have been lost or the client is incorrect. //Nothing else to do but close the connection, as returning to a good state will be too hard (or impossible) var peerEventData = new PeerEventData(PeerEventStatus.Error, PeerEventType.ConnectionClosed, 0, null, $"Unexpected event type: {(int) eventType}"); return(new PeerEventDataWrapper(peerEventData, new byte[0])); //Excess data is thrown away as the connection will be closed } if (EventTypesWithKnownLength.TryGetValue(eventType, out int expectedLength) && length != expectedLength) { //Length for some event types is known in advance. //A different length on a known event type indicates that some packets might have been lost or the client is incorrect. //Nothing else to do but close the connection, as returning to a good state will be too hard (or impossible) var errorMessage = $"Unexpected length for known event type: Event type: {eventType}, Length: {length}"; var peerEventData = new PeerEventData(PeerEventStatus.Error, PeerEventType.ConnectionClosed, 0, null, errorMessage); return(new PeerEventDataWrapper(peerEventData, new byte[0])); } if (payloadBytes.Length < length - 1) { var peerEventData = new PeerEventData(PeerEventStatus.Partial, eventType, length, null); return(new PeerEventDataWrapper(peerEventData, byteContent)); //everything sent is leftover, because it cannot be parsed yet } //If we got to this point, payload can be parsed return(ParsePeerEvent(length, eventType, payloadBytes)); }
private PeerEventDataWrapper ParsePeerEvent(long length, PeerEventType eventType, byte[] unparsedPayload) { var leftovers = new List <byte>(); var payload = new byte[length - 1]; int index = 0; foreach (var unsortedByte in unparsedPayload) { if (index == length - 1) { leftovers.Add(unsortedByte); continue; } payload[index] = unsortedByte; index++; } var peerEventData = new PeerEventData(PeerEventStatus.Ok, eventType, length, payload); return(new PeerEventDataWrapper(peerEventData, leftovers.ToArray())); }
private void ParseHave(PeerEventData peerEventData) { }
public PeerEventDataWrapper(PeerEventData eventData, byte[] unusedBytes) { EventData = eventData; UnusedBytes = unusedBytes; }