Fix for issue #6 - 1

This commit is contained in:
sta
2012-09-01 17:01:05 +09:00
parent 75417fba70
commit 3ef6d58f31
49 changed files with 151 additions and 83 deletions

View File

@@ -57,6 +57,8 @@ namespace WebSocketSharp
public static bool EqualsAndSaveTo(this int value, char c, List<byte> dest)
{
if (value < 0)
throw new ArgumentOutOfRangeException("value");
byte b = (byte)value;
dest.Add(b);
return b == Convert.ToByte(c);

View File

@@ -37,19 +37,65 @@ using System.Net.Sockets;
using System.Threading;
using WebSocketSharp.Frame;
namespace WebSocketSharp.Server
{
namespace WebSocketSharp.Server {
public class WebSocketServer<T>
where T : WebSocketService, new()
{
#region Private Fields
private Thread _acceptClientThread;
private Dictionary<string, WebSocketService> _services;
private TcpListener _tcpListener;
private Uri _uri;
#endregion
#region Constructor
public WebSocketServer(string url)
{
_uri = new Uri(url);
if (!isValidScheme(_uri))
{
var msg = "Unsupported WebSocket URI scheme: " + _uri.Scheme;
throw new ArgumentException(msg);
}
var host = _uri.DnsSafeHost;
var ips = Dns.GetHostAddresses(host);
if (ips.Length == 0)
{
var msg = "Invalid WebSocket URI host: " + host;
throw new ArgumentException(msg);
}
var scheme = _uri.Scheme;
var port = _uri.Port;
if (port <= 0)
{
port = 80;
if (scheme == "wss")
port = 443;
}
_tcpListener = new TcpListener(ips[0], port);
_services = new Dictionary<string, WebSocketService>();
}
public WebSocketServer(string absPath, int port)
{
_uri = new Uri(absPath, UriKind.Relative);
if (port <= 0)
port = 80;
_tcpListener = new TcpListener(IPAddress.Any, port);
_services = new Dictionary<string, WebSocketService>();
}
#endregion
#region Properties
public IPAddress Address
@@ -80,69 +126,27 @@ namespace WebSocketSharp.Server
#endregion
#region Public Constructor
public WebSocketServer(string url)
{
_uri = new Uri(url);
if (!isValidScheme(_uri))
{
var msg = "Unsupported WebSocket URI scheme: " + _uri.Scheme;
throw new ArgumentException(msg);
}
string scheme = _uri.Scheme;
int port = _uri.Port;
if (port <= 0)
{
if (scheme == "wss")
{
port = 443;
}
else
{
port = 80;
}
}
_tcpListener = new TcpListener(IPAddress.Any, port);
_services = new Dictionary<string, WebSocketService>();
}
#endregion
#region Private Methods
private void acceptClient(IAsyncResult ar)
private void acceptClient()
{
TcpListener listener = (TcpListener)ar.AsyncState;
if (listener.Server == null || !listener.Server.IsBound)
while (true)
{
return;
try {
var client = _tcpListener.AcceptTcpClient();
startService(client);
}
catch (SocketException)
{
// TcpListener has been stopped.
break;
}
catch (Exception ex)
{
error(ex.Message);
break;
}
}
try
{
TcpClient client = listener.EndAcceptTcpClient(ar);
WebSocket socket = new WebSocket(_uri, client);
T service = new T();
service.Bind(socket, _services);
service.Start();
}
catch (ObjectDisposedException)
{
// TcpListener has been stopped.
return;
}
catch (Exception ex)
{
error(ex.Message);
}
listener.BeginAcceptTcpClient(acceptClient, listener);
}
private void error(string message)
@@ -157,28 +161,57 @@ namespace WebSocketSharp.Server
private bool isValidScheme(Uri uri)
{
string scheme = uri.Scheme;
var scheme = uri.Scheme;
if (scheme == "ws" || scheme == "wss")
{
return true;
}
return false;
}
private void startAcceptClientThread()
{
_acceptClientThread = new Thread(new ThreadStart(acceptClient));
_acceptClientThread.IsBackground = true;
_acceptClientThread.Start();
}
private void startService(TcpClient client)
{
WaitCallback startCb = (state) =>
{
try {
var socket = new WebSocket(_uri, client);
BindWebSocket(socket);
}
catch (Exception ex)
{
error(ex.Message);
}
};
ThreadPool.QueueUserWorkItem(startCb);
}
#endregion
#region Public Methods
public void BindWebSocket(WebSocket socket)
{
T service = new T();
service.Bind(socket, _services);
service.Start();
}
public void Start()
{
_tcpListener.Start();
_tcpListener.BeginAcceptTcpClient(acceptClient, _tcpListener);
startAcceptClientThread();
}
public void Stop()
{
_tcpListener.Stop();
_acceptClientThread.Join(5 * 1000);
StopServices();
}
@@ -192,9 +225,7 @@ namespace WebSocketSharp.Server
lock (((ICollection)_services).SyncRoot)
{
foreach (WebSocketService service in _services.Values)
{
service.Stop(code, reason);
}
}
}

View File

@@ -62,6 +62,7 @@ namespace WebSocketSharp
private string _base64key;
private string _binaryType;
private IPEndPoint _endPoint;
private AutoResetEvent _exitedMessageLoop;
private string _extensions;
private Object _forClose;
@@ -106,6 +107,7 @@ namespace WebSocketSharp
{
_uri = uri;
_tcpClient = tcpClient;
_endPoint = (IPEndPoint)_tcpClient.Client.LocalEndPoint;
_isClient = false;
}
@@ -177,15 +179,24 @@ namespace WebSocketSharp
get { return _extensions; }
}
public bool IsConnected
{
get
{
if (_readyState != WsState.OPEN) return false;
public bool IsConnected {
get {
if (_readyState != WsState.OPEN)
return false;
return Ping();
}
}
public bool IsSecure {
get {
if (_endPoint.Port == 443)
return true;
return false;
}
}
public string Protocol
{
get { return _protocol; }
@@ -447,7 +458,7 @@ namespace WebSocketSharp
{
_netStream = _tcpClient.GetStream();
if (_uri.Scheme == "wss")
if (IsSecure)
{
_sslStream = new SslStream(_netStream);
@@ -507,16 +518,18 @@ namespace WebSocketSharp
};
};
string expectedHost = _uri.DnsSafeHost;
int port = ((IPEndPoint)_tcpClient.Client.LocalEndPoint).Port;
if (port != 80)
expectedHost += ":" + port;
if (_uri.IsAbsoluteUri)
{
if (_uri.PathAndQuery.NotEqualsDo(request.Uri, func("Request URI"), out message, false))
return false;
if (_uri.PathAndQuery.NotEqualsDo(request.Uri, func("Request URI"), out message, false))
return false;
if (!isValidRequestHost(request.GetHeaderValues("Host")[0], func("Host"), out message))
return false;
}
if (expectedHost.NotEqualsDo(request.GetHeaderValues("Host")[0], func("Host"), out message, false))
return false;
if (!_uri.IsAbsoluteUri)
if (_uri.ToString().NotEqualsDo(request.Uri, func("Request URI"), out message, false))
return false;
if (!request.HeaderExists("Sec-WebSocket-Version", _version))
{
@@ -536,6 +549,27 @@ namespace WebSocketSharp
return true;
}
private bool isValidRequestHost(string value, Func<string, string, string> func, out string message)
{
var address = _endPoint.Address;
var port = _endPoint.Port;
var expectedHost1 = _uri.DnsSafeHost;
var expectedHost2 = address.ToString();
if (port != 80)
{
expectedHost1 += ":" + port;
expectedHost2 += ":" + port;
}
if (expectedHost1.NotEqualsDo(value, func, out message, false))
if (expectedHost2.NotEqualsDo(value, func, out message, false))
return false;
message = String.Empty;
return true;
}
private bool isValidResponse(ResponseHandshake response, out string message)
{
if (!response.IsWebSocketResponse)

Binary file not shown.