Exemplo n.º 1
0
        public async Task ConnectionShouldGoAwayOnSettingsAckWithNonZeroLength(
            int frameLength)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            await inPipe.WriteSettings(Settings.Default);

            // Wait for remote settings
            await outPipe.ReadAndDiscardSettings();

            // Wait for ack to our settings
            await outPipe.AssertSettingsAck();

            var fh = new FrameHeader
            {
                Type     = FrameType.Settings,
                Flags    = (byte)SettingsFrameFlags.Ack,
                StreamId = 0,
                Length   = frameLength,
            };
            await inPipe.WriteFrameHeader(fh);

            // Wait for GoAway due to wrong stream ID
            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 2
0
        public async Task ShouldGoAwayWhenStreamWindowIsOverflowedThroughSettingsUpdate()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Let the remote increase the flow control window of the stream
            await inPipe.WriteWindowUpdate(
                1u,
                (int)(int.MaxValue - Settings.Default.InitialWindowSize));

            // Should be still alive
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // And now write new settings which overflow the window
            var newSettings = Settings.Default;

            newSettings.InitialWindowSize++;
            await inPipe.WriteSettings(newSettings);

            // Dead through overflow
            await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 1u);
        }
        public async Task ConnectionShouldCloseAndSignalDoneInCaseOfAProtocolError(bool isServer)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            // Cause a protocol error
            var fh = new FrameHeader
            {
                Type     = FrameType.Data,
                StreamId = 0u,
                Flags    = 0,
                Length   = 0,
            };
            await inPipe.WriteFrameHeader(fh);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);

            await outPipe.AssertStreamEnd();

            await inPipe.CloseAsync();

            // Expect the connection to close within timeout
            var closed = http2Con.Done;

            Assert.True(
                closed == await Task.WhenAny(closed, Task.Delay(1000)),
                "Expected connection to close");
        }
Exemplo n.º 4
0
        public async Task ConnectionShouldGoAwayOnUnsolicitedSettingsAck()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            await inPipe.WriteSettings(Settings.Default);

            // Wait for remote settings
            await outPipe.ReadAndDiscardSettings();

            // Wait for ack to our settings
            await outPipe.AssertSettingsAck();

            // Acknowledge remote settings 2 times
            await inPipe.WriteSettingsAck();

            await inPipe.WriteSettingsAck();

            // Wait for GoAway due to multiple ACKs
            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 5
0
        public async Task ConnectionShouldGoAwayOnInvalidWindowSizeSettingWithFlowControlError()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            var settings = Settings.Default;

            settings.InitialWindowSize = (uint)int.MaxValue + 1u; // Invalid
            var settingsData = new byte[settings.RequiredSize];
            var fh           = new FrameHeader
            {
                Type     = FrameType.Settings,
                Length   = settingsData.Length,
                Flags    = 0,
                StreamId = 0,
            };

            settings.EncodeInto(new ArraySegment <byte>(settingsData));
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(new ArraySegment <byte>(settingsData));

            await outPipe.ReadAndDiscardSettings();

            await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 6
0
        public async Task ConnectionShouldGoAwayOnInvalidSettingsFrameLength()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            var settings     = Settings.Default;
            var settingsData = new byte[settings.RequiredSize + 1]; // 1 byte extra
            var fh           = new FrameHeader
            {
                Type     = FrameType.Settings,
                Length   = settingsData.Length,
                Flags    = 0,
                StreamId = 0,
            };

            settings.EncodeInto(new ArraySegment <byte>(
                                    settingsData, 0, settingsData.Length - 1));
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(new ArraySegment <byte>(settingsData));

            await outPipe.ReadAndDiscardSettings();

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 7
0
        public async Task ClientShouldGoAwayIfFirstFrameIsNotSettings()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(false, Settings.Default, inPipe, outPipe);
            var fh       = new FrameHeader
            {
                Type     = FrameType.Headers,
                Length   = 0,
                Flags    = 0,
                StreamId = 2
            };
            await inPipe.WriteFrameHeader(fh);

            var expected = Settings.Default;

            expected.EnablePush = false;
            await outPipe.ReadAndDiscardPreface();

            await outPipe.ReadAndDiscardSettings();

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 8
0
        public async Task ConnectionShouldGoAwayOnInvalidGoAwayFrameLength(
            bool isServer, int frameLength)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var fh = new FrameHeader
            {
                Type     = FrameType.GoAway,
                Flags    = 0,
                Length   = frameLength,
                StreamId = 0,
            };
            await inPipe.WriteFrameHeader(fh);

            var expectedErr = frameLength > 65535
                ? ErrorCode.FrameSizeError
                : ErrorCode.ProtocolError;

            await outPipe.AssertGoAwayReception(expectedErr, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 9
0
        public async Task PaddingViolationsOnStreamsShouldLeadToGoAway(
            bool onKnownStream, int frameLength, byte?padData)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            var fh = new FrameHeader
            {
                Type     = FrameType.Data,
                StreamId = onKnownStream ? 1u : 2u,
                Flags    = (byte)DataFrameFlags.Padded,
                Length   = frameLength,
            };
            await inPipe.WriteFrameHeader(fh);

            if (frameLength > 0)
            {
                var data = new byte[frameLength];
                data[0] = padData.Value;
                await inPipe.WriteAsync(new ArraySegment <byte>(data));
            }
            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1u);
        }
        public async Task ResetsOnIdleStreamsShouldBeTreatedAsConnectionError(
            bool isServer, uint streamId)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            await inPipe.WriteResetStream(streamId, ErrorCode.RefusedStream);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);
        }
