Пример #1
0
        async Task <bool> ReuseConnection(TestContext ctx, HttpOperation operation, CancellationToken cancellationToken)
        {
            var me = $"{ME}({connection.ME}) REUSE";

            ctx.LogDebug(2, $"{me}");

            cancellationToken.ThrowIfCancellationRequested();
            var reusable = await connection.ReuseConnection(ctx, cancellationToken).ConfigureAwait(false);

            ctx.LogDebug(2, $"{me} #1: {reusable}");

            if (reusable && (operation?.HasAnyFlags(HttpOperationFlags.ClientUsesNewConnection) ?? false))
            {
                try {
                    await connection.ReadRequest(ctx, cancellationToken).ConfigureAwait(false);

                    throw ctx.AssertFail("Expected client to use a new connection.");
                } catch (OperationCanceledException) {
                    throw;
                } catch (Exception ex) {
                    ctx.LogDebug(2, $"{ME} EXPECTED EXCEPTION: {ex.GetType ()} {ex.Message}");
                }
                connection.Dispose();
                return(false);
            }

            return(reusable);
        }
Пример #2
0
        internal protected override Task <HttpResponse> HandleRequest(
            TestContext ctx, HttpOperation operation, HttpConnection connection, HttpRequest request,
            RequestFlags effectiveFlags, CancellationToken cancellationToken)
        {
            var keepAlive = (effectiveFlags & (RequestFlags.KeepAlive | RequestFlags.CloseConnection)) == RequestFlags.KeepAlive;

            var redirect = operation.RegisterRedirect(ctx, Target);
            var response = HttpResponse.CreateRedirect(Code, redirect.Uri);

            if (keepAlive)
            {
                response.KeepAlive = true;
            }

            if (operation.HasAnyFlags(HttpOperationFlags.ClientDoesNotSendRedirect))
            {
                redirect.Listener.UnregisterOperation(redirect);
            }
            else
            {
                response.Redirect = redirect;
            }

            return(Task.FromResult(response));
        }
Пример #3
0
        public async Task <HttpResponse> HandleRequest(TestContext ctx, HttpOperation operation,
                                                       HttpConnection connection, HttpRequest request,
                                                       CancellationToken cancellationToken)
        {
            Exception    originalError;
            HttpResponse response;

            if (operation == null)
            {
                throw new ArgumentNullException(nameof(operation));
            }
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }

            var expectServerError = operation.HasAnyFlags(HttpOperationFlags.ExpectServerException);

            try {
                Debug(ctx, 1, $"HANDLE REQUEST: {connection.RemoteEndPoint}");
                DumpHeaders(ctx, request);
                connection.Server.CheckEncryption(ctx, connection.SslStream);
                response = await HandleRequest(ctx, operation, connection, request, Flags, cancellationToken);

                if (response == null)
                {
                    response = HttpResponse.CreateSuccess();
                }
                if ((Flags & RequestFlags.CloseConnection) != 0)
                {
                    response.CloseConnection = true;
                }
                if (!response.KeepAlive.HasValue && ((Flags & RequestFlags.KeepAlive) != 0))
                {
                    response.KeepAlive = true;
                }
                response.ResolveHeaders();

                Debug(ctx, 1, $"HANDLE REQUEST DONE: {connection.RemoteEndPoint}", response);
                DumpHeaders(ctx, response);
                return(response);
            } catch (AssertionException ex) {
                originalError = ex;
                response      = HttpResponse.CreateError(ex.Message);
            } catch (OperationCanceledException) {
                throw;
            } catch (Exception ex) {
                originalError = ex;
                response      = HttpResponse.CreateError("Caught unhandled exception", ex);
            }

            if (ctx.IsCanceled || cancellationToken.IsCancellationRequested)
            {
                Debug(ctx, 1, "HANDLE REQUEST - CANCELED");
                throw new OperationCanceledException();
            }

            if (originalError is AssertionException)
            {
                Debug(ctx, 1, "HANDLE REQUEST - ASSERTION FAILED", originalError);
            }
            else if (expectServerError)
            {
                Debug(ctx, 1, "HANDLE REQUEST - EXPECTED ERROR", originalError.GetType());
            }
            else
            {
                Debug(ctx, 1, "HANDLE REQUEST - ERROR", originalError);
            }

            return(response);
        }
Пример #4
0
        async Task <bool> InitConnection(TestContext ctx, HttpOperation operation, CancellationToken cancellationToken)
        {
            var me = $"{ME}({connection.ME}) INIT";

            ctx.LogDebug(2, $"{me}");

            bool haveRequest;

            cancellationToken.ThrowIfCancellationRequested();
            try {
                await connection.Initialize(ctx, operation, cancellationToken);

                ctx.LogDebug(2, $"{me} #1 {connection.RemoteEndPoint}");

                if (operation != null && operation.HasAnyFlags(HttpOperationFlags.ServerAbortsHandshake))
                {
                    throw ctx.AssertFail("Expected server to abort handshake.");
                }

                /*
                 * There seems to be some kind of a race condition here.
                 *
                 * When the client aborts the handshake due the a certificate validation failure,
                 * then we either receive an exception during the TLS handshake or the connection
                 * will be closed when the handshake is completed.
                 *
                 */
                haveRequest = await connection.WaitForRequest(cancellationToken);

                ctx.LogDebug(2, $"{me} #2 {haveRequest}");

                if (operation != null && operation.HasAnyFlags(HttpOperationFlags.ClientAbortsHandshake))
                {
                    throw ctx.AssertFail("Expected client to abort handshake.");
                }
            } catch (Exception ex) {
                if (operation.HasAnyFlags(HttpOperationFlags.ServerAbortsHandshake, HttpOperationFlags.ClientAbortsHandshake))
                {
                    return(false);
                }
                ctx.LogDebug(2, $"{me} FAILED: {ex.Message}\n{ex}");
                throw;
            }

            if (!haveRequest)
            {
                ctx.LogMessage($"{me} got empty requets!");
                throw ctx.AssertFail("Got empty request.");
            }

            if (Server.UseSSL)
            {
                ctx.Assert(connection.SslStream.IsAuthenticated, "server is authenticated");
                if (operation != null && operation.HasAnyFlags(HttpOperationFlags.RequireClientCertificate))
                {
                    ctx.Assert(connection.SslStream.IsMutuallyAuthenticated, "server is mutually authenticated");
                }
            }

            ctx.LogDebug(2, $"{me} DONE");
            return(true);
        }