示例#1
0
 private void BeginRead()
 {
     if (HttpStream.CanRead && Running)
     {
         HttpStream.BeginRead(ReadBuffer, BytesRead, 2048, CompleteRead, null);
     }
 }
示例#2
0
        public override void OnOperation(HttpListenerContext context, Authentication authentication)
        {
            context.Response.ContentType = "application/json";

            byte[] data = Misc.ToByteArray(context.Request.InputStream);
            string json = Encoding.UTF8.GetString(data);

            if (!authentication.IsSignedIn)
            {
                HttpStream stream = new HttpStream(context.Response);
                stream.Send(new SignOutResponse()
                {
                    Error = "You are not signed in."
                }.ToJson());
                stream.Close();
                return;
            }

            SessionsManager.Instance.RemoveSession(authentication.SessionID);

            // Delete the sessionID cookie
            Cookie cookie = context.Request.Cookies["SessionID"];

            cookie.Expires = DateTime.Now.AddDays(-10);
            cookie.Value   = null;
            context.Response.SetCookie(cookie);

            HttpStream httpStream = new HttpStream(context.Response);

            httpStream.Send(new SignOutResponse()
            {
                message = "signed out!"
            }.ToJson());
            httpStream.Close();
        }
        public override void OnOperation(HttpListenerContext context, Authentication authentication)
        {
            string id = context.Request.QueryString["id"];

            if (!UploadedModsManager.Instance.HasModWithIdBeenUploaded(id))
            {
                Utils.SendErrorPage(context.Response, "No mod with the id \"" + id + "\" has been uploaded", true, HttpStatusCode.NotFound);
                return;
            }

            string path = UploadedModsManager.Instance.GetZippedFileForMod(id);

            byte[] data = File.ReadAllBytes(path);

            string displayName = UploadedModsManager.Instance.GetModInfoFromId(id).DisplayName + ".zip";

            displayName = displayName.Replace(' ', '_');
            foreach (char c in Path.GetInvalidFileNameChars())
            {
                displayName = displayName.Replace(c, '_');
            }

            SpecialModData specialModData = UploadedModsManager.Instance.GetSpecialModInfoFromId(id);

            specialModData.Downloads++;
            specialModData.Save();

            HttpStream httpStream = new HttpStream(context.Response);

            httpStream.SendFile(data, displayName);
            httpStream.Close();
        }
示例#4
0
 private void CompleteRead(IAsyncResult ar)
 {
     BytesRead += HttpStream.EndRead(ar);
     NotifyObservers();
     InitializeBuffer();
     BeginRead();
 }
示例#5
0
        /// <summary>从Http上下文获取数据流</summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public virtual Stream GetStream(HttpContext context)
        {
            HttpStream stream = null;
            String     method = context.Request.HttpMethod;

            if (method == "POST")
            {
                if (context.Request.ContentLength > 0)
                {
                    stream = new HttpStream(context);
                    return(stream);
                }
            }
            //else if (method == "GET")
            {
                if (context.Request.QueryString != null && context.Request.QueryString.Count == 1)
                {
                    String queryText = context.Request.QueryString[0];
                    if (!String.IsNullOrEmpty(queryText))
                    {
                        Byte[] data = FromHex(queryText);
                        if (data != null && data.Length > 0)
                        {
                            stream             = new HttpStream(context);
                            stream.InputStream = new MemoryStream(data);
                        }
                    }
                }
            }
            return(stream);
        }
示例#6
0
        public override void OnOperation(HttpListenerContext context, Authentication authentication)
        {
            context.Response.ContentType = "text/plain";
            HttpStream stream = new HttpStream(context.Response);

            stream.Send(authentication.IP);
            stream.Close();
        }
示例#7
0
            public void ProcessRequest()
            {
                try
                {
                    do
                    {
                        _clientStream = new HttpStream(_client);
                        _session      = new Session();
                        if (CheckServerTimeOut())
                        {
                            return;
                        }
                        ReceiveRequest();
                        if (_session.Request.Method == null)
                        {
                            return;
                        }
                        if (_session.Request.Method == "CONNECT")
                        {
                            HandleConnect();
                            return;
                        }
                        if (_session.Request.Host.StartsWith("localhost") ||
                            _session.Request.Host.StartsWith("127.0.0.1"))
                        {
                            LogServer.Process(_client, _session.Request.RequestLine);
                            return;
                        }
                        SendRequest();
                        ReceiveRequestBody();
                        SendRequestBody();
                        ReceiveResponse();
                        if (_session.Response.StatusCode == null)
                        {
                            return;
                        }
                        AfterSessionComplete?.Invoke(_session);
                        SendResponse();
                    } while (_client.Connected && _server.Connected &&
                             _session.Request.IsKeepAlive && _session.Response.IsKeepAlive);
                }
#if DEBUG
                catch (Exception e)
                {
                    lock (SyncObj)
                        File.AppendAllText("debug.log", $"[{DateTime.Now:g}] " + e + "\r\n");
                }
#else // ReSharper disable once EmptyGeneralCatchClause
                catch
                {
                }
#endif
                finally
                {
                    Close();
                }
            }
