// 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(); } }); }