Fix for issue #6 - 1

master
sta 13 years ago
parent 75417fba70
commit 3ef6d58f31

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.

@ -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.

@ -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);

@ -37,112 +37,116 @@ 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 Properties #region Constructor
public IPAddress Address public WebSocketServer(string url)
{ {
get { return Endpoint.Address; } _uri = new Uri(url);
if (!isValidScheme(_uri))
{
var msg = "Unsupported WebSocket URI scheme: " + _uri.Scheme;
throw new ArgumentException(msg);
} }
public IPEndPoint Endpoint var host = _uri.DnsSafeHost;
var ips = Dns.GetHostAddresses(host);
if (ips.Length == 0)
{ {
get { return (IPEndPoint)_tcpListener.LocalEndpoint; } var msg = "Invalid WebSocket URI host: " + host;
throw new ArgumentException(msg);
} }
public int Port var scheme = _uri.Scheme;
var port = _uri.Port;
if (port <= 0)
{ {
get { return Endpoint.Port; } port = 80;
if (scheme == "wss")
port = 443;
} }
public string Url _tcpListener = new TcpListener(ips[0], port);
{ _services = new Dictionary<string, WebSocketService>();
get { return _uri.ToString(); }
} }
#endregion public WebSocketServer(string absPath, int port)
{
_uri = new Uri(absPath, UriKind.Relative);
#region Events if (port <= 0)
port = 80;
public event EventHandler<ErrorEventArgs> OnError; _tcpListener = new TcpListener(IPAddress.Any, port);
_services = new Dictionary<string, WebSocketService>();
}
#endregion #endregion
#region Public Constructor #region Properties
public WebSocketServer(string url) public IPAddress Address
{ {
_uri = new Uri(url); get { return Endpoint.Address; }
}
if (!isValidScheme(_uri)) public IPEndPoint Endpoint
{ {
var msg = "Unsupported WebSocket URI scheme: " + _uri.Scheme; get { return (IPEndPoint)_tcpListener.LocalEndpoint; }
throw new ArgumentException(msg);
} }
string scheme = _uri.Scheme; public int Port
int port = _uri.Port;
if (port <= 0)
{
if (scheme == "wss")
{ {
port = 443; get { return Endpoint.Port; }
} }
else
public string Url
{ {
port = 80; get { return _uri.ToString(); }
}
} }
_tcpListener = new TcpListener(IPAddress.Any, port); #endregion
_services = new Dictionary<string, WebSocketService>();
} #region Events
public event EventHandler<ErrorEventArgs> OnError;
#endregion #endregion
#region Private Methods #region Private Methods
private void acceptClient(IAsyncResult ar) private void acceptClient()
{
TcpListener listener = (TcpListener)ar.AsyncState;
if (listener.Server == null || !listener.Server.IsBound)
{ {
return; while (true)
}
try
{ {
TcpClient client = listener.EndAcceptTcpClient(ar); try {
WebSocket socket = new WebSocket(_uri, client); var client = _tcpListener.AcceptTcpClient();
T service = new T(); startService(client);
service.Bind(socket, _services);
service.Start();
} }
catch (ObjectDisposedException) catch (SocketException)
{ {
// TcpListener has been stopped. // TcpListener has been stopped.
return; break;
} }
catch (Exception ex) catch (Exception ex)
{ {
error(ex.Message); error(ex.Message);
break;
}
} }
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,11 +225,9 @@ 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);
} }
} }
}
#endregion #endregion
} }

@ -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,15 +518,17 @@ namespace WebSocketSharp
}; };
}; };
string expectedHost = _uri.DnsSafeHost; if (_uri.IsAbsoluteUri)
int port = ((IPEndPoint)_tcpClient.Client.LocalEndPoint).Port; {
if (port != 80)
expectedHost += ":" + port;
if (_uri.PathAndQuery.NotEqualsDo(request.Uri, func("Request URI"), out message, false)) if (_uri.PathAndQuery.NotEqualsDo(request.Uri, func("Request URI"), out message, false))
return false; return false;
if (expectedHost.NotEqualsDo(request.GetHeaderValues("Host")[0], func("Host"), out message, false)) if (!isValidRequestHost(request.GetHeaderValues("Host")[0], func("Host"), out message))
return false;
}
if (!_uri.IsAbsoluteUri)
if (_uri.ToString().NotEqualsDo(request.Uri, func("Request URI"), out message, false))
return 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)

Loading…
Cancel
Save