/* * 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); } } } } }
/* * 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); });