Esempio n. 1
0
        /*
         * Returns the response of a partial response and clears it if it is read.
         */
        public HttpResponse GetPartialResponse(int responseId, int packetId)
        {
            // Get the partial response to return.
            PartialResponse completeResponse = null;

            try
            {
                completeResponse = this.UnfinishedResponses.Get(responseId);
            }
            catch (ArgumentOutOfRangeException)
            {
                return(CreateInvalidResponse("Response index invalid"));
            }

            // Get the packet to return.
            HttpResponse response = null;

            try
            {
                response = completeResponse.GetResponseFromId(packetId);
            }
            catch (IndexOutOfRangeException)
            {
                return(CreateInvalidResponse("Packet index invalid"));
            }

            // Remove the response if it has been full read.
            if (completeResponse.AllResponsesSent())
            {
                this.UnfinishedResponses.Remove(responseId);
            }

            // Return the response.
            return(CreatePartialResponse(responseId, packetId, completeResponse.GetNumberOfResponses(), Encoding.UTF8.GetString(response.GetResponseData())));
        }
        public void SplitResponseTest()
        {
            // Create the first component under testing.
            var responseWithHeaders = HttpResponse.CreateSuccessResponse("Hello world!");

            responseWithHeaders.AddHeader("header1", "value1");
            var CuT1 = PartialResponse.SplitResponse(responseWithHeaders, 4);

            // Assert reading the responses.
            Assert.AreEqual(CuT1.GetNumberOfResponses(), 3);
            Assert.AreEqual(CuT1.GetResponseFromId(0).GetResponseData(), "Hell");
            Assert.AreEqual(CuT1.GetResponseFromId(0).GetHeaders()["header1"], "value1");
            Assert.IsFalse(CuT1.AllResponsesSent());
            Assert.AreEqual(CuT1.GetResponseFromId(1).GetResponseData(), "o wo");
            Assert.AreEqual(CuT1.GetResponseFromId(1).GetHeaders()["header1"], "value1");
            Assert.IsFalse(CuT1.AllResponsesSent());
            Assert.AreEqual(CuT1.GetResponseFromId(2).GetResponseData(), "rld!");
            Assert.AreEqual(CuT1.GetResponseFromId(2).GetHeaders()["header1"], "value1");
            Assert.IsTrue(CuT1.AllResponsesSent());

            // Create the second component under testing.
            var CuT2 = PartialResponse.SplitResponse(HttpResponse.CreateSuccessResponse("Hello world!!!"), 4);

            // Assert reading the responses.
            Assert.AreEqual(CuT2.GetNumberOfResponses(), 4);
            Assert.AreEqual(CuT2.GetResponseFromId(0).GetResponseData(), "Hell");
            Assert.IsFalse(CuT2.AllResponsesSent());
            Assert.AreEqual(CuT2.GetResponseFromId(3).GetResponseData(), "!!");
            Assert.IsFalse(CuT2.AllResponsesSent());
            Assert.AreEqual(CuT2.GetResponseFromId(1).GetResponseData(), "o wo");
            Assert.IsFalse(CuT2.AllResponsesSent());
            Assert.AreEqual(CuT2.GetResponseFromId(2).GetResponseData(), "rld!");
            Assert.IsTrue(CuT2.AllResponsesSent());

            // Create the third component under testing with the built in size value.
            var CuT3 = PartialResponse.SplitResponse(HttpResponse.CreateSuccessResponse(new string('A', 160000)));

            // Assert reading the responses.
            Assert.AreEqual(CuT3.GetNumberOfResponses(), 3);
            Assert.AreEqual(CuT3.GetResponseFromId(1).GetResponseData().Length, 64000);
            Assert.IsFalse(CuT3.AllResponsesSent());
            Assert.AreEqual(CuT3.GetResponseFromId(0).GetResponseData().Length, 64000);
            Assert.IsFalse(CuT3.AllResponsesSent());
            Assert.AreEqual(CuT3.GetResponseFromId(2).GetResponseData().Length, 32000);
            Assert.IsTrue(CuT3.AllResponsesSent());
        }
    private void Poll(ClientState state)
    {
        var recvBytes        = state.ReceiveBytes;
        var remoteIpEndPoint = state.remoteIpEndPoint;
        QuicheHeaderInfo header;

        try{
            header = QuicheHeaderInfo.Construct(recvBytes);
        } catch (Exception e)
        {
            Debug.LogError($"{e}");
            return;
        }

        if (header.Type == 6 /* Type::VersionNegotiation */)
        {
            Debug.LogError("Version negotiation invalid on the server");
            return;
        }

        var key = HexDump(header.Dcid);

        Client client;

        if (!clients.TryGetValue(key, out client))
        {
            if (header.Type != 1 /* Type::Initial */)
            {
                Debug.LogError("Packet is not Initial");
                return;
            }

            if (!VersionIsSupported(header.Version))
            {
                Debug.LogWarning("Doing version negotiation");

                var length = (int)NegotiateVersion(
                    header.Scid, header.Dcid, negotiateBuf);
                var sendBuf = negotiateBuf.Take(length).ToArray();
                udpClient.Send(sendBuf, length, remoteIpEndPoint);
                return;
            }
            var scid = new byte[QuicheClient.LOCAL_CONN_ID_LEN];
            new System.Random().NextBytes(scid);
            byte[] odcid = new byte[65535];
            if (!noRetry)
            {
                if (header.Token.Length == 0)
                {
                    Debug.LogWarning("Doing stateless retry");

                    Debug.Log($"Retry: scid={HexDump(header.Scid)} new_scid={HexDump(scid)}");

                    var new_token = MintToken(header, remoteIpEndPoint);
                    var _out      = new byte[65535];
                    var written   = (int)Retry(header.Scid, header.Dcid, scid, new_token, _out);
                    udpClient.Send(
                        _out.Take(written).ToArray(), written, remoteIpEndPoint);
                    return;
                }
                odcid = ValidateToken(header.Token, remoteIpEndPoint);
                if (odcid == null)
                {
                    Debug.LogError("Invalid address validation token");
                    return;
                }
            }
            if (scid.Length != header.Dcid.Length)
            {
                Debug.LogError("Invalid destination connection ID");
                return;
            }
            scid = header.Dcid;
            var conn    = quiche.Accept(scid, odcid);
            var _client = new Client(conn, remoteIpEndPoint);
            clients.Add(HexDump(scid), _client);
            client = _client;
        }
        var read = client.Connection.Receive(recvBytes);

        if (read == (int)QuicheError.QUICHE_ERR_DONE)
        {
            Debug.Log("done reading");
            return;
        }
        if (read < 0)
        {
            QuicheError err = (QuicheError)Enum
                              .ToObject(typeof(QuicheError), read);
            Debug.LogError($"recv failed {err}");
            throw new Exception();
        }
        Debug.Log($"recv {read} bytes");
        if (client.Connection.IsInEarlyData || client.Connection.IsEstablished)
        {
            foreach (ulong streamId in client.Connection.Writable())
            {
                if (!client.PartialResponses.ContainsKey(streamId))
                {
                    continue;
                }
                var partialResponse = client.PartialResponses[streamId];
                var written         = client.Connection.StreamSend(streamId, partialResponse.Body, true);
                if (written < 0)
                {
                    continue;
                }
                partialResponse.Written += written;
                if (partialResponse.Written == partialResponse.Body.Length)
                {
                    client.PartialResponses.Remove(streamId);
                }
            }
            foreach (ulong streamId in client.Connection.Readable())
            {
                Debug.Log($"stream {streamId} is readable");
                bool fin        = false;
                var  readStream = client.Connection.StreamReceive(
                    streamId, streamRecv, ref fin);
                if (readStream < 0)
                {
                    continue;
                }
                if (fin)
                {
                    var body    = Encoding.ASCII.GetBytes("Hello World!\n");
                    var written = client.Connection.StreamSend(
                        streamId, body, true);
                    if (written < 0)
                    {
                        continue;
                    }
                    if (written < body.Length)
                    {
                        var partialResponse = new PartialResponse(body, written);
                        client.PartialResponses.Add(streamId, partialResponse);
                    }
                }
            }
        }
    }
