private static string createCommandString(string host, int port, ProxyInfos proxyInfos)
        {
            string connectCmd;

            if (!string.IsNullOrEmpty(proxyInfos.UserName))
            {
                //  gets the user/pass into base64 encoded string in the form of [username]:[password]
                string auth = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", proxyInfos.UserName, proxyInfos.Password)));

                // PROXY SERVER REQUEST
                // =======================================================================
                //CONNECT starksoft.com:443 HTTP/1.0<CR><LF>
                //HOST starksoft.com:443<CR><LF>
                //Proxy-Authorization: username:password<CR><LF>
                //              NOTE: username:password string will be base64 encoded as one
                //                        concatenated string
                //[... other HTTP header lines ending with <CR><LF> if required]>
                //<CR><LF>    // Last Empty Line
                connectCmd = String.Format(CultureInfo.InvariantCulture, "CONNECT {0}:{1} HTTP/1.1\r\nUser-Agent: rabbitmq-net-client/3.5.3\r\nHost: {0}:{1}\r\nProxy-Authorization: Basic {2}\r\n\r\n", host, port.ToString(CultureInfo.InvariantCulture), auth);
            }
            else
            {
                // PROXY SERVER REQUEST
                // =======================================================================
                //CONNECT starksoft.com:443 HTTP/1.0 <CR><LF>
                //HOST starksoft.com:443<CR><LF>
                //[... other HTTP header lines ending with <CR><LF> if required]>
                //<CR><LF>    // Last Empty Line
                connectCmd = String.Format(CultureInfo.InvariantCulture, "CONNECT {0}:{1} HTTP/1.1\r\nUser-Agent: rabbitmq-net-client/3.5.3\r\nHost: {0}:{1}\r\n\r\n", host, port.ToString(CultureInfo.InvariantCulture));
            }
            return(connectCmd);
        }
        /// <summary>
        /// Constructor.  
        /// </summary>
        /// <param name="proxyHost">Host name or IP address of the proxy server.</param>
        /// <param name="proxyPort">Port number to connect to the proxy server.</param>
        /// <param name="proxyUsername">Username for the proxy server.</param>
        /// <param name="proxyPassword">Password for the proxy server.</param>
        public TunneledTcpClient(AddressFamily addressFamily, string proxyHost, int proxyPort, string proxyUsername = null, string proxyPassword = null) :
            base(null)
        {
            if (!String.IsNullOrEmpty(proxyHost) && (proxyPort <= 0 || proxyPort > 65535))
                throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535");

            _proxyInformation = new ProxyInfos(proxyHost, proxyPort, proxyUsername, proxyPassword);
            _addressFamily = addressFamily;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="proxyHost">Host name or IP address of the proxy server.</param>
        /// <param name="proxyPort">Port number to connect to the proxy server.</param>
        /// <param name="proxyUsername">Username for the proxy server.</param>
        /// <param name="proxyPassword">Password for the proxy server.</param>
        public TunneledTcpClient(AddressFamily addressFamily, string proxyHost, int proxyPort, string proxyUsername = null, string proxyPassword = null) :
            base(null)
        {
            if (!String.IsNullOrEmpty(proxyHost) && (proxyPort <= 0 || proxyPort > 65535))
            {
                throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535");
            }

            _proxyInformation = new ProxyInfos(proxyHost, proxyPort, proxyUsername, proxyPassword);
            _addressFamily    = addressFamily;
        }
        private static void sendConnectionCommand(TcpClient tcpClient, ProxyInfos infos, string host, int port)
        {
            //log.DebugFormat("Start sending connection command");

            NetworkStream stream = tcpClient.GetStream();

            string connectCmd = createCommandString(host, port, infos);

            //log.DebugFormat("Connect command: {0}", connectCmd);

            byte[] request = ASCIIEncoding.ASCII.GetBytes(connectCmd);

            // send the connect request
            stream.Write(request, 0, request.Length);

            // wait for the proxy server to respond
            waitForData(tcpClient, stream);


            //log.DebugFormat("Reponse for connection command available!");
            // PROXY SERVER RESPONSE
            // =======================================================================
            //HTTP/1.0 200 Connection Established<CR><LF>
            //[.... other HTTP header lines ending with <CR><LF>..
            //ignore all of them]
            //<CR><LF>    // Last Empty Line

            // create an byte response array
            byte[]        response = new byte[tcpClient.ReceiveBufferSize];
            StringBuilder sbuilder = new StringBuilder();
            int           bytes    = 0;
            long          total    = 0;

            do
            {
                bytes  = stream.Read(response, 0, tcpClient.ReceiveBufferSize);
                total += bytes;
                sbuilder.Append(System.Text.ASCIIEncoding.UTF8.GetString(response, 0, bytes));
            } while (stream.DataAvailable);

            var resp = parseResponse(sbuilder.ToString());

            //log.DebugFormat("Response: {0} - {1}", resp.Code, resp.Message);

            //  evaluate the reply code for an error condition
            if (resp.Code != HttpResponseCodes.OK)
            {
                handleProxyCommandError(host, port, tcpClient, resp);
            }

            //log.DebugFormat("Connection to destination established: {0}", tcpClient.Client.RemoteEndPoint);
        }
        /// <summary>
        /// Creates a remote TCP connection through a proxy server to the destination host on the destination port.
        /// </summary>
        /// <param name="destinationHost">Destination host name or IP address.</param>
        /// <param name="destinationPort">Port number to connect to on the destination host.</param>
        /// <param name="addressFamily">AdressFamliy for tcp client. Currently ignored.</param>
        /// <param name="proxyInfos">Dto for all container infos</param>
        /// <returns>
        /// Returns an open TcpClient object that can be used normally to communicate
        /// with the destination server
        /// </returns>
        /// <remarks>
        /// This method creates a connection to the proxy server and instructs the proxy server
        /// to make a pass through connection to the specified destination host on the specified
        /// port.
        /// </remarks>
        private static TcpClient createConnection(string destinationHost, int destinationPort, AddressFamily addressFamily, ProxyInfos proxyInfos)
        {
            var tcpClient = new TcpClient()
            {
                NoDelay = true
            };

            try
            {
                //if (String.IsNullOrEmpty(proxyInfos.Host))
                //    throw new ProxyException("ProxyHost property must contain a value.");

                if (proxyInfos != null && proxyInfos.Uri != null && !String.IsNullOrEmpty(proxyInfos.Uri.DnsSafeHost))
                {
                    if (proxyInfos.Uri.Port <= 0 || proxyInfos.Uri.Port > 65535)
                    {
                        throw new ProxyException("ProxyPort value must be greater than zero and less than 65535");
                    }

                    // attempt to open the connection
                    tcpClient.Connect(proxyInfos.Uri.DnsSafeHost, proxyInfos.Uri.Port);

                    //log.DebugFormat("Connection to proxy established: {0}", tcpClient.Client.RemoteEndPoint);

                    //  send connection command to proxy host for the specified destination host and port
                    sendConnectionCommand(tcpClient, proxyInfos, destinationHost, destinationPort);
                }
                else // no proxy in use
                {
                    //log.DebugFormat("No proxy available. Connect directly to destination host.");

                    // attempt to open the connection
                    tcpClient.Connect(destinationHost, destinationPort);

                    //log.DebugFormat("Connection to destination established: {0}", tcpClient.Client.RemoteEndPoint);
                }

                return(tcpClient);
            }
            catch (SocketException ex)
            {
                throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "Connection to proxy host {0} on port {1} failed.", Utils.GetHost(tcpClient) ?? destinationHost, Utils.GetPort(tcpClient) ?? destinationPort.ToString(), ex));
            }
        }
        private static string createCommandString(string host, int port, ProxyInfos proxyInfos)
        {
            string connectCmd;
            if (!string.IsNullOrEmpty(proxyInfos.UserName))
            {
                //  gets the user/pass into base64 encoded string in the form of [username]:[password]
                string auth = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", proxyInfos.UserName, proxyInfos.Password)));

                // PROXY SERVER REQUEST
                // =======================================================================
                //CONNECT starksoft.com:443 HTTP/1.0<CR><LF>
                //HOST starksoft.com:443<CR><LF>
                //Proxy-Authorization: username:password<CR><LF>
                //              NOTE: username:password string will be base64 encoded as one 
                //                        concatenated string
                //[... other HTTP header lines ending with <CR><LF> if required]>
                //<CR><LF>    // Last Empty Line
                connectCmd = String.Format(CultureInfo.InvariantCulture, "CONNECT {0}:{1} HTTP/1.1\r\nUser-Agent: rabbitmq-net-client/3.5.3\r\nHost: {0}:{1}\r\nProxy-Authorization: Basic {2}\r\n\r\n", host, port.ToString(CultureInfo.InvariantCulture), auth);
            }
            else
            {
                // PROXY SERVER REQUEST
                // =======================================================================
                //CONNECT starksoft.com:443 HTTP/1.0 <CR><LF>
                //HOST starksoft.com:443<CR><LF>
                //[... other HTTP header lines ending with <CR><LF> if required]>
                //<CR><LF>    // Last Empty Line
                connectCmd = String.Format(CultureInfo.InvariantCulture, "CONNECT {0}:{1} HTTP/1.1\r\nUser-Agent: rabbitmq-net-client/3.5.3\r\nHost: {0}:{1}\r\n\r\n", host, port.ToString(CultureInfo.InvariantCulture));
            }
            return connectCmd;
        }
        private static void sendConnectionCommand(TcpClient tcpClient, ProxyInfos infos, string host, int port)
        {
            //log.DebugFormat("Start sending connection command");

            NetworkStream stream = tcpClient.GetStream();

            string connectCmd = createCommandString(host, port, infos);

            //log.DebugFormat("Connect command: {0}", connectCmd);

            byte[] request = ASCIIEncoding.ASCII.GetBytes(connectCmd);

            // send the connect request
            stream.Write(request, 0, request.Length);

            // wait for the proxy server to respond
            waitForData(tcpClient, stream);


            //log.DebugFormat("Reponse for connection command available!");
            // PROXY SERVER RESPONSE
            // =======================================================================
            //HTTP/1.0 200 Connection Established<CR><LF>
            //[.... other HTTP header lines ending with <CR><LF>..
            //ignore all of them]
            //<CR><LF>    // Last Empty Line

            // create an byte response array  
            byte[] response = new byte[tcpClient.ReceiveBufferSize];
            StringBuilder sbuilder = new StringBuilder();
            int bytes = 0;
            long total = 0;

            do
            {
                bytes = stream.Read(response, 0, tcpClient.ReceiveBufferSize);
                total += bytes;
                sbuilder.Append(System.Text.ASCIIEncoding.UTF8.GetString(response, 0, bytes));
            } while (stream.DataAvailable);

            var resp = parseResponse(sbuilder.ToString());

            //log.DebugFormat("Response: {0} - {1}", resp.Code, resp.Message);

            //  evaluate the reply code for an error condition
            if (resp.Code != HttpResponseCodes.OK)
                handleProxyCommandError(host, port, tcpClient, resp);

            //log.DebugFormat("Connection to destination established: {0}", tcpClient.Client.RemoteEndPoint);

        }
        /// <summary>
        /// Creates a remote TCP connection through a proxy server to the destination host on the destination port.
        /// </summary>
        /// <param name="destinationHost">Destination host name or IP address.</param>
        /// <param name="destinationPort">Port number to connect to on the destination host.</param>
        /// <param name="addressFamily">AdressFamliy for tcp client. Currently ignored.</param>
        /// <param name="proxyInfos">Dto for all container infos</param>
        /// <returns>
        /// Returns an open TcpClient object that can be used normally to communicate
        /// with the destination server
        /// </returns>
        /// <remarks>
        /// This method creates a connection to the proxy server and instructs the proxy server
        /// to make a pass through connection to the specified destination host on the specified
        /// port.  
        /// </remarks>
        private static TcpClient createConnection(string destinationHost, int destinationPort, AddressFamily addressFamily, ProxyInfos proxyInfos)
        {
            var tcpClient = new TcpClient()
            {
                NoDelay = true
            };

            try
            {
                //if (String.IsNullOrEmpty(proxyInfos.Host))
                //    throw new ProxyException("ProxyHost property must contain a value.");

                if (proxyInfos != null && proxyInfos.Uri!=null && !String.IsNullOrEmpty(proxyInfos.Uri.DnsSafeHost))
                {
                    if (proxyInfos.Uri.Port <= 0 || proxyInfos.Uri.Port > 65535)
                        throw new ProxyException("ProxyPort value must be greater than zero and less than 65535");

                    // attempt to open the connection
                    tcpClient.Connect(proxyInfos.Uri.DnsSafeHost, proxyInfos.Uri.Port);

                    //log.DebugFormat("Connection to proxy established: {0}", tcpClient.Client.RemoteEndPoint);

                    //  send connection command to proxy host for the specified destination host and port
                    sendConnectionCommand(tcpClient, proxyInfos, destinationHost, destinationPort);


                }
                else // no proxy in use
                {
                    //log.DebugFormat("No proxy available. Connect directly to destination host.");

                    // attempt to open the connection
                    tcpClient.Connect(destinationHost, destinationPort);

                    //log.DebugFormat("Connection to destination established: {0}", tcpClient.Client.RemoteEndPoint);

                }

                return tcpClient;
            }
            catch (SocketException ex)
            {
                throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "Connection to proxy host {0} on port {1} failed.", Utils.GetHost(tcpClient) ?? destinationHost, Utils.GetPort(tcpClient) ?? destinationPort.ToString(), ex));
            }
        }