Inheritance: AbstractPacketBase
示例#1
0
        public void FreshHello()
        {
            var connectionId = 15690248817103694251U;

            var packet = new RegularPacket(connectionId, 1, null);
            Assert.IsNotNull(packet.ConnectionId);
            packet.AddFrame(new StreamFrame(ClientHandshakeMessageTest.ClientInchoateGoogleFreshParametersClientMessageFactory.Value, false, 1, 0));
            var packetBytes = packet.PadAndNullEncrypt();
            Assert.IsNotNull(packet.MessageAuthenticationHash);

            Debug.WriteLine("Message authentication hash: " + packet.MessageAuthenticationHash.Select(b => b.ToString("x2")).Aggregate((c, n) => c + " " + n));
            Debug.WriteLine(packetBytes.GenerateHexDumpWithASCII());

            Assert.AreEqual(PacketLibrary.ClientInchoateGoogleFresh.Length, packetBytes.Length);

            // Soft warn
            for (var i = 0; i < packetBytes.Length; i++)
            {
                if (packetBytes[i] != PacketLibrary.ClientInchoateGoogleFresh[i])
                    Debug.WriteLine($"Byte difference at position {i}: generated byte is {packetBytes[i]:x2} but reference byte was {PacketLibrary.ClientInchoateGoogleFresh[i]:x2}");
            }

            // Hard test fail
            for (var i = 0; i < packetBytes.Length; i++)
                Assert.AreEqual(PacketLibrary.ClientInchoateGoogleFresh[i], packetBytes[i], $"Byte difference at position {i}: generated byte is {packetBytes[i]:x2} but reference byte was {PacketLibrary.ClientInchoateGoogleFresh[i]:x2}");

            // Now try to reverse engineer it to ensure packet parsing works.
            AbstractPacketBase rePacket;
            AbstractPacketBase.TryParse(packetBytes, out rePacket);

            Assert.IsNotNull(rePacket);
            Assert.IsInstanceOfType(rePacket, typeof(RegularPacket));
            var rp = (RegularPacket)rePacket;
            Assert.AreEqual(rp.ConnectionId, packet.ConnectionId.Value);
            Assert.AreEqual(rp.Entropy, packet.Entropy);
            Assert.AreEqual(rp.FecGroup, packet.FecGroup);
            Assert.IsNotNull(rp.MessageAuthenticationHash);
            Assert.AreEqual(rp.MessageAuthenticationHash.Sum(b => (int)b), packet.MessageAuthenticationHash.Sum(b => (int)b));
            Assert.AreEqual(rp.PacketNumber, packet.PacketNumber);

            var rpBytes = rp.ToByteArray();
            //Debug.WriteLine(rpBytes.GenerateHexDumpWithASCII());
            Assert.AreEqual(packetBytes.Length, rpBytes.Length);

            // Soft reverse engineering warn
            for (var i = 0; i < packetBytes.Length; i++)
            {
                if (packetBytes[i] != rpBytes[i])
                    Debug.WriteLine($"Byte difference at position {i}: generated byte is {rpBytes[i]:x2} but reference byte was {packetBytes[i]:x2}");
            }
            
            // Hard test fail
            for (var i = 0; i < packetBytes.Length; i++)
                Assert.AreEqual(packetBytes[i], rpBytes[i], $"Byte difference at position {i}: generated byte is {rpBytes[i]:x2} but reference byte was {packetBytes[i]:x2}");
        }
