From 149ff8575dc1f64db09c12e4c087cdd49c517137 Mon Sep 17 00:00:00 2001 From: Ferdinand Schober <39813048+fschober-atg@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:29:16 -0700 Subject: [PATCH] Added handling for delayed body data. (#10) --- .../Logic/Proxy/WebServiceProxy.cs | 78 ++++++++++++++++--- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/XMAT/Engines/WebServiceProxy/Logic/Proxy/WebServiceProxy.cs b/XMAT/Engines/WebServiceProxy/Logic/Proxy/WebServiceProxy.cs index 0810cd4..79b2e89 100644 --- a/XMAT/Engines/WebServiceProxy/Logic/Proxy/WebServiceProxy.cs +++ b/XMAT/Engines/WebServiceProxy/Logic/Proxy/WebServiceProxy.cs @@ -508,6 +508,39 @@ private ClientRequest ParseRequestAndHeaders(int clientId, List lines) return clientRequest; } + private int PrefetchContentLengthFromHeaders(int clientId, List lines) + { + // Return 0 if not found or malformed + int contentLength = 0; + + if (lines == null || lines.Count == 0) + { + _logger.Log(clientId, LogLevel.ERROR, "Connect request has no data."); + return contentLength; + } + + // Isolate the content-length header only + for (int i = 1; i < lines.Count; i++) + { + string line = lines[i]; + string[] header = line.Split(':', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + if (header.Length < 2) + { + _logger.Log(clientId, LogLevel.ERROR, $"Malformed header: {line}"); + } + else + { + if (header[0].Trim().ToLower() == "content-length") + { + contentLength = int.Parse(header[1].Trim()); + _logger.Log(clientId, LogLevel.DEBUG, $"Prefetch of Content-Length: {contentLength}"); + } + } + } + + return contentLength; + } + private async Task ReturnResponseAsync(ClientRequest clientRequest, ClientState clientState, HttpResponseMessage responseMessage) { ServerResponse serverResponse = await ParseServerResponseAsync(clientState.ID, responseMessage).ConfigureAwait(false); @@ -595,8 +628,6 @@ private async Task, byte[]>> ReadRequestAndHeadersAsync(Clien { do { - - readThisFrame = await stream.ReadAsync(buffer, readTotal, buffer.Length - readTotal); readTotal += readThisFrame; @@ -611,9 +642,9 @@ private async Task, byte[]>> ReadRequestAndHeadersAsync(Clien } while (clientState.TcpClient.Available > 0); } - catch + catch (Exception ex) { - + _logger.Log(clientState.ID, LogLevel.ERROR, $"Failed reading client request: {ex}"); } //File.WriteAllBytes($"XMAT_{clientState.ID}.dat", buffer); @@ -654,13 +685,38 @@ private async Task, byte[]>> ReadRequestAndHeadersAsync(Clien } } + // Get the actual body length from the content-length header + int expectedBodyLength = 0; + expectedBodyLength = PrefetchContentLengthFromHeaders(clientState.ID, lines); + + // Read the rest of the delayed body if needed + if (expectedBodyLength > readTotal - startIndex) + { + try + { + do + { + _logger.Log(clientState.ID, LogLevel.DEBUG, $"Delayed body bytes, reading {expectedBodyLength - (readTotal - startIndex)} at {readTotal - startIndex}"); + + readThisFrame = await stream.ReadAsync(buffer, expectedBodyLength - (readTotal - startIndex), buffer.Length - readTotal); + readTotal += readThisFrame; + + // Do we need to resize? + if (readTotal >= buffer.Length) + { + _logger.Log(clientState.ID, LogLevel.DEBUG, $"Resizing buffer from {buffer.Length} bytes, to {buffer.Length * 2} bytes"); + Array.Resize(ref buffer, buffer.Length * 2); + } + } + while (expectedBodyLength > readTotal - startIndex); + } + catch (Exception ex) + { + _logger.Log(clientState.ID, LogLevel.ERROR, $"Failed reading client request for delayed body: {ex}"); + } + } - //string strHeadersTotal = strAllData.Substring(0, startIndex); - //string strBody = strAllData.Substring(startIndex); - //_logger.Log(clientState.ID, LogLevel.DEBUG, $"Whole buffer was {strAllData}"); - //_logger.Log(clientState.ID, LogLevel.DEBUG, $"Headers buffer was {strHeadersTotal}"); - //_logger.Log(clientState.ID, LogLevel.DEBUG, $"Body buffer was {strBody}"); - //_logger.Log(clientState.ID, LogLevel.DEBUG, $"Done with read, read {readTotal} bytes total, and processed {startIndex} as headers, body remainder is {readTotal-startIndex}"); + _logger.Log(clientState.ID, LogLevel.DEBUG, $"Done with reading, read {readTotal} bytes total, and processed {startIndex} as headers, {readTotal-startIndex} as body"); // resize the buffer, otherwise we're taking up unnecessary memory Array.Resize(ref buffer, readTotal); @@ -694,6 +750,8 @@ private void CloseClientState(ClientState clientState) Timestamp = DateTime.Now } ); + + _logger.Log(clientState.ID, LogLevel.DEBUG, $"ConnectionClosed Event: {clientState.ID} | {DateTime.Now.ToString()}"); } private bool RaiseReceivedInitialConnection(int connectionID, TcpClient client)