Fix due to the added WebSocketServer class in WebSocketServer.cs

This commit is contained in:
sta 2012-09-24 15:01:25 +09:00
parent ab86ce8af8
commit b9859e08c0
52 changed files with 679 additions and 263 deletions

Binary file not shown.

View File

@ -76,6 +76,8 @@ namespace Example
using (WebSocket ws = new WebSocket("ws://echo.websocket.org", "echo"))
//using (WebSocket ws = new WebSocket("wss://echo.websocket.org", "echo"))
//using (WebSocket ws = new WebSocket("ws://localhost:4649"))
//using (WebSocket ws = new WebSocket("ws://localhost:4649/Echo"))
//using (WebSocket ws = new WebSocket("ws://localhost:4649/Chat"))
{
ws.OnOpen += (sender, e) =>
{

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -147,7 +147,7 @@ Required namespace.
using WebSocketSharp.Server;
```
`WebSocketServer<T>` class and `WebSocketService` class exist in `WebSocketSharp.Server` namespace.
`WebSocketServer`, `WebSocketServer<T>` and `WebSocketService` classes exist in `WebSocketSharp.Server` namespace.
#### Step 2 ####
@ -191,15 +191,25 @@ In addition, if you override `onOpen`, `onError` and `onClose` methods, each of
#### Step 3 ####
Creating a instance of `WebSocketServer<T>` class.
Creating a instance of `WebSocketServer<T>` class if you want single WebSocket service server.
```cs
var wssv = new WebSocketServer<Echo>("ws://example.com:4649");
```
Creating a instance of `WebSocketServer` class if you want multi WebSocket service server.
```cs
var wssv = new WebSocketServer(4649);
wssv.AddService<Echo>("/Echo");
wssv.AddService<Chat>("/Chat");
```
You can add to your `WebSocketServer` any WebSocket service and a matching path to that service by using `WebSocketServer.AddService<T>` method.
Type of `T` inherits `WebSocketService` class, so you can use a class that was created in **Step 2**.
If you set WebSocket url without port number, `WebSocketServer<T>` set **80** or **443** to port number automatically.
If you create a instance of WebSocket Server without port number, WebSocket Server set **80** or **443** to port number automatically.
So it is necessary to run with root permission.
$ sudo mono example2.exe
@ -272,6 +282,8 @@ Examples of using **websocket-sharp**.
[Example3] starts the HTTP server that the connection can be upgraded to the WebSocket connection.
Please access http://localhost:4649 to do WebSocket Echo Test with your web browser after [Example3] running.
## Supported WebSocket Protocol ##
**websocket-sharp** supports **[RFC 6455]**.

View File

@ -37,13 +37,20 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using WebSocketSharp.Net;
using WebSocketSharp.Net.Sockets;
namespace WebSocketSharp
{
public static class Ext
{
public static TcpListenerWebSocketContext AcceptWebSocket(this TcpClient client)
{
return new TcpListenerWebSocketContext(client);
}
public static void Emit(
this EventHandler eventHandler, object sender, EventArgs e)
{
@ -126,7 +133,7 @@ namespace WebSocketSharp
// Derived from System.Uri.IsPredefinedScheme method
public static bool IsPredefinedScheme(this string scheme)
{
if (scheme == null && scheme.Length < 3)
if (scheme == null && scheme.Length < 2)
return false;
char c = scheme[0];
@ -136,7 +143,10 @@ namespace WebSocketSharp
if (c == 'f')
return (scheme == "file" || scheme == "ftp");
if (c == 'w')
return (scheme == "ws" || scheme == "wss");
if (c == 'n')
{
c = scheme[1];
@ -156,6 +166,19 @@ namespace WebSocketSharp
return false;
}
// Derived from System.Uri.MaybeUri method
public static bool MaybeUri(this string uriString)
{
int p = uriString.IndexOf(':');
if (p == -1)
return false;
if (p >= 10)
return false;
return uriString.Substring(0, p).IsPredefinedScheme();
}
public static bool NotEqualsDo(
this string expected,
string actual,
@ -173,19 +196,6 @@ namespace WebSocketSharp
return false;
}
// Derived from System.Uri.MaybeUri method
public static bool MaybeUri(this string uriString)
{
int p = uriString.IndexOf(':');
if (p == -1)
return false;
if (p >= 10)
return false;
return uriString.Substring(0, p).IsPredefinedScheme();
}
public static byte[] ReadBytes<TStream>(this TStream stream, ulong length, int bufferLength)
where TStream : System.IO.Stream
{

View File

@ -33,12 +33,14 @@ namespace WebSocketSharp
{
public interface IWsStream : IDisposable
{
void Close();
int Read(byte[] buffer, int offset, int size);
int ReadByte();
WsFrame ReadFrame();
void Write(byte[] buffer, int offset, int count);
void WriteByte(byte value);
void WriteFrame(WsFrame frame);
void Close();
int Read(byte[] buffer, int offset, int size);
int ReadByte();
WsFrame ReadFrame();
string[] ReadHandshake();
void Write(byte[] buffer, int offset, int count);
void WriteByte(byte value);
void WriteFrame(WsFrame frame);
void WriteHandshake(Handshake handshake);
}
}

View File

@ -29,6 +29,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Principal;
@ -39,10 +40,12 @@ namespace WebSocketSharp.Net {
{
private HttpListenerContext _context;
private WebSocket _socket;
private IWsStream _stream;
internal HttpListenerWebSocketContext(string path, HttpListenerContext context)
{
_context = context;
_stream = WebSocket.CreateServerStream(context);
_socket = new WebSocket(path.ToUri(), this);
}
@ -50,6 +53,10 @@ namespace WebSocketSharp.Net {
get { return _context; }
}
internal IWsStream Stream {
get { return _stream; }
}
public override CookieCollection CookieCollection {
get { return _context.Request.Cookies; }
}

View File

@ -0,0 +1,120 @@
#region MIT License
/**
* TcpListenerWebSocketContext.cs
*
* The MIT License
*
* Copyright (c) 2012 sta.blockhead
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Principal;
namespace WebSocketSharp.Net.Sockets {
public class TcpListenerWebSocketContext : WebSocketContext
{
private TcpClient _client;
private bool _isSecure;
private RequestHandshake _request;
private WebSocket _socket;
private IWsStream _stream;
internal TcpListenerWebSocketContext(TcpClient client)
{
_client = client;
init();
}
internal TcpClient Client {
get { return _client; }
}
internal IWsStream Stream {
get { return _stream; }
}
public override CookieCollection CookieCollection {
get { throw new NotImplementedException(); }
}
public override NameValueCollection Headers {
get { return _request.Headers; }
}
public override bool IsAuthenticated {
get { throw new NotImplementedException(); }
}
public override bool IsSecureConnection {
get { return _isSecure; }
}
public override bool IsLocal {
get { throw new NotImplementedException(); }
}
public override string Origin {
get { return Headers["Origin"]; }
}
public override Uri RequestUri {
get { return _request.RequestUri; }
}
public override string SecWebSocketKey {
get { return Headers["Sec-WebSocket-Key"]; }
}
public override IEnumerable<string> SecWebSocketProtocols {
get { return Headers.GetValues("Sec-WebSocket-Protocol"); }
}
public override string SecWebSocketVersion {
get { return Headers["Sec-WebSocket-Version"]; }
}
public override IPrincipal User {
get { throw new NotImplementedException(); }
}
public override WebSocket WebSocket {
get { return _socket; }
}
private void init()
{
_stream = WebSocket.CreateServerStream(_client);
_request = RequestHandshake.Parse(_stream.ReadHandshake());
var port = ((IPEndPoint)_client.Client.LocalEndPoint).Port;
_isSecure = port == 443 ? true : false;
_socket = new WebSocket(this);
}
}
}

View File

@ -35,6 +35,36 @@ namespace WebSocketSharp {
public class ResponseHandshake : Handshake
{
#region Public Static Fields
public static ResponseHandshake BadRequest;
public static ResponseHandshake NotImplemented;
#endregion
#region Static Constructor
static ResponseHandshake()
{
var badRequest = new ResponseHandshake {
Reason = "Bad Request",
StatusCode = ((int)HttpStatusCode.BadRequest).ToString()
};
badRequest.Headers.Clear();
badRequest.AddHeader("Connection", "Close");
BadRequest = badRequest;
var notImplemented = new ResponseHandshake {
Reason = "Not Implemented",
StatusCode = ((int)HttpStatusCode.NotImplemented).ToString()
};
notImplemented.Headers.Clear();
notImplemented.AddHeader("Connection", "Close");
NotImplemented = notImplemented;
}
#endregion
#region Public Constructor
public ResponseHandshake()

View File

@ -31,25 +31,84 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using WebSocketSharp.Frame;
using WebSocketSharp.Net.Sockets;
namespace WebSocketSharp.Server {
public class WebSocketServer<T> : IWebSocketServer
public class WebSocketServer : WebSocketServerBase
{
#region Field
private Dictionary<string, IWebSocketServer> _servers;
#endregion
#region Public Constructors
public WebSocketServer()
: this(80)
{
}
public WebSocketServer(int port)
: base(IPAddress.Any, port)
{
_servers = new Dictionary<string, IWebSocketServer>();
}
#endregion
#region Protected Method
protected override void bindSocket(TcpClient client)
{
var context = client.AcceptWebSocket();
var path = context.RequestUri.ToString();
if (!_servers.ContainsKey(path))
{
var stream = context.Stream;
var res = ResponseHandshake.NotImplemented;
stream.WriteHandshake(res);
stream.Close();
client.Close();
return;
}
var socket = context.WebSocket;
var server = _servers[path];
server.BindWebSocket(socket);
}
#endregion
#region Public Methods
public void AddService<T>(string path)
where T : WebSocketService, new()
{
var server = new WebSocketServer<T>();
_servers.Add(path, server);
}
public override void Stop()
{
base.Stop();
foreach (var server in _servers.Values)
server.Stop();
}
#endregion
}
public class WebSocketServer<T> : WebSocketServerBase, IWebSocketServer
where T : WebSocketService, new()
{
#region Fields
private Thread _acceptClientThread;
private IPAddress _address;
private bool _isSelfHost;
private int _port;
private Dictionary<string, WebSocketService> _services;
private TcpListener _tcpListener;
private Uri _uri;
#endregion
@ -58,8 +117,7 @@ namespace WebSocketSharp.Server {
internal WebSocketServer()
{
_services = new Dictionary<string, WebSocketService>();
_isSelfHost = false;
init();
}
#endregion
@ -67,16 +125,10 @@ namespace WebSocketSharp.Server {
#region Public Constructors
public WebSocketServer(string url)
: this()
: base(url)
{
var uri = new Uri(url);
string msg;
if (!isValidUri(uri, out msg))
throw new ArgumentException(msg, "url");
_tcpListener = new TcpListener(_address, _port);
_isSelfHost = true;
_uri = url.ToUri();
init();
}
public WebSocketServer(int port)
@ -85,7 +137,7 @@ namespace WebSocketSharp.Server {
}
public WebSocketServer(int port, string path)
: this()
: base(IPAddress.Any, port)
{
var uri = path.ToUri();
if (uri.IsAbsoluteUri)
@ -94,31 +146,13 @@ namespace WebSocketSharp.Server {
throw new ArgumentException(msg, "path");
}
_uri = uri;
_address = IPAddress.Any;
_port = port <= 0 ? 80 : port;
_tcpListener = new TcpListener(_address, _port);
_isSelfHost = true;
_uri = uri;
init();
}
#endregion
#region Properties
public IPAddress Address
{
get { return _address; }
}
public bool IsSelfHost {
get { return _isSelfHost; }
}
public int Port
{
get { return _port; }
}
#region Property
public Uri Uri
{
@ -127,104 +161,21 @@ namespace WebSocketSharp.Server {
#endregion
#region Events
#region Private Method
public event EventHandler<ErrorEventArgs> OnError;
private void init()
{
_services = new Dictionary<string, WebSocketService>();
}
#endregion
#region Private Methods
#region Protected Method
private void acceptClient()
protected override void bindSocket(TcpClient client)
{
while (true)
{
try {
var client = _tcpListener.AcceptTcpClient();
startService(client);
}
catch (SocketException)
{
// TcpListener has been stopped.
break;
}
catch (Exception ex)
{
error(ex.Message);
break;
}
}
}
private void error(string message)
{
#if DEBUG
var callerFrame = new StackFrame(1);
var caller = callerFrame.GetMethod();
Console.WriteLine("WSSV: Error@{0}: {1}", caller.Name, message);
#endif
OnError.Emit(this, new ErrorEventArgs(message));
}
private bool isValidUri(Uri uri, out string message)
{
var scheme = uri.Scheme;
var port = uri.Port;
var host = uri.DnsSafeHost;
var ips = Dns.GetHostAddresses(host);
if (scheme != "ws" && scheme != "wss")
{
message = "Unsupported WebSocket URI scheme: " + scheme;
return false;
}
if ((scheme == "wss" && port != 443) ||
(scheme != "wss" && port == 443))
{
message = String.Format(
"Invalid pair of WebSocket URI scheme and port: {0}, {1}", scheme, port);
return false;
}
if (ips.Length == 0)
{
message = "Invalid WebSocket URI host: " + host;
return false;
}
if (port <= 0)
port = scheme == "ws" ? 80 : 443;
_uri = uri;
_address = ips[0];
_port = port;
message = String.Empty;
return true;
}
private void startAcceptClientThread()
{
_acceptClientThread = new Thread(new ThreadStart(acceptClient));
_acceptClientThread.IsBackground = true;
_acceptClientThread.Start();
}
private void startService(TcpClient client)
{
WaitCallback startServiceCb = (state) =>
{
try {
var socket = new WebSocket(_uri, client);
BindWebSocket(socket);
}
catch (Exception ex)
{
error(ex.Message);
}
};
ThreadPool.QueueUserWorkItem(startServiceCb);
var socket = new WebSocket(_uri, client);
BindWebSocket(socket);
}
#endregion
@ -238,23 +189,9 @@ namespace WebSocketSharp.Server {
service.Start();
}
public void Start()
public override void Stop()
{
if (!_isSelfHost)
return;
_tcpListener.Start();
startAcceptClientThread();
}
public void Stop()
{
if (_isSelfHost)
{
_tcpListener.Stop();
_acceptClientThread.Join(5 * 1000);
}
base.Stop();
StopServices();
}

View File

@ -0,0 +1,233 @@
#region MIT License
/**
* WebSocketServerBase.cs
*
* The MIT License
*
* Copyright (c) 2012 sta.blockhead
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#endregion
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace WebSocketSharp.Server {
public abstract class WebSocketServerBase
{
#region Fields
private Thread _acceptClientThread;
private IPAddress _address;
private bool _isSelfHost;
private int _port;
private TcpListener _tcpListener;
#endregion
#region Constructors
protected WebSocketServerBase()
{
_isSelfHost = false;
}
protected WebSocketServerBase(string url)
{
string msg;
if (!isValidUri(url, out msg))
throw new ArgumentException(msg, "url");
init();
}
protected WebSocketServerBase(IPAddress address, int port)
{
_port = port <= 0 ? 80 : port;
_address = address;
init();
}
#endregion
#region Property
public IPAddress Address {
get { return _address; }
}
public bool IsSelfHost {
get { return _isSelfHost; }
}
public int Port {
get { return _port; }
}
#endregion
#region Events
public event EventHandler<ErrorEventArgs> OnError;
#endregion
#region Private Methods
private void acceptClient()
{
while (true)
{
try
{
var client = _tcpListener.AcceptTcpClient();
acceptSocket(client);
}
catch (SocketException)
{
// TcpListener has been stopped.
break;
}
catch (Exception ex)
{
error(ex.Message);
break;
}
}
}
private void acceptSocket(TcpClient client)
{
WaitCallback acceptSocketCb = (state) =>
{
try
{
bindSocket(client);
}
catch (Exception ex)
{
error(ex.Message);
}
};
ThreadPool.QueueUserWorkItem(acceptSocketCb);
}
private void error(string message)
{
#if DEBUG
var callerFrame = new StackFrame(1);
var caller = callerFrame.GetMethod();
Console.WriteLine("WSSV: Error@{0}: {1}", caller.Name, message);
#endif
OnError.Emit(this, new ErrorEventArgs(message));
}
private void init()
{
_tcpListener = new TcpListener(_address, _port);
_isSelfHost = true;
}
private bool isValidUri(string url, out string message)
{
var uri = url.ToUri();
if (!uri.IsAbsoluteUri)
{
message = "Not absolute uri: " + url;
return false;
}
var scheme = uri.Scheme;
var port = uri.Port;
var host = uri.DnsSafeHost;
var ips = Dns.GetHostAddresses(host);
if (scheme != "ws" && scheme != "wss")
{
message = "Unsupported WebSocket URI scheme: " + scheme;
return false;
}
if ((scheme == "wss" && port != 443) ||
(scheme != "wss" && port == 443))
{
message = String.Format(
"Invalid pair of WebSocket URI scheme and port: {0}, {1}", scheme, port);
return false;
}
if (ips.Length == 0)
{
message = "Invalid WebSocket URI host: " + host;
return false;
}
if (port <= 0)
port = scheme == "ws" ? 80 : 443;
_address = ips[0];
_port = port;
message = String.Empty;
return true;
}
private void startAcceptClientThread()
{
_acceptClientThread = new Thread(new ThreadStart(acceptClient));
_acceptClientThread.IsBackground = true;
_acceptClientThread.Start();
}
#endregion
#region Protected Method
protected abstract void bindSocket(TcpClient client);
#endregion
#region Public Methods
public virtual void Start()
{
if (!_isSelfHost)
return;
_tcpListener.Start();
startAcceptClientThread();
}
public virtual void Stop()
{
if (!_isSelfHost)
return;
_tcpListener.Stop();
_acceptClientThread.Join(5 * 1000);
}
#endregion
}
}

View File

@ -48,6 +48,7 @@ using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using WebSocketSharp.Frame;
using WebSocketSharp.Net;
using WebSocketSharp.Net.Sockets;
namespace WebSocketSharp
{
@ -62,27 +63,28 @@ namespace WebSocketSharp
#region Private Fields
private string _base64key;
private string _binaryType;
private HttpListenerWebSocketContext _context;
private IPEndPoint _endPoint;
private AutoResetEvent _exitMessageLoop;
private string _extensions;
private Object _forClose;
private Object _forSend;
private int _fragmentLen;
private bool _isClient;
private bool _isSecure;
private NetworkStream _netStream;
private string _protocol;
private string _protocols;
private volatile WsState _readyState;
private AutoResetEvent _receivedPong;
private SslStream _sslStream;
private TcpClient _tcpClient;
private Uri _uri;
private SynchronizedCollection<WsFrame> _unTransmittedBuffer;
private IWsStream _wsStream;
private string _base64key;
private WebSocketSharp.Net.HttpListenerContext _baseContext;
private string _binaryType;
private WebSocketContext _context;
private IPEndPoint _endPoint;
private AutoResetEvent _exitMessageLoop;
private string _extensions;
private Object _forClose;
private Object _forSend;
private int _fragmentLen;
private bool _isClient;
private bool _isSecure;
private NetworkStream _netStream;
private string _protocol;
private string _protocols;
private volatile WsState _readyState;
private AutoResetEvent _receivedPong;
private SslStream _sslStream;
private TcpClient _tcpClient;
private Uri _uri;
private SynchronizedCollection<WsFrame> _unTransmittedBuffer;
private IWsStream _wsStream;
#endregion
@ -105,13 +107,28 @@ namespace WebSocketSharp
#region Internal Constructor
internal WebSocket(TcpListenerWebSocketContext context)
: this()
{
_uri = context.RequestUri;
_context = context;
_tcpClient = context.Client;
_wsStream = context.Stream;
_endPoint = (IPEndPoint)_tcpClient.Client.LocalEndPoint;
_isClient = false;
_isSecure = context.IsSecureConnection;
}
internal WebSocket(Uri uri, HttpListenerWebSocketContext context)
: this()
{
_uri = uri;
_context = context;
_isClient = false;
_isSecure = _context.IsSecureConnection;
_uri = uri;
_context = context;
_baseContext = context.BaseContext;
_wsStream = context.Stream;
_endPoint = _baseContext.Connection.LocalEndPoint;
_isClient = false;
_isSecure = context.IsSecureConnection;
}
internal WebSocket(Uri uri, TcpClient tcpClient)
@ -325,11 +342,11 @@ namespace WebSocketSharp
private void closeConnection()
{
if (_context != null)
if (_baseContext != null)
{
_context.BaseContext.Response.Close();
_wsStream = null;
_context = null;
_baseContext.Response.Close();
_wsStream = null;
_baseContext = null;
}
if (_wsStream != null)
@ -363,13 +380,10 @@ namespace WebSocketSharp
private void createClientStream()
{
var host = _uri.DnsSafeHost;
var port = _uri.Port;
if (port <= 0)
{
port = 80;
if (IsSecure)
port = 443;
}
port = IsSecure ? 443 : 80;
_tcpClient = new TcpClient(host, port);
_netStream = _tcpClient.GetStream();
@ -378,7 +392,7 @@ namespace WebSocketSharp
{
RemoteCertificateValidationCallback validation = (sender, certificate, chain, sslPolicyErrors) =>
{
// Temporary implementation
// FIXME: Always returns true
return true;
};
@ -449,44 +463,20 @@ namespace WebSocketSharp
private void createServerStream()
{
if (_context != null)
{
_wsStream = createServerStreamFromContext();
if (_wsStream != null)
return;
}
if (_tcpClient != null)
{
_wsStream = createServerStreamFromTcpClient();
_wsStream = CreateServerStream(_tcpClient);
return;
}
}
private IWsStream createServerStreamFromContext()
{
var stream = _context.BaseContext.Connection.Stream;
if (IsSecure)
return new WsStream<SslStream>((SslStream)stream);
return new WsStream<NetworkStream>((NetworkStream)stream);
}
private IWsStream createServerStreamFromTcpClient()
{
_netStream = _tcpClient.GetStream();
if (IsSecure)
if (_baseContext != null)
{
_sslStream = new SslStream(_netStream);
var certPath = ConfigurationManager.AppSettings["ServerCertPath"];
_sslStream.AuthenticateAsServer(new X509Certificate(certPath));
return new WsStream<SslStream>(_sslStream);
_wsStream = CreateServerStream(_baseContext);
return;
}
return new WsStream<NetworkStream>(_netStream);
}
private void doHandshake()
@ -695,20 +685,7 @@ namespace WebSocketSharp
private string[] readHandshake()
{
var buffer = new List<byte>();
while (true)
{
if (_wsStream.ReadByte().EqualsAndSaveTo('\r', buffer) &&
_wsStream.ReadByte().EqualsAndSaveTo('\n', buffer) &&
_wsStream.ReadByte().EqualsAndSaveTo('\r', buffer) &&
_wsStream.ReadByte().EqualsAndSaveTo('\n', buffer))
break;
}
return Encoding.UTF8.GetString(buffer.ToArray())
.Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n')
.Split('\n');
return _wsStream.ReadHandshake();
}
private MessageEventArgs receive()
@ -992,7 +969,7 @@ namespace WebSocketSharp
Console.WriteLine("WS: Info@sendOpeningHandshake: Opening handshake from client:\n");
Console.WriteLine(req.ToString());
#endif
_wsStream.Write(req.ToBytes(), 0, req.ToBytes().Length);
_wsStream.WriteHandshake(req);
var res = ResponseHandshake.Parse(readHandshake());
#if DEBUG
@ -1009,20 +986,14 @@ namespace WebSocketSharp
Console.WriteLine("WS: Info@sendResponseHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
_wsStream.Write(res.ToBytes(), 0, res.ToBytes().Length);
_wsStream.WriteHandshake(res);
}
private void sendResponseHandshakeForInvalid()
{
var code = (int)WebSocketSharp.Net.HttpStatusCode.BadRequest;
var res = new ResponseHandshake {
Reason = "Bad Request",
StatusCode = code.ToString()
};
res.Headers.Clear();
var res = ResponseHandshake.BadRequest;
res.AddHeader("Sec-WebSocket-Version", _version);
_wsStream.Write(res.ToBytes(), 0, res.ToBytes().Length);
_wsStream.WriteHandshake(res);
}
private void startMessageThread()
@ -1040,6 +1011,39 @@ namespace WebSocketSharp
#endregion
#region Internal Static Methods
internal static IWsStream CreateServerStream(TcpClient client)
{
var netStream = client.GetStream();
var port = ((IPEndPoint)client.Client.LocalEndPoint).Port;
if (port == 443)
{
var sslStream = new SslStream(netStream);
var certPath = ConfigurationManager.AppSettings["ServerCertPath"];
sslStream.AuthenticateAsServer(new X509Certificate2(certPath));
return new WsStream<SslStream>(sslStream);
}
return new WsStream<NetworkStream>(netStream);
}
internal static IWsStream CreateServerStream(WebSocketSharp.Net.HttpListenerContext context)
{
var conn = context.Connection;
var stream = conn.Stream;
if (conn.IsSecure)
return new WsStream<SslStream>((SslStream)stream);
return new WsStream<NetworkStream>((NetworkStream)stream);
}
#endregion
#region Public Methods
public void Close()

View File

@ -32,6 +32,7 @@ using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using WebSocketSharp.Frame;
namespace WebSocketSharp
@ -39,10 +40,16 @@ namespace WebSocketSharp
public class WsStream<TStream> : IWsStream
where TStream : Stream
{
#region Fields
private TStream _innerStream;
private Object _forRead;
private Object _forWrite;
#endregion
#region Constructor
public WsStream(TStream innerStream)
{
Type streamType = typeof(TStream);
@ -62,6 +69,10 @@ namespace WebSocketSharp
_forWrite = new object();
}
#endregion
#region Public Methods
public void Close()
{
_innerStream.Close();
@ -102,6 +113,27 @@ namespace WebSocketSharp
}
}
public string[] ReadHandshake()
{
lock (_forRead)
{
var buffer = new List<byte>();
while (true)
{
if (ReadByte().EqualsAndSaveTo('\r', buffer) &&
ReadByte().EqualsAndSaveTo('\n', buffer) &&
ReadByte().EqualsAndSaveTo('\r', buffer) &&
ReadByte().EqualsAndSaveTo('\n', buffer))
break;
}
return Encoding.UTF8.GetString(buffer.ToArray())
.Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n')
.Split('\n');
}
}
public void Write(byte[] buffer, int offset, int count)
{
lock (_forWrite)
@ -126,5 +158,16 @@ namespace WebSocketSharp
_innerStream.Write(buffer, 0, buffer.Length);
}
}
public void WriteHandshake(Handshake handshake)
{
lock (_forWrite)
{
var buffer = handshake.ToBytes();
_innerStream.Write(buffer, 0, buffer.Length);
}
}
#endregion
}
}

View File

@ -109,11 +109,14 @@
<Compile Include="Net\HttpVersion.cs" />
<Compile Include="Net\HttpStatusCode.cs" />
<Compile Include="Server\IWebSocketServer.cs" />
<Compile Include="Net\Sockets\TcpListenerWebSocketContext.cs" />
<Compile Include="Server\WebSocketServerBase.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Folder Include="Frame\" />
<Folder Include="Server\" />
<Folder Include="Net\" />
<Folder Include="Net\Sockets\" />
</ItemGroup>
</Project>

Binary file not shown.