private async Task ConnectWithProxyAsync()

in src/Microsoft.Azure.Relay/WebSockets/NetStandard20/WebSocketHandle.Managed.cs [222:304]


        private async Task ConnectWithProxyAsync(Uri uri, ClientWebSocketOptions options, Stream stream, CancellationToken cancellationToken)
        {
            const string successStatusCode = "HTTP/1.1 200";
            const string proxyAuthenticationStatusCode = "HTTP/1.1 407";
            const string Basic = "Basic ";
            const string Digest = "Digest ";
            AuthenticationHeaderValue ahv = null;

            string statusLine = await SendRequestToProxyAsync(uri, options, stream, ahv, cancellationToken).ConfigureAwait(false);
            if (statusLine == successStatusCode)
            {
                // Proxy connection succeeded.
                return;
            }

            // Proxy requires authentication.
            if (statusLine.StartsWith(proxyAuthenticationStatusCode))
            {
                if (statusLine.Length > proxyAuthenticationStatusCode.Length &&
                    !char.IsWhiteSpace(statusLine[proxyAuthenticationStatusCode.Length]))
                {
                    throw new WebSocketException(SR.net_webstatus_ConnectFailure);
                }

                string line;
                int contentLength = 0;
                while (!string.IsNullOrEmpty((line = await ReadResponseHeaderLineAsync(stream, cancellationToken).ConfigureAwait(false))))
                {
                    if (line.StartsWith("Proxy-Authenticate", StringComparison.OrdinalIgnoreCase))
                    {
                        int colon = line.IndexOf(':');
                        if (colon == -1 || colon == line.Length - 1)
                        {
                            throw new WebSocketException(SR.Format(SR.net_WebSockets_InvalidResponseHeader, "Proxy-Authenticate", line));
                        }

                        string authenticateString = line.Substring(colon + 1);
                        string authHeader = GetParameterForScheme(authenticateString, Digest) ?? GetParameterForScheme(authenticateString, Basic);
                        if (authHeader != null)
                        {
                            ahv = AuthenticationHeaderValue.Parse(authHeader);
                        }
                    }
                    else if (line.StartsWith("Content-Length", StringComparison.OrdinalIgnoreCase))
                    {
                        int colon = line.IndexOf(':');
                        if (colon == -1 || colon == line.Length - 1)
                        {
                            throw new WebSocketException(SR.Format(SR.net_WebSockets_InvalidResponseHeader, "Content-Length", line));
                        }

                        int.TryParse(line.Substring(colon + 1), out contentLength);
                    }
                    else if (line.StartsWith("Transfer-Encoding:", StringComparison.OrdinalIgnoreCase))
                    {
                        int nextValidIndex = line.IndexOf(':') + 1;
                        if (nextValidIndex < line.Length && line.SubstringTrim(nextValidIndex).Equals("chunked", StringComparison.OrdinalIgnoreCase))
                        {
                            throw new WebSocketException(SR.net_webstatus_ConnectFailure + " " + line);
                        }
                    }
                }

                if (ahv == null)
                {
                    throw new WebSocketException(SR.net_webstatus_ConnectFailure);
                }

                // Read any response content from proxy.
                await ReadResponseContent(stream, contentLength, cancellationToken).ConfigureAwait(false);

                // Retry request to proxy with authorization header.
                statusLine = await SendRequestToProxyAsync(uri, options, stream, ahv, cancellationToken).ConfigureAwait(false);

                if (statusLine == successStatusCode)
                {
                    return;
                }
            }

            // Failed to connect to proxy.
            throw new WebSocketException(SR.net_webstatus_ConnectFailure);
        }