示例#2
0
        public async Task ConnectAsync(string hostname, int port, CancellationToken cancellationToken = default(CancellationToken))
        {
            this._udpClient = new UdpClient(hostname, port);

            // Start listening
            this._receiveTask = Task.Run(async () =>
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    var received = await this._udpClient.ReceiveAsync();
                    Debug.WriteLine($"Received {received.Buffer.Length} bytes from {received.RemoteEndPoint}");
                }
            }, cancellationToken);

            // Setup default destination of client
            this._udpClient.Connect(hostname, port);


            // Generate random connection ID
            var random = new Random(Environment.TickCount);
            var buffer = new byte[sizeof(long)];
            random.NextBytes(buffer);

            var connectionId = BitConverter.ToUInt64(buffer, 0);
            var regularPacket = new RegularPacket(connectionId, 1, null);
            regularPacket.AddFrame(new StreamFrame(new ClientHandshakeMessage
                                                   {
                                                       { MessageTags.PAD, Enumerable.Repeat((byte)0x2d, 666).ToArray() },
                                                       { MessageTags.SNI, hostname },
                                                       { MessageTags.VER, QUIC_VERSION },
                                                       { MessageTags.CCS, new byte[] { 0x7b, 0x26, 0xe9, 0xe7, 0xe4, 0x5c, 0x71, 0xff, 0x01, 0xe8, 0x81, 0x60, 0x92, 0x92, 0x1a, 0xe8 } },
                                                       { MessageTags.MSPC, 100 },
                                                       { MessageTags.UAID, $"QuicDotNet/{Assembly.GetExecutingAssembly().GetName().Version} {System.Environment.OSVersion}" },
                                                       { MessageTags.TCID, 0 },
                                                       { MessageTags.PDMD, "X509" },
                                                       { MessageTags.SRBF, 1048576 },
                                                       { MessageTags.ICSL, 30 },
                                                       { MessageTags.SCLS, 1 },
                                                       { MessageTags.COPT, 1146636614 },
                                                       { MessageTags.IRTT, 9248 },
                                                       { MessageTags.CFCW, 15728640 },
                                                       { MessageTags.SFCW, 6291456 }
                                                   }, false, 1, 0));

            var bytesToSend = regularPacket.PadAndNullEncrypt();

            await this._udpClient.SendAsync(bytesToSend, bytesToSend.Length);
        }