示例#8
0
 private void SendRequest()
 {
     GetHostAndPort(out var host, out var port);
     if (_server == null || host != _host || port != _port || IsSocketDead(_server))
     {
         SocketClose(_server);
         _server = ConnectServer(host, port);
         _host   = host;
         _port   = port;
     }
     _serverStream =
         new HttpStream(_server).WriteLines(_session.Request.RequestLine + _session.Request.ModifiedHeaders);
 }
示例#9
0
        /// <inheritdoc />
        public override async Task HandleConnectionAsync(IConnection connection, ILogger logger)
        {
            var streams   = connection.Stream.CreateStreams();
            var outStream = streams.WriteableStream;
            var stream    = new HttpStream(streams.ReadableStream);
            await stream.WaitForHttpHeader();

            var req = HttpRequest.ParseFrom(
                Encoding.ASCII.GetString(
                    stream.HeaderBytes.Array, stream.HeaderBytes.Offset, stream.HeaderBytes.Count - 4),
                (MethodResolver <HttpMethod>)MethodResolver, connection);

            if (req.ExpectPayload && req.Headers.TryGetValue("content-length", out string contentLength))
            {
                if (int.TryParse(contentLength, out var length))
                {
                    await stream.WaitForPayloadAsync(length);

                    req.Payload = new ArraySegment <byte>(stream.Payload.ToArray(), 0, length).ToArray();
                }
                else
                {
                    await outStream.WriteAsync(
                        new ArraySegment <byte>(Encoding.ASCII.GetBytes(
                                                    "HTTP/1.1 400 Bad Request\r\nServer: SimpleServer\r\nContent-Type: text/html\r\nContent-Length: 26\r\n\r\nThe payload was too large.")));

                    await outStream.CloseAsync();

                    return;
                }
            }
            else if (req.ExpectPayload)
            {
                await outStream.WriteAsync(
                    new ArraySegment <byte>(Encoding.ASCII.GetBytes(
                                                "HTTP/1.1 400 Bad Request\r\nServer: SimpleServer\r\nContent-Type: text/html\r\nContent-Length: 25\r\n\r\nNo content-length header.")));

                await outStream.CloseAsync();

                return;
            }

            var request = req.Request;

#pragma warning disable 618
            logger?.LogInformation(request.Method.Id + " " + request.RawUrl + " " + request.Protocol);
#pragma warning restore 618
            PassContext(new HttpContext(request, new HttpOneResponse(request, connection), connection, logger));
        }
