/// <summary>
        /// Inspect if request if http2 upgrade
        /// If so starts http2 session via provider.
        /// Calls next layer if not.
        /// </summary>
        /// <param name="environment">The environment.</param>
        /// <returns></returns>
        public async Task Invoke(IDictionary<string, object> environment)
        {
            var context = new OwinContext(environment);

            if (IsOpaqueUpgradePossible(context.Request) && IsRequestForHttp2Upgrade(context.Request))
            {
                var upgradeDelegate = environment[CommonOwinKeys.OpaqueUpgrade] as UpgradeDelegate;
                Debug.Assert(upgradeDelegate != null, "upgradeDelegate is not null");

                var trInfo = CreateTransportInfo(context.Request);

                // save original request parameters; used to complete request after upaque upgrade is done
                var requestCopy = GetInitialRequestParams(context.Request);

                upgradeDelegate.Invoke(new Dictionary<string, object>(), async opaque =>
                    {
                        //use the same stream which was used during upgrade
                        var opaqueStream = opaque[CommonOwinKeys.OpaqueStream] as DuplexStream;

                        //TODO Provide cancellation token here
                        // Move to method
                        try
                        {
                            using (var http2MessageHandler = new Http2OwinMessageHandler(opaqueStream,
                                                                                            ConnectionEnd.Server,
                                                                                            trInfo, _next,
                                                                                            CancellationToken.None)
                                )
                            {
                                await http2MessageHandler.StartSessionAsync(requestCopy);
                                GC.Collect();
                            }
                        }
                        catch (Exception ex)
                        {
                            Http2Logger.LogError(ex.Message);
                        }
                    });

                // specify Upgrade protocol
                context.Response.Headers.Add(CommonHeaders.Upgrade, new[] { Protocols.Http2 });
                return;
            }

            //If we dont have upgrade delegate then pass request to the next layer
            await _next(environment);
        }
        private async void OpenHttp2Session(DuplexStream incomingClientStream, 
                                            TransportInformation transportInformation)
        {
            Http2Logger.LogDebug("Handshake successful");
            using (var messageHandler = new Http2OwinMessageHandler(incomingClientStream, ConnectionEnd.Server, transportInformation, _next, _cancelClientHandling.Token))
            {
                try
                {
                    await messageHandler.StartSessionAsync();
                }
                catch (Exception)
                {
                    Http2Logger.LogError("Client was disconnected");
                }
            }

            GC.Collect();
        }