Esempio n. 1
0
        /// <summary>
        /// Handle an InitialPacket to create a new QuicConnection related to this packet.
        /// </summary>
        /// <param name="packet">The packet received</param>
        /// <param name="client">The client that sent the packet</param>
        private void HandleInitialPacket(InitialPacket packet, IPEndPoint client)
        {
            InitialPacket incomingPacket = packet as InitialPacket;

            incomingPacket.DecodeFrames();

            // Create random connection ID and use it as SCID for server -> client communications
            // Make sure it's not already in use
            byte[] connID = new byte[8];
            do
            {
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                rng.GetBytes(connID);
            } while (_connectionPool.Find(connID) != null);

            QuicConnection qc = new QuicConnection(_server, client, connID, incomingPacket.SCID);

            _connectionPool.AddConnection(qc, connID);

            InitialPacket responsePacket = new InitialPacket(incomingPacket.SCID, connID, 0);

            responsePacket.AddFrame(new PaddingFrame());
            byte[] b = responsePacket.Encode();
            _server.Send(b, b.Length, client);
            Logger.Write($"Connection established. This is server {BitConverter.ToString(connID)} connected to client {BitConverter.ToString(incomingPacket.SCID)}");
        }
Esempio n. 2
0
        /// <summary>
        /// Connect to a remote server.
        /// </summary>
        /// <param name="ip">Ip of the remote server</param>
        /// <param name="port">Port of the remote server</param>
        public void Connect(string ip, int port)
        {
            // Create random DCID and SCID
            byte[] DCID = new byte[8];
            byte[] SCID = new byte[8];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            rng.GetBytes(DCID);
            rng.GetBytes(SCID);

            // Create and send an InitialPacket to open a connection with the remote server
            InitialPacket initialPacket = new InitialPacket(DCID, SCID, _packetNumber++);

            byte[] byteInitialPacket = initialPacket.Encode();
            _client.Send(byteInitialPacket, byteInitialPacket.Length, ip, port);

            IPEndPoint server = null;
            Packet     packet = Packet.Unpack(_client.Receive(ref server));

            // Start the connection with an InitialPacket
            if (packet.GetType() == typeof(InitialPacket))
            {
                packet.DecodeFrames();
                Logger.Write($"Data received from server {server.Address}:{server.Port}");

                InitialPacket initPack = packet as InitialPacket;
                Logger.Write($"Connection established. This is client {BitConverter.ToString(initPack.DCID)} connected to server {BitConverter.ToString(initPack.SCID)}");
                _connection = new QuicConnection(_client, server, initPack.DCID, initPack.SCID);
            }

            // Background task to receive packets from the remote server
            _receiveToken = new CancellationTokenSource();
            _receiveTask  = Task.Run(() => Receive(server), _receiveToken.Token);
        }
Esempio n. 3
0
        private static int _packetHeaderSize = 4; // In bytes

        /// <summary>
        /// Factory that creates the correct Packet type according to the payload
        /// Decode the received payload
        /// </summary>
        /// <param name="data">The raw packet received</param>
        /// <returns>The decoded packet</returns>
        public static Packet Unpack(byte[] data)
        {
            if (data.Length < _packetHeaderSize)
            {
                throw new CorruptedPacketException("Wrong header size");
            }
            Packet p;

            // Short header packets starts with the bits | 0 | 1 |
            if (!BitUtils.ReadBit(0, data))
            {
                // Short Header Packet
                p = new ShortHeaderPacket();
                if (!BitUtils.ReadBit(1, data))
                {
                    throw new CorruptedPacketException("Wrong second bit when decoding a ShortHeaderPacket");
                }

                p.Decode(data);
            }
            // Long header packets starts with the bits | 1 | 1 |
            else
            {
                // Long Header Packet
                if (!BitUtils.ReadBit(1, data))
                {
                    throw new CorruptedPacketException("Undefined packet header");
                }
                // The two next bits describe the type of the Long Header Packet
                switch (BitUtils.ReadNBits(2, data, 2))
                {
                case 0:
                    p = new InitialPacket();
                    break;

                case 1:
                    p = new RTTPacket();
                    break;

                case 2:
                    p = new HandshakePacket();
                    break;

                case 3:
                    p = new RetryPacket();
                    break;

                default:
                    throw new ArgumentException("2 Bit-encoded uint is not amongst {0, 1, 2, 3}");
                }
                p.Decode(data);
            }

            return(p);
        }