Exemplo n.º 11
0
        public async Task ADataFrameOnAnIdleStreamIdShouldTriggerAGoAway(
            bool isServer, uint streamId)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            Func <IStream, bool> listener = (s) => true;
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider, listener);

            await inPipe.WriteData(streamId, 0);

            await outPipe.AssertGoAwayReception(ErrorCode.StreamClosed, 0u);
        }
        public async Task ConnectionShouldGoAwayOnInvalidResetStreamId(
            bool isServer)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            await inPipe.WriteResetStream(0, ErrorCode.Cancel);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 13
0
        public async Task ReceivingWindowUpdatesOnIdleStreamsShouldTriggerGoAway(
            uint streamId)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            await inPipe.WriteWindowUpdate(streamId, 0);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1);

            await outPipe.AssertStreamEnd();
        }
        public async Task ConnectionShouldGoAwayOnPushPromiseWithInvalidLength(
            bool isServer, int?padLen)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            // This test is set up in a way where the payload length is 1 byte
            // too small for the transferred content
            var requiredLen = 4;
            var flags       = (byte)PushPromiseFrameFlags.EndOfHeaders;

            if (padLen != null)
            {
                flags       |= (byte)PushPromiseFrameFlags.Padded;
                requiredLen += 1 + padLen.Value;
            }
            var actualLen = requiredLen - 1;
            var fh        = new FrameHeader
            {
                Type     = FrameType.PushPromise,
                Flags    = flags,
                Length   = actualLen,
                StreamId = 1,
            };
            await inPipe.WriteFrameHeader(fh);

            var content = new byte[actualLen];
            var offset  = 0;

            if (padLen != null)
            {
                content[offset] = (byte)padLen.Value;
                offset++;
            }
            // Set promised stream Id
            content[offset + 0] = content[offset + 1] = content[offset + 2] = 0;
            if (offset + 3 <= content.Length - 1)
            {
                content[offset + 3] = 1;
            }
            offset += 4;
            await inPipe.WriteAsync(new ArraySegment <byte>(content));

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 15
0
        public async Task ShouldGoAwayWhenConnectionFlowControlWindowIsOverloaded(
            int amount)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, null);

            await inPipe.WriteWindowUpdate(0, amount);

            await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 16
0
        public async Task ContinuationsWithoutHeadersShouldLeadToGoAway()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            Func <IStream, bool> listener = (s) => true;
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, listener);

            var hEncoder = new Encoder();
            await inPipe.WriteContinuation(hEncoder, 1u, DefaultGetHeaders, true);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 17
0
        public async Task HeadersOnStreamId0ShouldTriggerAGoAway(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            Func <IStream, bool> listener = (s) => true;
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider, listener);

            var hEncoder = new Encoder();
            await inPipe.WriteHeaders(hEncoder, 0, false, DefaultGetHeaders);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
        public async Task ConnectionShouldGoAwayOnPriorityStreamIdZero()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider);

            var prioData = new PriorityData
            {
                StreamDependency            = 1,
                StreamDependencyIsExclusive = false,
                Weight = 0,
            };
            await inPipe.WritePriority(0, prioData);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 19
0
        public async Task InCaseOfManualGoAwayAndConnectionErrorOnlyASingleGoAwayShouldBeSent()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Send the manual GoAway
            await res.conn.GoAwayAsync(ErrorCode.NoError, false);

            // Expect to read it
            await outPipe.AssertGoAwayReception(ErrorCode.NoError, 1u);

            // And force a connection error that should not yield a further GoAway
            await inPipe.WriteSettingsAck();

            // Expect end of stream and not GoAway
            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 20
