diff --git a/websocket-sharp/IProxy.cs b/websocket-sharp/IProxy.cs
new file mode 100644
index 000000000..ca58261bc
--- /dev/null
+++ b/websocket-sharp/IProxy.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using WebSocketSharp.Net;
+using System.Text;
+
+namespace WebSocketSharp
+{
+ public interface IProxy
+ {
+ System.Net.Sockets.TcpClient ConnectThroughProxy(Uri DestinationUri);
+ }
+}
diff --git a/websocket-sharp/ProxyHTTP.cs b/websocket-sharp/ProxyHTTP.cs
new file mode 100644
index 000000000..dc2ca53ad
--- /dev/null
+++ b/websocket-sharp/ProxyHTTP.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using WebSocketSharp.Net;
+
+namespace WebSocketSharp
+{
+ public class ProxyHTTP : IProxy
+ {
+ private Logger _logger;
+ private Uri _proxyUri;
+ private NetworkCredential _proxyCredentials;
+ private System.IO.Stream _stream;
+ System.Net.Sockets.TcpClient _tcpClient;
+
+ ///
+ /// Occurs when the gets an error.
+ ///
+ public event EventHandler OnError;
+
+ public ProxyHTTP(string url, string username, string password)
+ {
+ _logger = new Logger();
+
+ if (url.IsNullOrEmpty()) {
+ _logger.Warn("The url and credentials for the proxy are initialized.");
+ _proxyUri = null;
+ _proxyCredentials = null;
+
+ return;
+ }
+
+ _proxyUri = new Uri(url);
+
+ if (username.IsNullOrEmpty()) {
+ _logger.Warn("The credentials for the proxy are initialized.");
+ _proxyCredentials = null;
+
+ return;
+ }
+
+ _proxyCredentials =
+ new NetworkCredential(
+ username, password, String.Format("{0}:{1}", _proxyUri.DnsSafeHost, _proxyUri.Port)
+ );
+ }
+
+ public System.Net.Sockets.TcpClient ConnectThroughProxy(Uri uri)
+ {
+ _tcpClient = new System.Net.Sockets.TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
+ _tcpClient.NoDelay = true;
+
+ _stream = _tcpClient.GetStream();
+
+ var req = HttpRequest.CreateConnectRequest(uri);
+ var res = sendHttpRequest(req, 90000);
+ if (res.IsProxyAuthenticationRequired) {
+ var chal = res.Headers["Proxy-Authenticate"];
+ _logger.Warn(
+ String.Format("Received a proxy authentication requirement for '{0}'.", chal));
+
+ if (chal.IsNullOrEmpty())
+ throw new WebSocketException("No proxy authentication challenge is specified.");
+
+ var authChal = AuthenticationChallenge.Parse(chal);
+ if (authChal == null)
+ throw new WebSocketException("An invalid proxy authentication challenge is specified.");
+
+ if (_proxyCredentials != null) {
+ if (res.HasConnectionClose) {
+ releaseClientResources();
+ _tcpClient = new System.Net.Sockets.TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
+ _tcpClient.NoDelay = true;
+ _stream = _tcpClient.GetStream();
+ }
+
+ var authRes = new AuthenticationResponse(authChal, _proxyCredentials, 0);
+ req.Headers["Proxy-Authorization"] = authRes.ToString();
+ res = sendHttpRequest(req, 15000);
+ }
+
+ if (res.IsProxyAuthenticationRequired)
+ throw new WebSocketException("A proxy authentication is required.");
+ }
+
+ if (res.StatusCode[0] != '2')
+ throw new WebSocketException(
+ "The proxy has failed a connection to the requested host and port.");
+ return _tcpClient;
+ }
+
+ private void releaseClientResources()
+ {
+ if (_stream != null) {
+ _stream.Dispose();
+ _stream = null;
+ }
+
+ if (_tcpClient != null) {
+ _tcpClient.Close();
+ _tcpClient = null;
+ }
+ }
+
+ private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout)
+ {
+ _logger.Debug("A request to the server:\n" + request.ToString());
+ var res = request.GetResponse(_stream, millisecondsTimeout);
+ _logger.Debug("A response to this request:\n" + res.ToString());
+
+ return res;
+ }
+
+ private static bool checkParametersForSetProxy(string url, string username, string password, out string message)
+ {
+ message = null;
+
+ if (url.IsNullOrEmpty())
+ return true;
+
+ Uri uri;
+ if (!Uri.TryCreate(url, UriKind.Absolute, out uri)
+ || uri.Scheme != "http"
+ || uri.Segments.Length > 1
+ ) {
+ message = "'url' is an invalid URL.";
+ return false;
+ }
+
+ if (username.IsNullOrEmpty())
+ return true;
+
+ if (username.Contains(':') || !username.IsText()) {
+ message = "'username' contains an invalid character.";
+ return false;
+ }
+
+ if (password.IsNullOrEmpty())
+ return true;
+
+ if (!password.IsText()) {
+ message = "'password' contains an invalid character.";
+ return false;
+ }
+
+ return true;
+ }
+
+ private void error(string message, Exception exception)
+ {
+ try
+ {
+ OnError.Emit(this, new ErrorEventArgs(message, exception));
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex.ToString());
+ }
+ }
+ }
+}
diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs
index 4167d44bf..3e7d634ba 100644
--- a/websocket-sharp/WebSocket.cs
+++ b/websocket-sharp/WebSocket.cs
@@ -103,8 +103,7 @@ public class WebSocket : IDisposable
private string _protocol;
private string[] _protocols;
private bool _protocolsRequested;
- private NetworkCredential _proxyCredentials;
- private Uri _proxyUri;
+ private IProxy _proxyManager;
private volatile WebSocketState _readyState;
private ManualResetEvent _receivingExited;
private int _retryCountForConnect;
@@ -880,43 +879,6 @@ private static bool checkParametersForSetCredentials (
return true;
}
- private static bool checkParametersForSetProxy (
- string url, string username, string password, out string message
- )
- {
- message = null;
-
- if (url.IsNullOrEmpty ())
- return true;
-
- Uri uri;
- if (!Uri.TryCreate (url, UriKind.Absolute, out uri)
- || uri.Scheme != "http"
- || uri.Segments.Length > 1
- ) {
- message = "'url' is an invalid URL.";
- return false;
- }
-
- if (username.IsNullOrEmpty ())
- return true;
-
- if (username.Contains (':') || !username.IsText ()) {
- message = "'username' contains an invalid character.";
- return false;
- }
-
- if (password.IsNullOrEmpty ())
- return true;
-
- if (!password.IsText ()) {
- message = "'password' contains an invalid character.";
- return false;
- }
-
- return true;
- }
-
private bool checkReceivedFrame (WebSocketFrame frame, out string message)
{
message = null;
@@ -1871,82 +1833,48 @@ private bool sendHttpResponse (HttpResponse response)
}
// As client
- private void sendProxyConnectRequest ()
+ private void setClientStream()
{
- var req = HttpRequest.CreateConnectRequest (_uri);
- var res = sendHttpRequest (req, 90000);
- if (res.IsProxyAuthenticationRequired) {
- var chal = res.Headers["Proxy-Authenticate"];
- _logger.Warn (
- String.Format ("Received a proxy authentication requirement for '{0}'.", chal));
-
- if (chal.IsNullOrEmpty ())
- throw new WebSocketException ("No proxy authentication challenge is specified.");
-
- var authChal = AuthenticationChallenge.Parse (chal);
- if (authChal == null)
- throw new WebSocketException ("An invalid proxy authentication challenge is specified.");
-
- if (_proxyCredentials != null) {
- if (res.HasConnectionClose) {
- releaseClientResources ();
- _tcpClient = new TcpClient (_proxyUri.DnsSafeHost, _proxyUri.Port);
- _stream = _tcpClient.GetStream ();
- }
-
- var authRes = new AuthenticationResponse (authChal, _proxyCredentials, 0);
- req.Headers["Proxy-Authorization"] = authRes.ToString ();
- res = sendHttpRequest (req, 15000);
+ if (_proxyManager != null) {
+ _tcpClient = _proxyManager.ConnectThroughProxy(_uri);
+ if (_tcpClient == null) {
+ throw new WebSocketException("Proxy failed to create stream.");
+ }
+ _tcpClient.NoDelay = true;
+ _stream = _tcpClient.GetStream();
}
-
- if (res.IsProxyAuthenticationRequired)
- throw new WebSocketException ("A proxy authentication is required.");
- }
-
- if (res.StatusCode[0] != '2')
- throw new WebSocketException (
- "The proxy has failed a connection to the requested host and port.");
- }
-
- // As client
- private void setClientStream ()
- {
- if (_proxyUri != null) {
- _tcpClient = new TcpClient (_proxyUri.DnsSafeHost, _proxyUri.Port);
- _stream = _tcpClient.GetStream ();
- sendProxyConnectRequest ();
- }
- else {
- _tcpClient = new TcpClient (_uri.DnsSafeHost, _uri.Port);
- _stream = _tcpClient.GetStream ();
- }
-
- if (_secure) {
- var conf = SslConfiguration;
- var host = conf.TargetHost;
- if (host != _uri.DnsSafeHost)
- throw new WebSocketException (
- CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified.");
-
- try {
- var sslStream = new SslStream (
- _stream,
- false,
- conf.ServerCertificateValidationCallback,
- conf.ClientCertificateSelectionCallback);
-
- sslStream.AuthenticateAsClient (
- host,
- conf.ClientCertificates,
- conf.EnabledSslProtocols,
- conf.CheckCertificateRevocation);
-
- _stream = sslStream;
+ else {
+ _tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port);
+ _tcpClient.NoDelay = true;
+ _stream = _tcpClient.GetStream();
}
- catch (Exception ex) {
- throw new WebSocketException (CloseStatusCode.TlsHandshakeFailure, ex);
+
+ if (_secure) {
+ var conf = SslConfiguration;
+ var host = conf.TargetHost;
+ if (host != _uri.DnsSafeHost)
+ throw new WebSocketException(
+ CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified.");
+
+ try {
+ var sslStream = new SslStream(
+ _stream,
+ false,
+ conf.ServerCertificateValidationCallback,
+ conf.ClientCertificateSelectionCallback);
+
+ sslStream.AuthenticateAsClient(
+ host,
+ conf.ClientCertificates,
+ conf.EnabledSslProtocols,
+ conf.CheckCertificateRevocation);
+
+ _stream = sslStream;
+ }
+ catch (Exception ex) {
+ throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, ex);
+ }
}
- }
}
private void startReceiving ()
@@ -3618,85 +3546,37 @@ public void SetCredentials (string username, string password, bool preAuth)
}
///
- /// Sets the HTTP proxy server URL to connect through, and if necessary,
- /// a pair of and for
- /// the proxy server authentication (Basic/Digest).
+ /// Sets the proxy server to connect through, and all the necessary configurations will pass through the interface
///
///
/// This method is not available in a server.
///
- ///
- ///
- /// A that represents the HTTP proxy server URL to
- /// connect through. The syntax must be http://<host>[:<port>].
- ///
+ ///
///
- /// If is or empty,
- /// the url and credentials for the proxy will be initialized,
- /// and the will not use the proxy to
+ /// A that represents the proxy type to
/// connect through.
///
///
- ///
- ///
- /// A that represents the user name used to authenticate.
- ///
- ///
- /// If is or empty,
- /// the credentials for the proxy will be initialized and not be sent.
- ///
- ///
- ///
- /// A that represents the password for
- /// used to authenticate.
- ///
- public void SetProxy (string url, string username, string password)
+ public void SetProxy(IProxy proxy)
{
- string msg;
- if (!checkIfAvailable (true, false, true, false, false, true, out msg)) {
- _logger.Error (msg);
- error ("An error has occurred in setting the proxy.", null);
-
- return;
- }
-
- if (!checkParametersForSetProxy (url, username, password, out msg)) {
- _logger.Error (msg);
- error ("An error has occurred in setting the proxy.", null);
-
- return;
- }
-
- lock (_forState) {
- if (!checkIfAvailable (true, false, false, true, out msg)) {
- _logger.Error (msg);
- error ("An error has occurred in setting the proxy.", null);
-
- return;
- }
-
- if (url.IsNullOrEmpty ()) {
- _logger.Warn ("The url and credentials for the proxy are initialized.");
- _proxyUri = null;
- _proxyCredentials = null;
+ string msg;
+ if (!checkIfAvailable(true, false, true, false, false, true, out msg)) {
+ _logger.Error(msg);
+ error("An error has occurred in setting the proxy.", null);
- return;
+ return;
}
- _proxyUri = new Uri (url);
+ lock (_forState) {
+ if (checkIfAvailable(true, false, false, true, out msg) == false) {
+ _logger.Error(msg);
+ error("An error has occurred in setting the proxy.", null);
- if (username.IsNullOrEmpty ()) {
- _logger.Warn ("The credentials for the proxy are initialized.");
- _proxyCredentials = null;
+ return;
+ }
- return;
+ _proxyManager = proxy;
}
-
- _proxyCredentials =
- new NetworkCredential (
- username, password, String.Format ("{0}:{1}", _uri.DnsSafeHost, _uri.Port)
- );
- }
}
#endregion
diff --git a/websocket-sharp/WebSocketException.cs b/websocket-sharp/WebSocketException.cs
index 81d7c8081..9fed334a9 100644
--- a/websocket-sharp/WebSocketException.cs
+++ b/websocket-sharp/WebSocketException.cs
@@ -54,7 +54,7 @@ internal WebSocketException (Exception innerException)
{
}
- internal WebSocketException (string message)
+ public WebSocketException (string message)
: this (CloseStatusCode.Abnormal, message, null)
{
}
diff --git a/websocket-sharp/websocket-sharp.csproj b/websocket-sharp/websocket-sharp.csproj
index 0860c0313..235437c54 100644
--- a/websocket-sharp/websocket-sharp.csproj
+++ b/websocket-sharp/websocket-sharp.csproj
@@ -64,6 +64,8 @@
+
+