Added logging
This commit is contained in:
		| @@ -113,6 +113,9 @@ namespace Example | |||||||
|  |  | ||||||
|         //ws.Origin = "http://echo.websocket.org"; |         //ws.Origin = "http://echo.websocket.org"; | ||||||
|         //ws.Compression = CompressionMethod.DEFLATE; |         //ws.Compression = CompressionMethod.DEFLATE; | ||||||
|  |         #if DEBUG | ||||||
|  |         ws.Log.Level = LogLevel.TRACE; | ||||||
|  |         #endif | ||||||
|         //ws.SetCookie(new Cookie("nobita", "\"idiot, gunfighter\"")); |         //ws.SetCookie(new Cookie("nobita", "\"idiot, gunfighter\"")); | ||||||
|         //ws.SetCookie(new Cookie("dora", "tanuki")); |         //ws.SetCookie(new Cookie("dora", "tanuki")); | ||||||
|         ws.Connect(); |         ws.Connect(); | ||||||
|   | |||||||
| @@ -72,6 +72,9 @@ namespace Example1 | |||||||
|  |  | ||||||
|     private void configure() |     private void configure() | ||||||
|     { |     { | ||||||
|  |       #if DEBUG | ||||||
|  |       _ws.Log.Level = LogLevel.TRACE; | ||||||
|  |       #endif | ||||||
|       _ws.OnOpen += (sender, e) => |       _ws.OnOpen += (sender, e) => | ||||||
|       { |       { | ||||||
|         var msg = createTextMessage("connection", String.Empty); |         var msg = createTextMessage("connection", String.Empty); | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using System; | using System; | ||||||
|  | using WebSocketSharp; | ||||||
| using WebSocketSharp.Server; | using WebSocketSharp.Server; | ||||||
|  |  | ||||||
| namespace Example2 | namespace Example2 | ||||||
| @@ -31,6 +32,9 @@ namespace Example2 | |||||||
|       // Multi services server |       // Multi services server | ||||||
|       var wssv = new WebSocketServer(4649); |       var wssv = new WebSocketServer(4649); | ||||||
|       //var wssv = new WebSocketServer("ws://localhost: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.Sweeping = false; // Stop the sweep inactive session timer. | ||||||
|       wssv.AddWebSocketService<Echo>("/Echo"); |       wssv.AddWebSocketService<Echo>("/Echo"); | ||||||
|       wssv.AddWebSocketService<Chat>("/Chat"); |       wssv.AddWebSocketService<Chat>("/Chat"); | ||||||
|   | |||||||
| @@ -12,6 +12,9 @@ namespace Example3 | |||||||
|     public static void Main(string[] args) |     public static void Main(string[] args) | ||||||
|     { |     { | ||||||
|       _httpsv = new HttpServer(4649); |       _httpsv = new HttpServer(4649); | ||||||
|  |       #if DEBUG | ||||||
|  |       _httpsv.Log.Level = LogLevel.TRACE; | ||||||
|  |       #endif | ||||||
|       //_httpsv.RootPath = "../../Public"; |       //_httpsv.RootPath = "../../Public"; | ||||||
|       //_httpsv.Sweeping = false; |       //_httpsv.Sweeping = false; | ||||||
|       _httpsv.AddWebSocketService<Echo>("/Echo"); |       _httpsv.AddWebSocketService<Echo>("/Echo"); | ||||||
| @@ -33,7 +36,7 @@ namespace Example3 | |||||||
|         Console.WriteLine("  {0}", path); |         Console.WriteLine("  {0}", path); | ||||||
|       Console.WriteLine(); |       Console.WriteLine(); | ||||||
|  |  | ||||||
|       Console.WriteLine("Press any key to stop server..."); |       Console.WriteLine("Press enter key to stop server..."); | ||||||
|       Console.ReadLine(); |       Console.ReadLine(); | ||||||
|  |  | ||||||
|       _httpsv.Stop();        |       _httpsv.Stop();        | ||||||
|   | |||||||
							
								
								
									
										95
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | |||||||
| <!-- # websocket-sharp # --> | <!-- # 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 ## | ## Usage ## | ||||||
|  |  | ||||||
| @@ -45,7 +45,7 @@ The `WebSocket` class exists in the `WebSocketSharp` namespace. | |||||||
|  |  | ||||||
| #### Step 2 #### | #### 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 | ```cs | ||||||
| using (var ws = new WebSocket("ws://example.com")) | using (var ws = new WebSocket("ws://example.com")) | ||||||
| @@ -62,7 +62,7 @@ Setting the `WebSocket` events. | |||||||
|  |  | ||||||
| ##### WebSocket.OnOpen event ##### | ##### 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 | ```cs | ||||||
| ws.OnOpen += (sender, e) => | 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 ##### | ##### 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 | ```cs | ||||||
| ws.OnMessage += (sender, e) => | 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 | ```cs | ||||||
| switch (e.Type) | if (e.Type == Opcode.TEXT) | ||||||
| { | { | ||||||
|   case Opcode.TEXT: |   // Do something with e.Data | ||||||
|     ... |   return; | ||||||
|     break; | } | ||||||
|   case Opcode.BINARY: |  | ||||||
|     ... | if (e.Type == Opcode.BINARY) | ||||||
|     break; | { | ||||||
|   default: |   // Do something with e.RawData | ||||||
|     break; |   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 ##### | ##### 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 | ```cs | ||||||
| ws.OnError += (sender, e) => | 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 ##### | ##### 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 | ```cs | ||||||
| ws.OnClose += (sender, e) => | 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 #### | #### Step 4 #### | ||||||
|  |  | ||||||
| @@ -157,11 +157,9 @@ Closing the WebSocket connection. | |||||||
| ws.Close(code, reason); | 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. | And the `Close` method is overloaded. The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, the type of `reason` is `string`. | ||||||
|  |  | ||||||
| The types of `code` are `WebSocketSharp.CloseStatusCode` and `ushort`, the type of `reason` is `string`. |  | ||||||
|  |  | ||||||
| In addition, the `Close()` and `Close(code)` methods exist. | 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"); | 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 | ```cs | ||||||
| var wssv = new WebSocketServer(4649); | var wssv = new WebSocketServer(4649); | ||||||
| @@ -264,12 +262,11 @@ wssv.AddWebSocketService<Echo>("/Echo"); | |||||||
| wssv.AddWebSocketService<Chat>("/Chat"); | 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**. | 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.   | 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. | ||||||
| So it is necessary to run with root permission. |  | ||||||
|  |  | ||||||
|     $ sudo mono example2.exe |     $ sudo mono example2.exe | ||||||
|  |  | ||||||
| @@ -279,7 +276,7 @@ Setting the event. | |||||||
|  |  | ||||||
| ##### WebSocketServiceHost<T>.OnError 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 | ```cs | ||||||
| wssv.OnError += (sender, e) => | 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 ##### | ##### WebSocketServer.OnError event ##### | ||||||
|  |  | ||||||
| @@ -312,9 +309,9 @@ wssv.Stop(); | |||||||
|  |  | ||||||
| ### HTTP Server with the WebSocket ### | ### 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 | ```cs | ||||||
| var httpsv = new HttpServer(4649); | var httpsv = new HttpServer(4649); | ||||||
| @@ -323,6 +320,28 @@ httpsv.AddWebSocketService<Echo>("/"); | |||||||
|  |  | ||||||
| For more information, could you see **[Example3]**? | 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 ## | ||||||
|  |  | ||||||
| Examples of using **websocket-sharp**. | Examples of using **websocket-sharp**. | ||||||
| @@ -333,19 +352,19 @@ Examples of using **websocket-sharp**. | |||||||
|  |  | ||||||
| ### Example1 ### | ### 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 ### | ||||||
|  |  | ||||||
| [Example2] starts the WebSocket server. | [Example2] starts a WebSocket server. | ||||||
|  |  | ||||||
| ### Example3 ### | ### 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 ## | ## 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 HttpListener       _listener; | ||||||
|     private bool               _listening; |     private bool               _listening; | ||||||
|  |     private Logger             _logger; | ||||||
|     private int                _port; |     private int                _port; | ||||||
|     private Thread             _receiveRequestThread; |     private Thread             _receiveRequestThread; | ||||||
|     private string             _rootPath; |     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> |     /// <summary> | ||||||
|     /// Gets the port on which to listen for incoming requests. |     /// Gets the port on which to listen for incoming requests. | ||||||
|     /// </summary> |     /// </summary> | ||||||
| @@ -231,10 +249,16 @@ namespace WebSocketSharp.Server { | |||||||
|  |  | ||||||
|     #region Private Methods |     #region Private Methods | ||||||
|  |  | ||||||
|  |     private void error(string message) | ||||||
|  |     { | ||||||
|  |       OnError.Emit(this, new ErrorEventArgs(message)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private void init() |     private void init() | ||||||
|     { |     { | ||||||
|       _listener = new HttpListener(); |       _listener = new HttpListener(); | ||||||
|       _listening = false; |       _listening = false; | ||||||
|  |       _logger = new Logger(); | ||||||
|       _rootPath = getRootPath(); |       _rootPath = getRootPath(); | ||||||
|       _svcHosts = new ServiceHostManager(); |       _svcHosts = new ServiceHostManager(); | ||||||
|  |  | ||||||
| @@ -262,103 +286,107 @@ namespace WebSocketSharp.Server { | |||||||
|              : rootPath; |              : 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); |       var eventArgs = new HttpRequestEventArgs(context); | ||||||
|  |       var method = context.Request.HttpMethod; | ||||||
|       if (req.HttpMethod == "GET" && !OnGet.IsNull()) |       if (method == "GET" && OnGet != null) | ||||||
|       { |       { | ||||||
|         OnGet(this, eventArgs); |         OnGet(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "HEAD" && !OnHead.IsNull()) |       if (method == "HEAD" && OnHead != null) | ||||||
|       { |       { | ||||||
|         OnHead(this, eventArgs); |         OnHead(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "POST" && !OnPost.IsNull()) |       if (method == "POST" && OnPost != null) | ||||||
|       { |       { | ||||||
|         OnPost(this, eventArgs); |         OnPost(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "PUT" && !OnPut.IsNull()) |       if (method == "PUT" && OnPut != null) | ||||||
|       { |       { | ||||||
|         OnPut(this, eventArgs); |         OnPut(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "DELETE" && !OnDelete.IsNull()) |       if (method == "DELETE" && OnDelete != null) | ||||||
|       { |       { | ||||||
|         OnDelete(this, eventArgs); |         OnDelete(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "OPTIONS" && !OnOptions.IsNull()) |       if (method == "OPTIONS" && OnOptions != null) | ||||||
|       { |       { | ||||||
|         OnOptions(this, eventArgs); |         OnOptions(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "TRACE" && !OnTrace.IsNull()) |       if (method == "TRACE" && OnTrace != null) | ||||||
|       { |       { | ||||||
|         OnTrace(this, eventArgs); |         OnTrace(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "CONNECT" && !OnConnect.IsNull()) |       if (method == "CONNECT" && OnConnect != null) | ||||||
|       { |       { | ||||||
|         OnConnect(this, eventArgs); |         OnConnect(this, eventArgs); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (req.HttpMethod == "PATCH" && !OnPatch.IsNull()) |       if (method == "PATCH" && OnPatch != null) | ||||||
|       { |       { | ||||||
|         OnPatch(this, eventArgs); |         OnPatch(this, eventArgs); | ||||||
|         return; |         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) |     private void processRequestAsync(HttpListenerContext context) | ||||||
|     { |     { | ||||||
|       WaitCallback callback = (state) => |       WaitCallback callback = (state) => | ||||||
|       { |       { | ||||||
|         var req = context.Request; |  | ||||||
|         var res = context.Response; |  | ||||||
|  |  | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|           if (req.IsUpgradeTo("websocket")) |           if (context.Request.IsUpgradeTo("websocket")) | ||||||
|           { |           { | ||||||
|             if (upgradeToWebSocket(context)) |             if (processWebSocketRequest(context)) | ||||||
|               return; |               return; | ||||||
|           } |           } | ||||||
|           else |           else | ||||||
|           { |           { | ||||||
|             onRequest(context); |             processHttpRequest(context); | ||||||
|           } |           } | ||||||
|  |  | ||||||
|           res.Close(); |           context.Response.Close(); | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|           onError(ex.Message); |           _logger.Fatal(ex.Message); | ||||||
|  |           error("An exception has occured."); | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
| @@ -371,8 +399,7 @@ namespace WebSocketSharp.Server { | |||||||
|       { |       { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|           var context = _listener.GetContext(); |           processRequestAsync(_listener.GetContext()); | ||||||
|           processRequestAsync(context); |  | ||||||
|         } |         } | ||||||
|         catch (HttpListenerException) |         catch (HttpListenerException) | ||||||
|         { |         { | ||||||
| @@ -381,7 +408,9 @@ namespace WebSocketSharp.Server { | |||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|           onError(ex.Message); |           _logger.Fatal(ex.Message); | ||||||
|  |           error("An exception has occured."); | ||||||
|  |  | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @@ -394,23 +423,6 @@ namespace WebSocketSharp.Server { | |||||||
|       _receiveRequestThread.Start(); |       _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 |     #endregion | ||||||
|  |  | ||||||
|     #region Public Methods |     #region Public Methods | ||||||
| @@ -430,11 +442,13 @@ namespace WebSocketSharp.Server { | |||||||
|       string msg; |       string msg; | ||||||
|       if (!absPath.IsValidAbsolutePath(out msg)) |       if (!absPath.IsValidAbsolutePath(out msg)) | ||||||
|       { |       { | ||||||
|         onError(msg); |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       var svcHost = new WebSocketServiceHost<T>(); |       var svcHost = new WebSocketServiceHost<T>(_logger); | ||||||
|       svcHost.Uri = absPath.ToUri(); |       svcHost.Uri = absPath.ToUri(); | ||||||
|       if (!Sweeping) |       if (!Sweeping) | ||||||
|         svcHost.Sweeping = false; |         svcHost.Sweeping = false; | ||||||
|   | |||||||
| @@ -194,6 +194,7 @@ namespace WebSocketSharp.Server { | |||||||
|       var ws = context.WebSocket; |       var ws = context.WebSocket; | ||||||
|       var path = context.Path.UrlDecode(); |       var path = context.Path.UrlDecode(); | ||||||
|  |  | ||||||
|  |       ws.Log = Log; | ||||||
|       IServiceHost svcHost; |       IServiceHost svcHost; | ||||||
|       if (!_svcHosts.TryGetServiceHost(path, out svcHost)) |       if (!_svcHosts.TryGetServiceHost(path, out svcHost)) | ||||||
|       { |       { | ||||||
| @@ -226,11 +227,13 @@ namespace WebSocketSharp.Server { | |||||||
|       string msg; |       string msg; | ||||||
|       if (!absPath.IsValidAbsolutePath(out msg)) |       if (!absPath.IsValidAbsolutePath(out msg)) | ||||||
|       { |       { | ||||||
|  |         Log.Error(msg); | ||||||
|         Error(msg); |         Error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       var svcHost = new WebSocketServiceHost<T>(); |       var svcHost = new WebSocketServiceHost<T>(Log); | ||||||
|       svcHost.Uri = BaseUri.IsAbsoluteUri |       svcHost.Uri = BaseUri.IsAbsoluteUri | ||||||
|                   ? new Uri(BaseUri, absPath) |                   ? new Uri(BaseUri, absPath) | ||||||
|                   : absPath.ToUri(); |                   : absPath.ToUri(); | ||||||
|   | |||||||
| @@ -47,6 +47,7 @@ namespace WebSocketSharp.Server { | |||||||
|  |  | ||||||
|     private IPAddress   _address; |     private IPAddress   _address; | ||||||
|     private bool        _listening; |     private bool        _listening; | ||||||
|  |     private Logger      _logger; | ||||||
|     private int         _port; |     private int         _port; | ||||||
|     private Thread      _receiveRequestThread; |     private Thread      _receiveRequestThread; | ||||||
|     private bool        _secure; |     private bool        _secure; | ||||||
| @@ -61,14 +62,33 @@ namespace WebSocketSharp.Server { | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Initializes a new instance of the <see cref="WebSocketServerBase"/> class. |     /// Initializes a new instance of the <see cref="WebSocketServerBase"/> class. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|  |     /// <remarks> | ||||||
|  |     /// This constructor initializes a new instance of this class as non self host. | ||||||
|  |     /// </remarks> | ||||||
|     protected WebSocketServerBase() |     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; |       _selfHost = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Initializes a new instance of the <see cref="WebSocketServerBase"/> class that listens for incoming connection attempts |     /// Initializes a new instance of the <see cref="WebSocketServerBase"/> class | ||||||
|     /// on the specified WebSocket URL. |     /// that listens for incoming connection attempts on the specified WebSocket URL. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="url"> |     /// <param name="url"> | ||||||
|     /// A <see cref="string"/> that contains a WebSocket URL. |     /// A <see cref="string"/> that contains a WebSocket URL. | ||||||
| @@ -93,8 +113,9 @@ namespace WebSocketSharp.Server { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Initializes a new instance of the <see cref="WebSocketServerBase"/> class that listens for incoming connection attempts |     /// Initializes a new instance of the <see cref="WebSocketServerBase"/> class | ||||||
|     /// on the specified <paramref name="address"/>, <paramref name="port"/>, <paramref name="absPath"/> and <paramref name="secure"/>. |     /// that listens for incoming connection attempts on the specified <paramref name="address"/>, | ||||||
|  |     /// <paramref name="port"/>, <paramref name="absPath"/> and <paramref name="secure"/>. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="address"> |     /// <param name="address"> | ||||||
|     /// A <see cref="IPAddress"/> that contains a local IP address. |     /// A <see cref="IPAddress"/> that contains a local IP address. | ||||||
| @@ -106,21 +127,22 @@ namespace WebSocketSharp.Server { | |||||||
|     /// A <see cref="string"/> that contains an absolute path. |     /// A <see cref="string"/> that contains an absolute path. | ||||||
|     /// </param> |     /// </param> | ||||||
|     /// <param name="secure"> |     /// <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> |     /// </param> | ||||||
|     /// <exception cref="ArgumentNullException"> |     /// <exception cref="ArgumentNullException"> | ||||||
|     /// Either <paramref name="address"/> or <paramref name="absPath"/> is <see langword="null"/>. |     /// Either <paramref name="address"/> or <paramref name="absPath"/> is <see langword="null"/>. | ||||||
|     /// </exception> |     /// </exception> | ||||||
|     /// <exception cref="ArgumentException"> |     /// <exception cref="ArgumentException"> | ||||||
|     /// <para> |     ///   <para> | ||||||
|     /// <paramref name="absPath"/> is invalid. |     ///   <paramref name="absPath"/> is invalid. | ||||||
|     /// </para> |     ///   </para> | ||||||
|     /// <para> |     ///   <para> | ||||||
|     /// -or- |     ///   -or- | ||||||
|     /// </para> |     ///   </para> | ||||||
|     /// <para> |     ///   <para> | ||||||
|     /// Pair of <paramref name="port"/> and <paramref name="secure"/> is invalid. |     ///   Pair of <paramref name="port"/> and <paramref name="secure"/> is invalid. | ||||||
|     /// </para> |     ///   </para> | ||||||
|     /// </exception> |     /// </exception> | ||||||
|     protected WebSocketServerBase(IPAddress address, int port, string absPath, bool secure) |     protected WebSocketServerBase(IPAddress address, int port, string absPath, bool secure) | ||||||
|     { |     { | ||||||
| @@ -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> |     /// <summary> | ||||||
|     /// Gets the port on which to listen for incoming connection attempts. |     /// Gets the port on which to listen for incoming connection attempts. | ||||||
|     /// </summary> |     /// </summary> | ||||||
| @@ -247,9 +293,15 @@ namespace WebSocketSharp.Server { | |||||||
|  |  | ||||||
|     #region Private Methods |     #region Private Methods | ||||||
|  |  | ||||||
|  |     private void error(string message) | ||||||
|  |     { | ||||||
|  |       OnError.Emit(this, new ErrorEventArgs(message)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private void init() |     private void init() | ||||||
|     { |     { | ||||||
|       _listening = false; |       _listening = false; | ||||||
|  |       _logger = new Logger(); | ||||||
|       _selfHost = true; |       _selfHost = true; | ||||||
|       _tcpListener = new TcpListener(_address, _port); |       _tcpListener = new TcpListener(_address, _port); | ||||||
|     } |     } | ||||||
| @@ -268,16 +320,6 @@ namespace WebSocketSharp.Server { | |||||||
|       init(); |       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) |     private void processRequestAsync(TcpListenerWebSocketContext context) | ||||||
|     { |     { | ||||||
|       WaitCallback callback = (state) => |       WaitCallback callback = (state) => | ||||||
| @@ -288,7 +330,8 @@ namespace WebSocketSharp.Server { | |||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|           onError(ex.Message); |           _logger.Fatal(ex.Message); | ||||||
|  |           error("An exception has occured."); | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
| @@ -301,8 +344,7 @@ namespace WebSocketSharp.Server { | |||||||
|       { |       { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|           var context = _tcpListener.AcceptWebSocket(_secure); |           processRequestAsync(_tcpListener.AcceptWebSocket(_secure)); | ||||||
|           processRequestAsync(context); |  | ||||||
|         } |         } | ||||||
|         catch (SocketException) |         catch (SocketException) | ||||||
|         { |         { | ||||||
| @@ -311,7 +353,9 @@ namespace WebSocketSharp.Server { | |||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|           onError(ex.Message); |           _logger.Fatal(ex.Message); | ||||||
|  |           error("An exception has occured."); | ||||||
|  |  | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @@ -360,7 +404,10 @@ namespace WebSocketSharp.Server { | |||||||
|     /// </param> |     /// </param> | ||||||
|     protected virtual void Error(string message) |     protected virtual void Error(string message) | ||||||
|     { |     { | ||||||
|       onError(message); |       if (message.IsNullOrEmpty()) | ||||||
|  |         return; | ||||||
|  |  | ||||||
|  |       error(message); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #endregion |     #endregion | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ namespace WebSocketSharp.Server { | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public WebSocketService() |     public WebSocketService() | ||||||
|     { |     { | ||||||
|       ID      = String.Empty; |       ID = String.Empty; | ||||||
|       IsBound = false; |       IsBound = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -66,6 +66,31 @@ namespace WebSocketSharp.Server { | |||||||
|  |  | ||||||
|     #region Protected Properties |     #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> |     /// <summary> | ||||||
|     /// Gets the collection of query string variables used in the WebSocket opening handshake. |     /// Gets the collection of query string variables used in the WebSocket opening handshake. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|   | |||||||
| @@ -56,7 +56,8 @@ namespace WebSocketSharp.Server { | |||||||
|  |  | ||||||
|     #region Internal Constructors |     #region Internal Constructors | ||||||
|  |  | ||||||
|     internal WebSocketServiceHost() |     internal WebSocketServiceHost(Logger logger) | ||||||
|  |       : base(logger) | ||||||
|     { |     { | ||||||
|       _sessions = new WebSocketServiceManager(); |       _sessions = new WebSocketServiceManager(); | ||||||
|     } |     } | ||||||
| @@ -230,6 +231,8 @@ namespace WebSocketSharp.Server { | |||||||
|     { |     { | ||||||
|       var ws = context.WebSocket; |       var ws = context.WebSocket; | ||||||
|       var path = context.Path.UrlDecode(); |       var path = context.Path.UrlDecode(); | ||||||
|  |  | ||||||
|  |       ws.Log = Log; | ||||||
|       if (path != Uri.GetAbsolutePath().UrlDecode()) |       if (path != Uri.GetAbsolutePath().UrlDecode()) | ||||||
|       { |       { | ||||||
|         ws.Close(HttpStatusCode.NotImplemented); |         ws.Close(HttpStatusCode.NotImplemented); | ||||||
|   | |||||||
| @@ -77,6 +77,7 @@ namespace WebSocketSharp { | |||||||
|     private object            _forClose; |     private object            _forClose; | ||||||
|     private object            _forFrame; |     private object            _forFrame; | ||||||
|     private object            _forSend; |     private object            _forSend; | ||||||
|  |     private volatile Logger   _logger; | ||||||
|     private string            _origin; |     private string            _origin; | ||||||
|     private bool              _preAuth; |     private bool              _preAuth; | ||||||
|     private string            _protocol; |     private string            _protocol; | ||||||
| @@ -100,6 +101,7 @@ namespace WebSocketSharp { | |||||||
|       _forClose = new object(); |       _forClose = new object(); | ||||||
|       _forFrame = new object(); |       _forFrame = new object(); | ||||||
|       _forSend = new object(); |       _forSend = new object(); | ||||||
|  |       _logger = new Logger(); | ||||||
|       _origin = String.Empty; |       _origin = String.Empty; | ||||||
|       _preAuth = false; |       _preAuth = false; | ||||||
|       _protocol = String.Empty; |       _protocol = String.Empty; | ||||||
| @@ -131,7 +133,8 @@ namespace WebSocketSharp { | |||||||
|     #region Public Constructors |     #region Public Constructors | ||||||
|  |  | ||||||
|     /// <summary> |     /// <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> |     /// </summary> | ||||||
|     /// <param name="url"> |     /// <param name="url"> | ||||||
|     /// A <see cref="string"/> that contains a WebSocket URL to connect. |     /// 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> |     /// <summary> | ||||||
|     /// Gets or sets the value of the Origin header used in the WebSocket opening handshake. |     /// Gets or sets the value of the Origin header used in the WebSocket opening handshake. | ||||||
|     /// </summary> |     /// </summary> | ||||||
| @@ -348,7 +375,10 @@ namespace WebSocketSharp { | |||||||
|         var origin = new Uri(value); |         var origin = new Uri(value); | ||||||
|         if (!origin.IsAbsoluteUri || origin.Segments.Length > 1) |         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; |           return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -435,11 +465,20 @@ namespace WebSocketSharp { | |||||||
|       return true; |       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) |     private void close(PayloadData data) | ||||||
|     { |     { | ||||||
|       #if DEBUG |       _logger.Debug("Is this thread background?: " + Thread.CurrentThread.IsBackground); | ||||||
|       Console.WriteLine("WS: Info@close: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground); |  | ||||||
|       #endif |  | ||||||
|       lock(_forClose) |       lock(_forClose) | ||||||
|       { |       { | ||||||
|         // Whether the closing handshake has been started already? |         // Whether the closing handshake has been started already? | ||||||
| @@ -450,7 +489,7 @@ namespace WebSocketSharp { | |||||||
|         if (_readyState == WsState.CONNECTING && !_client) |         if (_readyState == WsState.CONNECTING && !_client) | ||||||
|         { |         { | ||||||
|           sendResponseHandshake(HttpStatusCode.BadRequest); |           sendResponseHandshake(HttpStatusCode.BadRequest); | ||||||
|           onClose(new CloseEventArgs(data)); |           close(new CloseEventArgs(data)); | ||||||
|            |            | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
| @@ -461,14 +500,12 @@ namespace WebSocketSharp { | |||||||
|       // Whether a payload data contains the close status code which must not be set for send? |       // Whether a payload data contains the close status code which must not be set for send? | ||||||
|       if (data.ContainsReservedCloseStatusCode) |       if (data.ContainsReservedCloseStatusCode) | ||||||
|       { |       { | ||||||
|         onClose(new CloseEventArgs(data)); |         close(new CloseEventArgs(data)); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       closeHandshake(data); |       closeHandshake(data); | ||||||
|       #if DEBUG |       _logger.Trace("Exit close method."); | ||||||
|       Console.WriteLine("WS: Info@close: Exit close method."); |  | ||||||
|       #endif |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void close(HttpStatusCode code) |     private void close(HttpStatusCode code) | ||||||
| @@ -485,7 +522,10 @@ namespace WebSocketSharp { | |||||||
|       var data = code.Append(reason); |       var data = code.Append(reason); | ||||||
|       if (data.Length > 125) |       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; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -499,7 +539,7 @@ namespace WebSocketSharp { | |||||||
|       if (send(frame)) |       if (send(frame)) | ||||||
|         args.WasClean = true; |         args.WasClean = true; | ||||||
|  |  | ||||||
|       onClose(args); |       close(args); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private bool closeResources() |     private bool closeResources() | ||||||
| @@ -517,7 +557,9 @@ namespace WebSocketSharp { | |||||||
|       } |       } | ||||||
|       catch (Exception ex) |       catch (Exception ex) | ||||||
|       { |       { | ||||||
|         onError(ex.Message); |         _logger.Fatal(ex.Message); | ||||||
|  |         error("An exception has occured."); | ||||||
|  |  | ||||||
|         return false; |         return false; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -739,6 +781,11 @@ namespace WebSocketSharp { | |||||||
|       return processResponseHandshake(sendRequestHandshake()); |       return processResponseHandshake(sendRequestHandshake()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private void error(string message) | ||||||
|  |     { | ||||||
|  |       OnError.Emit(this, new ErrorEventArgs(message)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private static CompressionMethod getCompressionMethod(string value) |     private static CompressionMethod getCompressionMethod(string value) | ||||||
|     { |     { | ||||||
|       var deprecated = createDeprecatedCompressionExtension(CompressionMethod.DEFLATE); |       var deprecated = createDeprecatedCompressionExtension(CompressionMethod.DEFLATE); | ||||||
| @@ -791,7 +838,11 @@ namespace WebSocketSharp { | |||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|       if (errorIfOpened) |       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; |       return true; | ||||||
|     } |     } | ||||||
| @@ -837,29 +888,7 @@ namespace WebSocketSharp { | |||||||
|                  response.ContainsHeader("Sec-WebSocket-Version", _version); |                  response.ContainsHeader("Sec-WebSocket-Version", _version); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void onClose(CloseEventArgs eventArgs) |     private void open() | ||||||
|     { |  | ||||||
|       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() |  | ||||||
|     { |     { | ||||||
|       _readyState = WsState.OPEN; |       _readyState = WsState.OPEN; | ||||||
|       startReceiving(); |       startReceiving(); | ||||||
| @@ -887,9 +916,7 @@ namespace WebSocketSharp { | |||||||
|       if (frame != null) |       if (frame != null) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|       #if DEBUG |       _logger.Trace("Start closing handshake."); | ||||||
|       Console.WriteLine("WS: Info@processAbnormal: Start closing handshake."); |  | ||||||
|       #endif |  | ||||||
|       var code = CloseStatusCode.ABNORMAL; |       var code = CloseStatusCode.ABNORMAL; | ||||||
|       Close(code, code.GetMessage()); |       Close(code, code.GetMessage()); | ||||||
|  |  | ||||||
| @@ -901,9 +928,7 @@ namespace WebSocketSharp { | |||||||
|       if (!frame.IsClose) |       if (!frame.IsClose) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|       #if DEBUG |       _logger.Trace("Start closing handshake."); | ||||||
|       Console.WriteLine("WS: Info@processClose: Start closing handshake."); |  | ||||||
|       #endif |  | ||||||
|       close(frame.PayloadData); |       close(frame.PayloadData); | ||||||
|  |  | ||||||
|       return true; |       return true; | ||||||
| @@ -985,9 +1010,7 @@ namespace WebSocketSharp { | |||||||
|  |  | ||||||
|     private void processIncorrectFrame() |     private void processIncorrectFrame() | ||||||
|     { |     { | ||||||
|       #if DEBUG |       _logger.Trace("Start closing handshake."); | ||||||
|       Console.WriteLine("WS: Info@processIncorrectFrame: Start closing handshake."); |  | ||||||
|       #endif |  | ||||||
|       Close(CloseStatusCode.INCORRECT_DATA); |       Close(CloseStatusCode.INCORRECT_DATA); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -996,9 +1019,7 @@ namespace WebSocketSharp { | |||||||
|       if (!frame.IsPing) |       if (!frame.IsPing) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|       #if DEBUG |       _logger.Trace("Return Pong."); | ||||||
|       Console.WriteLine("WS: Info@processPing: Return Pong."); |  | ||||||
|       #endif |  | ||||||
|       pong(frame.PayloadData); |       pong(frame.PayloadData); | ||||||
|  |  | ||||||
|       return true; |       return true; | ||||||
| @@ -1009,9 +1030,7 @@ namespace WebSocketSharp { | |||||||
|       if (!frame.IsPong) |       if (!frame.IsPong) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|       #if DEBUG |       _logger.Trace("Receive Pong."); | ||||||
|       Console.WriteLine("WS: Info@processPong: Receive Pong."); |  | ||||||
|       #endif |  | ||||||
|       _receivePong.Set(); |       _receivePong.Set(); | ||||||
|  |  | ||||||
|       return true; |       return true; | ||||||
| @@ -1048,15 +1067,15 @@ namespace WebSocketSharp { | |||||||
|     // As server |     // As server | ||||||
|     private bool processRequestHandshake() |     private bool processRequestHandshake() | ||||||
|     { |     { | ||||||
|       #if DEBUG |  | ||||||
|       var req = RequestHandshake.Parse(_context); |       var req = RequestHandshake.Parse(_context); | ||||||
|       Console.WriteLine("WS: Info@processRequestHandshake: Request handshake from client:\n"); |       _logger.Debug("Request handshake from client:\n" + req.ToString()); | ||||||
|       Console.WriteLine(req.ToString()); |  | ||||||
|       #endif |  | ||||||
|       if (!isValidRequesHandshake()) |       if (!isValidRequesHandshake()) | ||||||
|       { |       { | ||||||
|         onError("Invalid WebSocket connection request."); |         var msg = "Invalid WebSocket connection request."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|         close(HttpStatusCode.BadRequest); |         close(HttpStatusCode.BadRequest); | ||||||
|  |  | ||||||
|         return false; |         return false; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1110,16 +1129,17 @@ namespace WebSocketSharp { | |||||||
|     // As client |     // As client | ||||||
|     private bool processResponseHandshake(ResponseHandshake response) |     private bool processResponseHandshake(ResponseHandshake response) | ||||||
|     { |     { | ||||||
|       var error = response.IsUnauthorized |       var msg = response.IsUnauthorized | ||||||
|                 ? String.Format("An HTTP {0} authorization is required.", response.AuthChallenge.Scheme) |               ? String.Format("An HTTP {0} authorization is required.", response.AuthChallenge.Scheme) | ||||||
|                 : !isValidResponseHandshake(response) |               : !isValidResponseHandshake(response) | ||||||
|                   ? "Invalid response to this WebSocket connection request." |                 ? "Invalid response to this WebSocket connection request." | ||||||
|                   : String.Empty; |                 : String.Empty; | ||||||
|  |  | ||||||
|       if (error.Length > 0) |       if (msg.Length > 0) | ||||||
|       { |       { | ||||||
|         onError(error); |         _logger.Error(msg); | ||||||
|         Close(CloseStatusCode.ABNORMAL, error); |         error(msg); | ||||||
|  |         Close(CloseStatusCode.ABNORMAL, msg); | ||||||
|  |  | ||||||
|         return false; |         return false; | ||||||
|       } |       } | ||||||
| @@ -1142,30 +1162,22 @@ namespace WebSocketSharp { | |||||||
|     private ResponseHandshake receiveResponseHandshake() |     private ResponseHandshake receiveResponseHandshake() | ||||||
|     { |     { | ||||||
|       var res = ResponseHandshake.Parse(_wsStream.ReadHandshake()); |       var res = ResponseHandshake.Parse(_wsStream.ReadHandshake()); | ||||||
|       #if DEBUG |       _logger.Debug("Response handshake from server:\n" + res.ToString()); | ||||||
|       Console.WriteLine("WS: Info@receiveResponseHandshake: Response handshake from server:\n"); |  | ||||||
|       Console.WriteLine(res.ToString()); |  | ||||||
|       #endif |  | ||||||
|       return res; |       return res; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // As client |     // As client | ||||||
|     private void send(RequestHandshake request) |     private void send(RequestHandshake request) | ||||||
|     { |     { | ||||||
|       #if DEBUG |       _logger.Debug("Request handshake to server:\n" + request.ToString()); | ||||||
|       Console.WriteLine("WS: Info@send: Request handshake to server:\n"); |  | ||||||
|       Console.WriteLine(request.ToString()); |  | ||||||
|       #endif |  | ||||||
|       _wsStream.WriteHandshake(request); |       _wsStream.WriteHandshake(request); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // As server |     // As server | ||||||
|     private void send(ResponseHandshake response) |     private void send(ResponseHandshake response) | ||||||
|     { |     { | ||||||
|       #if DEBUG |       _logger.Debug("Response handshake to client:\n" + response.ToString()); | ||||||
|       Console.WriteLine("WS: Info@send: Response handshake to client:\n"); |  | ||||||
|       Console.WriteLine(response.ToString()); |  | ||||||
|       #endif |  | ||||||
|       _wsStream.WriteHandshake(response); |       _wsStream.WriteHandshake(response); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1183,7 +1195,10 @@ namespace WebSocketSharp { | |||||||
|  |  | ||||||
|         if (!ready) |         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; |           return false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1199,7 +1214,10 @@ namespace WebSocketSharp { | |||||||
|       { |       { | ||||||
|         if (_readyState != WsState.OPEN) |         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; |           return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1220,7 +1238,8 @@ namespace WebSocketSharp { | |||||||
|       } |       } | ||||||
|       catch (Exception ex) |       catch (Exception ex) | ||||||
|       { |       { | ||||||
|         onError(ex.Message); |         _logger.Fatal(ex.Message); | ||||||
|  |         error("An exception has occured."); | ||||||
|       } |       } | ||||||
|       finally |       finally | ||||||
|       { |       { | ||||||
| @@ -1250,7 +1269,8 @@ namespace WebSocketSharp { | |||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|           onError(ex.Message); |           _logger.Fatal(ex.Message); | ||||||
|  |           error("An exception has occured."); | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
| @@ -1349,10 +1369,12 @@ namespace WebSocketSharp { | |||||||
|         } |         } | ||||||
|         catch (WebSocketException ex) |         catch (WebSocketException ex) | ||||||
|         { |         { | ||||||
|  |           _logger.Fatal(ex.Message); | ||||||
|           Close(ex.Code, ex.Message); |           Close(ex.Code, ex.Message); | ||||||
|         } |         } | ||||||
|         catch (Exception) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  |           _logger.Fatal(ex.Message); | ||||||
|           Close(CloseStatusCode.ABNORMAL, "An exception has occured."); |           Close(CloseStatusCode.ABNORMAL, "An exception has occured."); | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| @@ -1429,7 +1451,9 @@ namespace WebSocketSharp { | |||||||
|       if (!code.IsCloseStatusCode()) |       if (!code.IsCloseStatusCode()) | ||||||
|       { |       { | ||||||
|         var msg = String.Format("Invalid close status code: {0}", code); |         var msg = String.Format("Invalid close status code: {0}", code); | ||||||
|         onError(msg); |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1462,12 +1486,13 @@ namespace WebSocketSharp { | |||||||
|       try |       try | ||||||
|       { |       { | ||||||
|         if (connect()) |         if (connect()) | ||||||
|           onOpen(); |           open(); | ||||||
|       } |       } | ||||||
|       catch |       catch (Exception ex) | ||||||
|       { |       { | ||||||
|  |         _logger.Fatal(ex.Message); | ||||||
|         var msg = "An exception has occured."; |         var msg = "An exception has occured."; | ||||||
|         onError(msg); |         error(msg); | ||||||
|         Close(CloseStatusCode.ABNORMAL, msg); |         Close(CloseStatusCode.ABNORMAL, msg); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -1511,7 +1536,10 @@ namespace WebSocketSharp { | |||||||
|       var data = Encoding.UTF8.GetBytes(message); |       var data = Encoding.UTF8.GetBytes(message); | ||||||
|       if (data.Length > 125) |       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; |         return false; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1528,7 +1556,10 @@ namespace WebSocketSharp { | |||||||
|     { |     { | ||||||
|       if (data == null) |       if (data == null) | ||||||
|       { |       { | ||||||
|         onError("'data' must not be null."); |         var msg = "'data' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1546,7 +1577,10 @@ namespace WebSocketSharp { | |||||||
|     { |     { | ||||||
|       if (data == null) |       if (data == null) | ||||||
|       { |       { | ||||||
|         onError("'data' must not be null."); |         var msg = "'data' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1564,7 +1598,10 @@ namespace WebSocketSharp { | |||||||
|     { |     { | ||||||
|       if (file == null) |       if (file == null) | ||||||
|       { |       { | ||||||
|         onError("'file' must not be null."); |         var msg = "'file' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1585,7 +1622,10 @@ namespace WebSocketSharp { | |||||||
|     { |     { | ||||||
|       if (data == null) |       if (data == null) | ||||||
|       { |       { | ||||||
|         onError("'data' must not be null."); |         var msg = "'data' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1607,7 +1647,10 @@ namespace WebSocketSharp { | |||||||
|     { |     { | ||||||
|       if (data == null) |       if (data == null) | ||||||
|       { |       { | ||||||
|         onError("'data' must not be null."); |         var msg = "'data' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1629,7 +1672,10 @@ namespace WebSocketSharp { | |||||||
|     { |     { | ||||||
|       if (file == null) |       if (file == null) | ||||||
|       { |       { | ||||||
|         onError("'file' must not be null."); |         var msg = "'file' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1649,7 +1695,10 @@ namespace WebSocketSharp { | |||||||
|  |  | ||||||
|       if (cookie == null) |       if (cookie == null) | ||||||
|       { |       { | ||||||
|         onError("'cookie' must not be null."); |         var msg = "'cookie' must not be null."; | ||||||
|  |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1685,15 +1734,17 @@ namespace WebSocketSharp { | |||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       var error = userName.Length > 0 && (userName.Contains(':') || !userName.IsText()) |       var msg = userName.Length > 0 && (userName.Contains(':') || !userName.IsText()) | ||||||
|                 ? "'userName' contains an invalid character." |               ? "'userName' contains an invalid character." | ||||||
|                 : !password.IsNullOrEmpty() && !password.IsText() |               : !password.IsNullOrEmpty() && !password.IsText() | ||||||
|                   ? "'password' contains an invalid character." |                 ? "'password' contains an invalid character." | ||||||
|                   : String.Empty; |                 : String.Empty; | ||||||
|  |  | ||||||
|       if (error.Length > 0) |       if (msg.Length > 0) | ||||||
|       { |       { | ||||||
|         onError(error); |         _logger.Error(msg); | ||||||
|  |         error(msg); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -126,6 +126,9 @@ | |||||||
|     <Compile Include="AuthenticationChallenge.cs" /> |     <Compile Include="AuthenticationChallenge.cs" /> | ||||||
|     <Compile Include="AuthenticationResponse.cs" /> |     <Compile Include="AuthenticationResponse.cs" /> | ||||||
|     <Compile Include="WsCredential.cs" /> |     <Compile Include="WsCredential.cs" /> | ||||||
|  |     <Compile Include="LogData.cs" /> | ||||||
|  |     <Compile Include="LogLevel.cs" /> | ||||||
|  |     <Compile Include="Logger.cs" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user