HttpConnector
Establishes a tunnel via an HTTP proxy server.
            
                using Microsoft.Extensions.Logging;
using Renci.SshNet.Abstractions;
using Renci.SshNet.Common;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Text.RegularExpressions.Generated;
namespace Renci.SshNet.Connection
{
    internal sealed class HttpConnector : ProxyConnector
    {
        private const string HttpResponsePattern = "HTTP/(?<version>\\d[.]\\d) (?<statusCode>\\d{3}) (?<reasonPhrase>.+)$";
        private const string HttpHeaderPattern = "(?<fieldName>[^\\[\\]()<>@,;:\\\"/?={} \\t]+):(?<fieldValue>.+)?";
        private static readonly Regex HttpResponseRegex = GetHttpResponseRegex();
        private static readonly Regex HttpHeaderRegex = GetHttpHeaderRegex();
        [GeneratedRegex("HTTP/(?<version>\\d[.]\\d) (?<statusCode>\\d{3}) (?<reasonPhrase>.+)$")]
        [GeneratedCode("System.Text.RegularExpressions.Generator", "9.0.12.47515")]
        private static Regex GetHttpResponseRegex()
        {
            return <RegexGenerator_g>F13E84412258E915343E1B989C87CC052DFF95FC67A1DE317EDD2CB1D2C91A559__GetHttpResponseRegex_0.Instance;
        }
        [GeneratedRegex("(?<fieldName>[^\\[\\]()<>@,;:\\\"/?={} \\t]+):(?<fieldValue>.+)?")]
        [GeneratedCode("System.Text.RegularExpressions.Generator", "9.0.12.47515")]
        private static Regex GetHttpHeaderRegex()
        {
            return <RegexGenerator_g>F13E84412258E915343E1B989C87CC052DFF95FC67A1DE317EDD2CB1D2C91A559__GetHttpHeaderRegex_1.Instance;
        }
        public HttpConnector(ISocketFactory socketFactory, ILoggerFactory loggerFactory)
            : base(socketFactory, loggerFactory)
        {
        }
        protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket)
        {
            SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(string.Format(CultureInfo.InvariantCulture, "CONNECT {0}:{1} HTTP/1.0\r\n", connectionInfo.Host, connectionInfo.Port)));
            if (!string.IsNullOrEmpty(connectionInfo.ProxyUsername)) {
                string s = string.Format(CultureInfo.InvariantCulture, "Proxy-Authorization: Basic {0}\r\n", Convert.ToBase64String(SshData.Ascii.GetBytes(connectionInfo.ProxyUsername + ":" + connectionInfo.ProxyPassword)));
                SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(s));
            }
            SocketAbstraction.Send(socket, SshData.Ascii.GetBytes("\r\n"));
            HttpStatusCode? nullable = null;
            int num = 0;
            while (true) {
                string text = SocketReadLine(socket, connectionInfo.Timeout);
                if (text == null)
                    break;
                if (!nullable.HasValue) {
                    Match match = HttpResponseRegex.Match(text);
                    if (match.Success) {
                        string text2 = match.Result("${statusCode}");
                        nullable = (HttpStatusCode)int.Parse(text2, CultureInfo.InvariantCulture);
                        if (nullable.GetValueOrDefault() != HttpStatusCode.OK) {
                            DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(22, 2);
                            defaultInterpolatedStringHandler.AppendLiteral("HTTP: Status code ");
                            defaultInterpolatedStringHandler.AppendFormatted(text2);
                            defaultInterpolatedStringHandler.AppendLiteral(", \"");
                            defaultInterpolatedStringHandler.AppendFormatted(match.Result("${reasonPhrase}"));
                            defaultInterpolatedStringHandler.AppendLiteral("\"");
                            throw new ProxyException(defaultInterpolatedStringHandler.ToStringAndClear());
                        }
                    }
                } else {
                    Match match2 = HttpHeaderRegex.Match(text);
                    if (match2.Success) {
                        if (match2.Result("${fieldName}").Equals("Content-Length", StringComparison.OrdinalIgnoreCase))
                            num = int.Parse(match2.Result("${fieldValue}"), CultureInfo.InvariantCulture);
                    } else if (text.Length == 0) {
                        if (num > 0) {
                            byte[] buffer = new byte[num];
                            ConnectorBase.SocketRead(socket, buffer, 0, num, connectionInfo.Timeout);
                        }
                        break;
                    }
                }
            }
            if (!nullable.HasValue)
                throw new ProxyException("HTTP response does not contain status line.");
        }
        private static string SocketReadLine(Socket socket, TimeSpan readTimeout)
        {
            Encoding ascii = SshData.Ascii;
            List<byte> list = new List<byte>();
            byte[] array = new byte[1];
            while (SocketAbstraction.Read(socket, array, 0, array.Length, readTimeout) != 0) {
                byte b = array[0];
                list.Add(b);
                if (b == 10 && list.Count > 1 && list[list.Count - 2] == 13)
                    return ascii.GetString(list.ToArray(), 0, list.Count - 2);
            }
            if (list.Count == 0)
                return null;
            return ascii.GetString(list.ToArray(), 0, list.Count);
        }
    }
}