private static void FormatRequestAndValidate(HttpRequestMessage request, string expected) { var buffer = new byte[8192]; var result = HttpFormatter.FormatRequest(request, buffer); var decodedString = Encoding.UTF8.GetString(buffer, 0, result); Assert.Equal(expected, decodedString); }
private void ProcessRequest(BufferSegment buffer, bool isCompleted) { Logger.Debug("Request received (isCompleted = {isCompleted}), length = {length}", isCompleted, buffer.Length); var headerLength = HttpFormatter.ParseRequest(buffer, out var request); Logger.Trace("Request: {@request}", request); var stream = new BufferQueueStream(_socket.BufferPool); request.Body = stream; stream.PushBuffer(new ArraySegment <byte>(buffer.Buffer, buffer.Offset + headerLength, buffer.Length - headerLength)); var requestId = int.Parse(request.Headers[MazeHeaders.MazeSocketRequestIdHeader]); var cancellationTokenSource = _cancellableRequests.GetOrAdd(requestId, i => new CancellationTokenSource()); var token = cancellationTokenSource.Token; if (token.IsCancellationRequested) { cancellationTokenSource.Dispose(); _cancellableRequests.TryRemove(requestId, out _); return; } if (isCompleted) { stream.IsCompleted = true; } else { if (_activeRequests.TryAdd(requestId, stream)) { Logger.Debug("Added request {requestId} to active requests", requestId); } else { Logger.Error( "Adding the request {requestId} to the active requests failed because it already exists.", requestId); throw new InvalidOperationException("The request already exists, duplicate request id deteceted."); } } var response = new DefaultMazeResponse(requestId); response.Headers.Add(MazeHeaders.MazeSocketRequestIdHeader, requestId.ToString()); var rawStream = new HttpResponseStream(response, request, _socket, _packageBufferSize, _maxHeaderSize, _bufferPool, token); response.HttpResponseStream = rawStream; response.Body = new BufferingWriteStream(rawStream, _packageBufferSize, _bufferPool); LogTaskError(Task.Run(() => RequestReceived?.Invoke(this, new MazeRequestReceivedEventArgs(request, response, token)))); }
public static HttpResponseMessage DecodeResponse(string commandResultBase64) { var binary = Convert.FromBase64String(commandResultBase64); var length = HttpFormatter.ParseResponse(new ArraySegment <byte>(binary), out var response, out var contentHeaders); if (binary.Length > length) { response.Content = new ByteArrayContent(binary, length, binary.Length - length); foreach (var contentHeader in contentHeaders) { response.Content.Headers.Add(contentHeader.Key, (IEnumerable <string>)contentHeader.Value); } } return(response); }
private void ProcessResponse(BufferSegment buffer, bool isCompleted) { Logger.LogDataPackage("Received Response", buffer.Buffer, buffer.Offset, buffer.Length); var headerLength = HttpFormatter.ParseResponse(buffer, out var response, out var contentHeaders); var requestId = int.Parse(response.Headers.GetValues(MazeHeaders.MazeSocketRequestIdHeader).Single()); var bufferSegment = new ArraySegment <byte>(buffer.Buffer, buffer.Offset + headerLength, buffer.Length - headerLength); if (isCompleted) { response.Content = new RawStreamContent(new ArrayPoolMemoryStream(bufferSegment, _socket.BufferPool)); } else { var stream = new BufferQueueStream(_socket.BufferPool); stream.PushBuffer(bufferSegment); if (_activeResponses.TryAdd(requestId, stream)) { Logger.Debug("Added response {requestId} to active responses", requestId); } else { Logger.Error( "Adding the response {requestId} to the active response failed because it already exists.", requestId); throw new InvalidOperationException("The response already exists, duplicate response id deteceted."); } response.Content = new RawStreamContent(stream); } foreach (var contentHeader in contentHeaders) { response.Content.Headers.Add(contentHeader.Key, (IEnumerable <string>)contentHeader.Value); } if (!_waitingRequests.TryRemove(requestId, out var taskCompletionSource)) { Logger.Error("No TaskCompletionSource for request {requestId} found.", requestId); response.Dispose(); return; } taskCompletionSource.SetResult(response); }
static async Task MainAsync(CancellationToken cancellationToken) { var function = new Function(); function.PrepareFunctionContext(); System.Diagnostics.Debug.WriteLine("C# AfterBurn running."); var httpFormatter = new HttpFormatter(); var stdin = Console.OpenStandardInput(); using (TextReader reader = new StreamReader(stdin)) { while (!cancellationToken.IsCancellationRequested) { HeaderParser parser = new HeaderParser(); var header = parser.Parse(reader); foreach (string v in header.HttpHeaders) { System.Diagnostics.Debug.WriteLine(v + "=" + header.HttpHeaders[v]); } System.Diagnostics.Debug.WriteLine("Content-Length: " + header.ContentLength); BodyParser bodyParser = new BodyParser(); string body = String.Empty; if (header.ContentLength > 0) { body = bodyParser.Parse(reader, header.ContentLength); System.Diagnostics.Debug.WriteLine(body); } await function.Invoke(body, cancellationToken); var httpAdded = httpFormatter.Format(""); Console.WriteLine(httpAdded); } } }
static void Main(string[] args) { var function = new Function.Handler(); System.Diagnostics.Debug.WriteLine("C# AfterBurn running."); var httpFormatter = new HttpFormatter(); var stdin = Console.OpenStandardInput(); using (TextReader reader = new StreamReader(stdin)) { while (true) { HeaderParser parser = new HeaderParser(); var header = parser.Parse(reader); foreach (string v in header.HttpHeaders) { System.Diagnostics.Debug.WriteLine(v + "=" + header.HttpHeaders[v]); } System.Diagnostics.Debug.WriteLine("Content-Length: " + header.ContentLength); BodyParser bodyParser = new BodyParser(); char[] body = new char[0] { }; if (header.ContentLength > 0) { body = bodyParser.Parse(reader, header.ContentLength); System.Diagnostics.Debug.WriteLine(body); } var httpAdded = httpFormatter.Format(function.Invoke(body)); Console.WriteLine(httpAdded); } } }
public async Task <HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (requestMessage.Headers.Contains(MazeHeaders.MazeSocketRequestIdHeader)) { throw new ArgumentException( $"The maze request must not have a {MazeHeaders.MazeSocketRequestIdHeader} header.", nameof(requestMessage)); } var requestId = Interlocked.Increment(ref _requestCounter); requestMessage.Headers.Add(MazeHeaders.MazeSocketRequestIdHeader, requestId.ToString()); var requestWaiter = new TaskCompletionSource <HttpResponseMessage>(); _waitingRequests.TryAdd(requestId, requestWaiter); using (var sendBuffer = AllocateBuffer(_packageBufferSize)) { var headerLength = HttpFormatter.FormatRequest(requestMessage, sendBuffer); var maxReadLength = sendBuffer.Length - headerLength; var opCode = MazeSocket.MessageOpcode.Request; Stream bodyStream; if (requestMessage.Content != null) { bodyStream = await requestMessage.Content.ReadAsStreamAsync(); } else { bodyStream = null; } using (bodyStream) { int read; if (bodyStream == null) //no body, single package, easy { opCode = MazeSocket.MessageOpcode.RequestSinglePackage; read = 0; } else { //read something var readOffset = sendBuffer.Offset + headerLength; read = await bodyStream.ReadAsync(sendBuffer.Buffer, readOffset, maxReadLength, cancellationToken); if (read < maxReadLength) { if (read == 0) { //no data in the stream opCode = MazeSocket.MessageOpcode.RequestSinglePackage; } else { //we read less than requested. check if we already reached the end readOffset += read; var read2 = await bodyStream.ReadAsync(sendBuffer.Buffer, readOffset, maxReadLength - read, cancellationToken); if (read2 == 0) { opCode = MazeSocket.MessageOpcode.RequestSinglePackage; } else { read += read2; } } } } cancellationToken .ThrowIfCancellationRequested(); //last chance without having to send a cancel package try { await _socket.SendFrameAsync(opCode, new ArraySegment <byte>(sendBuffer.Buffer, sendBuffer.Offset, read + headerLength), bufferHasRequiredLength : true, cancellationToken); if (opCode == MazeSocket.MessageOpcode.Request) { BinaryUtils.WriteInt32(sendBuffer.Buffer, sendBuffer.Offset, requestId); opCode = MazeSocket.MessageOpcode.RequestContinuation; maxReadLength = sendBuffer.Length - 4; while (true) { var readOffset = sendBuffer.Offset + 4; //4 for the request id read = await bodyStream.ReadAsync(sendBuffer.Buffer, readOffset, maxReadLength, cancellationToken); if (read == 0) { opCode = MazeSocket.MessageOpcode.RequestContinuationFinished; } else if (read < maxReadLength) { var read2 = await bodyStream.ReadAsync(sendBuffer.Buffer, readOffset + read, maxReadLength - read, cancellationToken); if (read2 == 0) { opCode = MazeSocket.MessageOpcode.RequestContinuationFinished; } else { read += read2; } } await _socket.SendFrameAsync(opCode, new ArraySegment <byte>(sendBuffer.Buffer, sendBuffer.Offset, 4 + read), bufferHasRequiredLength : true, cancellationToken); if (opCode == MazeSocket.MessageOpcode.RequestContinuationFinished) { break; } } } } catch (Exception) { BinaryUtils.WriteInt32(sendBuffer.Buffer, sendBuffer.Offset, requestId); await _socket.SendFrameAsync(MazeSocket.MessageOpcode.CancelRequest, new ArraySegment <byte>(sendBuffer.Buffer, sendBuffer.Offset, 4), bufferHasRequiredLength : true, CancellationToken.None); //DO NOT USE THE CANCELLATION TOKEN HERE throw; } } cancellationToken.Register(() => { using (var buffer = AllocateBuffer(4)) { BinaryUtils.WriteInt32(buffer.Buffer, buffer.Offset, requestId); _socket.SendFrameAsync(MazeSocket.MessageOpcode.CancelRequest, new ArraySegment <byte>(buffer.Buffer, buffer.Offset, 4), bufferHasRequiredLength: true, CancellationToken.None).Wait(); } requestWaiter.TrySetCanceled(); }); return(await requestWaiter.Task); } }