Esempio n. 4
0
        /*
         * Returns a response for a given request.
         */
        public HttpResponse GetResponseData(HttpRequest request)
        {
            var url = request.GetURL();

            if (url.ParameterExists("getResponse") && url.GetParameter("getResponse").ToLower() == "true")
            {
                // Handle reading a split response.
                var responseId = 0;
                var packetId   = 0;

                // Get the packet info.
                if (url.ParameterExists("responseId"))
                {
                    responseId = int.Parse(url.GetParameter("responseId"));
                }
                if (url.ParameterExists("packet"))
                {
                    packetId = int.Parse(url.GetParameter("packet"));
                }

                // Return the partial packet.
                return(this.GetPartialResponse(responseId, packetId));
            }
            else
            {
                // Handle sending a split request.
                var requestId  = -1;
                var packetId   = -1;
                var maxPackets = -1;
                PartialHttpRequest completeRequest;

                // Get the packet info.
                if (url.ParameterExists("requestId"))
                {
                    requestId = int.Parse(url.GetParameter("requestId"));
                }
                if (url.ParameterExists("packet"))
                {
                    packetId = int.Parse(url.GetParameter("packet"));
                }
                if (url.ParameterExists("maxpackets"))
                {
                    maxPackets = int.Parse(url.GetParameter("maxpackets"));
                }

                // Treat the request as standalone if the parameters aren't specified.
                if (requestId == -1 && packetId == -1 && maxPackets == -1)
                {
                    return(GetCompleteResponseData(request));
                }
                else
                {
                    if (requestId == -1 && packetId == -1)
                    {
                        packetId = 0;
                    }
                }

                // Get the split request to use.
                if (requestId == -1)
                {
                    completeRequest = new PartialHttpRequest(request.GetRequestType(), url, request.GetHost(), maxPackets);
                    requestId       = this.IncompleteRequests.Store(completeRequest);
                }
                else
                {
                    completeRequest = this.IncompleteRequests.Get(requestId);
                }

                // Add the packet to the request.
                try
                {
                    completeRequest.AddPartialPacket(packetId, Encoding.UTF8.GetString(request.GetBody()));
                }
                catch (IndexOutOfRangeException)
                {
                    return(CreateInvalidResponse("Packet index invalid"));
                }

                // Return the response.
                if (completeRequest.IsComplete())
                {
                    this.IncompleteRequests.Remove(requestId);
                    var partialResponse = PartialResponse.SplitResponse(this.GetCompleteResponseData(completeRequest.ToSingleRequest()));

                    var responseId = this.UnfinishedResponses.Store(partialResponse);
                    return(this.GetPartialResponse(responseId, 0));
                }
                else
                {
                    return(CreateIncompleteResponse(requestId));
                }
            }
        }
 public void On <T1, T2, T3, T4, T5, T6>(string methodName, Action <T1, T2, T3, T4, T5, T6> handler) => On(methodName, args =>
 {
     var arr = new PartialResponse <T1, T2, T3, T4, T5, T6>(args);
     handler(arr.GetT1, arr.GetT2, arr.GetT3, arr.GetT4, arr.GetT5, arr.GetT6);
 });
 public void On <T1, T2>(string methodName, Action <T1, T2> handler) => On(methodName, args =>
 {
     var arr = new PartialResponse <T1, T2>(args);
     handler(arr.GetT1, arr.GetT2);
 });