Fix due to the added WebSocketServer class in WebSocketServer.cs
This commit is contained in:
parent
ab86ce8af8
commit
b9859e08c0
Binary file not shown.
@ -76,6 +76,8 @@ namespace Example
|
|||||||
using (WebSocket ws = new WebSocket("ws://echo.websocket.org", "echo"))
|
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("wss://echo.websocket.org", "echo"))
|
||||||
//using (WebSocket ws = new WebSocket("ws://localhost:4649"))
|
//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) =>
|
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.
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.
Binary file not shown.
Binary file not shown.
@ -7,14 +7,27 @@ namespace Example2
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
/* Single service server
|
||||||
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<Echo>(4649);
|
//var wssv = new WebSocketServer<Echo>(4649);
|
||||||
|
//var wssv = new WebSocketServer<Chat>("ws://localhost:4649");
|
||||||
|
//var wssv = new WebSocketServer<Chat>(4649);
|
||||||
|
|
||||||
wssv.Start();
|
wssv.Start();
|
||||||
Console.WriteLine(
|
Console.WriteLine(
|
||||||
"WebSocket Server (url: {0})\n listening on address: {1} port: {2}\n",
|
"WebSocket Server (url: {0})\n listening on address: {1} port: {2}\n",
|
||||||
wssv.Uri, wssv.Address, wssv.Port);
|
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.WriteLine("Press any key to stop server...");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
|
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.
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.
18
README.md
18
README.md
@ -147,7 +147,7 @@ Required namespace.
|
|||||||
using WebSocketSharp.Server;
|
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 ####
|
#### Step 2 ####
|
||||||
|
|
||||||
@ -191,15 +191,25 @@ In addition, if you override `onOpen`, `onError` and `onClose` methods, each of
|
|||||||
|
|
||||||
#### Step 3 ####
|
#### Step 3 ####
|
||||||
|
|
||||||
Creating a instance of `WebSocketServer<T>` class.
|
Creating a instance of `WebSocketServer<T>` class if you want single WebSocket service server.
|
||||||
|
|
||||||
```cs
|
```cs
|
||||||
var wssv = new WebSocketServer<Echo>("ws://example.com:4649");
|
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**.
|
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.
|
So it is necessary to run with root permission.
|
||||||
|
|
||||||
$ sudo mono example2.exe
|
$ 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.
|
[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 ##
|
## Supported WebSocket Protocol ##
|
||||||
|
|
||||||
**websocket-sharp** supports **[RFC 6455]**.
|
**websocket-sharp** supports **[RFC 6455]**.
|
||||||
|
@ -37,13 +37,20 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
|
using WebSocketSharp.Net.Sockets;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
public static class Ext
|
public static class Ext
|
||||||
{
|
{
|
||||||
|
public static TcpListenerWebSocketContext AcceptWebSocket(this TcpClient client)
|
||||||
|
{
|
||||||
|
return new TcpListenerWebSocketContext(client);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Emit(
|
public static void Emit(
|
||||||
this EventHandler eventHandler, object sender, EventArgs e)
|
this EventHandler eventHandler, object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
@ -126,7 +133,7 @@ namespace WebSocketSharp
|
|||||||
// Derived from System.Uri.IsPredefinedScheme method
|
// Derived from System.Uri.IsPredefinedScheme method
|
||||||
public static bool IsPredefinedScheme(this string scheme)
|
public static bool IsPredefinedScheme(this string scheme)
|
||||||
{
|
{
|
||||||
if (scheme == null && scheme.Length < 3)
|
if (scheme == null && scheme.Length < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char c = scheme[0];
|
char c = scheme[0];
|
||||||
@ -136,7 +143,10 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
if (c == 'f')
|
if (c == 'f')
|
||||||
return (scheme == "file" || scheme == "ftp");
|
return (scheme == "file" || scheme == "ftp");
|
||||||
|
|
||||||
|
if (c == 'w')
|
||||||
|
return (scheme == "ws" || scheme == "wss");
|
||||||
|
|
||||||
if (c == 'n')
|
if (c == 'n')
|
||||||
{
|
{
|
||||||
c = scheme[1];
|
c = scheme[1];
|
||||||
@ -156,6 +166,19 @@ namespace WebSocketSharp
|
|||||||
return false;
|
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(
|
public static bool NotEqualsDo(
|
||||||
this string expected,
|
this string expected,
|
||||||
string actual,
|
string actual,
|
||||||
@ -173,19 +196,6 @@ namespace WebSocketSharp
|
|||||||
return false;
|
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)
|
public static byte[] ReadBytes<TStream>(this TStream stream, ulong length, int bufferLength)
|
||||||
where TStream : System.IO.Stream
|
where TStream : System.IO.Stream
|
||||||
{
|
{
|
||||||
|
@ -33,12 +33,14 @@ namespace WebSocketSharp
|
|||||||
{
|
{
|
||||||
public interface IWsStream : IDisposable
|
public interface IWsStream : IDisposable
|
||||||
{
|
{
|
||||||
void Close();
|
void Close();
|
||||||
int Read(byte[] buffer, int offset, int size);
|
int Read(byte[] buffer, int offset, int size);
|
||||||
int ReadByte();
|
int ReadByte();
|
||||||
WsFrame ReadFrame();
|
WsFrame ReadFrame();
|
||||||
void Write(byte[] buffer, int offset, int count);
|
string[] ReadHandshake();
|
||||||
void WriteByte(byte value);
|
void Write(byte[] buffer, int offset, int count);
|
||||||
void WriteFrame(WsFrame frame);
|
void WriteByte(byte value);
|
||||||
|
void WriteFrame(WsFrame frame);
|
||||||
|
void WriteHandshake(Handshake handshake);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.IO;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
@ -39,10 +40,12 @@ namespace WebSocketSharp.Net {
|
|||||||
{
|
{
|
||||||
private HttpListenerContext _context;
|
private HttpListenerContext _context;
|
||||||
private WebSocket _socket;
|
private WebSocket _socket;
|
||||||
|
private IWsStream _stream;
|
||||||
|
|
||||||
internal HttpListenerWebSocketContext(string path, HttpListenerContext context)
|
internal HttpListenerWebSocketContext(string path, HttpListenerContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_stream = WebSocket.CreateServerStream(context);
|
||||||
_socket = new WebSocket(path.ToUri(), this);
|
_socket = new WebSocket(path.ToUri(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +53,10 @@ namespace WebSocketSharp.Net {
|
|||||||
get { return _context; }
|
get { return _context; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal IWsStream Stream {
|
||||||
|
get { return _stream; }
|
||||||
|
}
|
||||||
|
|
||||||
public override CookieCollection CookieCollection {
|
public override CookieCollection CookieCollection {
|
||||||
get { return _context.Request.Cookies; }
|
get { return _context.Request.Cookies; }
|
||||||
}
|
}
|
||||||
|
120
websocket-sharp/Net/Sockets/TcpListenerWebSocketContext.cs
Normal file
120
websocket-sharp/Net/Sockets/TcpListenerWebSocketContext.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,36 @@ namespace WebSocketSharp {
|
|||||||
|
|
||||||
public class ResponseHandshake : Handshake
|
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
|
#region Public Constructor
|
||||||
|
|
||||||
public ResponseHandshake()
|
public ResponseHandshake()
|
||||||
|
@ -31,25 +31,84 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
|
||||||
using WebSocketSharp.Frame;
|
using WebSocketSharp.Frame;
|
||||||
|
using WebSocketSharp.Net.Sockets;
|
||||||
|
|
||||||
namespace WebSocketSharp.Server {
|
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()
|
where T : WebSocketService, new()
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
private Thread _acceptClientThread;
|
|
||||||
private IPAddress _address;
|
|
||||||
private bool _isSelfHost;
|
|
||||||
private int _port;
|
|
||||||
private Dictionary<string, WebSocketService> _services;
|
private Dictionary<string, WebSocketService> _services;
|
||||||
private TcpListener _tcpListener;
|
|
||||||
private Uri _uri;
|
private Uri _uri;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -58,8 +117,7 @@ namespace WebSocketSharp.Server {
|
|||||||
|
|
||||||
internal WebSocketServer()
|
internal WebSocketServer()
|
||||||
{
|
{
|
||||||
_services = new Dictionary<string, WebSocketService>();
|
init();
|
||||||
_isSelfHost = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -67,16 +125,10 @@ namespace WebSocketSharp.Server {
|
|||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
public WebSocketServer(string url)
|
public WebSocketServer(string url)
|
||||||
: this()
|
: base(url)
|
||||||
{
|
{
|
||||||
var uri = new Uri(url);
|
_uri = url.ToUri();
|
||||||
|
init();
|
||||||
string msg;
|
|
||||||
if (!isValidUri(uri, out msg))
|
|
||||||
throw new ArgumentException(msg, "url");
|
|
||||||
|
|
||||||
_tcpListener = new TcpListener(_address, _port);
|
|
||||||
_isSelfHost = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServer(int port)
|
public WebSocketServer(int port)
|
||||||
@ -85,7 +137,7 @@ namespace WebSocketSharp.Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServer(int port, string path)
|
public WebSocketServer(int port, string path)
|
||||||
: this()
|
: base(IPAddress.Any, port)
|
||||||
{
|
{
|
||||||
var uri = path.ToUri();
|
var uri = path.ToUri();
|
||||||
if (uri.IsAbsoluteUri)
|
if (uri.IsAbsoluteUri)
|
||||||
@ -94,31 +146,13 @@ namespace WebSocketSharp.Server {
|
|||||||
throw new ArgumentException(msg, "path");
|
throw new ArgumentException(msg, "path");
|
||||||
}
|
}
|
||||||
|
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
_address = IPAddress.Any;
|
init();
|
||||||
_port = port <= 0 ? 80 : port;
|
|
||||||
|
|
||||||
_tcpListener = new TcpListener(_address, _port);
|
|
||||||
_isSelfHost = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Property
|
||||||
|
|
||||||
public IPAddress Address
|
|
||||||
{
|
|
||||||
get { return _address; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSelfHost {
|
|
||||||
get { return _isSelfHost; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Port
|
|
||||||
{
|
|
||||||
get { return _port; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri Uri
|
public Uri Uri
|
||||||
{
|
{
|
||||||
@ -127,104 +161,21 @@ namespace WebSocketSharp.Server {
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Private Method
|
||||||
|
|
||||||
public event EventHandler<ErrorEventArgs> OnError;
|
private void init()
|
||||||
|
{
|
||||||
|
_services = new Dictionary<string, WebSocketService>();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
#region Protected Method
|
||||||
|
|
||||||
private void acceptClient()
|
protected override void bindSocket(TcpClient client)
|
||||||
{
|
{
|
||||||
while (true)
|
var socket = new WebSocket(_uri, client);
|
||||||
{
|
BindWebSocket(socket);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -238,23 +189,9 @@ namespace WebSocketSharp.Server {
|
|||||||
service.Start();
|
service.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public override void Stop()
|
||||||
{
|
{
|
||||||
if (!_isSelfHost)
|
base.Stop();
|
||||||
return;
|
|
||||||
|
|
||||||
_tcpListener.Start();
|
|
||||||
startAcceptClientThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
if (_isSelfHost)
|
|
||||||
{
|
|
||||||
_tcpListener.Stop();
|
|
||||||
_acceptClientThread.Join(5 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopServices();
|
StopServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
233
websocket-sharp/Server/WebSocketServerBase.cs
Normal file
233
websocket-sharp/Server/WebSocketServerBase.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,7 @@ using System.Security.Cryptography;
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using WebSocketSharp.Frame;
|
using WebSocketSharp.Frame;
|
||||||
using WebSocketSharp.Net;
|
using WebSocketSharp.Net;
|
||||||
|
using WebSocketSharp.Net.Sockets;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
{
|
{
|
||||||
@ -62,27 +63,28 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private string _base64key;
|
private string _base64key;
|
||||||
private string _binaryType;
|
private WebSocketSharp.Net.HttpListenerContext _baseContext;
|
||||||
private HttpListenerWebSocketContext _context;
|
private string _binaryType;
|
||||||
private IPEndPoint _endPoint;
|
private WebSocketContext _context;
|
||||||
private AutoResetEvent _exitMessageLoop;
|
private IPEndPoint _endPoint;
|
||||||
private string _extensions;
|
private AutoResetEvent _exitMessageLoop;
|
||||||
private Object _forClose;
|
private string _extensions;
|
||||||
private Object _forSend;
|
private Object _forClose;
|
||||||
private int _fragmentLen;
|
private Object _forSend;
|
||||||
private bool _isClient;
|
private int _fragmentLen;
|
||||||
private bool _isSecure;
|
private bool _isClient;
|
||||||
private NetworkStream _netStream;
|
private bool _isSecure;
|
||||||
private string _protocol;
|
private NetworkStream _netStream;
|
||||||
private string _protocols;
|
private string _protocol;
|
||||||
private volatile WsState _readyState;
|
private string _protocols;
|
||||||
private AutoResetEvent _receivedPong;
|
private volatile WsState _readyState;
|
||||||
private SslStream _sslStream;
|
private AutoResetEvent _receivedPong;
|
||||||
private TcpClient _tcpClient;
|
private SslStream _sslStream;
|
||||||
private Uri _uri;
|
private TcpClient _tcpClient;
|
||||||
private SynchronizedCollection<WsFrame> _unTransmittedBuffer;
|
private Uri _uri;
|
||||||
private IWsStream _wsStream;
|
private SynchronizedCollection<WsFrame> _unTransmittedBuffer;
|
||||||
|
private IWsStream _wsStream;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -105,13 +107,28 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#region Internal Constructor
|
#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)
|
internal WebSocket(Uri uri, HttpListenerWebSocketContext context)
|
||||||
: this()
|
: this()
|
||||||
{
|
{
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
_context = context;
|
_context = context;
|
||||||
_isClient = false;
|
_baseContext = context.BaseContext;
|
||||||
_isSecure = _context.IsSecureConnection;
|
_wsStream = context.Stream;
|
||||||
|
_endPoint = _baseContext.Connection.LocalEndPoint;
|
||||||
|
_isClient = false;
|
||||||
|
_isSecure = context.IsSecureConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal WebSocket(Uri uri, TcpClient tcpClient)
|
internal WebSocket(Uri uri, TcpClient tcpClient)
|
||||||
@ -325,11 +342,11 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
private void closeConnection()
|
private void closeConnection()
|
||||||
{
|
{
|
||||||
if (_context != null)
|
if (_baseContext != null)
|
||||||
{
|
{
|
||||||
_context.BaseContext.Response.Close();
|
_baseContext.Response.Close();
|
||||||
_wsStream = null;
|
_wsStream = null;
|
||||||
_context = null;
|
_baseContext = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_wsStream != null)
|
if (_wsStream != null)
|
||||||
@ -363,13 +380,10 @@ namespace WebSocketSharp
|
|||||||
private void createClientStream()
|
private void createClientStream()
|
||||||
{
|
{
|
||||||
var host = _uri.DnsSafeHost;
|
var host = _uri.DnsSafeHost;
|
||||||
|
|
||||||
var port = _uri.Port;
|
var port = _uri.Port;
|
||||||
if (port <= 0)
|
if (port <= 0)
|
||||||
{
|
port = IsSecure ? 443 : 80;
|
||||||
port = 80;
|
|
||||||
if (IsSecure)
|
|
||||||
port = 443;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tcpClient = new TcpClient(host, port);
|
_tcpClient = new TcpClient(host, port);
|
||||||
_netStream = _tcpClient.GetStream();
|
_netStream = _tcpClient.GetStream();
|
||||||
@ -378,7 +392,7 @@ namespace WebSocketSharp
|
|||||||
{
|
{
|
||||||
RemoteCertificateValidationCallback validation = (sender, certificate, chain, sslPolicyErrors) =>
|
RemoteCertificateValidationCallback validation = (sender, certificate, chain, sslPolicyErrors) =>
|
||||||
{
|
{
|
||||||
// Temporary implementation
|
// FIXME: Always returns true
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -449,44 +463,20 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
private void createServerStream()
|
private void createServerStream()
|
||||||
{
|
{
|
||||||
if (_context != null)
|
if (_wsStream != null)
|
||||||
{
|
|
||||||
_wsStream = createServerStreamFromContext();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (_tcpClient != null)
|
if (_tcpClient != null)
|
||||||
{
|
{
|
||||||
_wsStream = createServerStreamFromTcpClient();
|
_wsStream = CreateServerStream(_tcpClient);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private IWsStream createServerStreamFromContext()
|
if (_baseContext != null)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
_sslStream = new SslStream(_netStream);
|
_wsStream = CreateServerStream(_baseContext);
|
||||||
|
return;
|
||||||
var certPath = ConfigurationManager.AppSettings["ServerCertPath"];
|
|
||||||
_sslStream.AuthenticateAsServer(new X509Certificate(certPath));
|
|
||||||
|
|
||||||
return new WsStream<SslStream>(_sslStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WsStream<NetworkStream>(_netStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doHandshake()
|
private void doHandshake()
|
||||||
@ -695,20 +685,7 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
private string[] readHandshake()
|
private string[] readHandshake()
|
||||||
{
|
{
|
||||||
var buffer = new List<byte>();
|
return _wsStream.ReadHandshake();
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessageEventArgs receive()
|
private MessageEventArgs receive()
|
||||||
@ -992,7 +969,7 @@ namespace WebSocketSharp
|
|||||||
Console.WriteLine("WS: Info@sendOpeningHandshake: Opening handshake from client:\n");
|
Console.WriteLine("WS: Info@sendOpeningHandshake: Opening handshake from client:\n");
|
||||||
Console.WriteLine(req.ToString());
|
Console.WriteLine(req.ToString());
|
||||||
#endif
|
#endif
|
||||||
_wsStream.Write(req.ToBytes(), 0, req.ToBytes().Length);
|
_wsStream.WriteHandshake(req);
|
||||||
|
|
||||||
var res = ResponseHandshake.Parse(readHandshake());
|
var res = ResponseHandshake.Parse(readHandshake());
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -1009,20 +986,14 @@ namespace WebSocketSharp
|
|||||||
Console.WriteLine("WS: Info@sendResponseHandshake: Response handshake from server:\n");
|
Console.WriteLine("WS: Info@sendResponseHandshake: Response handshake from server:\n");
|
||||||
Console.WriteLine(res.ToString());
|
Console.WriteLine(res.ToString());
|
||||||
#endif
|
#endif
|
||||||
_wsStream.Write(res.ToBytes(), 0, res.ToBytes().Length);
|
_wsStream.WriteHandshake(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendResponseHandshakeForInvalid()
|
private void sendResponseHandshakeForInvalid()
|
||||||
{
|
{
|
||||||
var code = (int)WebSocketSharp.Net.HttpStatusCode.BadRequest;
|
var res = ResponseHandshake.BadRequest;
|
||||||
var res = new ResponseHandshake {
|
|
||||||
Reason = "Bad Request",
|
|
||||||
StatusCode = code.ToString()
|
|
||||||
};
|
|
||||||
res.Headers.Clear();
|
|
||||||
res.AddHeader("Sec-WebSocket-Version", _version);
|
res.AddHeader("Sec-WebSocket-Version", _version);
|
||||||
|
_wsStream.WriteHandshake(res);
|
||||||
_wsStream.Write(res.ToBytes(), 0, res.ToBytes().Length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startMessageThread()
|
private void startMessageThread()
|
||||||
@ -1040,6 +1011,39 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#endregion
|
#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
|
#region Public Methods
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
|
@ -32,6 +32,7 @@ using System.IO;
|
|||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using WebSocketSharp.Frame;
|
using WebSocketSharp.Frame;
|
||||||
|
|
||||||
namespace WebSocketSharp
|
namespace WebSocketSharp
|
||||||
@ -39,10 +40,16 @@ namespace WebSocketSharp
|
|||||||
public class WsStream<TStream> : IWsStream
|
public class WsStream<TStream> : IWsStream
|
||||||
where TStream : Stream
|
where TStream : Stream
|
||||||
{
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
private TStream _innerStream;
|
private TStream _innerStream;
|
||||||
private Object _forRead;
|
private Object _forRead;
|
||||||
private Object _forWrite;
|
private Object _forWrite;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
public WsStream(TStream innerStream)
|
public WsStream(TStream innerStream)
|
||||||
{
|
{
|
||||||
Type streamType = typeof(TStream);
|
Type streamType = typeof(TStream);
|
||||||
@ -62,6 +69,10 @@ namespace WebSocketSharp
|
|||||||
_forWrite = new object();
|
_forWrite = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
_innerStream.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)
|
public void Write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
lock (_forWrite)
|
lock (_forWrite)
|
||||||
@ -126,5 +158,16 @@ namespace WebSocketSharp
|
|||||||
_innerStream.Write(buffer, 0, buffer.Length);
|
_innerStream.Write(buffer, 0, buffer.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WriteHandshake(Handshake handshake)
|
||||||
|
{
|
||||||
|
lock (_forWrite)
|
||||||
|
{
|
||||||
|
var buffer = handshake.ToBytes();
|
||||||
|
_innerStream.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -109,11 +109,14 @@
|
|||||||
<Compile Include="Net\HttpVersion.cs" />
|
<Compile Include="Net\HttpVersion.cs" />
|
||||||
<Compile Include="Net\HttpStatusCode.cs" />
|
<Compile Include="Net\HttpStatusCode.cs" />
|
||||||
<Compile Include="Server\IWebSocketServer.cs" />
|
<Compile Include="Server\IWebSocketServer.cs" />
|
||||||
|
<Compile Include="Net\Sockets\TcpListenerWebSocketContext.cs" />
|
||||||
|
<Compile Include="Server\WebSocketServerBase.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Frame\" />
|
<Folder Include="Frame\" />
|
||||||
<Folder Include="Server\" />
|
<Folder Include="Server\" />
|
||||||
<Folder Include="Net\" />
|
<Folder Include="Net\" />
|
||||||
|
<Folder Include="Net\Sockets\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user