0
        public async Task ConnectionShouldGoAwayOnInvalidPingFrameLength(int pingFrameLength)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider);

            var pingHeader = new FrameHeader
            {
                Type     = FrameType.Ping,
                Flags    = 0,
                Length   = pingFrameLength,
                StreamId = 0,
            };
            await inPipe.WriteFrameHeader(pingHeader);

            await outPipe.AssertGoAwayReception(ErrorCode.FrameSizeError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 21
0
        public async Task NewStreamsAfterGoAwayShouldBeRejected()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Start the GoAway process
            await res.conn.GoAwayAsync(ErrorCode.NoError, false);

            // Expect the GoAway message
            await outPipe.AssertGoAwayReception(ErrorCode.NoError, 1u);

            // Try to establish a new stream
            var hEncoder = new Http2.Hpack.Encoder();
            await inPipe.WriteHeaders(hEncoder, 3, true, TestHeaders.DefaultGetHeaders);

            // Expect a stream rejection
            await outPipe.AssertResetStreamReception(3u, ErrorCode.RefusedStream);
        }
        public async Task ConnectionShouldGoAwayOnPushPromiseWithInvalidStreamId(
            bool isServer)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var fh = new FrameHeader
            {
                Type     = FrameType.PushPromise,
                Flags    = (byte)PushPromiseFrameFlags.EndOfHeaders,
                Length   = 128,
                StreamId = 1,
            };
            await inPipe.WriteFrameHeader(fh);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
        public async Task ConnectionShouldGoAwayOnInvalidResetStreamFrameLength(
            bool isServer, int resetFrameLength)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var rstStreamHeader = new FrameHeader
            {
                Type     = FrameType.ResetStream,
                Flags    = 0,
                Length   = resetFrameLength,
                StreamId = 1,
            };
            await inPipe.WriteFrameHeader(rstStreamHeader);

            await outPipe.AssertGoAwayReception(ErrorCode.FrameSizeError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 24
0
        public async Task ReceivingWindowUpdatesWith0AmountShouldTriggerGoAwayOrReset(
            uint streamId)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            await inPipe.WriteWindowUpdate(streamId, 0);

            if (streamId == 0)
            {
                await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1);

                await outPipe.AssertStreamEnd();
            }
            else
            {
                await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError);
            }
        }
        public async Task ConnectionShouldGoAwayOnPushPromise(
            bool isServer, uint streamId, int payloadLength)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var fh = new FrameHeader
            {
                Type     = FrameType.PushPromise,
                Flags    = 0,
                Length   = payloadLength,
                StreamId = streamId,
            };
            await inPipe.WriteFrameHeader(fh);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 26
0
        public async Task ServersShouldGoAwayIfFirstFrameIsNotSettings()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            var fh = new FrameHeader
            {
                Type     = FrameType.Headers,
                Length   = 0,
                Flags    = 0,
                StreamId = 2,
            };
            await inPipe.WriteFrameHeader(fh);

            await outPipe.ReadAndDiscardSettings();

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 27
0
        public async Task ConnectionShouldGoAwayOnSettingsStreamIdNonZero()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            var fh = new FrameHeader
            {
                Type     = FrameType.Settings,
                Length   = Settings.Default.RequiredSize,
                Flags    = 0,
                StreamId = 1,
            };
            await inPipe.WriteFrameHeader(fh);

            await outPipe.ReadAndDiscardSettings();

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 28
0
        public async Task ConnectionShouldGoAwayOnInvalidSettingsMaxLengthExceeded()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe);
            await ClientPreface.WriteAsync(inPipe);

            var fh = new FrameHeader
            {
                Type     = FrameType.Settings,
                Length   = (int)Settings.Default.MaxFrameSize + 1,
                Flags    = 0,
                StreamId = 0,
            };
            await inPipe.WriteFrameHeader(fh);

            await outPipe.ReadAndDiscardSettings();

            await outPipe.AssertGoAwayReception(ErrorCode.FrameSizeError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 29
0
        public async Task ConnectionShouldGoAwayOnInvalidGoAwayStreamId(
            bool isServer)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var goAwayData = new GoAwayFrameData
            {
                Reason = new GoAwayReason
                {
                    LastStreamId = 0u,
                    ErrorCode    = ErrorCode.NoError,
                    DebugData    = new ArraySegment <byte>(new byte[0]),
                },
            };

            var fh = new FrameHeader
            {
                Type     = FrameType.GoAway,
                Flags    = 0,
                StreamId = 1,
                Length   = goAwayData.RequiredSize,
            };

            var dataBytes = new byte[goAwayData.RequiredSize];

            goAwayData.EncodeInto(new ArraySegment <byte>(dataBytes));
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(new ArraySegment <byte>(dataBytes));

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 30
0
        public async Task GoAwayShouldBeSendable(bool withConnectionClose)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Start the GoAway process in a background task.
            // As waiting for this will block the current task in case
            // of connection close
            var closeTask = Task.Run(() =>
                                     res.conn.GoAwayAsync(ErrorCode.InternalError, withConnectionClose));
            // Expect the GoAway message
            await outPipe.AssertGoAwayReception(ErrorCode.InternalError, 1u);

            if (withConnectionClose)
            {
                await outPipe.AssertStreamEnd();

                await inPipe.CloseAsync();
            }
            await closeTask;
        }