Added logging
This commit is contained in:
parent
e3ff26a2d5
commit
49dc8800d3
@ -113,6 +113,9 @@ namespace Example
|
||||
|
||||
//ws.Origin = "http://echo.websocket.org";
|
||||
//ws.Compression = CompressionMethod.DEFLATE;
|
||||
#if DEBUG
|
||||
ws.Log.Level = LogLevel.TRACE;
|
||||
#endif
|
||||
//ws.SetCookie(new Cookie("nobita", "\"idiot, gunfighter\""));
|
||||
//ws.SetCookie(new Cookie("dora", "tanuki"));
|
||||
ws.Connect();
|
||||
|
@ -72,6 +72,9 @@ namespace Example1
|
||||
|
||||
private void configure()
|
||||
{
|
||||
#if DEBUG
|
||||
_ws.Log.Level = LogLevel.TRACE;
|
||||
#endif
|
||||
_ws.OnOpen += (sender, e) =>
|
||||
{
|
||||
var msg = createTextMessage("connection", String.Empty);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using WebSocketSharp;
|
||||
using WebSocketSharp.Server;
|
||||
|
||||
namespace Example2
|
||||
@ -31,6 +32,9 @@ namespace Example2
|
||||
// Multi services server
|
||||
var wssv = new WebSocketServer(4649);
|
||||
//var wssv = new WebSocketServer("ws://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");
|
||||
|
@ -12,6 +12,9 @@ namespace Example3
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
_httpsv = new HttpServer(4649);
|
||||
#if DEBUG
|
||||
_httpsv.Log.Level = LogLevel.TRACE;
|
||||
#endif
|
||||
//_httpsv.RootPath = "../../Public";
|
||||
//_httpsv.Sweeping = false;
|
||||
_httpsv.AddWebSocketService<Echo>("/Echo");
|
||||
@ -33,7 +36,7 @@ namespace Example3
|
||||
Console.WriteLine(" {0}", path);
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Press any key to stop server...");
|
||||
Console.WriteLine("Press enter key to stop server...");
|
||||
Console.ReadLine();
|
||||
|
||||
_httpsv.Stop();
|
||||
|
95
README.md
95
README.md
@ -1,7 +1,7 @@
|
||||
<!-- # websocket-sharp # -->
|
||||

|
||||
|
||||
**websocket-sharp** is a C# implementation of the **WebSocket** protocol client & server.
|
||||
**websocket-sharp** is a C# implementation of the **WebSocket** protocol client and server.
|
||||
|
||||
## Usage ##
|
||||
|
||||
@ -45,7 +45,7 @@ The `WebSocket` class exists in the `WebSocketSharp` namespace.
|
||||
|
||||
#### Step 2 ####
|
||||
|
||||
Creating a instance of the `WebSocket` class with the specified WebSocket URL.
|
||||
Creating a instance of the `WebSocket` class with the specified WebSocket URL to connect.
|
||||
|
||||
```cs
|
||||
using (var ws = new WebSocket("ws://example.com"))
|
||||
@ -62,7 +62,7 @@ Setting the `WebSocket` events.
|
||||
|
||||
##### WebSocket.OnOpen event #####
|
||||
|
||||
The `WebSocket.OnOpen` event occurs when the WebSocket connection has been established.
|
||||
A `WebSocket.OnOpen` event occurs when the WebSocket connection has been established.
|
||||
|
||||
```cs
|
||||
ws.OnOpen += (sender, e) =>
|
||||
@ -71,11 +71,11 @@ ws.OnOpen += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
The `e` has come across as the `EventArgs.Empty`, so there is no operation on the `e`.
|
||||
`e` has come across as `EventArgs.Empty`, so there is no operation on `e`.
|
||||
|
||||
##### WebSocket.OnMessage event #####
|
||||
|
||||
The `WebSocket.OnMessage` event occurs when the `WebSocket` receives a data frame.
|
||||
A `WebSocket.OnMessage` event occurs when the `WebSocket` receives a WebSocket data frame.
|
||||
|
||||
```cs
|
||||
ws.OnMessage += (sender, e) =>
|
||||
@ -84,29 +84,29 @@ ws.OnMessage += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
The `e.Type` (`WebSocketSharp.MessageEventArgs.Type`, its type is `WebSocketSharp.Opcode`) indicates the **Frame type** of the WebSocket frame, so you check it out and 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 operate.
|
||||
|
||||
```cs
|
||||
switch (e.Type)
|
||||
if (e.Type == Opcode.TEXT)
|
||||
{
|
||||
case Opcode.TEXT:
|
||||
...
|
||||
break;
|
||||
case Opcode.BINARY:
|
||||
...
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// Do something with e.Data
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Type == Opcode.BINARY)
|
||||
{
|
||||
// Do something with e.RawData
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
If the `e.Type` is `Opcode.TEXT`, you operate the `e.Data` (`WebSocketSharp.MessageEventArgs.Data`, its type is `string`).
|
||||
If `e.Type` equaled `Opcode.TEXT`, you would operate `e.Data` (`WebSocketSharp.MessageEventArgs.Data`, the type of this property is `string`).
|
||||
|
||||
If the `e.Type` is `Opcode.BINARY`, you operate the `e.RawData` (`WebSocketSharp.MessageEventArgs.RawData`, its type is `byte[]`).
|
||||
If `e.Type` equaled `Opcode.BINARY`, you would operate `e.RawData` (`WebSocketSharp.MessageEventArgs.RawData`, the type of this property is `byte[]`).
|
||||
|
||||
##### WebSocket.OnError event #####
|
||||
|
||||
The `WebSocket.OnError` event occurs when the `WebSocket` gets an error.
|
||||
A `WebSocket.OnError` event occurs when the `WebSocket` gets an error.
|
||||
|
||||
```cs
|
||||
ws.OnError += (sender, e) =>
|
||||
@ -114,11 +114,11 @@ ws.OnError += (sender, e) =>
|
||||
...
|
||||
};
|
||||
```
|
||||
The `e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, its type is `string`) contains the error message, so you operate it.
|
||||
`e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, the type of this property is `string`) contains an error message, so you operate this.
|
||||
|
||||
##### WebSocket.OnClose event #####
|
||||
|
||||
The `WebSocket.OnClose` event occurs when the `WebSocket` connection has been closed.
|
||||
A `WebSocket.OnClose` event occurs when the WebSocket connection has been closed.
|
||||
|
||||
```cs
|
||||
ws.OnClose += (sender, e) =>
|
||||
@ -127,7 +127,7 @@ ws.OnClose += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
The `e.Code` (`WebSocketSharp.CloseEventArgs.Code`, its type is `ushort`) contains a status code indicating a reason for closure and the `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, its type is `string`) contains a reason for closure, so you operate them.
|
||||
`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.
|
||||
|
||||
#### Step 4 ####
|
||||
|
||||
@ -157,11 +157,9 @@ Closing the WebSocket connection.
|
||||
ws.Close(code, reason);
|
||||
```
|
||||
|
||||
If you want to close the WebSocket connection explicitly, you can use the `Close` method.
|
||||
If you wanted to close the WebSocket connection explicitly, you would use the `Close` method.
|
||||
|
||||
The `Close` method is overloaded.
|
||||
|
||||
The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, the type of `reason` is `string`.
|
||||
And the `Close` method is overloaded. The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, the type of `reason` is `string`.
|
||||
|
||||
In addition, the `Close()` and `Close(code)` methods exist.
|
||||
|
||||
@ -256,7 +254,7 @@ Creating a instance of the `WebSocketServiceHost<T>` class if you want the singl
|
||||
var wssv = new WebSocketServiceHost<Echo>("ws://example.com:4649");
|
||||
```
|
||||
|
||||
Creating a instance of the `WebSocketServer` class if you want the multi WebSocket service server.
|
||||
Or creating a instance of the `WebSocketServer` class if you want the multi WebSocket service server.
|
||||
|
||||
```cs
|
||||
var wssv = new WebSocketServer(4649);
|
||||
@ -264,12 +262,11 @@ wssv.AddWebSocketService<Echo>("/Echo");
|
||||
wssv.AddWebSocketService<Chat>("/Chat");
|
||||
```
|
||||
|
||||
You can add to your `WebSocketServer` any WebSocket service and a matching path to that service by using the `WebSocketServer.AddWebSocketService<T>` method.
|
||||
You can add any WebSocket service with a specified path to the service to your `WebSocketServer` by using the `WebSocketServer.AddWebSocketService<T>` method.
|
||||
|
||||
The type of `T` inherits `WebSocketService` class, so you can use a class that was created in **Step 2**.
|
||||
|
||||
If you create a instance of the `WebSocketServer` class without port number, `WebSocketServer` set **80** to port number automatically.
|
||||
So it is necessary to run with root permission.
|
||||
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.
|
||||
|
||||
$ sudo mono example2.exe
|
||||
|
||||
@ -279,7 +276,7 @@ Setting the event.
|
||||
|
||||
##### WebSocketServiceHost<T>.OnError event #####
|
||||
|
||||
The `WebSocketServiceHost<T>.OnError` event occurs when the `WebSocketServiceHost<T>` gets an error.
|
||||
A `WebSocketServiceHost<T>.OnError` event occurs when the `WebSocketServiceHost<T>` gets an error.
|
||||
|
||||
```cs
|
||||
wssv.OnError += (sender, e) =>
|
||||
@ -288,7 +285,7 @@ wssv.OnError += (sender, e) =>
|
||||
};
|
||||
```
|
||||
|
||||
The `e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, its type is `string`) contains the error message, so you operate it.
|
||||
`e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, the type of this property is `string`) contains an error message, so you operate this.
|
||||
|
||||
##### WebSocketServer.OnError event #####
|
||||
|
||||
@ -312,9 +309,9 @@ wssv.Stop();
|
||||
|
||||
### HTTP Server with the WebSocket ###
|
||||
|
||||
I modified the `System.Net.HttpListener`, `System.Net.HttpListenerContext` and some other classes of [Mono] to create the HTTP server that can upgrade the connection to the WebSocket connection when receives a WebSocket request.
|
||||
I modified the `System.Net.HttpListener`, `System.Net.HttpListenerContext` and some other classes of [Mono] to create the HTTP server that can upgrade the connection to the WebSocket connection when receives a WebSocket connection request.
|
||||
|
||||
You can add to your `HttpServer` any WebSocket service and a matching path to that service by using the `HttpServer.AddWebSocketService<T>` method.
|
||||
You can add any WebSocket service with a specified path to the service to your `HttpServer` by using the `HttpServer.AddWebSocketService<T>` method.
|
||||
|
||||
```cs
|
||||
var httpsv = new HttpServer(4649);
|
||||
@ -323,6 +320,28 @@ httpsv.AddWebSocketService<Echo>("/");
|
||||
|
||||
For more information, could you see **[Example3]**?
|
||||
|
||||
### 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.
|
||||
|
||||
```cs
|
||||
ws.Log.Level = LogLevel.DEBUG;
|
||||
```
|
||||
|
||||
This setting means that the logging outputs with a less than the `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`.
|
||||
|
||||
```cs
|
||||
ws.Log.Debug("This is a debug message.");
|
||||
```
|
||||
|
||||
The `WebSocketServiceHost<T>`, `WebSocketServer` and `HttpServer` classes include the same logging functions.
|
||||
|
||||
## Examples ##
|
||||
|
||||
Examples of using **websocket-sharp**.
|
||||
@ -333,19 +352,19 @@ Examples of using **websocket-sharp**.
|
||||
|
||||
### Example1 ###
|
||||
|
||||
[Example1] connects to the [Audio Data delivery server] using the WebSocket ([Example1] is only implemented a chat feature, still unfinished).
|
||||
[Example1] connects to the [Audio Data delivery server] using the WebSocket ([Example1] is only implemented the chat feature, still unfinished).
|
||||
|
||||
[Example1] uses [Json.NET].
|
||||
And [Example1] uses the [Json.NET].
|
||||
|
||||
### Example2 ###
|
||||
|
||||
[Example2] starts the WebSocket server.
|
||||
[Example2] starts a WebSocket server.
|
||||
|
||||
### Example3 ###
|
||||
|
||||
[Example3] starts the HTTP server that can upgrade the connection to the WebSocket connection.
|
||||
[Example3] starts an HTTP server that can upgrade the connection to the WebSocket connection.
|
||||
|
||||
Please access [http://localhost:4649](http://localhost:4649) to do WebSocket Echo Test with your web browser after [Example3] running.
|
||||
Could you access to [http://localhost:4649](http://localhost:4649) to do **WebSocket Echo Test** with your web browser after [Example3] running?
|
||||
|
||||
## websocket-sharp for Unity ##
|
||||
|
||||
|
150
websocket-sharp/LogData.cs
Normal file
150
websocket-sharp/LogData.cs
Normal file
@ -0,0 +1,150 @@
|
||||
#region License
|
||||
/*
|
||||
* LogData.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013 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.Text;
|
||||
|
||||
namespace WebSocketSharp {
|
||||
|
||||
/// <summary>
|
||||
/// Represents the log data used by the <see cref="Logger"/> class.
|
||||
/// </summary>
|
||||
public class LogData {
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private StackFrame _caller;
|
||||
private DateTime _date;
|
||||
private LogLevel _level;
|
||||
private string _message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal LogData (DateTime date, LogLevel level, StackFrame caller, string message)
|
||||
{
|
||||
_date = date;
|
||||
_level = level;
|
||||
_caller = caller;
|
||||
_message = message;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the information of the logging method caller.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="StackFrame"/> that contains the information of a logging method caller.
|
||||
/// </value>
|
||||
public StackFrame Caller {
|
||||
get {
|
||||
return _caller;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date and time when the log data was created.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTime"/> that contains the date and time when the log data was created.
|
||||
/// </value>
|
||||
public DateTime Date {
|
||||
get {
|
||||
return _date;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logging level associated with the log data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// One of the <see cref="LogLevel"/> values that indicates the logging level
|
||||
/// associated with the log data.
|
||||
/// </value>
|
||||
public LogLevel Level {
|
||||
get {
|
||||
return _level;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message of the log data.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that contains the message of a log data.
|
||||
/// </value>
|
||||
public string Message {
|
||||
get {
|
||||
return _message;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> that represents the current <see cref="LogData"/>.
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
var header = String.Format ("{0}|{1,-5}|", _date, _level);
|
||||
var method = _caller.GetMethod ();
|
||||
var type = method.DeclaringType;
|
||||
#if DEBUG
|
||||
var lineNum = _caller.GetFileLineNumber ();
|
||||
var headerAndCaller = String.Format ("{0}{1}.{2}:{3}|", header, type.Name, method.Name, lineNum);
|
||||
#else
|
||||
var headerAndCaller = String.Format ("{0}{1}.{2}|", header, type.Name, method.Name);
|
||||
#endif
|
||||
|
||||
var messages = _message.Replace ("\r\n", "\n").TrimEnd ('\n').Split ('\n');
|
||||
if (messages.Length <= 1)
|
||||
return String.Format ("{0}{1}", headerAndCaller, _message);
|
||||
|
||||
var output = new StringBuilder (String.Format ("{0}{1}\n", headerAndCaller, messages [0]), 64);
|
||||
var space = header.Length;
|
||||
var format = String.Format ("{{0,{0}}}{{1}}\n", space);
|
||||
for (var i = 1; i < messages.Length; i++)
|
||||
output.AppendFormat (format, "", messages [i]);
|
||||
|
||||
output.Length--;
|
||||
return output.ToString ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
63
websocket-sharp/LogLevel.cs
Normal file
63
websocket-sharp/LogLevel.cs
Normal file
@ -0,0 +1,63 @@
|
||||
#region License
|
||||
/*
|
||||
* LogLevel.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013 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;
|
||||
|
||||
namespace WebSocketSharp {
|
||||
|
||||
/// <summary>
|
||||
/// Contains the values of the logging level.
|
||||
/// </summary>
|
||||
public enum LogLevel {
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the bottom logging level.
|
||||
/// </summary>
|
||||
TRACE,
|
||||
/// <summary>
|
||||
/// Indicates the 2nd logging level from the bottom.
|
||||
/// </summary>
|
||||
DEBUG,
|
||||
/// <summary>
|
||||
/// Indicates the 3rd logging level from the bottom.
|
||||
/// </summary>
|
||||
INFO,
|
||||
/// <summary>
|
||||
/// Indicates the 3rd logging level from the top.
|
||||
/// </summary>
|
||||
WARN,
|
||||
/// <summary>
|
||||
/// Indicates the 2nd logging level from the top.
|
||||
/// </summary>
|
||||
ERROR,
|
||||
/// <summary>
|
||||
/// Indicates the top logging level.
|
||||
/// </summary>
|
||||
FATAL
|
||||
}
|
||||
}
|
323
websocket-sharp/Logger.cs
Normal file
323
websocket-sharp/Logger.cs
Normal file
@ -0,0 +1,323 @@
|
||||
#region License
|
||||
/*
|
||||
* Logger.cs
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013 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.IO;
|
||||
|
||||
namespace WebSocketSharp {
|
||||
|
||||
/// <summary>
|
||||
/// Provides the simple logging functions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The Logger class provides some methods that output the logs associated with the each
|
||||
/// <see cref="LogLevel"/> values.
|
||||
/// If the <see cref="LogLevel"/> value associated with a log was less than the <see cref="Level"/>,
|
||||
/// the log could not be outputted.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The default output action used by the output methods outputs the log data to the standard output stream
|
||||
/// and writes the same log data to the <see cref="Logger.File"/> if it has a valid path.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you wanted to run your custom output action, you would replace the current output action with
|
||||
/// your output action by using the <see cref="SetOutput"/> method.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class Logger {
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private volatile string _file;
|
||||
private volatile LogLevel _level;
|
||||
private Action<LogData, string> _output;
|
||||
private object _sync;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes the current logging level with the <see cref="LogLevel.ERROR"/> and
|
||||
/// initializes the path to the log file with <see langword="null"/>.
|
||||
/// </remarks>
|
||||
public Logger ()
|
||||
: this (LogLevel.ERROR, null, defaultOutput)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class
|
||||
/// with the specified logging <paramref name="level"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes the path to the log file with <see langword="null"/>.
|
||||
/// </remarks>
|
||||
/// <param name="level">
|
||||
/// One of the <see cref="LogLevel"/> values to initialize.
|
||||
/// </param>
|
||||
public Logger (LogLevel level)
|
||||
: this (level, null, defaultOutput)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Logger"/> class
|
||||
/// with the specified logging <paramref name="level"/>, path to the log <paramref name="file"/>
|
||||
/// and <paramref name="output"/> action.
|
||||
/// </summary>
|
||||
/// <param name="level">
|
||||
/// One of the <see cref="LogLevel"/> values to initialize.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="string"/> that contains a path to the log file to initialize.
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// An <c>Action<LogData, string></c> delegate that references the method(s) to initialize.
|
||||
/// A <see cref="string"/> parameter to pass to the method(s) is the value of <see cref="Logger.File"/>
|
||||
/// if any.
|
||||
/// </param>
|
||||
public Logger (LogLevel level, string file, Action<LogData, string> output)
|
||||
{
|
||||
_level = level;
|
||||
_file = file;
|
||||
if (output != null)
|
||||
_output = output;
|
||||
else
|
||||
_output = defaultOutput;
|
||||
|
||||
_sync = new object ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the log file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that contains a path to the log file.
|
||||
/// </value>
|
||||
public string File {
|
||||
get {
|
||||
return _file;
|
||||
}
|
||||
|
||||
set {
|
||||
lock (_sync)
|
||||
{
|
||||
_file = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current logging level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A log associated with a less than the current logging level can not be outputted.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// One of the <see cref="LogLevel"/> values that indicates the current logging level.
|
||||
/// </value>
|
||||
public LogLevel Level {
|
||||
get {
|
||||
return _level;
|
||||
}
|
||||
|
||||
set {
|
||||
_level = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static void defaultOutput (LogData data, string path)
|
||||
{
|
||||
var log = data.ToString ();
|
||||
Console.WriteLine (log);
|
||||
if (path != null && path.Length > 0)
|
||||
writeLine (log, path);
|
||||
}
|
||||
|
||||
private void output (LogLevel level, string message)
|
||||
{
|
||||
if (level < _level || message == null || message.Length == 0)
|
||||
return;
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
LogData data = null;
|
||||
try {
|
||||
data = new LogData (DateTime.Now, level, new StackFrame (2, true), message);
|
||||
_output (data, _file);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
data = new LogData (DateTime.Now, LogLevel.FATAL, new StackFrame (0, true), ex.Message);
|
||||
Console.WriteLine (data.ToString ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeLine (string value, string path)
|
||||
{
|
||||
using (var writer = new StreamWriter (path, true))
|
||||
using (var syncWriter = TextWriter.Synchronized (writer))
|
||||
{
|
||||
syncWriter.WriteLine (value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the specified <paramref name="message"/> as a log with the <see cref="LogLevel.DEBUG"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not output <paramref name="message"/> as a log
|
||||
/// if the current logging level is greater than the <see cref="LogLevel.DEBUG"/>.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that contains a message to output as a log.
|
||||
/// </param>
|
||||
public void Debug (string message)
|
||||
{
|
||||
output (LogLevel.DEBUG, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the specified <paramref name="message"/> as a log with the <see cref="LogLevel.ERROR"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not output <paramref name="message"/> as a log
|
||||
/// if the current logging level is greater than the <see cref="LogLevel.ERROR"/>.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that contains a message to output as a log.
|
||||
/// </param>
|
||||
public void Error (string message)
|
||||
{
|
||||
output (LogLevel.ERROR, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the specified <paramref name="message"/> as a log with the <see cref="LogLevel.FATAL"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not output <paramref name="message"/> as a log
|
||||
/// if the current logging level is greater than the <see cref="LogLevel.FATAL"/>.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that contains a message to output as a log.
|
||||
/// </param>
|
||||
public void Fatal (string message)
|
||||
{
|
||||
output (LogLevel.FATAL, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the specified <paramref name="message"/> as a log with the <see cref="LogLevel.INFO"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not output <paramref name="message"/> as a log
|
||||
/// if the current logging level is greater than the <see cref="LogLevel.INFO"/>.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that contains a message to output as a log.
|
||||
/// </param>
|
||||
public void Info (string message)
|
||||
{
|
||||
output (LogLevel.INFO, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the current output action with the specified <paramref name="output"/> action.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method replaces the current output action with the default output action
|
||||
/// if <paramref name="output"/> is <see langword="null"/>.
|
||||
/// </remarks>
|
||||
/// <param name="output">
|
||||
/// An <c>Action<LogData, string></c> delegate that references the method(s) to set.
|
||||
/// A <see cref="string"/> parameter to pass to the method(s) is the value of <see cref="Logger.File"/>
|
||||
/// if any.
|
||||
/// </param>
|
||||
public void SetOutput (Action<LogData, string> output)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
if (output != null)
|
||||
_output = output;
|
||||
else
|
||||
_output = defaultOutput;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the specified <paramref name="message"/> as a log with the <see cref="LogLevel.TRACE"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not output <paramref name="message"/> as a log
|
||||
/// if the current logging level is greater than the <see cref="LogLevel.TRACE"/>.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that contains a message to output as a log.
|
||||
/// </param>
|
||||
public void Trace (string message)
|
||||
{
|
||||
output (LogLevel.TRACE, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the specified <paramref name="message"/> as a log with the <see cref="LogLevel.WARN"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method does not output <paramref name="message"/> as a log
|
||||
/// if the current logging level is greater than the <see cref="LogLevel.WARN"/>.
|
||||
/// </remarks>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string"/> that contains a message to output as a log.
|
||||
/// </param>
|
||||
public void Warn (string message)
|
||||
{
|
||||
output (LogLevel.WARN, message);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -64,6 +64,7 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
private HttpListener _listener;
|
||||
private bool _listening;
|
||||
private Logger _logger;
|
||||
private int _port;
|
||||
private Thread _receiveRequestThread;
|
||||
private string _rootPath;
|
||||
@ -112,6 +113,23 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logging functions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default logging level is the <see cref="LogLevel.ERROR"/>.
|
||||
/// If you wanted to change the current logging level, you would set the <c>Log.Level</c> property
|
||||
/// to one of the <see cref="LogLevel"/> values which you want.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// A <see cref="Logger"/> that provides the logging functions.
|
||||
/// </value>
|
||||
public Logger Log {
|
||||
get {
|
||||
return _logger;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the port on which to listen for incoming requests.
|
||||
/// </summary>
|
||||
@ -231,10 +249,16 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void error(string message)
|
||||
{
|
||||
OnError.Emit(this, new ErrorEventArgs(message));
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
_listener = new HttpListener();
|
||||
_listening = false;
|
||||
_logger = new Logger();
|
||||
_rootPath = getRootPath();
|
||||
_svcHosts = new ServiceHostManager();
|
||||
|
||||
@ -262,103 +286,107 @@ namespace WebSocketSharp.Server {
|
||||
: rootPath;
|
||||
}
|
||||
|
||||
private void onError(string message)
|
||||
private void processHttpRequest(HttpListenerContext context)
|
||||
{
|
||||
#if DEBUG
|
||||
var callerFrame = new StackFrame(1);
|
||||
var caller = callerFrame.GetMethod();
|
||||
Console.WriteLine("HTTPSV: Error@{0}: {1}", caller.Name, message);
|
||||
#endif
|
||||
OnError.Emit(this, new ErrorEventArgs(message));
|
||||
}
|
||||
|
||||
private void onRequest(HttpListenerContext context)
|
||||
{
|
||||
var req = context.Request;
|
||||
var res = context.Response;
|
||||
var eventArgs = new HttpRequestEventArgs(context);
|
||||
|
||||
if (req.HttpMethod == "GET" && !OnGet.IsNull())
|
||||
var method = context.Request.HttpMethod;
|
||||
if (method == "GET" && OnGet != null)
|
||||
{
|
||||
OnGet(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "HEAD" && !OnHead.IsNull())
|
||||
if (method == "HEAD" && OnHead != null)
|
||||
{
|
||||
OnHead(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "POST" && !OnPost.IsNull())
|
||||
if (method == "POST" && OnPost != null)
|
||||
{
|
||||
OnPost(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "PUT" && !OnPut.IsNull())
|
||||
if (method == "PUT" && OnPut != null)
|
||||
{
|
||||
OnPut(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "DELETE" && !OnDelete.IsNull())
|
||||
if (method == "DELETE" && OnDelete != null)
|
||||
{
|
||||
OnDelete(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "OPTIONS" && !OnOptions.IsNull())
|
||||
if (method == "OPTIONS" && OnOptions != null)
|
||||
{
|
||||
OnOptions(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "TRACE" && !OnTrace.IsNull())
|
||||
if (method == "TRACE" && OnTrace != null)
|
||||
{
|
||||
OnTrace(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "CONNECT" && !OnConnect.IsNull())
|
||||
if (method == "CONNECT" && OnConnect != null)
|
||||
{
|
||||
OnConnect(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.HttpMethod == "PATCH" && !OnPatch.IsNull())
|
||||
if (method == "PATCH" && OnPatch != null)
|
||||
{
|
||||
OnPatch(this, eventArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
res.StatusCode = (int)HttpStatusCode.NotImplemented;
|
||||
context.Response.StatusCode = (int)HttpStatusCode.NotImplemented;
|
||||
}
|
||||
|
||||
private bool processWebSocketRequest(HttpListenerContext context)
|
||||
{
|
||||
var wsContext = context.AcceptWebSocket();
|
||||
var path = wsContext.Path.UrlDecode();
|
||||
|
||||
IServiceHost svcHost;
|
||||
if (!_svcHosts.TryGetServiceHost(path, out svcHost))
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.NotImplemented;
|
||||
return false;
|
||||
}
|
||||
|
||||
wsContext.WebSocket.Log = _logger;
|
||||
svcHost.BindWebSocket(wsContext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void processRequestAsync(HttpListenerContext context)
|
||||
{
|
||||
WaitCallback callback = (state) =>
|
||||
{
|
||||
var req = context.Request;
|
||||
var res = context.Response;
|
||||
|
||||
try
|
||||
{
|
||||
if (req.IsUpgradeTo("websocket"))
|
||||
if (context.Request.IsUpgradeTo("websocket"))
|
||||
{
|
||||
if (upgradeToWebSocket(context))
|
||||
if (processWebSocketRequest(context))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
onRequest(context);
|
||||
processHttpRequest(context);
|
||||
}
|
||||
|
||||
res.Close();
|
||||
context.Response.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
}
|
||||
};
|
||||
|
||||
@ -371,8 +399,7 @@ namespace WebSocketSharp.Server {
|
||||
{
|
||||
try
|
||||
{
|
||||
var context = _listener.GetContext();
|
||||
processRequestAsync(context);
|
||||
processRequestAsync(_listener.GetContext());
|
||||
}
|
||||
catch (HttpListenerException)
|
||||
{
|
||||
@ -381,7 +408,9 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -394,23 +423,6 @@ namespace WebSocketSharp.Server {
|
||||
_receiveRequestThread.Start();
|
||||
}
|
||||
|
||||
private bool upgradeToWebSocket(HttpListenerContext context)
|
||||
{
|
||||
var res = context.Response;
|
||||
var wsContext = context.AcceptWebSocket();
|
||||
var path = wsContext.Path.UrlDecode();
|
||||
|
||||
IServiceHost svcHost;
|
||||
if (!_svcHosts.TryGetServiceHost(path, out svcHost))
|
||||
{
|
||||
res.StatusCode = (int)HttpStatusCode.NotImplemented;
|
||||
return false;
|
||||
}
|
||||
|
||||
svcHost.BindWebSocket(wsContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
@ -430,11 +442,13 @@ namespace WebSocketSharp.Server {
|
||||
string msg;
|
||||
if (!absPath.IsValidAbsolutePath(out msg))
|
||||
{
|
||||
onError(msg);
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var svcHost = new WebSocketServiceHost<T>();
|
||||
var svcHost = new WebSocketServiceHost<T>(_logger);
|
||||
svcHost.Uri = absPath.ToUri();
|
||||
if (!Sweeping)
|
||||
svcHost.Sweeping = false;
|
||||
|
@ -194,6 +194,7 @@ namespace WebSocketSharp.Server {
|
||||
var ws = context.WebSocket;
|
||||
var path = context.Path.UrlDecode();
|
||||
|
||||
ws.Log = Log;
|
||||
IServiceHost svcHost;
|
||||
if (!_svcHosts.TryGetServiceHost(path, out svcHost))
|
||||
{
|
||||
@ -226,11 +227,13 @@ namespace WebSocketSharp.Server {
|
||||
string msg;
|
||||
if (!absPath.IsValidAbsolutePath(out msg))
|
||||
{
|
||||
Log.Error(msg);
|
||||
Error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var svcHost = new WebSocketServiceHost<T>();
|
||||
var svcHost = new WebSocketServiceHost<T>(Log);
|
||||
svcHost.Uri = BaseUri.IsAbsoluteUri
|
||||
? new Uri(BaseUri, absPath)
|
||||
: absPath.ToUri();
|
||||
|
@ -47,6 +47,7 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
private IPAddress _address;
|
||||
private bool _listening;
|
||||
private Logger _logger;
|
||||
private int _port;
|
||||
private Thread _receiveRequestThread;
|
||||
private bool _secure;
|
||||
@ -61,14 +62,33 @@ namespace WebSocketSharp.Server {
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
protected WebSocketServerBase()
|
||||
: this(new Logger())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class
|
||||
/// with the specified <paramref name="logger"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This constructor initializes a new instance of this class as non self host.
|
||||
/// </remarks>
|
||||
/// <param name="logger">
|
||||
/// A <see cref="Logger"/> that provides the logging functions.
|
||||
/// </param>
|
||||
protected WebSocketServerBase(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_selfHost = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class that listens for incoming connection attempts
|
||||
/// on the specified WebSocket URL.
|
||||
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class
|
||||
/// that listens for incoming connection attempts on the specified WebSocket URL.
|
||||
/// </summary>
|
||||
/// <param name="url">
|
||||
/// A <see cref="string"/> that contains a WebSocket URL.
|
||||
@ -93,8 +113,9 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class that listens for incoming connection attempts
|
||||
/// on the specified <paramref name="address"/>, <paramref name="port"/>, <paramref name="absPath"/> and <paramref name="secure"/>.
|
||||
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class
|
||||
/// that listens for incoming connection attempts on the specified <paramref name="address"/>,
|
||||
/// <paramref name="port"/>, <paramref name="absPath"/> and <paramref name="secure"/>.
|
||||
/// </summary>
|
||||
/// <param name="address">
|
||||
/// A <see cref="IPAddress"/> that contains a local IP address.
|
||||
@ -106,7 +127,8 @@ namespace WebSocketSharp.Server {
|
||||
/// A <see cref="string"/> that contains an absolute path.
|
||||
/// </param>
|
||||
/// <param name="secure">
|
||||
/// A <see cref="bool"/> that indicates providing a secure connection or not. (<c>true</c> indicates providing a secure connection.)
|
||||
/// A <see cref="bool"/> that indicates providing a secure connection or not.
|
||||
/// (<c>true</c> indicates providing a secure connection.)
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// Either <paramref name="address"/> or <paramref name="absPath"/> is <see langword="null"/>.
|
||||
@ -222,6 +244,30 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logging functions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default logging level is the <see cref="LogLevel.ERROR"/>.
|
||||
/// If you wanted to change the current logging level, you would set the <c>Log.Level</c> property
|
||||
/// to one of the <see cref="LogLevel"/> values which you want.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// A <see cref="Logger"/> that provides the logging functions.
|
||||
/// </value>
|
||||
public Logger Log {
|
||||
get {
|
||||
return _logger;
|
||||
}
|
||||
|
||||
internal set {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
_logger = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the port on which to listen for incoming connection attempts.
|
||||
/// </summary>
|
||||
@ -247,9 +293,15 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void error(string message)
|
||||
{
|
||||
OnError.Emit(this, new ErrorEventArgs(message));
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
_listening = false;
|
||||
_logger = new Logger();
|
||||
_selfHost = true;
|
||||
_tcpListener = new TcpListener(_address, _port);
|
||||
}
|
||||
@ -268,16 +320,6 @@ namespace WebSocketSharp.Server {
|
||||
init();
|
||||
}
|
||||
|
||||
private void onError(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 processRequestAsync(TcpListenerWebSocketContext context)
|
||||
{
|
||||
WaitCallback callback = (state) =>
|
||||
@ -288,7 +330,8 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
}
|
||||
};
|
||||
|
||||
@ -301,8 +344,7 @@ namespace WebSocketSharp.Server {
|
||||
{
|
||||
try
|
||||
{
|
||||
var context = _tcpListener.AcceptWebSocket(_secure);
|
||||
processRequestAsync(context);
|
||||
processRequestAsync(_tcpListener.AcceptWebSocket(_secure));
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
@ -311,7 +353,9 @@ namespace WebSocketSharp.Server {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -360,7 +404,10 @@ namespace WebSocketSharp.Server {
|
||||
/// </param>
|
||||
protected virtual void Error(string message)
|
||||
{
|
||||
onError(message);
|
||||
if (message.IsNullOrEmpty())
|
||||
return;
|
||||
|
||||
error(message);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -66,6 +66,31 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the logging functions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you wanted to change the current logger to the service own logger, you would set this property
|
||||
/// to a new <see cref="Logger"/> instance that you created.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// A <see cref="Logger"/> that provides the logging functions.
|
||||
/// </value>
|
||||
protected Logger Log {
|
||||
get {
|
||||
return IsBound
|
||||
? _websocket.Log
|
||||
: null;
|
||||
}
|
||||
|
||||
set {
|
||||
if (!IsBound)
|
||||
return;
|
||||
|
||||
_websocket.Log = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of query string variables used in the WebSocket opening handshake.
|
||||
/// </summary>
|
||||
|
@ -56,7 +56,8 @@ namespace WebSocketSharp.Server {
|
||||
|
||||
#region Internal Constructors
|
||||
|
||||
internal WebSocketServiceHost()
|
||||
internal WebSocketServiceHost(Logger logger)
|
||||
: base(logger)
|
||||
{
|
||||
_sessions = new WebSocketServiceManager();
|
||||
}
|
||||
@ -230,6 +231,8 @@ namespace WebSocketSharp.Server {
|
||||
{
|
||||
var ws = context.WebSocket;
|
||||
var path = context.Path.UrlDecode();
|
||||
|
||||
ws.Log = Log;
|
||||
if (path != Uri.GetAbsolutePath().UrlDecode())
|
||||
{
|
||||
ws.Close(HttpStatusCode.NotImplemented);
|
||||
|
@ -77,6 +77,7 @@ namespace WebSocketSharp {
|
||||
private object _forClose;
|
||||
private object _forFrame;
|
||||
private object _forSend;
|
||||
private volatile Logger _logger;
|
||||
private string _origin;
|
||||
private bool _preAuth;
|
||||
private string _protocol;
|
||||
@ -100,6 +101,7 @@ namespace WebSocketSharp {
|
||||
_forClose = new object();
|
||||
_forFrame = new object();
|
||||
_forSend = new object();
|
||||
_logger = new Logger();
|
||||
_origin = String.Empty;
|
||||
_preAuth = false;
|
||||
_protocol = String.Empty;
|
||||
@ -131,7 +133,8 @@ namespace WebSocketSharp {
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocket"/> class with the specified WebSocket URL and subprotocols.
|
||||
/// Initializes a new instance of the <see cref="WebSocket"/> class with the specified WebSocket URL
|
||||
/// and subprotocols.
|
||||
/// </summary>
|
||||
/// <param name="url">
|
||||
/// A <see cref="string"/> that contains a WebSocket URL to connect.
|
||||
@ -314,6 +317,30 @@ namespace WebSocketSharp {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logging functions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default logging level is the <see cref="LogLevel.ERROR"/>.
|
||||
/// If you wanted to change the current logging level, you would set the <c>Log.Level</c> property
|
||||
/// to one of the <see cref="LogLevel"/> values which you want.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// A <see cref="Logger"/> that provides the logging functions.
|
||||
/// </value>
|
||||
public Logger Log {
|
||||
get {
|
||||
return _logger;
|
||||
}
|
||||
|
||||
internal set {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
_logger = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the Origin header used in the WebSocket opening handshake.
|
||||
/// </summary>
|
||||
@ -348,7 +375,10 @@ namespace WebSocketSharp {
|
||||
var origin = new Uri(value);
|
||||
if (!origin.IsAbsoluteUri || origin.Segments.Length > 1)
|
||||
{
|
||||
onError("The syntax of value of Origin must be '<scheme>://<host>[:<port>]'.");
|
||||
var msg = "The syntax of value of Origin must be '<scheme>://<host>[:<port>]'.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -435,11 +465,20 @@ namespace WebSocketSharp {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void close(CloseEventArgs eventArgs)
|
||||
{
|
||||
if (!Thread.CurrentThread.IsBackground && _exitReceiving != null)
|
||||
_exitReceiving.WaitOne(5 * 1000);
|
||||
|
||||
if (!closeResources())
|
||||
eventArgs.WasClean = false;
|
||||
|
||||
OnClose.Emit(this, eventArgs);
|
||||
}
|
||||
|
||||
private void close(PayloadData data)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@close: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground);
|
||||
#endif
|
||||
_logger.Debug("Is this thread background?: " + Thread.CurrentThread.IsBackground);
|
||||
lock(_forClose)
|
||||
{
|
||||
// Whether the closing handshake has been started already?
|
||||
@ -450,7 +489,7 @@ namespace WebSocketSharp {
|
||||
if (_readyState == WsState.CONNECTING && !_client)
|
||||
{
|
||||
sendResponseHandshake(HttpStatusCode.BadRequest);
|
||||
onClose(new CloseEventArgs(data));
|
||||
close(new CloseEventArgs(data));
|
||||
|
||||
return;
|
||||
}
|
||||
@ -461,14 +500,12 @@ namespace WebSocketSharp {
|
||||
// Whether a payload data contains the close status code which must not be set for send?
|
||||
if (data.ContainsReservedCloseStatusCode)
|
||||
{
|
||||
onClose(new CloseEventArgs(data));
|
||||
close(new CloseEventArgs(data));
|
||||
return;
|
||||
}
|
||||
|
||||
closeHandshake(data);
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@close: Exit close method.");
|
||||
#endif
|
||||
_logger.Trace("Exit close method.");
|
||||
}
|
||||
|
||||
private void close(HttpStatusCode code)
|
||||
@ -485,7 +522,10 @@ namespace WebSocketSharp {
|
||||
var data = code.Append(reason);
|
||||
if (data.Length > 125)
|
||||
{
|
||||
onError("The payload length of a Close frame must be 125 bytes or less.");
|
||||
var msg = "The payload length of a Close frame must be 125 bytes or less.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -499,7 +539,7 @@ namespace WebSocketSharp {
|
||||
if (send(frame))
|
||||
args.WasClean = true;
|
||||
|
||||
onClose(args);
|
||||
close(args);
|
||||
}
|
||||
|
||||
private bool closeResources()
|
||||
@ -517,7 +557,9 @@ namespace WebSocketSharp {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -739,6 +781,11 @@ namespace WebSocketSharp {
|
||||
return processResponseHandshake(sendRequestHandshake());
|
||||
}
|
||||
|
||||
private void error(string message)
|
||||
{
|
||||
OnError.Emit(this, new ErrorEventArgs(message));
|
||||
}
|
||||
|
||||
private static CompressionMethod getCompressionMethod(string value)
|
||||
{
|
||||
var deprecated = createDeprecatedCompressionExtension(CompressionMethod.DEFLATE);
|
||||
@ -791,7 +838,11 @@ namespace WebSocketSharp {
|
||||
return false;
|
||||
|
||||
if (errorIfOpened)
|
||||
onError("The WebSocket connection has been established already.");
|
||||
{
|
||||
var msg = "The WebSocket connection has been established already.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -837,29 +888,7 @@ namespace WebSocketSharp {
|
||||
response.ContainsHeader("Sec-WebSocket-Version", _version);
|
||||
}
|
||||
|
||||
private void onClose(CloseEventArgs eventArgs)
|
||||
{
|
||||
if (!Thread.CurrentThread.IsBackground)
|
||||
if (_exitReceiving != null)
|
||||
_exitReceiving.WaitOne(5 * 1000);
|
||||
|
||||
if (!closeResources())
|
||||
eventArgs.WasClean = false;
|
||||
|
||||
OnClose.Emit(this, eventArgs);
|
||||
}
|
||||
|
||||
private void onError(string message)
|
||||
{
|
||||
#if DEBUG
|
||||
var callerFrame = new StackFrame(1);
|
||||
var caller = callerFrame.GetMethod();
|
||||
Console.WriteLine("WS: Error@{0}: {1}", caller.Name, message);
|
||||
#endif
|
||||
OnError.Emit(this, new ErrorEventArgs(message));
|
||||
}
|
||||
|
||||
private void onOpen()
|
||||
private void open()
|
||||
{
|
||||
_readyState = WsState.OPEN;
|
||||
startReceiving();
|
||||
@ -887,9 +916,7 @@ namespace WebSocketSharp {
|
||||
if (frame != null)
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@processAbnormal: Start closing handshake.");
|
||||
#endif
|
||||
_logger.Trace("Start closing handshake.");
|
||||
var code = CloseStatusCode.ABNORMAL;
|
||||
Close(code, code.GetMessage());
|
||||
|
||||
@ -901,9 +928,7 @@ namespace WebSocketSharp {
|
||||
if (!frame.IsClose)
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@processClose: Start closing handshake.");
|
||||
#endif
|
||||
_logger.Trace("Start closing handshake.");
|
||||
close(frame.PayloadData);
|
||||
|
||||
return true;
|
||||
@ -985,9 +1010,7 @@ namespace WebSocketSharp {
|
||||
|
||||
private void processIncorrectFrame()
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@processIncorrectFrame: Start closing handshake.");
|
||||
#endif
|
||||
_logger.Trace("Start closing handshake.");
|
||||
Close(CloseStatusCode.INCORRECT_DATA);
|
||||
}
|
||||
|
||||
@ -996,9 +1019,7 @@ namespace WebSocketSharp {
|
||||
if (!frame.IsPing)
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@processPing: Return Pong.");
|
||||
#endif
|
||||
_logger.Trace("Return Pong.");
|
||||
pong(frame.PayloadData);
|
||||
|
||||
return true;
|
||||
@ -1009,9 +1030,7 @@ namespace WebSocketSharp {
|
||||
if (!frame.IsPong)
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@processPong: Receive Pong.");
|
||||
#endif
|
||||
_logger.Trace("Receive Pong.");
|
||||
_receivePong.Set();
|
||||
|
||||
return true;
|
||||
@ -1048,15 +1067,15 @@ namespace WebSocketSharp {
|
||||
// As server
|
||||
private bool processRequestHandshake()
|
||||
{
|
||||
#if DEBUG
|
||||
var req = RequestHandshake.Parse(_context);
|
||||
Console.WriteLine("WS: Info@processRequestHandshake: Request handshake from client:\n");
|
||||
Console.WriteLine(req.ToString());
|
||||
#endif
|
||||
_logger.Debug("Request handshake from client:\n" + req.ToString());
|
||||
if (!isValidRequesHandshake())
|
||||
{
|
||||
onError("Invalid WebSocket connection request.");
|
||||
var msg = "Invalid WebSocket connection request.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
close(HttpStatusCode.BadRequest);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1110,16 +1129,17 @@ namespace WebSocketSharp {
|
||||
// As client
|
||||
private bool processResponseHandshake(ResponseHandshake response)
|
||||
{
|
||||
var error = response.IsUnauthorized
|
||||
var msg = response.IsUnauthorized
|
||||
? String.Format("An HTTP {0} authorization is required.", response.AuthChallenge.Scheme)
|
||||
: !isValidResponseHandshake(response)
|
||||
? "Invalid response to this WebSocket connection request."
|
||||
: String.Empty;
|
||||
|
||||
if (error.Length > 0)
|
||||
if (msg.Length > 0)
|
||||
{
|
||||
onError(error);
|
||||
Close(CloseStatusCode.ABNORMAL, error);
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
Close(CloseStatusCode.ABNORMAL, msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1142,30 +1162,22 @@ namespace WebSocketSharp {
|
||||
private ResponseHandshake receiveResponseHandshake()
|
||||
{
|
||||
var res = ResponseHandshake.Parse(_wsStream.ReadHandshake());
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@receiveResponseHandshake: Response handshake from server:\n");
|
||||
Console.WriteLine(res.ToString());
|
||||
#endif
|
||||
_logger.Debug("Response handshake from server:\n" + res.ToString());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// As client
|
||||
private void send(RequestHandshake request)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@send: Request handshake to server:\n");
|
||||
Console.WriteLine(request.ToString());
|
||||
#endif
|
||||
_logger.Debug("Request handshake to server:\n" + request.ToString());
|
||||
_wsStream.WriteHandshake(request);
|
||||
}
|
||||
|
||||
// As server
|
||||
private void send(ResponseHandshake response)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine("WS: Info@send: Response handshake to client:\n");
|
||||
Console.WriteLine(response.ToString());
|
||||
#endif
|
||||
_logger.Debug("Response handshake to client:\n" + response.ToString());
|
||||
_wsStream.WriteHandshake(response);
|
||||
}
|
||||
|
||||
@ -1183,7 +1195,10 @@ namespace WebSocketSharp {
|
||||
|
||||
if (!ready)
|
||||
{
|
||||
onError("The WebSocket connection isn't established or has been closed.");
|
||||
var msg = "The WebSocket connection isn't established or has been closed.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1199,7 +1214,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (_readyState != WsState.OPEN)
|
||||
{
|
||||
onError("The WebSocket connection isn't established or has been closed.");
|
||||
var msg = "The WebSocket connection isn't established or has been closed.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1220,7 +1238,8 @@ namespace WebSocketSharp {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -1250,7 +1269,8 @@ namespace WebSocketSharp {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex.Message);
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1349,10 +1369,12 @@ namespace WebSocketSharp {
|
||||
}
|
||||
catch (WebSocketException ex)
|
||||
{
|
||||
_logger.Fatal(ex.Message);
|
||||
Close(ex.Code, ex.Message);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Fatal(ex.Message);
|
||||
Close(CloseStatusCode.ABNORMAL, "An exception has occured.");
|
||||
}
|
||||
};
|
||||
@ -1429,7 +1451,9 @@ namespace WebSocketSharp {
|
||||
if (!code.IsCloseStatusCode())
|
||||
{
|
||||
var msg = String.Format("Invalid close status code: {0}", code);
|
||||
onError(msg);
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1462,12 +1486,13 @@ namespace WebSocketSharp {
|
||||
try
|
||||
{
|
||||
if (connect())
|
||||
onOpen();
|
||||
open();
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Fatal(ex.Message);
|
||||
var msg = "An exception has occured.";
|
||||
onError(msg);
|
||||
error(msg);
|
||||
Close(CloseStatusCode.ABNORMAL, msg);
|
||||
}
|
||||
}
|
||||
@ -1511,7 +1536,10 @@ namespace WebSocketSharp {
|
||||
var data = Encoding.UTF8.GetBytes(message);
|
||||
if (data.Length > 125)
|
||||
{
|
||||
onError("The payload length of a Ping frame must be 125 bytes or less.");
|
||||
var msg = "The payload length of a Ping frame must be 125 bytes or less.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1528,7 +1556,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
onError("'data' must not be null.");
|
||||
var msg = "'data' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1546,7 +1577,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
onError("'data' must not be null.");
|
||||
var msg = "'data' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1564,7 +1598,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
onError("'file' must not be null.");
|
||||
var msg = "'file' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1585,7 +1622,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
onError("'data' must not be null.");
|
||||
var msg = "'data' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1607,7 +1647,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
onError("'data' must not be null.");
|
||||
var msg = "'data' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1629,7 +1672,10 @@ namespace WebSocketSharp {
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
onError("'file' must not be null.");
|
||||
var msg = "'file' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1649,7 +1695,10 @@ namespace WebSocketSharp {
|
||||
|
||||
if (cookie == null)
|
||||
{
|
||||
onError("'cookie' must not be null.");
|
||||
var msg = "'cookie' must not be null.";
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1685,15 +1734,17 @@ namespace WebSocketSharp {
|
||||
return;
|
||||
}
|
||||
|
||||
var error = userName.Length > 0 && (userName.Contains(':') || !userName.IsText())
|
||||
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 (error.Length > 0)
|
||||
if (msg.Length > 0)
|
||||
{
|
||||
onError(error);
|
||||
_logger.Error(msg);
|
||||
error(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,9 @@
|
||||
<Compile Include="AuthenticationChallenge.cs" />
|
||||
<Compile Include="AuthenticationResponse.cs" />
|
||||
<Compile Include="WsCredential.cs" />
|
||||
<Compile Include="LogData.cs" />
|
||||
<Compile Include="LogLevel.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user