示例#3
0
        public static bool TryParse(byte[] packetBytes, out AbstractPacketBase packet)
        {
            var publicFlags = packetBytes[0];
            var index       = 1;
            var versionFlag = (publicFlags & (1 << 0)) != 0;
            var resetFlag   = (publicFlags & (1 << 1)) != 0;
            var cidFlag1    = (publicFlags & (1 << 2)) != 0;
            var cidFlag2    = (publicFlags & (1 << 3)) != 0;
            var pnFlag1     = (publicFlags & (1 << 4)) != 0;
            var pnFlag2     = (publicFlags & (1 << 5)) != 0;

            ulong?connectionId;

            if (cidFlag1 && cidFlag2)
            {
                connectionId = BitConverter.ToUInt64(packetBytes, index);
                index       += 8;
            }
            else if (!cidFlag1 && cidFlag2)
            {
                connectionId = BitConverter.ToUInt32(packetBytes, index);
                index       += 4;
            }
            else if (cidFlag1)
            {
                connectionId = packetBytes[1];
                index       += 1;
            }
            else
            {
                connectionId = null;
            }

            uint?version;

            if (versionFlag)
            {
                version = BitConverter.ToUInt32(packetBytes, index);
                index  += 4;
            }

            ulong packetNumber;

            if (pnFlag1 && pnFlag2)
            {
                var ba = new byte[8];
                Array.Copy(packetBytes, index, ba, 2, 6);
                packetNumber = BitConverter.ToUInt64(ba, 0);
                index       += 6;
            }
            else if (!pnFlag1 && pnFlag2)
            {
                packetNumber = BitConverter.ToUInt32(packetBytes, index);
                index       += 4;
            }
            else if (pnFlag1)
            {
                packetNumber = BitConverter.ToUInt16(packetBytes, index);
                index       += 2;
            }
            else
            {
                packetNumber = packetBytes[index];
                index       += 1;
            }

            var rp           = new RegularPacket(connectionId, packetNumber, null);
            var payloadBytes = new byte[packetBytes.Length - index];

            Array.Copy(packetBytes, index, payloadBytes, 0, payloadBytes.Length);
            rp.FromByteArray(payloadBytes);
            packet = rp;

            return(true);
        }
        public static bool TryParse(byte[] packetBytes, out AbstractPacketBase packet)
        {
            var publicFlags = packetBytes[0];
            var index = 1;
            var versionFlag = (publicFlags & (1 << 0)) != 0;
            var resetFlag = (publicFlags & (1 << 1)) != 0;
            var cidFlag1 = (publicFlags & (1 << 2)) != 0;
            var cidFlag2 = (publicFlags & (1 << 3)) != 0;
            var pnFlag1 = (publicFlags & (1 << 4)) != 0;
            var pnFlag2 = (publicFlags & (1 << 5)) != 0;

            ulong? connectionId;
            if (cidFlag1 && cidFlag2)
            {
                connectionId = BitConverter.ToUInt64(packetBytes, index);
                index += 8;
            }
            else if (!cidFlag1 && cidFlag2)
            {
                connectionId = BitConverter.ToUInt32(packetBytes, index);
                index += 4;
            }
            else if (cidFlag1)
            {
                connectionId = packetBytes[1];
                index += 1;
            }
            else
                connectionId = null;

            uint? version;
            if (versionFlag)
            {
                version = BitConverter.ToUInt32(packetBytes, index);
                index += 4;
            }

            ulong packetNumber;
            if (pnFlag1 && pnFlag2)
            {
                var ba = new byte[8];
                Array.Copy(packetBytes, index, ba, 2, 6);
                packetNumber = BitConverter.ToUInt64(ba, 0);
                index += 6;
            }
            else if (!pnFlag1 && pnFlag2)
            {
                packetNumber = BitConverter.ToUInt32(packetBytes, index);
                index += 4;
            }
            else if (pnFlag1)
            {
                packetNumber = BitConverter.ToUInt16(packetBytes, index);
                index += 2;
            }
            else
            {
                packetNumber = packetBytes[index];
                index += 1;
            }

            var rp = new RegularPacket(connectionId, packetNumber, null);
            var payloadBytes = new byte[packetBytes.Length - index];
            Array.Copy(packetBytes, index, payloadBytes, 0, payloadBytes.Length);
            rp.FromByteArray(payloadBytes);
            packet = rp;

            return true;
        }
        public async Task <Packets.RegularPacket> CutNextPacketAsync()
        {
            if (!this._connectionid.HasValue)
            {
                throw new InvalidOperationException("Connection ID is not established!");
            }

            if (this.Count == 0)
            {
                return(null);
            }

            uint remaining = Packets.AbstractPacketBase.MTU;

            ulong packetNumber;

            lock (this._packetNumberLock)
            {
                this._packetNumber++;
                packetNumber = this._packetNumber;
            }

            var regular = new Packets.RegularPacket(this._connectionid.Value, packetNumber, null); // TODO: FEC GROUP's.

            remaining -= regular.GetHeaderLength();

            MultiplexedTransfer nextTransfer;
            long        assignedDataSize;
            bool        fin;
            StreamFrame streamFrame;

            lock (this._dequeueLock)
            {
                MultiplexedTransfer peekedTransfer;
                do
                {
                    if (!this.TryPeek(out peekedTransfer))
                    {
                        return(null); // My queue is _now_ empty, just say nothing to do.
                    }
                    // Prototype our stream frame
                    var streamRemainingByteCount = peekedTransfer.Stream.Length - peekedTransfer.Stream.Position;

                    streamFrame = new StreamFrame(peekedTransfer.StreamId, Convert.ToUInt64(peekedTransfer.Stream.Position));
                    var prototypeLength = streamFrame.GetMetadataLength();

                    assignedDataSize = Math.Min(remaining, prototypeLength);
                    var transferDone = assignedDataSize == streamRemainingByteCount;
                    fin = transferDone && peekedTransfer.TerminateStream;

                    if (!this.TryDequeue(out nextTransfer))
                    {
                        return(null); // My queue is _now_ empty, just say nothing to do.
                    }
                    if (nextTransfer.TransferId != peekedTransfer.TransferId)
                    {
                        this.Enqueue(nextTransfer); // Whoops, something changed outside of our lock... so, redo our calculations.
                    }
                }while (nextTransfer.TransferId != peekedTransfer.TransferId);
            }

            try
            {
                // Hydrate our stream frame prototype
                var streamData = new byte[assignedDataSize];
                await nextTransfer.Stream.ReadAsync(streamData, (int)nextTransfer.Stream.Position, streamData.Length);

                streamFrame.SetData(streamData, fin);
            }
            catch (Exception)
            {
                // Something went wrong.  Requeue the transfer.
                this.Enqueue(nextTransfer);
                throw;
            }

            return(regular);
        }