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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7,13 +7,14 @@ namespace Example2
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
var wssv = new WebSocketServer<Echo>("ws://localhost:4649"); //var wssv = new WebSocketServer<Echo>("ws://localhost:4649");
//var wssv = new WebSocketServer<Chat>("ws://localhost:4649"); //var wssv = new WebSocketServer<Chat>("ws://localhost:4649");
var wssv = new WebSocketServer<Echo>("/", 4649);
wssv.Start(); wssv.Start();
Console.WriteLine( Console.WriteLine(
"WebSocket Server (url: {0}) listening on port: {1}\n", "WebSocket Server (url: {0})\n listening on address: {1} port: {2}\n",
wssv.Url, wssv.Port); wssv.Url, wssv.Address, wssv.Port);
Console.WriteLine("Press any key to stop server..."); Console.WriteLine("Press any key to stop server...");
Console.ReadLine(); Console.ReadLine();

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

@ -37,19 +37,65 @@ using System.Net.Sockets;
using System.Threading; using System.Threading;
using WebSocketSharp.Frame; using WebSocketSharp.Frame;
namespace WebSocketSharp.Server namespace WebSocketSharp.Server {
{
public class WebSocketServer<T> public class WebSocketServer<T>
where T : WebSocketService, new() where T : WebSocketService, new()
{ {
#region Private Fields #region Private Fields
private Thread _acceptClientThread;
private Dictionary<string, WebSocketService> _services; private Dictionary<string, WebSocketService> _services;
private TcpListener _tcpListener; private TcpListener _tcpListener;
private Uri _uri; private Uri _uri;
#endregion #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 #region Properties
public IPAddress Address public IPAddress Address
@ -80,69 +126,27 @@ namespace WebSocketSharp.Server
#endregion #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 #region Private Methods
private void acceptClient(IAsyncResult ar) private void acceptClient()
{ {
TcpListener listener = (TcpListener)ar.AsyncState; while (true)
if (listener.Server == null || !listener.Server.IsBound)
{ {
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) private void error(string message)
@ -157,28 +161,57 @@ namespace WebSocketSharp.Server
private bool isValidScheme(Uri uri) private bool isValidScheme(Uri uri)
{ {
string scheme = uri.Scheme; var scheme = uri.Scheme;
if (scheme == "ws" || scheme == "wss") if (scheme == "ws" || scheme == "wss")
{
return true; return true;
}
return false; 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 #endregion
#region Public Methods #region Public Methods
public void BindWebSocket(WebSocket socket)
{
T service = new T();
service.Bind(socket, _services);
service.Start();
}
public void Start() public void Start()
{ {
_tcpListener.Start(); _tcpListener.Start();
_tcpListener.BeginAcceptTcpClient(acceptClient, _tcpListener); startAcceptClientThread();
} }
public void Stop() public void Stop()
{ {
_tcpListener.Stop(); _tcpListener.Stop();
_acceptClientThread.Join(5 * 1000);
StopServices(); StopServices();
} }
@ -192,9 +225,7 @@ namespace WebSocketSharp.Server
lock (((ICollection)_services).SyncRoot) lock (((ICollection)_services).SyncRoot)
{ {
foreach (WebSocketService service in _services.Values) foreach (WebSocketService service in _services.Values)
{
service.Stop(code, reason); service.Stop(code, reason);
}
} }
} }

View File

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

Binary file not shown.