Fix for the secure connection
This commit is contained in:
parent
49dc8800d3
commit
3e6c589953
@ -8,29 +8,29 @@ using System.Threading;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Net;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
public struct NfMessage
|
||||
{
|
||||
namespace Example {
|
||||
|
||||
public struct NfMessage {
|
||||
|
||||
public string Summary;
|
||||
public string Body;
|
||||
public string Icon;
|
||||
}
|
||||
|
||||
public class ThreadState
|
||||
{
|
||||
public class ThreadState {
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
public AutoResetEvent Notification { get; private set; }
|
||||
|
||||
public ThreadState()
|
||||
{
|
||||
Enabled = true;
|
||||
Enabled = true;
|
||||
Notification = new AutoResetEvent(false);
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public class Program {
|
||||
|
||||
private static Queue _msgQ = Queue.Synchronized(new Queue());
|
||||
|
||||
private static void enNfMessage(string summary, string body, string icon)
|
||||
@ -38,8 +38,8 @@ namespace Example
|
||||
var msg = new NfMessage
|
||||
{
|
||||
Summary = summary,
|
||||
Body = body,
|
||||
Icon = icon
|
||||
Body = body,
|
||||
Icon = icon
|
||||
};
|
||||
|
||||
_msgQ.Enqueue(msg);
|
||||
@ -47,7 +47,7 @@ namespace Example
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
ThreadState ts = new ThreadState();
|
||||
var ts = new ThreadState();
|
||||
|
||||
WaitCallback notifyMsg = state =>
|
||||
{
|
||||
@ -57,11 +57,9 @@ namespace Example
|
||||
|
||||
if (_msgQ.Count > 0)
|
||||
{
|
||||
NfMessage msg = (NfMessage)_msgQ.Dequeue();
|
||||
var msg = (NfMessage)_msgQ.Dequeue();
|
||||
#if NOTIFY
|
||||
Notification nf = new Notification(msg.Summary,
|
||||
msg.Body,
|
||||
msg.Icon);
|
||||
var nf = new Notification(msg.Summary, msg.Body, msg.Icon);
|
||||
nf.AddHint("append", "allowed");
|
||||
nf.Show();
|
||||
#else
|
||||
@ -75,15 +73,16 @@ namespace Example
|
||||
|
||||
ThreadPool.QueueUserWorkItem(notifyMsg);
|
||||
|
||||
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/Echo?name=nobita"))
|
||||
//using (WebSocket ws = new WebSocket("ws://localhost:4649/エコー?name=のび太"))
|
||||
//using (WebSocket ws = new WebSocket("ws://localhost:4649/Chat"))
|
||||
//using (WebSocket ws = new WebSocket("ws://localhost:4649/Chat?name=nobita"))
|
||||
//using (WebSocket ws = new WebSocket("ws://localhost:4649/チャット?name=のび太"))
|
||||
using (var ws = new WebSocket("ws://echo.websocket.org", "echo"))
|
||||
//using (var ws = new WebSocket("wss://echo.websocket.org", "echo"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649/Echo"))
|
||||
//using (var ws = new WebSocket("wss://localhost:4649/Echo"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649/Echo?name=nobita"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649/エコー?name=のび太"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649/Chat"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649/Chat?name=nobita"))
|
||||
//using (var ws = new WebSocket("ws://localhost:4649/チャット?name=のび太"))
|
||||
{
|
||||
ws.OnOpen += (sender, e) =>
|
||||
{
|
||||
@ -111,11 +110,16 @@ namespace Example
|
||||
"notification-message-im");
|
||||
};
|
||||
|
||||
//ws.Origin = "http://echo.websocket.org";
|
||||
//ws.Compression = CompressionMethod.DEFLATE;
|
||||
#if DEBUG
|
||||
ws.Log.Level = LogLevel.TRACE;
|
||||
#endif
|
||||
//ws.Compression = CompressionMethod.DEFLATE;
|
||||
//ws.Origin = "http://echo.websocket.org";
|
||||
//ws.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
//{
|
||||
// ws.Log.Debug(String.Format("\n{0}\n{1}", certificate.Issuer, certificate.Subject));
|
||||
// return true;
|
||||
//};
|
||||
//ws.SetCookie(new Cookie("nobita", "\"idiot, gunfighter\""));
|
||||
//ws.SetCookie(new Cookie("dora", "tanuki"));
|
||||
ws.Connect();
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="ServerCertPath" value="/path/to/server.cer" />
|
||||
<add key="ServerCertFile" value="/path/to/cert.pfx"/>
|
||||
<add key="CertFilePassword" value="password"/>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
|
@ -49,6 +49,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
|
@ -1,58 +1,67 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
namespace Example2 {
|
||||
|
||||
public class Program {
|
||||
|
||||
public static void Main (string [] args)
|
||||
{
|
||||
/* Single service server
|
||||
//var wssv = new WebSocketServiceHost<Echo>("ws://localhost:4649");
|
||||
var wssv = new WebSocketServiceHost<Echo>("ws://localhost:4649/Echo");
|
||||
//var wssv = new WebSocketServiceHost<Echo>("ws://localhost:4649/エコー");
|
||||
//var wssv = new WebSocketServiceHost<Echo>(4649);
|
||||
//var wssv = new WebSocketServiceHost<Echo>(4649, "/Echo");
|
||||
//var wssv = new WebSocketServiceHost<Echo>(4649, "/エコー");
|
||||
//var wssv = new WebSocketServiceHost<Chat>("ws://localhost:4649");
|
||||
//var wssv = new WebSocketServiceHost<Chat>("ws://localhost:4649/Chat");
|
||||
//var wssv = new WebSocketServiceHost<Chat>("ws://localhost:4649/チャット");
|
||||
//var wssv = new WebSocketServiceHost<Chat>(4649);
|
||||
//var wssv = new WebSocketServiceHost<Chat>(4649, "/Chat");
|
||||
//var wssv = new WebSocketServiceHost<Chat>(4649, "/チャット");
|
||||
//wssv.Sweeping = false; // Stop the sweep inactive session timer.
|
||||
var wssv = new WebSocketServiceHost<Echo> ("ws://localhost:4649");
|
||||
//var wssv = new WebSocketServiceHost<Echo> ("ws://localhost:4649/Echo");
|
||||
//var wssv = new WebSocketServiceHost<Echo> ("ws://localhost:4649/エコー");
|
||||
//var wssv = new WebSocketServiceHost<Echo> (4649);
|
||||
//var wssv = new WebSocketServiceHost<Echo> (4649, "/Echo");
|
||||
//var wssv = new WebSocketServiceHost<Echo> (4649, "/エコー");
|
||||
//var wssv = new WebSocketServiceHost<Chat> ("ws://localhost:4649");
|
||||
//var wssv = new WebSocketServiceHost<Chat> ("ws://localhost:4649/Chat");
|
||||
//var wssv = new WebSocketServiceHost<Chat> ("ws://localhost:4649/チャット");
|
||||
//var wssv = new WebSocketServiceHost<Chat> (4649);
|
||||
//var wssv = new WebSocketServiceHost<Chat> (4649, "/Chat");
|
||||
//var wssv = new WebSocketServiceHost<Chat> (4649, "/チャット");
|
||||
#if DEBUG
|
||||
wssv.Log.Level = LogLevel.TRACE;
|
||||
#endif
|
||||
//wssv.Sweeping = false;
|
||||
|
||||
wssv.Start();
|
||||
Console.WriteLine(
|
||||
wssv.Start ();
|
||||
Console.WriteLine (
|
||||
"WebSocket Service Host (url: {0})\n listening on address: {1} port: {2}\n",
|
||||
wssv.Uri, wssv.Address, wssv.Port);
|
||||
*/
|
||||
|
||||
// Multi services server
|
||||
var wssv = new WebSocketServer(4649);
|
||||
//var wssv = new WebSocketServer("ws://localhost:4649");
|
||||
/* Multi services server */
|
||||
var wssv = new WebSocketServer (4649);
|
||||
//var wssv = new WebSocketServer (4649, true);
|
||||
//var wssv = new WebSocketServer ("ws://localhost:4649");
|
||||
//var wssv = new WebSocketServer ("wss://localhost:4649");
|
||||
#if DEBUG
|
||||
wssv.Log.Level = LogLevel.TRACE;
|
||||
#endif
|
||||
//wssv.Sweeping = false; // Stop the sweep inactive session timer.
|
||||
wssv.AddWebSocketService<Echo>("/Echo");
|
||||
wssv.AddWebSocketService<Chat>("/Chat");
|
||||
//wssv.AddWebSocketService<Echo>("/エコー");
|
||||
//wssv.AddWebSocketService<Chat>("/チャット");
|
||||
//var file = ConfigurationManager.AppSettings ["ServerCertFile"];
|
||||
//var password = ConfigurationManager.AppSettings ["CertFilePassword"];
|
||||
//wssv.Certificate = new X509Certificate2 (file, password);
|
||||
//wssv.Sweeping = false;
|
||||
wssv.AddWebSocketService<Echo> ("/Echo");
|
||||
wssv.AddWebSocketService<Chat> ("/Chat");
|
||||
//wssv.AddWebSocketService<Echo> ("/エコー");
|
||||
//wssv.AddWebSocketService<Chat> ("/チャット");
|
||||
|
||||
wssv.Start();
|
||||
Console.WriteLine(
|
||||
wssv.Start ();
|
||||
Console.WriteLine (
|
||||
"WebSocket Server listening on port: {0} service path:", wssv.Port);
|
||||
foreach (var path in wssv.ServicePaths)
|
||||
Console.WriteLine(" {0}", path);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine (" {0}", path);
|
||||
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine ("Press enter key to stop server...");
|
||||
Console.ReadLine ();
|
||||
|
||||
Console.WriteLine("Press any key to stop server...");
|
||||
Console.ReadLine();
|
||||
|
||||
wssv.Stop();
|
||||
wssv.Stop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
README.md
62
README.md
@ -71,7 +71,7 @@ ws.OnOpen += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
`e` has come across as `EventArgs.Empty`, so there is no operation on `e`.
|
||||
`e` has come across as `EventArgs.Empty`, so you don't use `e`.
|
||||
|
||||
##### WebSocket.OnMessage event #####
|
||||
|
||||
@ -84,7 +84,11 @@ ws.OnMessage += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
`e.Type` (`WebSocketSharp.MessageEventArgs.Type`, the type of this property is `WebSocketSharp.Opcode`) indicates the **Frame type** of a WebSocket frame, so by checking this property, you determine which item you should operate.
|
||||
`e.Type` (`WebSocketSharp.MessageEventArgs.Type`, the type of this property is `WebSocketSharp.Opcode`) indicates the **Frame Type** of a WebSocket frame, so by checking this property, you determine which item you should use.
|
||||
|
||||
If `e.Type` equals `Opcode.TEXT`, you use `e.Data` (`WebSocketSharp.MessageEventArgs.Data`, the type of this property is `string`) that contains the received data.
|
||||
|
||||
If `e.Type` equals `Opcode.BINARY`, you use `e.RawData` (`WebSocketSharp.MessageEventArgs.RawData`, the type of this property is `byte[]`) that contains the received data.
|
||||
|
||||
```cs
|
||||
if (e.Type == Opcode.TEXT)
|
||||
@ -100,10 +104,6 @@ if (e.Type == Opcode.BINARY)
|
||||
}
|
||||
```
|
||||
|
||||
If `e.Type` equaled `Opcode.TEXT`, you would operate `e.Data` (`WebSocketSharp.MessageEventArgs.Data`, the type of this property is `string`).
|
||||
|
||||
If `e.Type` equaled `Opcode.BINARY`, you would operate `e.RawData` (`WebSocketSharp.MessageEventArgs.RawData`, the type of this property is `byte[]`).
|
||||
|
||||
##### WebSocket.OnError event #####
|
||||
|
||||
A `WebSocket.OnError` event occurs when the `WebSocket` gets an error.
|
||||
@ -114,7 +114,7 @@ ws.OnError += (sender, e) =>
|
||||
...
|
||||
};
|
||||
```
|
||||
`e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, the type of this property is `string`) contains an error message, so you operate this.
|
||||
`e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, the type of this property is `string`) contains an error message, so you use this.
|
||||
|
||||
##### WebSocket.OnClose event #####
|
||||
|
||||
@ -127,7 +127,7 @@ ws.OnClose += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
`e.Code` (`WebSocketSharp.CloseEventArgs.Code`, the type of this property is `ushort`) contains a status code indicating the reason for closure and `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, the type of this property is `string`) contains the reason for closure, so you operate these.
|
||||
`e.Code` (`WebSocketSharp.CloseEventArgs.Code`, the type of this property is `ushort`) contains a status code indicating the reason for closure and `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, the type of this property is `string`) contains the reason for closure, so you use these.
|
||||
|
||||
#### Step 4 ####
|
||||
|
||||
@ -157,7 +157,7 @@ Closing the WebSocket connection.
|
||||
ws.Close(code, reason);
|
||||
```
|
||||
|
||||
If you wanted to close the WebSocket connection explicitly, you would use the `Close` method.
|
||||
If you want to close the WebSocket connection explicitly, you can use the `Close` method.
|
||||
|
||||
And the `Close` method is overloaded. The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, the type of `reason` is `string`.
|
||||
|
||||
@ -176,7 +176,7 @@ namespace Example {
|
||||
{
|
||||
protected override void OnMessage(MessageEventArgs e)
|
||||
{
|
||||
var msg = e.Data.ToLower().Equals("balus")
|
||||
var msg = e.Data.ToLower() == "balus"
|
||||
? "I've been balused already..."
|
||||
: "I'm not available now.";
|
||||
Send(msg);
|
||||
@ -266,7 +266,7 @@ You can add any WebSocket service with a specified path to the service to your `
|
||||
|
||||
The type of `T` inherits `WebSocketService` class, so you can use a class that was created in **Step 2**.
|
||||
|
||||
If you created a instance of the `WebSocketServer` class without the port number, the `WebSocketServer` would set the port number to **80** automatically. So it is necessary to run with root permission.
|
||||
If you create a instance of the `WebSocketServer` class without the port number, the `WebSocketServer` set the port number to **80** automatically. So it is necessary to run with root permission.
|
||||
|
||||
$ sudo mono example2.exe
|
||||
|
||||
@ -285,7 +285,7 @@ wssv.OnError += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
`e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, the type of this property is `string`) contains an error message, so you operate this.
|
||||
`e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, the type of this property is `string`) contains an error message, so you use this.
|
||||
|
||||
##### WebSocketServer.OnError event #####
|
||||
|
||||
@ -320,21 +320,51 @@ httpsv.AddWebSocketService<Echo>("/");
|
||||
|
||||
For more information, could you see **[Example3]**?
|
||||
|
||||
### Secure Connection ###
|
||||
|
||||
As a **WebSocket Client**, creating a instance of the `WebSocket` class with the WebSocket URL with the **wss** scheme.
|
||||
|
||||
```cs
|
||||
using (var ws = new WebSocket("wss://example.com"))
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
If you want to set the custom validation for the server certificate, you can use the `WebSocket.ServerCertificateValidationCallback` property.
|
||||
|
||||
```cs
|
||||
ws.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
{
|
||||
// Do something to validate the server certificate.
|
||||
return true; // The server certificate is valid.
|
||||
};
|
||||
```
|
||||
|
||||
If you set this property to nothing, the validation does nothing with the server certificate, always returns valid.
|
||||
|
||||
As a **WebSocket Server**, creating and setting a instance of the WebSocket server with some settings for the secure connection.
|
||||
|
||||
```cs
|
||||
var wssv = new WebSocketServer(4649, true);
|
||||
wssv.Certificate = new X509Certificate2("/path/to/cert.pfx", "password for cert.pfx");
|
||||
```
|
||||
|
||||
### Logging ###
|
||||
|
||||
The `WebSocket` class includes own logging functions.
|
||||
|
||||
The `WebSocket.Log` property provides the logging functions.
|
||||
|
||||
If you wanted to change the current logging level (the default is the `LogLevel.ERROR`), you would operate the `WebSocket.Log.Level` property.
|
||||
If you want to change the current logging level (the default is `LogLevel.ERROR`), you can use the `WebSocket.Log.Level` property.
|
||||
|
||||
```cs
|
||||
ws.Log.Level = LogLevel.DEBUG;
|
||||
```
|
||||
|
||||
This setting means that the logging outputs with a less than the `LogLevel.DEBUG` are not outputted.
|
||||
This setting means that the logging outputs with a less than `LogLevel.DEBUG` are not outputted.
|
||||
|
||||
And if you wanted to output a log, you would use some output methods. The following outputs a log with the `LogLevel.DEBUG`.
|
||||
And if you want to output a log, you can use some output methods. The following outputs a log with `LogLevel.DEBUG`.
|
||||
|
||||
```cs
|
||||
ws.Log.Debug("This is a debug message.");
|
||||
@ -354,7 +384,7 @@ Examples of using **websocket-sharp**.
|
||||
|
||||
[Example1] connects to the [Audio Data delivery server] using the WebSocket ([Example1] is only implemented the chat feature, still unfinished).
|
||||
|
||||
And [Example1] uses the [Json.NET].
|
||||
And [Example1] uses [Json.NET].
|
||||
|
||||
### Example2 ###
|
||||
|
||||
|
@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("websocket-sharp")]
|
||||
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client & server")]
|
||||
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("websocket-sharp.dll")]
|
||||
|
@ -45,6 +45,7 @@ using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using WebSocketSharp.Net;
|
||||
using WebSocketSharp.Net.WebSockets;
|
||||
@ -282,6 +283,12 @@ namespace WebSocketSharp {
|
||||
: null;
|
||||
}
|
||||
|
||||
internal static TcpListenerWebSocketContext GetWebSocketContext(
|
||||
this TcpClient client, bool secure, X509Certificate cert)
|
||||
{
|
||||
return new TcpListenerWebSocketContext(client, secure, cert);
|
||||
}
|
||||
|
||||
// <summary>
|
||||
// Determines whether the specified object is <see langword="null"/>.
|
||||
// </summary>
|
||||
@ -532,60 +539,6 @@ namespace WebSocketSharp {
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Accepts a WebSocket connection by the <see cref="TcpListener"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="TcpListenerWebSocketContext"/> that contains a WebSocket connection.
|
||||
/// </returns>
|
||||
/// <param name="listener">
|
||||
/// A <see cref="TcpListener"/> that provides a TCP connection to accept a WebSocket connection.
|
||||
/// </param>
|
||||
/// <param name="secure">
|
||||
/// A <see cref="bool"/> that indicates a secure connection or not. (<c>true</c> indicates a secure connection.)
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="listener"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
public static TcpListenerWebSocketContext AcceptWebSocket(this TcpListener listener, bool secure)
|
||||
{
|
||||
if (listener == null)
|
||||
throw new ArgumentNullException("listener");
|
||||
|
||||
var client = listener.AcceptTcpClient();
|
||||
return new TcpListenerWebSocketContext(client, secure);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accepts a WebSocket connection asynchronously by the <see cref="TcpListener"/>.
|
||||
/// </summary>
|
||||
/// <param name="listener">
|
||||
/// A <see cref="TcpListener"/> that provides a TCP connection to accept a WebSocket connection.
|
||||
/// </param>
|
||||
/// <param name="secure">
|
||||
/// A <see cref="bool"/> that indicates a secure connection or not. (<c>true</c> indicates a secure connection.)
|
||||
/// </param>
|
||||
/// <param name="completed">
|
||||
/// An Action<TcpListenerWebSocketContext> delegate that contains the method(s) that is called when an asynchronous operation completes.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="listener"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
public static void AcceptWebSocketAsync(this TcpListener listener, bool secure, Action<TcpListenerWebSocketContext> completed)
|
||||
{
|
||||
if (listener == null)
|
||||
throw new ArgumentNullException("listener");
|
||||
|
||||
AsyncCallback callback = (ar) =>
|
||||
{
|
||||
var client = listener.EndAcceptTcpClient(ar);
|
||||
var context = new TcpListenerWebSocketContext(client, secure);
|
||||
completed(context);
|
||||
};
|
||||
|
||||
listener.BeginAcceptTcpClient(callback, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="string"/> contains any of characters
|
||||
/// in the specified array of <see cref="char"/>.
|
||||
|
@ -30,12 +30,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace WebSocketSharp.Net.WebSockets {
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to the WebSocket connection request objects received by the <see cref="TcpListener"/> class.
|
||||
/// Provides access to the WebSocket connection request objects received by the <see cref="TcpListener"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
@ -44,22 +45,22 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
#region Private Fields
|
||||
|
||||
private CookieCollection _cookies;
|
||||
private TcpClient _tcpClient;
|
||||
private bool _isSecure;
|
||||
private TcpClient _client;
|
||||
private RequestHandshake _request;
|
||||
private bool _secure;
|
||||
private WsStream _stream;
|
||||
private WebSocket _websocket;
|
||||
private WsStream _wsStream;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal TcpListenerWebSocketContext(TcpClient tcpClient, bool secure)
|
||||
internal TcpListenerWebSocketContext(TcpClient client, bool secure, X509Certificate cert)
|
||||
{
|
||||
_tcpClient = tcpClient;
|
||||
_isSecure = secure;
|
||||
_wsStream = WsStream.CreateServerStream(tcpClient, secure);
|
||||
_request = RequestHandshake.Parse(_wsStream.ReadHandshake());
|
||||
_client = client;
|
||||
_secure = secure;
|
||||
_stream = WsStream.CreateServerStream(client, secure, cert);
|
||||
_request = RequestHandshake.Parse(_stream.ReadHandshake());
|
||||
_websocket = new WebSocket(this);
|
||||
}
|
||||
|
||||
@ -69,7 +70,7 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
|
||||
internal WsStream Stream {
|
||||
get {
|
||||
return _wsStream;
|
||||
return _stream;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +86,7 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
/// </value>
|
||||
public override CookieCollection CookieCollection {
|
||||
get {
|
||||
if (_cookies.IsNull())
|
||||
if (_cookies == null)
|
||||
_cookies = _request.Cookies;
|
||||
|
||||
return _cookies;
|
||||
@ -139,7 +140,7 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
/// </value>
|
||||
public override bool IsSecureConnection {
|
||||
get {
|
||||
return _isSecure;
|
||||
return _secure;
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,7 +261,7 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
/// </value>
|
||||
public virtual System.Net.IPEndPoint ServerEndPoint {
|
||||
get {
|
||||
return (System.Net.IPEndPoint)_tcpClient.Client.LocalEndPoint;
|
||||
return (System.Net.IPEndPoint)_client.Client.LocalEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,7 +288,7 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
/// </value>
|
||||
public virtual System.Net.IPEndPoint UserEndPoint {
|
||||
get {
|
||||
return (System.Net.IPEndPoint)_tcpClient.Client.RemoteEndPoint;
|
||||
return (System.Net.IPEndPoint)_client.Client.RemoteEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,8 +310,8 @@ namespace WebSocketSharp.Net.WebSockets {
|
||||
|
||||
internal void Close()
|
||||
{
|
||||
_wsStream.Close();
|
||||
_tcpClient.Close();
|
||||
_stream.Close();
|
||||
_client.Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -30,6 +30,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using WebSocketSharp.Net.WebSockets;
|
||||
|
||||
@ -45,15 +46,16 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private IPAddress _address;
|
||||
private bool _listening;
|
||||
private Logger _logger;
|
||||
private int _port;
|
||||
private Thread _receiveRequestThread;
|
||||
private bool _secure;
|
||||
private bool _selfHost;
|
||||
private TcpListener _tcpListener;
|
||||
private Uri _uri;
|
||||
private IPAddress _address;
|
||||
private X509Certificate2 _cert;
|
||||
private bool _listening;
|
||||
private Logger _logger;
|
||||
private int _port;
|
||||
private Thread _receiveRequestThread;
|
||||
private bool _secure;
|
||||
private bool _selfHost;
|
||||
private TcpListener _listener;
|
||||
private Uri _uri;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -63,7 +65,7 @@ namespace WebSocketSharp.Server {
|
||||
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes a new instance of this class as non self host.
|
||||
/// This constructor initializes a new instance of this class as non self hosted server.
|
||||
/// </remarks>
|
||||
protected WebSocketServerBase()
|
||||
: this(new Logger())
|
||||
@ -75,7 +77,7 @@ namespace WebSocketSharp.Server {
|
||||
/// with the specified <paramref name="logger"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes a new instance of this class as non self host.
|
||||
/// This constructor initializes a new instance of this class as non self hosted server.
|
||||
/// </remarks>
|
||||
/// <param name="logger">
|
||||
/// A <see cref="Logger"/> that provides the logging functions.
|
||||
@ -104,7 +106,7 @@ namespace WebSocketSharp.Server {
|
||||
if (url.IsNull())
|
||||
throw new ArgumentNullException("url");
|
||||
|
||||
Uri uri;
|
||||
Uri uri;
|
||||
string msg;
|
||||
if (!tryCreateUri(url, out uri, out msg))
|
||||
throw new ArgumentException(msg, "url");
|
||||
@ -208,6 +210,25 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the certificate used to authenticate the server on the secure connection.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="X509Certificate2"/> used to authenticate the server.
|
||||
/// </value>
|
||||
public X509Certificate2 Certificate {
|
||||
get {
|
||||
return _cert;
|
||||
}
|
||||
|
||||
set {
|
||||
if (_listening)
|
||||
return;
|
||||
|
||||
_cert = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the server has been started.
|
||||
/// </summary>
|
||||
@ -303,7 +324,7 @@ namespace WebSocketSharp.Server {
|
||||
_listening = false;
|
||||
_logger = new Logger();
|
||||
_selfHost = true;
|
||||
_tcpListener = new TcpListener(_address, _port);
|
||||
_listener = new TcpListener(_address, _port);
|
||||
}
|
||||
|
||||
private void init(Uri uri)
|
||||
@ -320,13 +341,13 @@ namespace WebSocketSharp.Server {
|
||||
init();
|
||||
}
|
||||
|
||||
private void processRequestAsync(TcpListenerWebSocketContext context)
|
||||
private void processRequestAsync(TcpClient client)
|
||||
{
|
||||
WaitCallback callback = (state) =>
|
||||
WaitCallback callback = state =>
|
||||
{
|
||||
try
|
||||
{
|
||||
AcceptWebSocket(context);
|
||||
AcceptWebSocket(client.GetWebSocketContext(_secure, _cert));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -344,11 +365,11 @@ namespace WebSocketSharp.Server {
|
||||
{
|
||||
try
|
||||
{
|
||||
processRequestAsync(_tcpListener.AcceptWebSocket(_secure));
|
||||
processRequestAsync(_listener.AcceptTcpClient());
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
// TcpListener has been stopped.
|
||||
_logger.Info("TcpListener has been stopped.");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -368,7 +389,7 @@ namespace WebSocketSharp.Server {
|
||||
_receiveRequestThread.Start();
|
||||
}
|
||||
|
||||
private bool tryCreateUri(string uriString, out Uri result, out string message)
|
||||
private static bool tryCreateUri(string uriString, out Uri result, out string message)
|
||||
{
|
||||
if (!uriString.TryCreateWebSocketUri(out result, out message))
|
||||
return false;
|
||||
@ -422,7 +443,16 @@ namespace WebSocketSharp.Server {
|
||||
if (!_selfHost || _listening)
|
||||
return;
|
||||
|
||||
_tcpListener.Start();
|
||||
if (_secure && _cert == null)
|
||||
{
|
||||
var msg = "Secure connection requires a server certificate.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_listener.Start();
|
||||
startReceiveRequestThread();
|
||||
_listening = true;
|
||||
}
|
||||
@ -435,7 +465,7 @@ namespace WebSocketSharp.Server {
|
||||
if (!_selfHost || !_listening)
|
||||
return;
|
||||
|
||||
_tcpListener.Stop();
|
||||
_listener.Stop();
|
||||
_receiveRequestThread.Join(5 * 1000);
|
||||
_listening = false;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@ -66,6 +67,8 @@ namespace WebSocketSharp {
|
||||
#region Private Fields
|
||||
|
||||
private string _base64key;
|
||||
private RemoteCertificateValidationCallback
|
||||
_certValidationCallback;
|
||||
private bool _client;
|
||||
private Action _closeContext;
|
||||
private CookieCollection _cookies;
|
||||
@ -162,9 +165,8 @@ namespace WebSocketSharp {
|
||||
_uri = uri;
|
||||
_protocols = protocols.ToString(", ");
|
||||
_client = true;
|
||||
_secure = uri.Scheme == "wss"
|
||||
? true
|
||||
: false;
|
||||
_secure = uri.Scheme == "wss" ? true : false;
|
||||
_base64key = createBase64Key();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -226,6 +228,12 @@ namespace WebSocketSharp {
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsOpened {
|
||||
get {
|
||||
return _readyState == WsState.OPEN || _readyState == WsState.CLOSING;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
@ -243,8 +251,14 @@ namespace WebSocketSharp {
|
||||
}
|
||||
|
||||
set {
|
||||
if (isOpened(true))
|
||||
if (IsOpened)
|
||||
{
|
||||
var msg = "The WebSocket connection has already been established.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_compression = value;
|
||||
}
|
||||
@ -363,19 +377,25 @@ namespace WebSocketSharp {
|
||||
}
|
||||
|
||||
set {
|
||||
if (isOpened(true))
|
||||
return;
|
||||
|
||||
if (value.IsNullOrEmpty())
|
||||
string msg = null;
|
||||
if (IsOpened)
|
||||
{
|
||||
msg = "The WebSocket connection has already been established.";
|
||||
}
|
||||
else if (value.IsNullOrEmpty())
|
||||
{
|
||||
_origin = String.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
var origin = new Uri(value);
|
||||
if (!origin.IsAbsoluteUri || origin.Segments.Length > 1)
|
||||
else
|
||||
{
|
||||
var origin = new Uri(value);
|
||||
if (!origin.IsAbsoluteUri || origin.Segments.Length > 1)
|
||||
msg = "The syntax of value of Origin must be '<scheme>://<host>[:<port>]'.";
|
||||
}
|
||||
|
||||
if (msg != null)
|
||||
{
|
||||
var msg = "The syntax of value of Origin must be '<scheme>://<host>[:<port>]'.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
@ -410,6 +430,27 @@ namespace WebSocketSharp {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the callback used to validate the certificate supplied by the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the value of this property is <see langword="null"/>, the validation does nothing
|
||||
/// with the server certificate, always returns valid.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// A <see cref="RemoteCertificateValidationCallback"/> delegate that references the method(s)
|
||||
/// used to validate the server certificate. The default is <see langword="null"/>.
|
||||
/// </value>
|
||||
public RemoteCertificateValidationCallback ServerCertificateValidationCallback {
|
||||
get {
|
||||
return _certValidationCallback;
|
||||
}
|
||||
|
||||
set {
|
||||
_certValidationCallback = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the WebSocket URL to connect.
|
||||
/// </summary>
|
||||
@ -777,7 +818,7 @@ namespace WebSocketSharp {
|
||||
// As client
|
||||
private bool doHandshake()
|
||||
{
|
||||
init();
|
||||
setWsStream();
|
||||
return processResponseHandshake(sendRequestHandshake());
|
||||
}
|
||||
|
||||
@ -799,24 +840,13 @@ namespace WebSocketSharp {
|
||||
return CompressionMethod.NONE;
|
||||
}
|
||||
|
||||
// As client
|
||||
private void init()
|
||||
{
|
||||
_base64key = createBase64Key();
|
||||
|
||||
var host = _uri.DnsSafeHost;
|
||||
var port = _uri.Port;
|
||||
_tcpClient = new TcpClient(host, port);
|
||||
_wsStream = WsStream.CreateClientStream(_tcpClient, host, _secure);
|
||||
}
|
||||
|
||||
// As server
|
||||
private void init(WebSocketContext context)
|
||||
{
|
||||
_context = context;
|
||||
_uri = context.Path.ToUri();
|
||||
_secure = context.IsSecureConnection;
|
||||
_client = false;
|
||||
_uri = context.Path.ToUri();
|
||||
_secure = context.IsSecureConnection;
|
||||
_client = false;
|
||||
}
|
||||
|
||||
private static bool isCompressionExtension(string value)
|
||||
@ -832,21 +862,6 @@ namespace WebSocketSharp {
|
||||
: false;
|
||||
}
|
||||
|
||||
private bool isOpened(bool errorIfOpened)
|
||||
{
|
||||
if (_readyState != WsState.OPEN && _readyState != WsState.CLOSING)
|
||||
return false;
|
||||
|
||||
if (errorIfOpened)
|
||||
{
|
||||
var msg = "The WebSocket connection has been established already.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// As server
|
||||
private bool isValidHostHeader()
|
||||
{
|
||||
@ -1351,6 +1366,15 @@ namespace WebSocketSharp {
|
||||
send(res);
|
||||
}
|
||||
|
||||
// As client
|
||||
private void setWsStream()
|
||||
{
|
||||
var host = _uri.DnsSafeHost;
|
||||
var port = _uri.Port;
|
||||
_tcpClient = new TcpClient(host, port);
|
||||
_wsStream = WsStream.CreateClientStream(_tcpClient, _secure, host, _certValidationCallback);
|
||||
}
|
||||
|
||||
private void startReceiving()
|
||||
{
|
||||
_exitReceiving = new AutoResetEvent(false);
|
||||
@ -1480,8 +1504,14 @@ namespace WebSocketSharp {
|
||||
/// </summary>
|
||||
public void Connect()
|
||||
{
|
||||
if (isOpened(true))
|
||||
if (IsOpened)
|
||||
{
|
||||
var msg = "The WebSocket connection has already been established.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@ -1690,12 +1720,14 @@ namespace WebSocketSharp {
|
||||
/// </param>
|
||||
public void SetCookie(Cookie cookie)
|
||||
{
|
||||
if (isOpened(true))
|
||||
return;
|
||||
var msg = IsOpened
|
||||
? "The WebSocket connection has already been established."
|
||||
: cookie == null
|
||||
? "'cookie' must not be null."
|
||||
: null;
|
||||
|
||||
if (cookie == null)
|
||||
if (msg != null)
|
||||
{
|
||||
var msg = "'cookie' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
@ -1723,24 +1755,28 @@ namespace WebSocketSharp {
|
||||
/// </param>
|
||||
public void SetCredentials(string userName, string password, bool preAuth)
|
||||
{
|
||||
if (isOpened(true))
|
||||
return;
|
||||
|
||||
if (userName == null)
|
||||
string msg = null;
|
||||
if (IsOpened)
|
||||
{
|
||||
msg = "The WebSocket connection has already been established.";
|
||||
}
|
||||
else if (userName == null)
|
||||
{
|
||||
_credentials = null;
|
||||
_preAuth = false;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = userName.Length > 0 && (userName.Contains(':') || !userName.IsText())
|
||||
? "'userName' contains an invalid character."
|
||||
: !password.IsNullOrEmpty() && !password.IsText()
|
||||
? "'password' contains an invalid character."
|
||||
: null;
|
||||
}
|
||||
|
||||
var msg = userName.Length > 0 && (userName.Contains(':') || !userName.IsText())
|
||||
? "'userName' contains an invalid character."
|
||||
: !password.IsNullOrEmpty() && !password.IsText()
|
||||
? "'password' contains an invalid character."
|
||||
: String.Empty;
|
||||
|
||||
if (msg.Length > 0)
|
||||
if (msg != null)
|
||||
{
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
@ -119,18 +118,20 @@ namespace WebSocketSharp {
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal static WsStream CreateClientStream(TcpClient tcpClient, string host, bool secure)
|
||||
internal static WsStream CreateClientStream(
|
||||
TcpClient client,
|
||||
bool secure,
|
||||
string host,
|
||||
System.Net.Security.RemoteCertificateValidationCallback validationCallback
|
||||
)
|
||||
{
|
||||
var netStream = tcpClient.GetStream();
|
||||
var netStream = client.GetStream();
|
||||
if (secure)
|
||||
{
|
||||
System.Net.Security.RemoteCertificateValidationCallback callback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
{
|
||||
// FIXME: Always returns true
|
||||
return true;
|
||||
};
|
||||
if (validationCallback == null)
|
||||
validationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
|
||||
|
||||
var sslStream = new SslStream(netStream, false, callback);
|
||||
var sslStream = new SslStream(netStream, false, validationCallback);
|
||||
sslStream.AuthenticateAsClient(host);
|
||||
|
||||
return new WsStream(sslStream);
|
||||
@ -139,14 +140,13 @@ namespace WebSocketSharp {
|
||||
return new WsStream(netStream);
|
||||
}
|
||||
|
||||
internal static WsStream CreateServerStream(TcpClient tcpClient, bool secure)
|
||||
internal static WsStream CreateServerStream(TcpClient client, bool secure, X509Certificate cert)
|
||||
{
|
||||
var netStream = tcpClient.GetStream();
|
||||
var netStream = client.GetStream();
|
||||
if (secure)
|
||||
{
|
||||
var sslStream = new SslStream(netStream, false);
|
||||
var certPath = ConfigurationManager.AppSettings["ServerCertPath"];
|
||||
sslStream.AuthenticateAsServer(new X509Certificate2(certPath));
|
||||
sslStream.AuthenticateAsServer(cert);
|
||||
|
||||
return new WsStream(sslStream);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user