Пример #1
0
        private static bool ReadQuery(ref string name, BinaryReaderExt reader, MD5 md5, MemoryStream stream)
        {
            if (!reader.TryRead(out name))
            {
                return(false);
            }

            if (!IsMessageAuthentic(md5, stream, reader))
            {
                name = null;
                return(false);
            }

            return(true);
        }
Пример #2
0
        public static bool TryRead(byte[] message, out string token, out string name, out IPEndPoint endPoint,
                                   out byte[] payload)
        {
            token    = null;
            name     = null;
            endPoint = null;
            payload  = null;
            if (message.Length == 0)
            {
                return(false);
            }

            using (var md5 = MD5.Create())
                using (var stream = new MemoryStream(message))
                    using (var reader = new BinaryReaderExt(stream))
                    {
                        if (!reader.TryRead(out token))
                        {
                            return(false);
                        }

                        if (token == P2PQueryToken)
                        {
                            return(ReadQuery(ref name, reader, md5, stream));
                        }
                        if (token == P2PResponse2Token)
                        {
                            return(ReadResponse2(ref name, ref endPoint, ref payload, reader, md5, stream));
                        }
                        if (token == P2PResponseLegacyToken)
                        {
                            return(ReadLegacyResponse(ref name, ref endPoint, reader, md5, stream));
                        }

                        return(false);
                    }
        }
Пример #3
0
        private static bool ReadLegacyResponse(ref string name, ref IPEndPoint endPoint, BinaryReaderExt reader, MD5 md5,
                                               MemoryStream stream)
        {
            if (!reader.TryRead(out name))
            {
                return(false);
            }

            if (!reader.TryRead(out endPoint))
            {
                return(false);
            }

            if (!IsMessageAuthentic(md5, stream, reader))
            {
                name     = null;
                endPoint = null;
                return(false);
            }

            return(true);
        }
Пример #4
0
        private static bool ReadResponse2(ref string name, ref IPEndPoint endPoint, ref byte[] payload,
                                          BinaryReaderExt reader, MD5 md5, MemoryStream stream)
        {
            // This code is intended to be forwards compatible.
            // This means that it needs to be able to deal with content types which
            // it does simply not know (yet). Obviously such content would not
            // be decoded, however it is super important that we do not discard future
            // responses just because we calculated the hash wrong.
            // For this reason, we include the total message length here, so that even if we
            // do not know the additional content, we include it in our hash code calculation.
            var    contentLengthStart = (int)stream.Position;
            ushort contentLength;

            if (!reader.TryRead(out contentLength))
            {
                return(false);
            }

            if (reader.BytesLeft < contentLength)
            {
                return(false);
            }

            var hashStart = (int)reader.BaseStream.Position;
            var hash      = reader.ReadBytes(count: 16);
            var content   = (MessageContent)reader.ReadInt32();

            if ((content & MessageContent.Name) == MessageContent.Name)
            {
                if (!reader.TryRead(out name))
                {
                    return(false);
                }
            }
            if ((content & MessageContent.EndPoint) == MessageContent.EndPoint)
            {
                if (!reader.TryRead(out endPoint))
                {
                    return(false);
                }
            }
            if ((content & MessageContent.Payload) == MessageContent.Payload)
            {
                int payloadLength = reader.ReadUInt16();
                payload = reader.ReadBytes(payloadLength);
            }

            // We need to black out the actual hash to 0 before
            // we compute the hash of the received content
            stream.Position = hashStart;
            for (var i = 0; i < 16; ++i)
            {
                stream.WriteByte(value: 0);
            }
            var actualHash = md5.ComputeHash(stream.ToArray(), contentLengthStart, contentLength + 2);

            if (!AreHashesEqual(hash, actualHash))
            {
                return(false);
            }

            return(true);
        }