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);
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        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)
 {
 }
Beispiel #7
0
 public PeerEventDataWrapper(PeerEventData eventData, byte[] unusedBytes)
 {
     EventData   = eventData;
     UnusedBytes = unusedBytes;
 }