diff --git a/websocket-sharp/Server/WebSocketService.cs b/websocket-sharp/Server/WebSocketService.cs index 04c15e77..92633f12 100644 --- a/websocket-sharp/Server/WebSocketService.cs +++ b/websocket-sharp/Server/WebSocketService.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.IO; using System.Text; using System.Threading; using WebSocketSharp.Net; @@ -225,6 +226,11 @@ namespace WebSocketSharp.Server IsBound = true; } + internal void Start () + { + _websocket.Connect (); + } + #endregion #region Protected Methods @@ -235,7 +241,7 @@ namespace WebSocketSharp.Server /// /// A that contains an error message. /// - protected virtual void Error (string message) + protected void Error (string message) { if (!message.IsNullOrEmpty ()) OnError (new ErrorEventArgs (message)); @@ -282,33 +288,6 @@ namespace WebSocketSharp.Server { } - /// - /// Validates the cookies used in the WebSocket connection request. - /// - /// - /// This method is called when the inner validates - /// the WebSocket connection request. - /// - /// - /// true if the cookies is valid; otherwise, false. - /// The default returns true. - /// - /// - /// A that contains a collection of the HTTP Cookies - /// to validate. - /// - /// - /// A that receives the HTTP Cookies to send to the client. - /// - protected virtual bool ValidateCookies (CookieCollection request, CookieCollection response) - { - return true; - } - - #endregion - - #region Public Methods - /// /// Sends a Ping to the client of the current instance. /// @@ -316,7 +295,7 @@ namespace WebSocketSharp.Server /// true if the current instance receives a Pong /// from the client in a time; otherwise, false. /// - public bool Ping () + protected bool Ping () { return IsBound ? _websocket.Ping () @@ -334,7 +313,7 @@ namespace WebSocketSharp.Server /// /// A that contains a message to send. /// - public bool Ping (string message) + protected bool Ping (string message) { return IsBound ? _websocket.Ping (message) @@ -345,75 +324,172 @@ namespace WebSocketSharp.Server /// Sends a binary to the client of the current /// instance. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// An array of that contains a binary data to send. /// - public virtual void Send (byte [] data) + protected void Send (byte [] data) { if (IsBound) - _websocket.Send (data); + _websocket.Send (data, null); } /// /// Sends a text to the client of the current /// instance. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// A that contains a text data to send. /// - public virtual void Send (string data) + protected void Send (string data) { if (IsBound) - _websocket.Send (data); + _websocket.Send (data, null); + } + + /// + /// Sends a binary data from the specified to + /// the client of the current instance. + /// + /// + /// This method does not wait for the send to be complete. + /// + /// + /// A from which contains a binary data to send. + /// + protected void Send (FileInfo file) + { + if (IsBound) + _websocket.Send (file, null); } /// /// Sends a binary to the client of the current - /// instance asynchronously. + /// instance. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// An array of that contains a binary data to send. /// /// - /// An delegate that references the method(s) called when - /// the asynchronous operation completes. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is + /// complete successfully; otherwise, false. /// - public virtual void SendAsync (byte [] data, Action completed) + protected void Send (byte [] data, Action completed) { if (IsBound) - _websocket.SendAsync (data, completed); + _websocket.Send (data, completed); } /// /// Sends a text to the client of the current - /// instance asynchronously. + /// instance. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// A that contains a text data to send. /// /// - /// An delegate that references the method(s) called when - /// the asynchronous operation completes. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is + /// complete successfully; otherwise, false. + /// + protected void Send (string data, Action completed) + { + if (IsBound) + _websocket.Send (data, completed); + } + + /// + /// Sends a binary data from the specified to + /// the client of the current instance. + /// + /// + /// This method does not wait for the send to be complete. + /// + /// + /// A from which contains a binary data to send. + /// + /// + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is + /// complete successfully; otherwise, false. /// - public virtual void SendAsync (string data, Action completed) + protected void Send (FileInfo file, Action completed) { if (IsBound) - _websocket.SendAsync (data, completed); + _websocket.Send (file, completed); } /// - /// Starts the current instance. + /// Sends a binary data from the specified to + /// the client of the current instance. /// - public void Start () + /// + /// This method does not wait for the send to be complete. + /// + /// + /// A object from which contains a binary data to send. + /// + /// + /// An that contains the number of bytes to send. + /// + /// + /// true if is disposed after a binary data read; + /// otherwise, false. + /// + protected void Send (Stream stream, int length, bool dispose) + { + if (IsBound) + _websocket.Send (stream, length, dispose, null); + } + + /// + /// Sends a binary data from the specified to + /// the client of the current instance. + /// + /// + /// This method does not wait for the send to be complete. + /// + /// + /// A object from which contains a binary data to send. + /// + /// + /// An that contains the number of bytes to send. + /// + /// + /// true if is disposed after a binary data read; + /// otherwise, false. + /// + /// + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is + /// complete successfully; otherwise, false. + /// + protected void Send (Stream stream, int length, bool dispose, Action completed) { if (IsBound) - _websocket.Connect (); + _websocket.Send (stream, length, dispose, completed); } /// /// Stops the current instance. /// - public void Stop () + protected void Stop () { if (IsBound) _websocket.Close (); @@ -429,7 +505,7 @@ namespace WebSocketSharp.Server /// /// A that contains the reason for stop. /// - public void Stop (ushort code, string reason) + protected void Stop (ushort code, string reason) { if (IsBound) _websocket.Close (code, reason); @@ -446,12 +522,35 @@ namespace WebSocketSharp.Server /// /// A that contains the reason for stop. /// - public void Stop (CloseStatusCode code, string reason) + protected void Stop (CloseStatusCode code, string reason) { if (IsBound) _websocket.Close (code, reason); } + /// + /// Validates the cookies used in the WebSocket connection request. + /// + /// + /// This method is called when the inner validates + /// the WebSocket connection request. + /// + /// + /// true if the cookies is valid; otherwise, false. + /// The default returns true. + /// + /// + /// A that contains a collection of the HTTP Cookies + /// to validate. + /// + /// + /// A that receives the HTTP Cookies to send to the client. + /// + protected virtual bool ValidateCookies (CookieCollection request, CookieCollection response) + { + return true; + } + #endregion } } diff --git a/websocket-sharp/Server/WebSocketSessionManager.cs b/websocket-sharp/Server/WebSocketSessionManager.cs index ac4f5afb..d8273d80 100644 --- a/websocket-sharp/Server/WebSocketSessionManager.cs +++ b/websocket-sharp/Server/WebSocketSessionManager.cs @@ -649,14 +649,14 @@ namespace WebSocketSharp.Server return; } - WebSocketService service; - if (!TryGetServiceInstance (id, out service)) + WebSocketService session; + if (!TryGetServiceInstance (id, out session)) { _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id); return; } - service.Send (data); + session.Context.WebSocket.Send (data, null); } /// @@ -678,14 +678,14 @@ namespace WebSocketSharp.Server return; } - WebSocketService service; - if (!TryGetServiceInstance (id, out service)) + WebSocketService session; + if (!TryGetServiceInstance (id, out session)) { _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id); return; } - service.Send (data); + session.Context.WebSocket.Send (data, null); } /// diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index a8c075d9..d0765bd4 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -1028,65 +1028,72 @@ namespace WebSocketSharp return _stream.Write (frame.ToByteArray ()); } - private void send (Opcode opcode, byte [] data) + private bool send (Opcode opcode, byte [] data) { lock (_forSend) { + var sent = false; try { - var comped = false; + var compressed = false; if (_compression != CompressionMethod.NONE) { data = data.Compress (_compression); - comped = true; + compressed = true; } - - send (WsFrame.CreateFrame ( - Fin.FINAL, opcode, _client ? Mask.MASK : Mask.UNMASK, data, comped)); + + sent = send (WsFrame.CreateFrame ( + Fin.FINAL, opcode, _client ? Mask.MASK : Mask.UNMASK, data, compressed)); } catch (Exception ex) { _logger.Fatal (ex.ToString ()); error ("An exception has occured."); } + + return sent; } } - private void send (Opcode opcode, Stream stream) + private bool send (Opcode opcode, Stream stream) { lock (_forSend) { - var comp = stream; - var comped = false; + var sent = false; + + var src = stream; + var compressed = false; try { if (_compression != CompressionMethod.NONE) { - comp = stream.Compress (_compression); - comped = true; + stream = stream.Compress (_compression); + compressed = true; } - sendFragmented (opcode, comp, _client ? Mask.MASK : Mask.UNMASK, comped); + sent = sendFragmented (opcode, stream, _client ? Mask.MASK : Mask.UNMASK, compressed); } catch (Exception ex) { _logger.Fatal (ex.ToString ()); error ("An exception has occured."); } finally { - if (comped) - comp.Dispose (); + if (compressed) + stream.Dispose (); - stream.Dispose (); + src.Dispose (); } + + return sent; } } - private void sendAsync (Opcode opcode, byte [] data, Action completed) + private void send (Opcode opcode, byte [] data, Action completed) { - Action sender = send; + Func sender = send; AsyncCallback callback = ar => { try { - sender.EndInvoke (ar); + var sent = sender.EndInvoke (ar); if (completed != null) - completed (); + completed (sent); } catch (Exception ex) { @@ -1098,15 +1105,15 @@ namespace WebSocketSharp sender.BeginInvoke (opcode, data, callback, null); } - private void sendAsync (Opcode opcode, Stream stream, Action completed) + private void send (Opcode opcode, Stream stream, Action completed) { - Action sender = send; + Func sender = send; AsyncCallback callback = ar => { try { - sender.EndInvoke (ar); + var sent = sender.EndInvoke (ar); if (completed != null) - completed (); + completed (sent); } catch (Exception ex) { @@ -1585,127 +1592,62 @@ namespace WebSocketSharp /// /// Sends a binary using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// An array of that contains a binary data to send. /// public void Send (byte[] data) { - var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData (); - if (msg != null) - { - _logger.Error (msg); - error (msg); - - return; - } - - if (data.LongLength <= FragmentLength) - send (Opcode.BINARY, data); - else - send (Opcode.BINARY, new MemoryStream (data)); + Send (data, null); } /// /// Sends a text using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// A that contains a text data to send. /// public void Send (string data) { - var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData (); - if (msg != null) - { - _logger.Error (msg); - error (msg); - - return; - } - - var rawData = Encoding.UTF8.GetBytes (data); - if (rawData.LongLength <= FragmentLength) - send (Opcode.TEXT, rawData); - else - send (Opcode.TEXT, new MemoryStream (rawData)); + Send (data, null); } /// - /// Sends a binary data using the WebSocket connection. + /// Sends a binary data from the specified + /// using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// /// - /// A that contains a binary data to send. + /// A from which contains a binary data to send. /// public void Send (FileInfo file) { - var msg = _readyState.CheckIfOpen () ?? - (file == null ? "'file' must not be null." : null); - - if (msg != null) - { - _logger.Error (msg); - error (msg); - - return; - } - - send (Opcode.BINARY, file.OpenRead ()); - } - - /// - /// Sends a binary data from the specified using the WebSocket connection. - /// - /// - /// A object from which contains a binary data to send. - /// - /// - /// An that contains the number of bytes to send. - /// - /// - /// true if is disposed after a binary data read; - /// otherwise, false. - /// - public void Send (Stream stream, int length, bool dispose) - { - byte [] data = null; - int readLen = 0; - var msg = _readyState.CheckIfOpen () ?? - stream.CheckIfCanRead () ?? - (length < 1 ? "'length' must be greater than 0." : null) ?? - ((readLen = (data = stream.ReadBytes (length)).Length) == 0 - ? "A data cannot be read from 'stream'." : null); - - if (msg != null) - { - _logger.Error (msg); - error (msg); - - return; - } - - if (readLen != length) - _logger.Warn (String.Format ( - "A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}", length, readLen)); - - if (dispose) - stream.Dispose (); - - if (readLen <= FragmentLength) - send (Opcode.BINARY, data); - else - send (Opcode.BINARY, new MemoryStream (data)); + Send (file, null); } /// - /// Sends a binary asynchronously using the WebSocket connection. + /// Sends a binary using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// An array of that contains a binary data to send. /// /// - /// An delegate that references the method(s) called when - /// the asynchronous operation completes. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is complete + /// successfully; otherwise, false. /// - public void SendAsync (byte [] data, Action completed) + public void Send (byte [] data, Action completed) { var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData (); if (msg != null) @@ -1717,22 +1659,27 @@ namespace WebSocketSharp } if (data.LongLength <= FragmentLength) - sendAsync (Opcode.BINARY, data, completed); + send (Opcode.BINARY, data, completed); else - sendAsync (Opcode.BINARY, new MemoryStream (data), completed); + send (Opcode.BINARY, new MemoryStream (data), completed); } /// - /// Sends a text asynchronously using the WebSocket connection. + /// Sends a text using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// /// /// A that contains a text data to send. /// /// - /// An delegate that references the method(s) called when - /// the asynchronous operation completes. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is complete + /// successfully; otherwise, false. /// - public void SendAsync (string data, Action completed) + public void Send (string data, Action completed) { var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData (); if (msg != null) @@ -1745,22 +1692,28 @@ namespace WebSocketSharp var rawData = Encoding.UTF8.GetBytes (data); if (rawData.LongLength <= FragmentLength) - sendAsync (Opcode.TEXT, rawData, completed); + send (Opcode.TEXT, rawData, completed); else - sendAsync (Opcode.TEXT, new MemoryStream (rawData), completed); + send (Opcode.TEXT, new MemoryStream (rawData), completed); } /// - /// Sends a binary data asynchronously using the WebSocket connection. + /// Sends a binary data from the specified + /// using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// /// - /// A that contains a binary data to send. + /// A from which contains a binary data to send. /// /// - /// An delegate that references the method(s) called when - /// the asynchronous operation completes. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is complete + /// successfully; otherwise, false. /// - public void SendAsync (FileInfo file, Action completed) + public void Send (FileInfo file, Action completed) { var msg = _readyState.CheckIfOpen () ?? (file == null ? "'file' must not be null." : null); @@ -1773,13 +1726,38 @@ namespace WebSocketSharp return; } - sendAsync (Opcode.BINARY, file.OpenRead (), completed); + send (Opcode.BINARY, file.OpenRead (), completed); } /// - /// Sends a binary data asynchronously from the specified + /// Sends a binary data from the specified /// using the WebSocket connection. /// + /// + /// This method does not wait for the send to be complete. + /// + /// + /// A object from which contains a binary data to send. + /// + /// + /// An that contains the number of bytes to send. + /// + /// + /// true if is disposed after a binary data read; + /// otherwise, false. + /// + public void Send (Stream stream, int length, bool dispose) + { + Send (stream, length, dispose, null); + } + + /// + /// Sends a binary data from the specified + /// using the WebSocket connection. + /// + /// + /// This method does not wait for the send to be complete. + /// /// /// A object from which contains a binary data to send. /// @@ -1791,10 +1769,12 @@ namespace WebSocketSharp /// otherwise, false. /// /// - /// An delegate that references the method(s) called when - /// the asynchronous operation completes. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. + /// A passed to this delegate is true if the send is complete + /// successfully; otherwise, false. /// - public void SendAsync (Stream stream, int length, bool dispose, Action completed) + public void Send (Stream stream, int length, bool dispose, Action completed) { var msg = _readyState.CheckIfOpen () ?? stream.CheckIfCanRead () ?? @@ -1829,10 +1809,12 @@ namespace WebSocketSharp if (dispose) stream.Dispose (); - if (readLen <= FragmentLength) - sendAsync (Opcode.BINARY, data, completed); - else - sendAsync (Opcode.BINARY, new MemoryStream (data), completed); + var sent = readLen <= FragmentLength + ? send (Opcode.BINARY, data) + : send (Opcode.BINARY, new MemoryStream (data)); + + if (completed != null) + completed (sent); }; Action exception = ex =>