diff --git a/websocket-sharp/CloseEventArgs.cs b/websocket-sharp/CloseEventArgs.cs index 67cbdea5..cec627a4 100644 --- a/websocket-sharp/CloseEventArgs.cs +++ b/websocket-sharp/CloseEventArgs.cs @@ -110,7 +110,7 @@ namespace WebSocketSharp private static ushort getCodeFrom (byte [] data) { return data.Length > 1 - ? data.SubArray (0, 2).To (ByteOrder.BIG) + ? data.SubArray (0, 2).ToUInt16 (ByteOrder.BIG) : (ushort) 0; } diff --git a/websocket-sharp/Ext.cs b/websocket-sharp/Ext.cs index 1725c4cb..36914e5c 100644 --- a/websocket-sharp/Ext.cs +++ b/websocket-sharp/Ext.cs @@ -138,6 +138,37 @@ namespace WebSocketSharp } } + private static byte [] readBytes (this Stream stream, byte [] buffer, int offset, int length) + { + var readLen = stream.Read (buffer, offset, length); + if (readLen < 1) + return buffer.SubArray (0, offset); + + var tmpLen = 0; + while (readLen < length) + { + tmpLen = stream.Read (buffer, offset + readLen, length - readLen); + if (tmpLen < 1) + break; + + readLen += tmpLen; + } + + return readLen < length + ? buffer.SubArray (0, offset + readLen) + : buffer; + } + + private static bool readBytes ( + this Stream stream, byte [] buffer, int offset, int length, Stream dest) + { + var bytes = stream.readBytes (buffer, offset, length); + var len = bytes.Length; + dest.Write (bytes, 0, len); + + return len == offset + length; + } + private static void times (this ulong n, Action act) { for (ulong i = 0; i < n; i++) @@ -152,7 +183,7 @@ namespace WebSocketSharp { using (var buffer = new MemoryStream ()) { - var tmp = code.ToByteArray (ByteOrder.BIG); + var tmp = code.ToByteArrayInternally (ByteOrder.BIG); buffer.Write (tmp, 0, 2); if (reason != null && reason.Length > 0) { @@ -467,76 +498,63 @@ namespace WebSocketSharp : String.Format ("\"{0}\"", value.Replace ("\"", "\\\"")); } - internal static byte [] ReadBytesInternal (this Stream stream, int length) + internal static byte [] ReadBytes (this Stream stream, int length) { - var buffer = new byte [length]; - var readLen = stream.Read (buffer, 0, length); - if (readLen <= 0) - return new byte []{}; - - var tmpLen = 0; - while (readLen < length) - { - tmpLen = stream.Read (buffer, readLen, length - readLen); - if (tmpLen <= 0) - break; - - readLen += tmpLen; - } - - return readLen == length - ? buffer - : buffer.SubArray (0, readLen); + return stream.readBytes (new byte [length], 0, length); } - internal static byte [] ReadBytesInternal (this Stream stream, long length, int bufferLength) + internal static byte [] ReadBytes (this Stream stream, long length, int bufferLength) { - var count = length / bufferLength; - var rem = length % bufferLength; - using (var readData = new MemoryStream ()) + using (var result = new MemoryStream ()) { - var readLen = 0; - var bufferLen = 0; - var tmpLen = 0; - Func read = buffer => - { - bufferLen = buffer.Length; - readLen = stream.Read (buffer, 0, bufferLen); - if (readLen <= 0) - return false; + var count = length / bufferLength; + var rem = (int) (length % bufferLength); - while (readLen < bufferLen) - { - tmpLen = stream.Read (buffer, readLen, bufferLen - readLen); - if (tmpLen <= 0) - break; - - readLen += tmpLen; - } - - readData.Write (buffer, 0, readLen); - return readLen == bufferLen; - }; - - var readBuffer = new byte [bufferLength]; - var readEnd = false; + var buffer = new byte [bufferLength]; + var end = false; for (long i = 0; i < count; i++) { - if (!read (readBuffer)) + if (!stream.readBytes (buffer, 0, bufferLength, result)) { - readEnd = true; + end = true; break; } } - if (!readEnd && rem > 0) - read (new byte [rem]); + if (!end && rem > 0) + stream.readBytes (new byte [rem], 0, rem, result); - readData.Close (); - return readData.ToArray (); + result.Close (); + return result.ToArray (); } } + internal static void ReadBytesAsync ( + this Stream stream, int length, Action completed, Action error) + { + var buffer = new byte [length]; + AsyncCallback callback = ar => + { + try { + var readLen = stream.EndRead (ar); + var result = readLen < 1 + ? new byte []{} + : readLen < length + ? stream.readBytes (buffer, readLen, length - readLen) + : buffer; + + if (completed != null) + completed (result); + } + catch (Exception ex) { + if (error != null) + error (ex); + } + }; + + stream.BeginRead (buffer, 0, length, callback, null); + } + internal static string RemovePrefix (this string value, params string [] prefixes) { int i = 0; @@ -607,6 +625,22 @@ namespace WebSocketSharp } } + internal static byte [] ToByteArrayInternally (this ushort value, ByteOrder order) + { + var buffer = BitConverter.GetBytes (value); + return order.IsHostOrder () + ? buffer + : buffer.Reverse ().ToArray (); + } + + internal static byte [] ToByteArrayInternally (this ulong value, ByteOrder order) + { + var buffer = BitConverter.GetBytes (value); + return order.IsHostOrder () + ? buffer + : buffer.Reverse ().ToArray (); + } + internal static string ToCompressionExtension (this CompressionMethod method) { return method != CompressionMethod.NONE @@ -623,6 +657,16 @@ namespace WebSocketSharp return CompressionMethod.NONE; } + internal static ushort ToUInt16 (this byte [] src, ByteOrder srcOrder) + { + return BitConverter.ToUInt16 (src.ToHostOrder (srcOrder), 0); + } + + internal static ulong ToUInt64 (this byte [] src, ByteOrder srcOrder) + { + return BitConverter.ToUInt64 (src.ToHostOrder (srcOrder), 0); + } + internal static string TrimEndSlash (this string value) { value = value.TrimEnd ('/'); @@ -1148,48 +1192,6 @@ namespace WebSocketSharp return uriString.Substring (0, p).IsPredefinedScheme (); } - /// - /// Reads a block of bytes from the specified - /// and returns the read data in an array of . - /// - /// - /// An array of that receives the read data. - /// - /// - /// A that contains the data to read. - /// - /// - /// An that contains the number of bytes to read. - /// - public static byte [] ReadBytes (this Stream stream, int length) - { - return stream == null || length < 1 - ? new byte []{} - : stream.ReadBytesInternal (length); - } - - /// - /// Reads a block of bytes from the specified - /// and returns the read data in an array of . - /// - /// - /// An array of that receives the read data. - /// - /// - /// A that contains the data to read. - /// - /// - /// A that contains the number of bytes to read. - /// - public static byte [] ReadBytes (this Stream stream, long length) - { - return stream == null || length < 1 - ? new byte []{} - : length > 1024 - ? stream.ReadBytesInternal (length, 1024) - : stream.ReadBytesInternal ((int) length); - } - /// /// Retrieves a sub-array from the specified . /// A sub-array starts at the specified element position. @@ -1212,13 +1214,13 @@ namespace WebSocketSharp public static T [] SubArray (this T [] array, int startIndex, int length) { if (array == null || array.Length == 0) - return new T [] {}; + return new T []{}; if (startIndex < 0 || length <= 0) - return new T [] {}; + return new T []{}; if (startIndex + length > array.Length) - return new T [] {}; + return new T []{}; if (startIndex == 0 && array.Length == length) return array; diff --git a/websocket-sharp/PayloadData.cs b/websocket-sharp/PayloadData.cs index 2c4034b3..8816fe0c 100644 --- a/websocket-sharp/PayloadData.cs +++ b/websocket-sharp/PayloadData.cs @@ -88,7 +88,7 @@ namespace WebSocketSharp internal bool ContainsReservedCloseStatusCode { get { return ApplicationData.Length > 1 - ? ApplicationData.SubArray (0, 2).To (ByteOrder.BIG).IsReserved () + ? ApplicationData.SubArray (0, 2).ToUInt16 (ByteOrder.BIG).IsReserved () : false; } } diff --git a/websocket-sharp/Server/HttpServer.cs b/websocket-sharp/Server/HttpServer.cs index 0d2c18c1..706b08fc 100644 --- a/websocket-sharp/Server/HttpServer.cs +++ b/websocket-sharp/Server/HttpServer.cs @@ -330,7 +330,8 @@ namespace WebSocketSharp.Server } _listening = false; - _serviceHosts.Stop (((ushort) CloseStatusCode.SERVER_ERROR).ToByteArray (ByteOrder.BIG), true); + _serviceHosts.Stop ( + ((ushort) CloseStatusCode.SERVER_ERROR).ToByteArrayInternally (ByteOrder.BIG), true); _listener.Abort (); _state = ServerState.STOP; diff --git a/websocket-sharp/Server/WebSocketServer.cs b/websocket-sharp/Server/WebSocketServer.cs index 05e2a2c5..e39dbca9 100644 --- a/websocket-sharp/Server/WebSocketServer.cs +++ b/websocket-sharp/Server/WebSocketServer.cs @@ -208,7 +208,8 @@ namespace WebSocketSharp.Server } StopListener (); - _serviceHosts.Stop (((ushort) CloseStatusCode.SERVER_ERROR).ToByteArray (ByteOrder.BIG), true); + _serviceHosts.Stop ( + ((ushort) CloseStatusCode.SERVER_ERROR).ToByteArrayInternally (ByteOrder.BIG), true); _state = ServerState.STOP; } diff --git a/websocket-sharp/Server/WebSocketServiceHost.cs b/websocket-sharp/Server/WebSocketServiceHost.cs index 4f49786a..101f40a0 100644 --- a/websocket-sharp/Server/WebSocketServiceHost.cs +++ b/websocket-sharp/Server/WebSocketServiceHost.cs @@ -467,7 +467,8 @@ namespace WebSocketSharp.Server } StopListener (); - _sessions.Stop (((ushort) CloseStatusCode.SERVER_ERROR).ToByteArray (ByteOrder.BIG), true); + _sessions.Stop ( + ((ushort) CloseStatusCode.SERVER_ERROR).ToByteArrayInternally (ByteOrder.BIG), true); _state = ServerState.STOP; } diff --git a/websocket-sharp/Server/WebSocketServiceHostManager.cs b/websocket-sharp/Server/WebSocketServiceHostManager.cs index fb8cee71..922b1526 100644 --- a/websocket-sharp/Server/WebSocketServiceHostManager.cs +++ b/websocket-sharp/Server/WebSocketServiceHostManager.cs @@ -305,7 +305,7 @@ namespace WebSocketSharp.Server } if (host.Sessions.State == ServerState.START) - host.Sessions.Stop (((ushort) CloseStatusCode.AWAY).ToByteArray (ByteOrder.BIG), true); + host.Sessions.Stop (((ushort) CloseStatusCode.AWAY).ToByteArrayInternally (ByteOrder.BIG), true); return true; } diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 9e0699cb..a8c075d9 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -1420,7 +1420,7 @@ namespace WebSocketSharp } var send = _readyState == WebSocketState.OPEN && !code.IsReserved (); - close (new PayloadData (code.ToByteArray (ByteOrder.BIG)), send, true); + close (new PayloadData (code.ToByteArrayInternally (ByteOrder.BIG)), send, true); } /// @@ -1433,7 +1433,7 @@ namespace WebSocketSharp public void Close (CloseStatusCode code) { var send = _readyState == WebSocketState.OPEN && !code.IsReserved (); - close (new PayloadData (((ushort) code).ToByteArray (ByteOrder.BIG)), send, true); + close (new PayloadData (((ushort) code).ToByteArrayInternally (ByteOrder.BIG)), send, true); } /// @@ -1671,7 +1671,7 @@ namespace WebSocketSharp var msg = _readyState.CheckIfOpen () ?? stream.CheckIfCanRead () ?? (length < 1 ? "'length' must be greater than 0." : null) ?? - ((readLen = (data = stream.ReadBytesInternal (length)).Length) == 0 + ((readLen = (data = stream.ReadBytes (length)).Length) == 0 ? "A data cannot be read from 'stream'." : null); if (msg != null) @@ -1796,13 +1796,9 @@ namespace WebSocketSharp /// public void SendAsync (Stream stream, int length, bool dispose, Action completed) { - byte [] data = null; - int readLen = 0; var msg = _readyState.CheckIfOpen () ?? stream.CheckIfCanRead () ?? - (length < 1 ? "'length' must be greater than 0." : null) ?? - ((readLen = (data = stream.ReadBytesInternal (length)).Length) == 0 - ? "A data cannot be read from 'stream'." : null); + (length < 1 ? "'length' must be greater than 0." : null); if (msg != null) { @@ -1812,17 +1808,40 @@ namespace WebSocketSharp return; } - if (readLen != length) - _logger.Warn (String.Format ( - "A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}", length, readLen)); + Action result = data => + { + var readLen = data.Length; + if (readLen == 0) + { + var err = "A data cannot be read from 'stream'."; + _logger.Error (err); + error (err); - if (dispose) - stream.Dispose (); + return; + } - if (readLen <= FragmentLength) - sendAsync (Opcode.BINARY, data, completed); - else - sendAsync (Opcode.BINARY, new MemoryStream (data), completed); + 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) + sendAsync (Opcode.BINARY, data, completed); + else + sendAsync (Opcode.BINARY, new MemoryStream (data), completed); + }; + + Action exception = ex => + { + _logger.Fatal (ex.ToString ()); + error ("An exception has occured."); + }; + + stream.ReadBytesAsync (length, result, exception); } /// diff --git a/websocket-sharp/WsFrame.cs b/websocket-sharp/WsFrame.cs index 8d9e937f..c91f184a 100644 --- a/websocket-sharp/WsFrame.cs +++ b/websocket-sharp/WsFrame.cs @@ -87,8 +87,8 @@ namespace WebSocketSharp ExtPayloadLen = payloadLen < 126 ? new byte []{} : payloadLen == 126 - ? ((ushort) dataLen).ToByteArray (ByteOrder.BIG) - : dataLen.ToByteArray (ByteOrder.BIG); + ? ((ushort) dataLen).ToByteArrayInternally (ByteOrder.BIG) + : dataLen.ToByteArrayInternally (ByteOrder.BIG); /* MaskingKey */ @@ -399,7 +399,7 @@ namespace WebSocketSharp : 8; var extPayloadLen = extLen > 0 - ? stream.ReadBytesInternal (extLen) + ? stream.ReadBytes (extLen) : new byte []{}; if (extLen > 0 && extPayloadLen.Length != extLen) @@ -414,7 +414,7 @@ namespace WebSocketSharp var masked = mask == Mask.MASK; var maskingKey = masked - ? stream.ReadBytesInternal (4) + ? stream.ReadBytes (4) : new byte []{}; if (masked && maskingKey.Length != 4) @@ -430,8 +430,8 @@ namespace WebSocketSharp ulong dataLen = payloadLen < 126 ? payloadLen : payloadLen == 126 - ? extPayloadLen.To (ByteOrder.BIG) - : extPayloadLen.To (ByteOrder.BIG); + ? extPayloadLen.ToUInt16 (ByteOrder.BIG) + : extPayloadLen.ToUInt64 (ByteOrder.BIG); byte [] data = null; if (dataLen > 0) @@ -442,9 +442,9 @@ namespace WebSocketSharp return CreateCloseFrame (Mask.UNMASK, code, code.GetMessage ()); } - data = dataLen > 1024 - ? stream.ReadBytesInternal ((long) dataLen, 1024) - : stream.ReadBytesInternal ((int) dataLen); + data = payloadLen > 126 + ? stream.ReadBytes ((long) dataLen, 1024) + : stream.ReadBytes ((int) dataLen); if (data.LongLength != (long) dataLen) return CreateCloseFrame ( @@ -473,9 +473,9 @@ namespace WebSocketSharp { var len = frame.ExtPayloadLen.Length; var extPayloadLen = len == 2 - ? frame.ExtPayloadLen.To (ByteOrder.BIG).ToString () + ? frame.ExtPayloadLen.ToUInt16 (ByteOrder.BIG).ToString () : len == 8 - ? frame.ExtPayloadLen.To (ByteOrder.BIG).ToString () + ? frame.ExtPayloadLen.ToUInt64 (ByteOrder.BIG).ToString () : String.Empty; var masked = frame.IsMasked; @@ -584,7 +584,7 @@ namespace WebSocketSharp WsFrame frame = null; try { - var header = stream.ReadBytesInternal (2); + var header = stream.ReadBytes (2); frame = header.Length == 2 ? parse (header, stream, unmask) : CreateCloseFrame ( @@ -672,7 +672,7 @@ namespace WebSocketSharp header = (header << 4) + (int) Opcode; header = (header << 1) + (int) Mask; header = (header << 7) + (int) PayloadLen; - buffer.Write (((ushort) header).ToByteArray (ByteOrder.BIG), 0, 2); + buffer.Write (((ushort) header).ToByteArrayInternally (ByteOrder.BIG), 0, 2); if (PayloadLen > 125) buffer.Write (ExtPayloadLen, 0, ExtPayloadLen.Length);