Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
            }
        }