From 49dc8800d37d07878f6d1e09fc22a3b876bc1fa7 Mon Sep 17 00:00:00 2001 From: sta Date: Mon, 15 Jul 2013 20:42:55 +0900 Subject: [PATCH] Added logging --- Example/Program.cs | 3 + Example1/AudioStreamer.cs | 3 + Example2/Program.cs | 4 + Example3/Program.cs | 5 +- README.md | 95 +++--- websocket-sharp/LogData.cs | 150 ++++++++ websocket-sharp/LogLevel.cs | 63 ++++ websocket-sharp/Logger.cs | 323 ++++++++++++++++++ websocket-sharp/Server/HttpServer.cs | 122 ++++--- websocket-sharp/Server/WebSocketServer.cs | 5 +- websocket-sharp/Server/WebSocketServerBase.cs | 105 ++++-- websocket-sharp/Server/WebSocketService.cs | 27 +- .../Server/WebSocketServiceHost.cs | 5 +- websocket-sharp/WebSocket.cs | 253 ++++++++------ websocket-sharp/websocket-sharp.csproj | 3 + 15 files changed, 940 insertions(+), 226 deletions(-) create mode 100644 websocket-sharp/LogData.cs create mode 100644 websocket-sharp/LogLevel.cs create mode 100644 websocket-sharp/Logger.cs diff --git a/Example/Program.cs b/Example/Program.cs index 111d3962..b60af931 100644 --- a/Example/Program.cs +++ b/Example/Program.cs @@ -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(); diff --git a/Example1/AudioStreamer.cs b/Example1/AudioStreamer.cs index dce931e2..ec410feb 100644 --- a/Example1/AudioStreamer.cs +++ b/Example1/AudioStreamer.cs @@ -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); diff --git a/Example2/Program.cs b/Example2/Program.cs index 91472af1..9bc5cb1a 100644 --- a/Example2/Program.cs +++ b/Example2/Program.cs @@ -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"); wssv.AddWebSocketService("/Chat"); diff --git a/Example3/Program.cs b/Example3/Program.cs index 1da01968..e7103bd6 100644 --- a/Example3/Program.cs +++ b/Example3/Program.cs @@ -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"); @@ -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(); diff --git a/README.md b/README.md index 0a7bda64..d6149d21 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Logo](websocket-sharp.png) -**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` class if you want the singl var wssv = new WebSocketServiceHost("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"); wssv.AddWebSocketService("/Chat"); ``` -You can add to your `WebSocketServer` any WebSocket service and a matching path to that service by using the `WebSocketServer.AddWebSocketService` method. +You can add any WebSocket service with a specified path to the service to your `WebSocketServer` by using the `WebSocketServer.AddWebSocketService` 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.OnError` event occurs when the `WebSocketServiceHost` gets an error. +A `WebSocketServiceHost.OnError` event occurs when the `WebSocketServiceHost` 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` method. +You can add any WebSocket service with a specified path to the service to your `HttpServer` by using the `HttpServer.AddWebSocketService` method. ```cs var httpsv = new HttpServer(4649); @@ -323,6 +320,28 @@ httpsv.AddWebSocketService("/"); 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`, `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 ## diff --git a/websocket-sharp/LogData.cs b/websocket-sharp/LogData.cs new file mode 100644 index 00000000..db65d21f --- /dev/null +++ b/websocket-sharp/LogData.cs @@ -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 { + + /// + /// Represents the log data used by the class. + /// + 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 + + /// + /// Gets the information of the logging method caller. + /// + /// + /// A that contains the information of a logging method caller. + /// + public StackFrame Caller { + get { + return _caller; + } + } + + /// + /// Gets the date and time when the log data was created. + /// + /// + /// A that contains the date and time when the log data was created. + /// + public DateTime Date { + get { + return _date; + } + } + + /// + /// Gets the logging level associated with the log data. + /// + /// + /// One of the values that indicates the logging level + /// associated with the log data. + /// + public LogLevel Level { + get { + return _level; + } + } + + /// + /// Gets the message of the log data. + /// + /// + /// A that contains the message of a log data. + /// + public string Message { + get { + return _message; + } + } + + #endregion + + #region Public Methods + + /// + /// Returns a that represents the current . + /// + /// + /// A that represents the current . + /// + 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 + } +} diff --git a/websocket-sharp/LogLevel.cs b/websocket-sharp/LogLevel.cs new file mode 100644 index 00000000..9cbdd02d --- /dev/null +++ b/websocket-sharp/LogLevel.cs @@ -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 { + + /// + /// Contains the values of the logging level. + /// + public enum LogLevel { + + /// + /// Indicates the bottom logging level. + /// + TRACE, + /// + /// Indicates the 2nd logging level from the bottom. + /// + DEBUG, + /// + /// Indicates the 3rd logging level from the bottom. + /// + INFO, + /// + /// Indicates the 3rd logging level from the top. + /// + WARN, + /// + /// Indicates the 2nd logging level from the top. + /// + ERROR, + /// + /// Indicates the top logging level. + /// + FATAL + } +} diff --git a/websocket-sharp/Logger.cs b/websocket-sharp/Logger.cs new file mode 100644 index 00000000..3cffd7ac --- /dev/null +++ b/websocket-sharp/Logger.cs @@ -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 { + + /// + /// Provides the simple logging functions. + /// + /// + /// + /// The Logger class provides some methods that output the logs associated with the each + /// values. + /// If the value associated with a log was less than the , + /// the log could not be outputted. + /// + /// + /// 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 if it has a valid path. + /// + /// + /// If you wanted to run your custom output action, you would replace the current output action with + /// your output action by using the method. + /// + /// + public class Logger { + + #region Private Fields + + private volatile string _file; + private volatile LogLevel _level; + private Action _output; + private object _sync; + + #endregion + + #region Public Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor initializes the current logging level with the and + /// initializes the path to the log file with . + /// + public Logger () + : this (LogLevel.ERROR, null, defaultOutput) + { + } + + /// + /// Initializes a new instance of the class + /// with the specified logging . + /// + /// + /// This constructor initializes the path to the log file with . + /// + /// + /// One of the values to initialize. + /// + public Logger (LogLevel level) + : this (level, null, defaultOutput) + { + } + + /// + /// Initializes a new instance of the class + /// with the specified logging , path to the log + /// and action. + /// + /// + /// One of the values to initialize. + /// + /// + /// A that contains a path to the log file to initialize. + /// + /// + /// An Action<LogData, string> delegate that references the method(s) to initialize. + /// A parameter to pass to the method(s) is the value of + /// if any. + /// + public Logger (LogLevel level, string file, Action output) + { + _level = level; + _file = file; + if (output != null) + _output = output; + else + _output = defaultOutput; + + _sync = new object (); + } + + #endregion + + #region Public Properties + + /// + /// Gets or sets the path to the log file. + /// + /// + /// A that contains a path to the log file. + /// + public string File { + get { + return _file; + } + + set { + lock (_sync) + { + _file = value; + } + } + } + + /// + /// Gets or sets the current logging level. + /// + /// + /// A log associated with a less than the current logging level can not be outputted. + /// + /// + /// One of the values that indicates the current logging level. + /// + 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 + + /// + /// Outputs the specified as a log with the . + /// + /// + /// This method does not output as a log + /// if the current logging level is greater than the . + /// + /// + /// A that contains a message to output as a log. + /// + public void Debug (string message) + { + output (LogLevel.DEBUG, message); + } + + /// + /// Outputs the specified as a log with the . + /// + /// + /// This method does not output as a log + /// if the current logging level is greater than the . + /// + /// + /// A that contains a message to output as a log. + /// + public void Error (string message) + { + output (LogLevel.ERROR, message); + } + + /// + /// Outputs the specified as a log with the . + /// + /// + /// This method does not output as a log + /// if the current logging level is greater than the . + /// + /// + /// A that contains a message to output as a log. + /// + public void Fatal (string message) + { + output (LogLevel.FATAL, message); + } + + /// + /// Outputs the specified as a log with the . + /// + /// + /// This method does not output as a log + /// if the current logging level is greater than the . + /// + /// + /// A that contains a message to output as a log. + /// + public void Info (string message) + { + output (LogLevel.INFO, message); + } + + /// + /// Replaces the current output action with the specified action. + /// + /// + /// This method replaces the current output action with the default output action + /// if is . + /// + /// + /// An Action<LogData, string> delegate that references the method(s) to set. + /// A parameter to pass to the method(s) is the value of + /// if any. + /// + public void SetOutput (Action output) + { + lock (_sync) + { + if (output != null) + _output = output; + else + _output = defaultOutput; + } + } + + /// + /// Outputs the specified as a log with the . + /// + /// + /// This method does not output as a log + /// if the current logging level is greater than the . + /// + /// + /// A that contains a message to output as a log. + /// + public void Trace (string message) + { + output (LogLevel.TRACE, message); + } + + /// + /// Outputs the specified as a log with the . + /// + /// + /// This method does not output as a log + /// if the current logging level is greater than the . + /// + /// + /// A that contains a message to output as a log. + /// + public void Warn (string message) + { + output (LogLevel.WARN, message); + } + + #endregion + } +} diff --git a/websocket-sharp/Server/HttpServer.cs b/websocket-sharp/Server/HttpServer.cs index 360958e5..86b2cfdf 100644 --- a/websocket-sharp/Server/HttpServer.cs +++ b/websocket-sharp/Server/HttpServer.cs @@ -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 { } } + /// + /// Gets the logging functions. + /// + /// + /// The default logging level is the . + /// If you wanted to change the current logging level, you would set the Log.Level property + /// to one of the values which you want. + /// + /// + /// A that provides the logging functions. + /// + public Logger Log { + get { + return _logger; + } + } + /// /// Gets the port on which to listen for incoming requests. /// @@ -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(); + var svcHost = new WebSocketServiceHost(_logger); svcHost.Uri = absPath.ToUri(); if (!Sweeping) svcHost.Sweeping = false; diff --git a/websocket-sharp/Server/WebSocketServer.cs b/websocket-sharp/Server/WebSocketServer.cs index 33dbfe97..53f2865e 100644 --- a/websocket-sharp/Server/WebSocketServer.cs +++ b/websocket-sharp/Server/WebSocketServer.cs @@ -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(); + var svcHost = new WebSocketServiceHost(Log); svcHost.Uri = BaseUri.IsAbsoluteUri ? new Uri(BaseUri, absPath) : absPath.ToUri(); diff --git a/websocket-sharp/Server/WebSocketServerBase.cs b/websocket-sharp/Server/WebSocketServerBase.cs index 7c488e68..62fc50ee 100644 --- a/websocket-sharp/Server/WebSocketServerBase.cs +++ b/websocket-sharp/Server/WebSocketServerBase.cs @@ -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 { /// /// Initializes a new instance of the class. /// + /// + /// This constructor initializes a new instance of this class as non self host. + /// protected WebSocketServerBase() + : this(new Logger()) { + } + + /// + /// Initializes a new instance of the class + /// with the specified . + /// + /// + /// This constructor initializes a new instance of this class as non self host. + /// + /// + /// A that provides the logging functions. + /// + protected WebSocketServerBase(Logger logger) + { + _logger = logger; _selfHost = false; } /// - /// Initializes a new instance of the class that listens for incoming connection attempts - /// on the specified WebSocket URL. + /// Initializes a new instance of the class + /// that listens for incoming connection attempts on the specified WebSocket URL. /// /// /// A that contains a WebSocket URL. @@ -93,8 +113,9 @@ namespace WebSocketSharp.Server { } /// - /// Initializes a new instance of the class that listens for incoming connection attempts - /// on the specified , , and . + /// Initializes a new instance of the class + /// that listens for incoming connection attempts on the specified , + /// , and . /// /// /// A that contains a local IP address. @@ -106,21 +127,22 @@ namespace WebSocketSharp.Server { /// A that contains an absolute path. /// /// - /// A that indicates providing a secure connection or not. (true indicates providing a secure connection.) + /// A that indicates providing a secure connection or not. + /// (true indicates providing a secure connection.) /// /// /// Either or is . /// /// - /// - /// is invalid. - /// - /// - /// -or- - /// - /// - /// Pair of and is invalid. - /// + /// + /// is invalid. + /// + /// + /// -or- + /// + /// + /// Pair of and is invalid. + /// /// protected WebSocketServerBase(IPAddress address, int port, string absPath, bool secure) { @@ -222,6 +244,30 @@ namespace WebSocketSharp.Server { } } + /// + /// Gets the logging functions. + /// + /// + /// The default logging level is the . + /// If you wanted to change the current logging level, you would set the Log.Level property + /// to one of the values which you want. + /// + /// + /// A that provides the logging functions. + /// + public Logger Log { + get { + return _logger; + } + + internal set { + if (value == null) + return; + + _logger = value; + } + } + /// /// Gets the port on which to listen for incoming connection attempts. /// @@ -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 { /// protected virtual void Error(string message) { - onError(message); + if (message.IsNullOrEmpty()) + return; + + error(message); } #endregion diff --git a/websocket-sharp/Server/WebSocketService.cs b/websocket-sharp/Server/WebSocketService.cs index 7d626343..e7500a70 100644 --- a/websocket-sharp/Server/WebSocketService.cs +++ b/websocket-sharp/Server/WebSocketService.cs @@ -58,7 +58,7 @@ namespace WebSocketSharp.Server { /// public WebSocketService() { - ID = String.Empty; + ID = String.Empty; IsBound = false; } @@ -66,6 +66,31 @@ namespace WebSocketSharp.Server { #region Protected Properties + /// + /// Gets or sets the logging functions. + /// + /// + /// If you wanted to change the current logger to the service own logger, you would set this property + /// to a new instance that you created. + /// + /// + /// A that provides the logging functions. + /// + protected Logger Log { + get { + return IsBound + ? _websocket.Log + : null; + } + + set { + if (!IsBound) + return; + + _websocket.Log = value; + } + } + /// /// Gets the collection of query string variables used in the WebSocket opening handshake. /// diff --git a/websocket-sharp/Server/WebSocketServiceHost.cs b/websocket-sharp/Server/WebSocketServiceHost.cs index 3d01f2c5..31a0663a 100644 --- a/websocket-sharp/Server/WebSocketServiceHost.cs +++ b/websocket-sharp/Server/WebSocketServiceHost.cs @@ -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); diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 1c2084ae..466590a9 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -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 /// - /// Initializes a new instance of the class with the specified WebSocket URL and subprotocols. + /// Initializes a new instance of the class with the specified WebSocket URL + /// and subprotocols. /// /// /// A that contains a WebSocket URL to connect. @@ -314,6 +317,30 @@ namespace WebSocketSharp { } } + /// + /// Gets the logging functions. + /// + /// + /// The default logging level is the . + /// If you wanted to change the current logging level, you would set the Log.Level property + /// to one of the values which you want. + /// + /// + /// A that provides the logging functions. + /// + public Logger Log { + get { + return _logger; + } + + internal set { + if (value == null) + return; + + _logger = value; + } + } + /// /// Gets or sets the value of the Origin header used in the WebSocket opening handshake. /// @@ -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 '://[:]'."); + var msg = "The syntax of value of Origin must be '://[:]'."; + _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 - ? String.Format("An HTTP {0} authorization is required.", response.AuthChallenge.Scheme) - : !isValidResponseHandshake(response) - ? "Invalid response to this WebSocket connection request." - : String.Empty; + 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()) - ? "'userName' contains an invalid character." - : !password.IsNullOrEmpty() && !password.IsText() - ? "'password' contains an invalid character." - : String.Empty; + 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; } diff --git a/websocket-sharp/websocket-sharp.csproj b/websocket-sharp/websocket-sharp.csproj index 300bc6b7..89f2c54d 100644 --- a/websocket-sharp/websocket-sharp.csproj +++ b/websocket-sharp/websocket-sharp.csproj @@ -126,6 +126,9 @@ + + +