示例#10
0
        public async Task DownloadExtractZipArchiveAsync(Download download, DirectoryInfo extractDirectory, DownloadProgress progress, CancellationToken cancellationToken)
        {
            var bytesTransferred = 0L;

            using var headResponse = await _options.HttpClient.SendAsync(new HttpRequestMessage (HttpMethod.Head, download.Archive.Url), cancellationToken);

            var contentLength = headResponse.Content.Headers.ContentLength ?? 0;
            var cacheFile     = new FileInfo(Path.Combine(_options.CacheDirectory.FullName, download.Archive.Url.Segments.Last()));

            await using var cacheStream = new FileStream(cacheFile.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
            var stopwatch = Stopwatch.StartNew();

            await using var httpStream  = new HttpStream(download.Archive.Url, cacheStream, ownStream: false, CachePageSize, cached: null);
            httpStream.RangeDownloaded += (_, args) =>
            {
                bytesTransferred += args.Length;
                progress.Report(new CopyProgress(stopwatch.Elapsed, 0, bytesTransferred, contentLength));
            };
            using var zipFile = new ZipFile(httpStream);
            var binaryRegex  = _options.Binaries[(download.Product, download.Platform)];
示例#11
0
        static void Main(string[] args)
        {
            try
            {
                var httpStream = new HttpStream(new Uri(args[0]));
                var size       = (int)httpStream.Length;
                var first      = Math.Min(1024, size);
                var second     = size - first;

                var mem        = new byte[size];
                var head       = httpStream.Read(mem, 0, 1);
                var firstRead  = httpStream.Read(mem, 1, first - 1);
                var secondRead = httpStream.Read(mem, first, second);
                var pos        = httpStream.Position;

                Console.WriteLine($"Pos={pos}, Length={size}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"{e.Message}\n{e.StackTrace}");
            }
        }
示例#12
0
        public override void OnOperation(HttpListenerContext context, Authentication authentication)
        {
            if (!context.Request.IsWebSocketRequest)
            {
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                HttpStream httpStream = new HttpStream(context.Response);
                httpStream.Send("<html><body>websocket only!</body></html>");
                httpStream.Close();
            }

            if (!authentication.HasAtLeastAuthenticationLevel(Users.AuthenticationLevel.Admin))
            {
                HttpListenerWebSocketContext webNoSocket = context.AcceptWebSocketAsync(null).ConfigureAwait(true).GetAwaiter().GetResult();
                byte[] buffer = Encoding.UTF8.GetBytes("You do not have the requierd permissions to use this.");
                webNoSocket.WebSocket.SendAsync(new ArraySegment <byte>(buffer), WebSocketMessageType.Text, true, System.Threading.CancellationToken.None).ConfigureAwait(true).GetAwaiter().GetResult();
                webNoSocket.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "You do not have the requierd permissions to use this.", System.Threading.CancellationToken.None).ConfigureAwait(true).GetAwaiter().GetResult();
                webNoSocket.WebSocket.Dispose();
                return;
            }

            Task.Factory.StartNew(() => handleWebSocket(context, authentication));
        }
示例#13
0
        private static Http2Connection.Http2Stream OpenHttp2Stream(
            string scheme, string host, int port,
            X509CertificateCollection clientCertificates,
            SslProtocols enabledSslProtocols,
            bool checkCertificateRevocation,
            RemoteCertificateValidationCallback remoteCertificateValidationCallback,
            bool enableIPv6)
        {
            Http2Connection.Http2Stream h2stream = TryReuseStream(scheme, host, port);
            if (h2stream != null)
            {
                return(h2stream);
            }

            Stream s;

            if (scheme == Uri.UriSchemeHttp)
            {
                s = new HttpStream(ConnectToTcp(host, port, enableIPv6))
                {
                    IsReusable = false
                };
            }
            else if (scheme == Uri.UriSchemeHttps)
            {
                s = ConnectToSslServer(host, port, clientCertificates, enabledSslProtocols, checkCertificateRevocation, false, remoteCertificateValidationCallback, enableIPv6);
            }
            else
            {
                throw new NotSupportedException();
            }

            var h2con = new Http2Connection(s, false);

            h2stream = h2con.OpenClientStream();
            AddH2Connection(h2con, scheme, host, port);
            return(h2stream);
        }
示例#14
0
        public override void OnOperation(HttpListenerContext context, Authentication authentication)
        {
            string key = Utils.GenerateSecureKey();

            NotesManager.Instance.SetNote(key, "Operation still loading....");

            HttpStream stream = new HttpStream(context.Response);

            stream.Send("Link: https://modbot.org/api?operation=noteOperation&key=" + key);
            stream.Close();

            string output;

            try
            {
                output = OnFrontendPushed();
            }
            catch (Exception e)
            {
                output = "Error!\n" + e.ToString();
            }

            NotesManager.Instance.SetNote(key, output);
        }
示例#15
0
 public HttpStream(HttpWebRequest req, bool computeContentLength)
     : this(req, HttpStream.OpenStream(req), computeContentLength)
 {
 }
示例#16
0
        public static void AsyncDownloadFile(object o)
        {
            var             Param = (ThreadParam)o;
            HttpWebRequest  Request;
            HttpWebResponse Response;
            Stream          HttpStream;
            FileStream      OutStream;
            Int32           ReadBytes = 0;

            Byte[] Buffer          = new Byte[1024];
            int    statictime      = System.Environment.TickCount;
            int    CountTime       = 0;
            int    CountingBytenum = 0;

            while (true)
            {
                Param.mStartEvent.WaitOne();
                if (-1 == Param.mBeginBlock)
                {
                    Param.mStartEvent.Reset();
                    Param.mDoneEvent.Set();
                    continue;
                }

                try
                {
                    Request = WebRequest.Create(Param.url /* + "//" + Param.mFileName*/) as HttpWebRequest;
                    Request.AddRange(Param.mBeginBlock, Param.mEndBlock);

                    Response = Request.GetResponse() as HttpWebResponse;
                    //Response.StatusCode; 这个值为200表示一切OK
                    HttpStream = Response.GetResponseStream();
                    OutStream  = new FileStream(Param.mFileName + Param.mId.ToString(), FileMode.Create);
                    while (true)
                    {
                        ReadBytes = HttpStream.Read(Buffer, 0, Buffer.Length);
                        if (ReadBytes <= 0)
                        {
                            break;
                        }
                        Param.mDownloadSize += ReadBytes;
                        int atime     = Environment.TickCount;
                        int deltatime = atime - statictime;
                        CountTime += deltatime;
                        if (CountTime >= 1000)
                        {
                            Param.mSpeed    = CountingBytenum;
                            CountTime       = 0;
                            CountingBytenum = 0;
                        }
                        else
                        {
                            CountingBytenum += ReadBytes;
                        }
                        statictime = atime;

                        OutStream.Write(Buffer, 0, ReadBytes);
                    }
                    OutStream.Close();
                    HttpStream.Close();
                    Response.Close();
                    Request.Abort();
                    Param.mStartEvent.Reset();
                    Param.mDoneEvent.Set();
                }
                catch (WebException e)
                {
                }
            }
        }
示例#17
0
 public ValueTask <string?> ReadLineAsync(CancellationToken cancellationToken = default)
 {
     return(HttpStream.ReadLineInternalAsync(this, bufferPool, cancellationToken));
 }
示例#18
0
        private void DoClient()
        {
            string lastRequest = null;

            try
            {
                DateTime lastRequestWriteUtc = DateTime.MinValue;
                int      repeated            = 0;

                var buffer = new byte[BUFFER_LENGTH];
                int read;

                client.SendBufferSize    = SEND_BUFFER_LENGTH;
                client.ReceiveBufferSize = RECEIVE_BUFFER_LENGTH;

                HttpStream            stream = new HttpStream(client.GetStream());
                HttpStream.HttpHeader header;

                while (client.Connected)
                {
                    if ((read = stream.ReadHeader(buffer, 0, out header)) == 0)
                    {
                        return;
                    }

                    try
                    {
                        do
                        {
                            read = stream.Read(buffer, 0, BUFFER_LENGTH);
                        }while (read > 0);

                        var request = (HttpStream.HttpRequestHeader)header;
                        var source  = Path.Combine(root, Util.FileName.FromAssetRequest(request.Location));

                        if (RequestHeaderReceived != null)
                        {
                            RequestHeaderReceived(this, request);
                        }

                        bool retry = false;
                        do
                        {
                            var fi = new FileInfo(source);
                            if (fi.Exists)
                            {
                                if (!retry && lastRequest == request.Location)
                                {
                                    if (lastRequestWriteUtc != fi.LastWriteTimeUtc)
                                    {
                                        lastRequestWriteUtc = fi.LastWriteTimeUtc;
                                        repeated            = 0;
                                    }
                                    else if (++repeated == 2)
                                    {
                                        //saved data is likely corrupted
                                        if (RequestRepeated != null)
                                        {
                                            RequestRepeated(this, request.Location);
                                        }
                                    }
                                }
                                else
                                {
                                    lastRequest         = request.Location;
                                    repeated            = 0;
                                    lastRequestWriteUtc = fi.LastWriteTimeUtc;
                                    retry = false;
                                }

                                bool headers = true;
                                using (var r = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
                                {
                                    do
                                    {
                                        read = r.Read(buffer, 0, BUFFER_LENGTH);
                                        if (read > 0)
                                        {
                                            int offset = 0;

                                            if (headers)
                                            {
                                                headers = false;
                                                var h = BitConverter.ToUInt32(buffer, 0);
                                                if (h == HEADER_HTTP_UPPER || h == HEADER_HTTP_LOWER)
                                                {
                                                    //already has headers

                                                    int n = 0;
                                                    for (var i = 0; i < read; i++)
                                                    {
                                                        switch (buffer[i])
                                                        {
                                                        case (byte)'\r':
                                                            break;

                                                        case (byte)'\n':
                                                            if (++n == 2)
                                                            {
                                                                stream.Write(buffer, 0, offset = i + 1);
                                                                i = read;
                                                            }
                                                            break;

                                                        default:
                                                            n = 0;
                                                            break;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    //warning: only full files can have empty headers - checksum required for patches
                                                    WriteHeader(stream, r.Length);
                                                    stream.Write(buffer, 0, read);
                                                }
                                            }

                                            while (offset < read)
                                            {
                                                int c = read - offset;
                                                if (c > SEND_BUFFER_LENGTH)
                                                {
                                                    c = SEND_BUFFER_LENGTH;
                                                }
                                                stream.Write(buffer, offset, c);
                                                offset += c;
                                            }
                                        }
                                    }while (read > 0);
                                }
                            }
                            else
                            {
                                if (retry)
                                {
                                    retry = false;
                                }
                                else
                                {
                                    if (FileNotFound != null)
                                    {
                                        FileNotFoundEventArgs e = new FileNotFoundEventArgs(request.Location);
                                        FileNotFound(this, e);
                                        if (e.Retry)
                                        {
                                            retry = true;
                                        }
                                    }
                                }

                                //sending a bad response will cause GW2 to try different versions:
                                //patch (baseId/fileId) > full file compressed (0/fileId/compressed) > full file (0/fileId)
                                if (!retry)
                                {
                                    WriteHeader(stream, 404, "Not Found");
                                }
                            }
                        }while (retry);

                        var keepAlive = request.Headers[HttpRequestHeader.Connection];
                        if (keepAlive == null || !keepAlive.Equals("keep-alive", StringComparison.OrdinalIgnoreCase))
                        {
                            return;
                        }
                    }
                    finally
                    {
                    }
                }
            }
            catch (Exception e)
            {
                if (Error != null)
                {
                    Error(this, e);
                }
            }
            finally
            {
                server.ActiveStateChanged -= server_ActiveStateChanged;

                if (client != null)
                {
                    client.Close();
                }

                if (Closed != null)
                {
                    Closed(this, EventArgs.Empty);
                }
            }
        }
示例#19
0
        private async Task HandleConnection(
            ILogger logger,
            ConnectionByteStream stream)
        {
            var config = new ConnectionConfigurationBuilder(true)
                         .UseStreamListener(arg =>
            {
                Task.Run(() =>
                {
                    var headers  = arg.ReadHeadersAsync().GetAwaiter().GetResult();
                    var optional = HttpRequest.ParseFrom(new HttpHeaderCollection(headers),
                                                         new HttpMethodResolver(Methods));
                    if (optional.ExpectPayload)
                    {
                        var seg = new ArraySegment <byte>(new byte[int.Parse(optional.Headers["content-length"])]);
                        // TODO: Use the StreamReadResult, as sometimes the packets won't all be sent at once
                        arg.ReadAsync(seg).GetAwaiter().GetResult();
                        optional.Payload = seg.ToArray();
                    }

                    var req = optional.Request;
                    PassContext(new HttpContext(req, new HttpTwoResponse(arg), stream.Connection, logger));
                });
                return(true);
            })
                         .UseSettings(Settings.Default)
                         .UseHuffmanStrategy(HuffmanStrategy.IfSmaller)
                         .Build();
            var upgradeReadStream           = new HttpStream(stream);
            ServerUpgradeRequest upgrade    = null;
            var writeAndCloseableByteStream = stream;

            try
            {
                // Wait for either HTTP/1 upgrade header or HTTP/2 magic header
                await upgradeReadStream.WaitForHttpHeader();

                var headerBytes = upgradeReadStream.HeaderBytes;
                if (MaybeHttpStart(headerBytes))
                {
                    // This seems to be a HTTP/2 request
                    upgradeReadStream.Unread();
                }
                else
                {
                    // This seems to be a HTTP/1 request
                    // Parse the header and check whether it's an upgrade
                    var req = HttpRequest.ParseFrom(
                        Encoding.ASCII.GetString(
                            headerBytes.Array, headerBytes.Offset, headerBytes.Count - 4),
                        (MethodResolver <HttpMethod>)MethodResolver, stream.Connection);

                    if (req.ExpectPayload && req.Headers.TryGetValue("content-length", out string contentLength))
                    {
                        if (int.TryParse(contentLength, out var length))
                        {
                            await upgradeReadStream.WaitForPayloadAsync(length);

                            req.Payload = upgradeReadStream.Payload.ToArray();
                        }
                        else
                        {
                            await stream.WriteAsync(
                                new ArraySegment <byte>(Encoding.ASCII.GetBytes(
                                                            "HTTP/1.1 400 Bad Request\r\nServer: SimpleServer/1.0 sshttp2\r\nContent-Type: text/html\r\nContent-Length: 26\r\n\r\nThe payload was too large.")));

                            await stream.CloseAsync();

                            return;
                        }
                    }
                    else if (req.ExpectPayload)
                    {
                        await stream.WriteAsync(
                            new ArraySegment <byte>(Encoding.ASCII.GetBytes(
                                                        "HTTP/1.1 400 Bad Request\r\nServer: SimpleServer/1.0 sshttp2\r\nContent-Type: text/html\r\nContent-Length: 25\r\n\r\nNo content-length header.")));

                        await stream.CloseAsync();

                        return;
                    }

                    // Assure that the HTTP/2 library does not get passed the HTTP/1 request
                    upgradeReadStream.Consume();

                    var request = req.Request;

#pragma warning disable 618
                    if (request.Protocol != "HTTP/1.1")
#pragma warning restore 618
                    {
                        PassContext(new HttpContext(request, new HttpOneResponse(request, stream.Connection),
                                                    stream.Connection, logger));
                        return;
                    }

                    if (!request.Headers.TryGetValue("connection", out string connectionHeader) ||
                        !request.Headers.TryGetValue("host", out string _) ||
                        !request.Headers.TryGetValue("upgrade", out string upgradeHeader) ||
                        !request.Headers.TryGetValue("http2-settings", out string http2SettingsHeader) ||
                        upgradeHeader != "h2c" ||
                        http2SettingsHeader.Length == 0)
                    {
                        // STAY H1
                        PassContext(new HttpContext(request, new HttpOneResponse(request, stream.Connection),
                                                    stream.Connection, logger));
                        return;
                    }

                    var connParts =
                        connectionHeader
                        .Split(',')
                        .Select(p => p.Trim())
                        .ToArray();
                    if (connParts.Length != 2 ||
                        !connParts.Contains("Upgrade") ||
                        !connParts.Contains("HTTP2-Settings"))
                    {
                        PassContext(new HttpContext(request, new HttpOneResponse(request, stream.Connection),
                                                    stream.Connection, logger));
                    }

                    var headers = new List <HeaderField>
                    {
                        new HeaderField {
                            Name = ":method", Value = request.Method.Id
                        },
                        new HeaderField {
                            Name = ":path", Value = request.RawUrl
                        },
                        new HeaderField
                        {
                            Name = ":scheme",
#if NETCOREAPP2_1 || NETSTANDARD2_1
                            Value = stream.Connection is SslListener.SecureConnection ? "https" : "http"
                            #else
                            Value = "http"
#endif
                        }
                    };
                    foreach (var kvp in request.Headers)
                    {
                        // Skip Connection upgrade related headers
                        if (kvp.Name == "connection" ||
                            kvp.Name == "upgrade" ||
                            kvp.Name == "http2-settings")
                        {
                            continue;
                        }
                        headers.Add(new HeaderField
                        {
                            Name  = kvp.Name,
                            Value = kvp.Value
                        });
                    }

                    var upgradeBuilder = new ServerUpgradeRequestBuilder();
                    upgradeBuilder.SetHeaders(headers);
                    upgradeBuilder.SetPayload(new ArraySegment <byte>(req.Payload));
                    upgradeBuilder.SetHttp2Settings(http2SettingsHeader);
                    upgrade = upgradeBuilder.Build();

                    if (!upgrade.IsValid)
                    {
                        // STAY H1
                        PassContext(new HttpContext(request, new HttpOneResponse(request, stream.Connection),
                                                    stream.Connection, logger));
                        return;
                    }

                    // Respond to upgrade
                    await writeAndCloseableByteStream.WriteAsync(
                        new ArraySegment <byte>(UpgradeSuccessResponse));
                }
            }
            catch (Exception e)
            {
                logger?.LogError(new EventId(stream.Connection.Id, "StartFail"), e,
                                 "An error occured while trying to upgrade a HTTP/1.X request to a H2 request.");
                await writeAndCloseableByteStream.CloseAsync();

                return;
            }

            // Build a H2 connection
            var http2Con = new Connection(
                config, upgradeReadStream, writeAndCloseableByteStream,
                new Connection.Options
            {
                Logger = logger,
                ServerUpgradeRequest = upgrade
            });

            // Close the connection if we get a GoAway from the client
            var remoteGoAwayTask = http2Con.RemoteGoAwayReason;
#pragma warning disable 4014
            Task.Run(async() =>
#pragma warning restore 4014
            {
                await remoteGoAwayTask;
                await http2Con.GoAwayAsync(ErrorCode.NoError, true);
            });
        }