// This starts the flow of data, and it is quite an intense multi step process
        // So I will label it in sequential order
        public void Start()
        {
            _queue.DispatchAsync(() =>
            {
                if (_client != null)
                {
                    Log.To.Sync.W(Tag, "Ignoring duplicate call to Start...");
                    return;
                }

                _readWriteCancellationTokenSource = new CancellationTokenSource();
                _writeQueue   = new BlockingCollection <byte[]>();
                _receivePause = new ManualResetEventSlim(true);

                // STEP 1: Create the TcpClient, which is responsible for negotiating
                // the socket connection between here and the server
                try {
                    // ReSharper disable once UseObjectOrCollectionInitializer
                    _client = new TcpClient(AddressFamily.InterNetworkV6)
                    {
                        SendTimeout    = (int)IdleTimeout.TotalMilliseconds,
                        ReceiveTimeout = (int)IdleTimeout.TotalMilliseconds
                    };
                } catch (Exception e) {
                    DidClose(e);
                    return;
                }

                try {
                    _client.Client.DualMode = true;
                } catch (ArgumentException) {
                    Log.To.Sync.I(Tag, "IPv4/IPv6 dual mode not supported on this device, falling back to IPv4");
                    _client = new TcpClient(AddressFamily.InterNetwork)
                    {
                        SendTimeout    = (int)IdleTimeout.TotalMilliseconds,
                        ReceiveTimeout = (int)IdleTimeout.TotalMilliseconds
                    };
                }

                // STEP 2.5: The IProxy interface will detect a system wide proxy that is set
                // And if it is, it will return an IWebProxy object to use
                // Sending "CONNECT" request if IWebProxy object is not null
                IProxy proxy      = Service.GetInstance <IProxy>();
                WebProxy webproxy = null;

                try {
                    if (_client != null && !_client.Connected)
                    {
                        if (proxy != null)
                        {
                            Uri proxyUri = new Uri("http://" + _logic.UrlRequest.Host + ":" + _logic.UrlRequest.Port);
                            webproxy     = (WebProxy)proxy.CreateProxy(proxyUri);
                            if (webproxy != null)
                            {
                                _logic.HasProxy = true;
                                connectProxyAsync(webproxy.Address.Host, webproxy.Address.Port, "proxyUer", "proxyPassword");
                            }
                        }
                    }
                } catch { }

                if (!_logic.HasProxy)
                {
                    OpenConnectionToRemote();
                }
            });
        }