/// <summary> /// The establish method is used to connect to the server and try to request access to the specific address. /// </summary> /// <param name="address"> /// The requested address. /// </param> /// <param name="port"> /// The requested port. /// </param> /// <param name="client"> /// The client to connect with. /// </param> /// <param name="headerData"> /// The data to send after connecting. /// </param> /// <param name="sendDataDelegate"> /// The send callback. /// </param> /// <param name="receiveDataDelegate"> /// The receive callback. /// </param> /// <param name="connectionStatusCallback"> /// The connection status changed callback. /// </param> public abstract void Establish( string address, ushort port, ProxyClient client, byte[] headerData = null, DataCallbackDelegate sendDataDelegate = null, DataCallbackDelegate receiveDataDelegate = null, ConnectionCallbackDelegate connectionStatusCallback = null);
/// <summary> /// Initializes a new instance of the <see cref="RequestGetData"/> class. /// </summary> /// <param name="request">Request to wrap</param> /// <param name="context">Context associated with the request</param> /// <param name="callback">Callback to invoke when the request is completed</param> public RequestGetData(RequestDefinitions.RequestGetData request, object context, DataCallbackDelegate callback) : base(request, context) { this.callback = callback; }
/// <summary> /// Initializes a new instance of the <see cref="RequestGetData"/> class. /// </summary> /// <param name="path">Path to the node</param> /// <param name="options">the options for this request</param> /// <param name="optionArgument">Arguments for the option</param> /// <param name="context">Context associated with the request</param> /// <param name="watcher"><see cref="IWatcher"/> to associate with the node</param> /// <param name="callback">Callback to invoke when the request is completed</param> /// <param name="uid">Unique id to assign to the request</param> public RequestGetData(string path, GetDataOptions options, IGetDataOptionArgument optionArgument, object context, IWatcher watcher, DataCallbackDelegate callback, ulong uid = 0) : this(new RequestDefinitions.RequestGetData(path, options, optionArgument, watcher, MakeUid(uid)), context, callback) { }
/// <summary> /// Initializes a new instance of the <see cref="RequestGetData"/> class. /// </summary> /// <param name="path">Path to the node</param> /// <param name="options">the options for this request</param> /// <param name="context">Context associated with the request</param> /// <param name="watcher"><see cref="IWatcher"/> to associate with the node</param> /// <param name="callback">Callback to invoke when the request is completed</param> /// <param name="uid">Unique id to assign to the request</param> public RequestGetData(string path, GetDataOptions options, object context, IWatcher watcher, DataCallbackDelegate callback, ulong uid = 0) : this(path, options, null, context, watcher, callback, uid) { }
/// <summary> /// Initializes a new instance of the <see cref="RequestGetData"/> class. /// </summary> /// <param name="path">Path to the node.</param> /// <param name="faultbackOnParentData">if true, if the requested path doesnt exist, it will return the data for the first ancestor with some non-null data</param> /// <param name="context">Context associated with the request</param> /// <param name="watcher"><see cref="IWatcher"/> to associate with the node</param> /// <param name="callback">Callback to invoke when the request is completed</param> /// <param name="uid">Unique id to assign to the request</param> public RequestGetData(string path, bool faultbackOnParentData, object context, IWatcher watcher, DataCallbackDelegate callback, ulong uid = 0) : this(path, faultbackOnParentData ? GetDataOptions.FaultbackOnParentData : GetDataOptions.None, context, watcher, callback, uid) { }
/// <summary> /// The establish method is used to connect to the server and try to request access to the specific address. /// </summary> /// <param name="address"> /// The requested address. /// </param> /// <param name="port"> /// The requested port. /// </param> /// <param name="client"> /// The client to connect with. /// </param> /// <param name="headerData"> /// The data to send after connecting. /// </param> /// <param name="sendDataDelegate"> /// The send callback. /// </param> /// <param name="receiveDataDelegate"> /// The receive callback. /// </param> /// <param name="connectionStatusCallback"> /// The connection status changed callback. /// </param> public override void Establish( string address, ushort port, ProxyClient client, byte[] headerData = null, DataCallbackDelegate sendDataDelegate = null, DataCallbackDelegate receiveDataDelegate = null, ConnectionCallbackDelegate connectionStatusCallback = null) { try { this.requestedAddress = address; this.requestedPort = port; this.ParentClient = client; this.SendDataDelegate = sendDataDelegate; this.ReceiveDataDelegate = receiveDataDelegate; this.ConnectionStatusCallback = connectionStatusCallback; this.UnderlyingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.UnderlyingSocket.BeginConnect( this.ServerAddress, this.ServerPort, delegate(IAsyncResult ar) { try { this.UnderlyingSocket.EndConnect(ar); this.UnderlyingSocket.Blocking = false; this.ParentClient.Controller.FailAttempts = 0; string httpsHeader = "CONNECT " + this.requestedAddress + ":" + this.requestedPort + " HTTP/1.1" + "\r\n"; if (this.Username != string.Empty) { httpsHeader += "Proxy-Authorization: Basic " + Convert.ToBase64String( Encoding.UTF8.GetBytes(this.Username + ":" + this.Password)) + "\r\n"; } httpsHeader += "\r\n"; bool firstTry = true; sendHeader: this.Write(Encoding.ASCII.GetBytes(httpsHeader)); this.currentTimeout = this.NoDataTimeout * 1000; while (this.UnderlyingSocket.Available <= 0) { if ((client.UnderlyingSocket != null && !Common.IsSocketConnected(client.UnderlyingSocket)) || !Common.IsSocketConnected(this.UnderlyingSocket)) { this.Close(); return; } if (!this.BusyWrite) { this.currentTimeout--; if (this.currentTimeout == 0) { this.Close( "No response, Timeout.", null, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); return; } } Thread.Sleep(1); } string response = Encoding.ASCII.GetString(this.Read()).ToLower(); if (firstTry && this.Username != string.Empty && (response.StartsWith("HTTP/1.1 407".ToLower()) || response.StartsWith("HTTP/1.0 407".ToLower()))) { firstTry = false; goto sendHeader; } if (response.StartsWith("HTTP/1.1 200".ToLower()) || response.StartsWith("HTTP/1.0 200".ToLower())) { this.IsServerValid = true; if (headerData != null && Common.IsSocketConnected(this.UnderlyingSocket)) { this.Write(headerData); } this.currentTimeout = this.NoDataTimeout * 1000; client.Controller.ClientMoveToRouting(this); } else { this.Close( "Connection failed", "response: " + response.Substring(0, Math.Min(response.Length, 50)), ErrorRenderer.HttpHeaderCode.C502BadGateway); } } catch (Exception ex) { this.ParentClient.Controller.FailAttempts++; this.Close(ex.Message, ex.StackTrace, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); } }, null); } catch (Exception e) { this.Close(e.Message, e.StackTrace); } }
/// <summary> /// The establish method is used to connect to the server and try to request access to the specific address. /// </summary> /// <param name="address"> /// The requested address. /// </param> /// <param name="port"> /// The requested port. /// </param> /// <param name="client"> /// The client to connect with. /// </param> /// <param name="headerData"> /// The data to send after connecting. /// </param> /// <param name="sendDataDelegate"> /// The send callback. /// </param> /// <param name="receiveDataDelegate"> /// The receive callback. /// </param> /// <param name="connectionStatusCallback"> /// The connection status changed callback. /// </param> public override void Establish( string address, ushort port, ProxyClient client, byte[] headerData = null, DataCallbackDelegate sendDataDelegate = null, DataCallbackDelegate receiveDataDelegate = null, ConnectionCallbackDelegate connectionStatusCallback = null) { try { this.requestedAddress = address; this.requestedPort = port; this.ParentClient = client; this.SendDataDelegate = sendDataDelegate; this.ReceiveDataDelegate = receiveDataDelegate; this.ConnectionStatusCallback = connectionStatusCallback; this.UnderlyingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.UnderlyingSocket.BeginConnect( this.ServerAddress, this.ServerPort, delegate(IAsyncResult ar) { try { this.UnderlyingSocket.EndConnect(ar); this.ParentClient.Controller.FailAttempts = 0; this.UnderlyingSocket.Blocking = false; byte[] clientRequest = new byte[0]; if (this.Username.Trim() != string.Empty && this.Password != string.Empty) { Array.Resize(ref clientRequest, 4); clientRequest[0] = ProtocolVersion; // version clientRequest[1] = 2; // 2 authentication methods clientRequest[2] = 0; // No authentication clientRequest[3] = 2; // User and pass } else { Array.Resize(ref clientRequest, 3); clientRequest[0] = ProtocolVersion; // version clientRequest[1] = 1; // 1 authentication method clientRequest[2] = 0; // No authentication } this.Write(clientRequest, false); byte[] serverResponse = this.Read(); if (serverResponse == null || serverResponse.Length < 2) { this.Close( "Connection timeout.", null, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); return; } if (serverResponse[0] != ProtocolVersion) { this.Close( "Unsupported version of proxy.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); return; } if ((serverResponse[1] != 0 && serverResponse[1] != 2) || (serverResponse[1] == 2 && !(this.Username.Trim() != string.Empty && this.Password != string.Empty))) { this.Close( "Unsupported authentication method.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); return; } if (serverResponse[1] == 2 && this.Username.Trim() != string.Empty && this.Password != string.Empty) { byte[] username = Encoding.ASCII.GetBytes(this.Username.Trim()); byte[] password = Encoding.ASCII.GetBytes(this.Password); if (username.Length > byte.MaxValue) { this.Close( "Username is to long.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } Array.Resize(ref clientRequest, username.Length + password.Length + 3); clientRequest[0] = 1; // Authenticator version clientRequest[1] = (byte)username.Length; clientRequest[username.Length + 2] = (byte)password.Length; Array.Copy(username, 0, clientRequest, 2, username.Length); Array.Copy(password, 0, clientRequest, username.Length + 3, password.Length); this.Write(clientRequest, false); serverResponse = this.Read(); if (serverResponse == null || serverResponse.Length < 2) { this.Close( "Connection timeout.", null, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); return; } if (serverResponse[0] != 1) { this.Close( "Unsupported version of proxy's user/pass authentication method.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); return; } if (serverResponse[1] != 0) { this.Close( "Authentication failed.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } } IPAddress clientIp; byte[] clientAddressBytes; byte clientAddressType; if (IPAddress.TryParse(this.requestedAddress, out clientIp)) { clientAddressBytes = clientIp.GetAddressBytes(); if (clientAddressBytes.Length == 16) { clientAddressType = 4; } else if (clientAddressBytes.Length == 4) { clientAddressType = 1; } else { this.Close( "Unknown IP Type.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } } else { clientAddressType = 3; clientAddressBytes = Encoding.ASCII.GetBytes(this.requestedAddress); } clientRequest = new byte[6 + clientAddressBytes.Length + ((clientAddressType == 3) ? 1 : 0)]; clientRequest[0] = ProtocolVersion; clientRequest[1] = 1; clientRequest[2] = 0; clientRequest[3] = clientAddressType; if (clientAddressType == 3) { if (clientAddressBytes.Length > 255) { this.Close( "Hostname is too long.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } clientRequest[4] = (byte)clientAddressBytes.Length; } Array.Copy( clientAddressBytes, 0, clientRequest, 4 + ((clientAddressType == 3) ? 1 : 0), clientAddressBytes.Length); clientRequest[clientRequest.GetUpperBound(0) - 1] = (byte)Math.Floor(this.requestedPort / 256d); clientRequest[clientRequest.GetUpperBound(0)] = (byte)(this.requestedPort % 256); this.Write(clientRequest, false); serverResponse = this.Read(); if (serverResponse == null) { this.Close( "Connection timeout.", null, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); return; } if (serverResponse[0] != clientRequest[0]) { this.Close( string.Format( "Server version is different from what we expect. Server's version: {0}, Expected: {1}", serverResponse[0], clientRequest[0]), null, ErrorRenderer.HttpHeaderCode.C502BadGateway); return; } if (serverResponse[1] != 0) { switch (serverResponse[1]) { case 1: this.Close( "Connection failed, Error Code: " + serverResponse[1], null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 2: this.Close( "SOCKS Error Message: General failure.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 3: this.Close( "SOCKS Error Message: Connection not allowed by rule set.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 4: this.Close( "SOCKS Error Message: Network unreachable.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 5: this.Close( "SOCKS Error Message: Connection refused by destination host.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 6: this.Close( "SOCKS Error Message: TTL expired.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 7: this.Close( "SOCKS Error Message: Command not supported / protocol error.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; case 8: this.Close( "SOCKS Error Message: Address type not supported.", null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; default: this.Close( "Connection failed, Error Code: " + serverResponse[1], null, ErrorRenderer.HttpHeaderCode.C502BadGateway); break; } return; } this.IsServerValid = true; if (headerData != null && Common.IsSocketConnected(this.UnderlyingSocket)) { this.Write(headerData); } this.currentTimeout = this.NoDataTimeout * 1000; client.Controller.ClientMoveToRouting(this); } catch (Exception ex) { this.ParentClient.Controller.FailAttempts++; this.Close(ex.Message, ex.StackTrace, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); } }, null); } catch (Exception e) { this.Close(e.Message, e.StackTrace); } }
/// <summary> /// The establish method is used to connect to the server and try to request access to the specific address. /// </summary> /// <param name="address"> /// The requested address. /// </param> /// <param name="port"> /// The requested port. /// </param> /// <param name="client"> /// The client to connect with. /// </param> /// <param name="headerData"> /// The data to send after connecting. /// </param> /// <param name="sendDataDelegate"> /// The send callback. /// </param> /// <param name="receiveDataDelegate"> /// The receive callback. /// </param> /// <param name="connectionStatusCallback"> /// The connection status changed callback. /// </param> public override void Establish( string address, ushort port, ProxyClient client, byte[] headerData = null, DataCallbackDelegate sendDataDelegate = null, DataCallbackDelegate receiveDataDelegate = null, ConnectionCallbackDelegate connectionStatusCallback = null) { try { this.requestedAddress = address; this.requestedPort = port; this.ParentClient = client; this.SendDataDelegate = sendDataDelegate; this.ReceiveDataDelegate = receiveDataDelegate; this.ConnectionStatusCallback = connectionStatusCallback; this.UnderlyingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.UnderlyingSocket.BeginConnect( this.ServerAddress, this.ServerPort, delegate(IAsyncResult ar) { try { this.UnderlyingSocket.EndConnect(ar); this.UnderlyingSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment, true); this.ParentClient.Controller.FailAttempts = 0; HttpForger.SendRequest( this.UnderlyingSocket, string.IsNullOrWhiteSpace(this.ServerDomain) ? "~" : this.ServerDomain, "~", this.ForgerCompatibility ? "LINK" : "GET"); if (new HttpForger(this.UnderlyingSocket).ReceiveResponse() != HttpForger.CurrentState.ValidData) { this.Close( "HTTPForger failed to validate server response.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } this.Protocol = new PeaRoxyProtocol( this.UnderlyingSocket, this.encryptionType, this.compressionTypes) { ReceivePacketSize = this.ParentClient.ReceivePacketSize, SendPacketSize = this.ParentClient.SendPacketSize, CloseCallback = this.Close }; byte[] clientRequest; if (this.Username.Trim() != string.Empty && this.Password != string.Empty) { byte[] username = Encoding.ASCII.GetBytes(this.Username.Trim()); byte[] password = Encoding.ASCII.GetBytes(this.Password); password = MD5.Create().ComputeHash(password); if (username.Length > 255) { this.Close( "Username is too long.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } clientRequest = new byte[3 + username.Length + password.Length]; clientRequest[0] = (byte)Common.AuthenticationMethods.UserPass; clientRequest[1] = (byte)username.Length; clientRequest[username.Length + 2] = (byte)password.Length; Array.Copy(username, 0, clientRequest, 2, username.Length); Array.Copy(password, 0, clientRequest, username.Length + 3, password.Length); } else { clientRequest = new byte[1]; clientRequest[0] = (byte)Common.AuthenticationMethods.None; } byte clientAddressType; IPAddress clientIp; byte[] clientAddressBytes; if (IPAddress.TryParse(this.requestedAddress, out clientIp)) { clientAddressBytes = clientIp.GetAddressBytes(); if (clientAddressBytes.Length == 16) { clientAddressType = 4; } else if (clientAddressBytes.Length == 4) { clientAddressType = 1; } else { this.Close( "Unknown IP Type.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } } else { clientAddressType = 3; clientAddressBytes = Encoding.ASCII.GetBytes(this.requestedAddress); } byte[] clientRequestAddress = new byte[6 + clientAddressBytes.Length + ((clientAddressType == 3) ? 1 : 0)]; clientRequestAddress[0] = ProtocolVersion; clientRequestAddress[1] = 0; clientRequestAddress[2] = 0; clientRequestAddress[3] = clientAddressType; if (clientAddressType == 3) { if (clientAddressBytes.Length > 255) { this.Close( "Hostname is too long.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } clientRequestAddress[4] = (byte)clientAddressBytes.Length; } Array.Copy( clientAddressBytes, 0, clientRequestAddress, 4 + ((clientAddressType == 3) ? 1 : 0), clientAddressBytes.Length); clientRequestAddress[clientRequestAddress.GetUpperBound(0) - 1] = (byte)Math.Floor(this.requestedPort / 256d); clientRequestAddress[clientRequestAddress.GetUpperBound(0)] = (byte)(this.requestedPort % 256); Array.Resize(ref clientRequest, clientRequestAddress.Length + clientRequest.Length); Array.Copy( clientRequestAddress, 0, clientRequest, clientRequest.Length - clientRequestAddress.Length, clientRequestAddress.Length); this.Protocol.Write(clientRequest, false); byte[] serverResponse = this.Protocol.Read(); if (serverResponse == null) { this.Close( "Connection closed by server or timed out.", null, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); return; } if (serverResponse[0] != clientRequestAddress[0]) { this.Close( string.Format( "Server version is different from what we expect. Server's version: {0}, Expected: {1}", serverResponse[0], clientRequestAddress[0]), null, ErrorRenderer.HttpHeaderCode.C502BadGateway); return; } if (serverResponse[1] == 99) { this.Close( "Connection failed, Error Code: Authentication Failed.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } if (serverResponse[1] != 0) { this.Close( "Connection failed, Error Code: " + serverResponse[1], null, ErrorRenderer.HttpHeaderCode.C502BadGateway); return; } if (this.Password != string.Empty) { this.Protocol.EncryptionKey = Encoding.ASCII.GetBytes(this.Password); } this.IsServerValid = true; if (headerData != null && Common.IsSocketConnected(this.UnderlyingSocket)) { this.Protocol.Write(headerData, true); } this.currentTimeout = this.NoDataTimeout * 1000; client.Controller.ClientMoveToRouting(this); } catch (Exception ex) { this.ParentClient.Controller.FailAttempts++; this.Close(ex.Message, ex.StackTrace, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); } }, null); } catch (Exception e) { this.Close(e.Message, e.StackTrace); } }
/// <summary> /// The establish method is used to connect to the server and try to request access to the specific address. /// </summary> /// <param name="address"> /// The requested address. /// </param> /// <param name="port"> /// The requested port. /// </param> /// <param name="client"> /// The client to connect with. /// </param> /// <param name="headerData"> /// The data to send after connecting. /// </param> /// <param name="sendDataDelegate"> /// The send callback. /// </param> /// <param name="receiveDataDelegate"> /// The receive callback. /// </param> /// <param name="connectionStatusCallback"> /// The connection status changed callback. /// </param> public override void Establish( string address, ushort port, ProxyClient client, byte[] headerData = null, DataCallbackDelegate sendDataDelegate = null, DataCallbackDelegate receiveDataDelegate = null, ConnectionCallbackDelegate connectionStatusCallback = null) { try { this.requestedAddress = address; this.requestedPort = port; this.ParentClient = client; this.SendDataDelegate = sendDataDelegate; this.ReceiveDataDelegate = receiveDataDelegate; this.ConnectionStatusCallback = connectionStatusCallback; this.UnderlyingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ThreadStart st = delegate { try { if (this.isServerExist == false) { this.isServerExist = true; if (this.GetType().Name != client.Controller.ActiveServer.GetType().Name && this.ConnectionStatusCallback != null && this.ConnectionStatusCallback.Invoke(false, this, this.ParentClient) == false) { this.ParentClient = null; this.Close(); } else { this.Close( "Connection timeout. " + this.requestedAddress + ":" + this.requestedPort, null, ErrorRenderer.HttpHeaderCode.C504GatewayTimeout); } } } catch (Exception) { } }; if (this.GetType().Name != client.Controller.ActiveServer.GetType().Name && this.ConnectionStatusCallback != null) { client.Controller.AddTasksToQueue(st, Math.Min(this.NoDataTimeout, 30) * 1000); } else { client.Controller.AddTasksToQueue(st, 60 * 1000); } this.UnderlyingSocket.BeginConnect( this.requestedAddress, this.requestedPort, delegate(IAsyncResult ar) { if (this.isServerExist == false) { try { this.isServerExist = true; client.Controller.RemoveTaskFromQueue(st); this.UnderlyingSocket.EndConnect(ar); if (this.GetType().Name != client.Controller.ActiveServer.GetType().Name && this.ConnectionStatusCallback != null && this.ConnectionStatusCallback.Invoke(true, this, this.ParentClient) == false) { this.ParentClient = null; this.Close(); return; } this.UnderlyingSocket.Blocking = false; this.IsServerValid = true; if (headerData != null && Common.IsSocketConnected(this.UnderlyingSocket)) { this.Write(headerData); } this.currentTimeout = this.NoDataTimeout * 1000; client.Controller.ClientMoveToRouting(this); } catch (Exception ex) { if (this.GetType().Name != client.Controller.ActiveServer.GetType().Name && this.ConnectionStatusCallback != null && this.ConnectionStatusCallback.Invoke(false, this, this.ParentClient) == false) { this.ParentClient = null; this.Close(); } else { this.Close( ex.Message, ex.StackTrace, ErrorRenderer.HttpHeaderCode.C502BadGateway); } } } }, null); } catch (Exception e) { if (e.TargetSite.Name == "Receive") { this.Close(); } else { this.Close(e.Message, e.StackTrace); } } }
/// <summary> /// The establish method is used to connect to the server and try to request access to the specific address. /// </summary> /// <param name="address"> /// The requested address. /// </param> /// <param name="port"> /// The requested port. /// </param> /// <param name="client"> /// The client to connect with. /// </param> /// <param name="headerData"> /// The data to send after connecting. /// </param> /// <param name="sendDataDelegate"> /// The send callback. /// </param> /// <param name="receiveDataDelegate"> /// The receive callback. /// </param> /// <param name="connectionStatusCallback"> /// The connection status changed callback. /// </param> public override void Establish( string address, ushort port, ProxyClient client, byte[] headerData = null, DataCallbackDelegate sendDataDelegate = null, DataCallbackDelegate receiveDataDelegate = null, ConnectionCallbackDelegate connectionStatusCallback = null) { try { this.requestedAddress = address; this.requestedPort = port; this.ParentClient = client; this.SendDataDelegate = sendDataDelegate; this.ReceiveDataDelegate = receiveDataDelegate; this.ConnectionStatusCallback = connectionStatusCallback; this.UnderlyingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.UnderlyingSocket.BeginConnect( this.ServerUri.Host, this.ServerUri.Port, delegate(IAsyncResult ar) { try { this.UnderlyingSocket.EndConnect(ar); this.UnderlyingSocket.Blocking = false; this.ParentClient.Controller.FailAttempts = 0; if (!this.CheckConnectionTypeWithClient(ref headerData)) { return; } if (!this.SendRequestToServer(ref headerData)) { return; } if (!this.ReadServerResponse(ref headerData)) { return; } this.ParentClient.Controller.ClientMoveToRouting(this); if (!this.ReadHeaderOfActualResponse(ref headerData)) { return; } this.WriteToClient(headerData); this.isDoneForRouting = true; this.currentTimeout = this.NoDataTimeout * 1000; } catch (Exception ex) { this.ParentClient.Controller.FailAttempts++; this.Close(ex.Message, ex.StackTrace); } }, null); } catch (Exception e) { this.Close(e.Message, e.StackTrace); } }