diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 44a600a8..53b361b5 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -90,7 +90,7 @@ namespace WebSocketSharp private string _origin; private bool _preAuth; private string _protocol; - private string [] _protocols; + private string[] _protocols; private NetworkCredential _proxyCredentials; private Uri _proxyUri; private volatile WebSocketState _readyState; @@ -168,7 +168,7 @@ namespace WebSocketSharp /// /// is . /// - public WebSocket (string url, params string [] protocols) + public WebSocket (string url, params string[] protocols) { if (url == null) throw new ArgumentNullException ("url"); @@ -261,10 +261,9 @@ namespace WebSocketSharp /// public IEnumerable Cookies { get { - lock (_cookies.SyncRoot) { + lock (_cookies.SyncRoot) foreach (Cookie cookie in _cookies) yield return cookie; - } } } @@ -548,7 +547,7 @@ namespace WebSocketSharp if (!concatenateFragmentsInto (concatenated)) return false; - byte [] data; + byte[] data; if (_compression != CompressionMethod.None) { data = concatenated.DecompressToArray (_compression); } @@ -602,17 +601,17 @@ namespace WebSocketSharp !_context.SecWebSocketProtocols.Contains (protocol => protocol == _protocol)) _protocol = null; - var extensions = _context.Headers ["Sec-WebSocket-Extensions"]; + var extensions = _context.Headers["Sec-WebSocket-Extensions"]; if (extensions != null && extensions.Length > 0) acceptSecWebSocketExtensionsHeader (extensions); - return send (createHandshakeResponse ()); + return sendHandshakeResponse (createHandshakeResponse ()); } private bool acceptPingFrame (WebSocketFrame frame) { var mask = _client ? Mask.Mask : Mask.Unmask; - if (send (WebSocketFrame.CreatePongFrame (mask, frame.PayloadData))) + if (sendWebSocketFrame (WebSocketFrame.CreatePongFrame (mask, frame.PayloadData))) _logger.Trace ("Returned a Pong."); return true; @@ -687,9 +686,9 @@ namespace WebSocketSharp ? "Invalid request url." : !context.IsWebSocketRequest ? "Not WebSocket connection request." - : !validateSecWebSocketKeyHeader (headers ["Sec-WebSocket-Key"]) + : !validateSecWebSocketKeyHeader (headers["Sec-WebSocket-Key"]) ? "Invalid Sec-WebSocket-Key header." - : !validateSecWebSocketVersionClientHeader (headers ["Sec-WebSocket-Version"]) + : !validateSecWebSocketVersionClientHeader (headers["Sec-WebSocket-Version"]) ? "Invalid Sec-WebSocket-Version header." : CustomHandshakeRequestChecker (context); } @@ -700,16 +699,16 @@ namespace WebSocketSharp var headers = response.Headers; return response.IsUnauthorized ? String.Format ( - "HTTP {0} authorization is required.", response.AuthenticationChallenge.Scheme) + "HTTP {0} authentication is required.", response.AuthenticationChallenge.Scheme) : !response.IsWebSocketResponse ? "Not WebSocket connection response." - : !validateSecWebSocketAcceptHeader (headers ["Sec-WebSocket-Accept"]) + : !validateSecWebSocketAcceptHeader (headers["Sec-WebSocket-Accept"]) ? "Invalid Sec-WebSocket-Accept header." - : !validateSecWebSocketProtocolHeader (headers ["Sec-WebSocket-Protocol"]) + : !validateSecWebSocketProtocolHeader (headers["Sec-WebSocket-Protocol"]) ? "Invalid Sec-WebSocket-Protocol header." - : !validateSecWebSocketExtensionsHeader (headers ["Sec-WebSocket-Extensions"]) + : !validateSecWebSocketExtensionsHeader (headers["Sec-WebSocket-Extensions"]) ? "Invalid Sec-WebSocket-Extensions header." - : !validateSecWebSocketVersionServerHeader (headers ["Sec-WebSocket-Version"]) + : !validateSecWebSocketVersionServerHeader (headers["Sec-WebSocket-Version"]) ? "Invalid Sec-WebSocket-Version header." : null; } @@ -776,11 +775,12 @@ namespace WebSocketSharp } } - private bool closeHandshake (byte [] frame, int timeout, Action release) + private bool closeHandshake (byte[] data, int millisecondsTimeout, Action release) { - var sent = frame != null && _stream.WriteBytes (frame); - var received = timeout == 0 || - (sent && _exitReceiving != null && _exitReceiving.WaitOne (timeout)); + var sent = data != null && _stream.WriteBytes (data); + var received = + millisecondsTimeout == 0 || + (sent && _exitReceiving != null && _exitReceiving.WaitOne (millisecondsTimeout)); release (); if (_receivePong != null) { @@ -904,7 +904,7 @@ namespace WebSocketSharp private HttpResponse createHandshakeCloseResponse (HttpStatusCode code) { var res = HttpResponse.CreateCloseResponse (code); - res.Headers ["Sec-WebSocket-Version"] = _version; + res.Headers["Sec-WebSocket-Version"] = _version; return res; } @@ -916,18 +916,18 @@ namespace WebSocketSharp var headers = req.Headers; if (!_origin.IsNullOrEmpty ()) - headers ["Origin"] = _origin; + headers["Origin"] = _origin; - headers ["Sec-WebSocket-Key"] = _base64Key; + headers["Sec-WebSocket-Key"] = _base64Key; if (_protocols != null) - headers ["Sec-WebSocket-Protocol"] = _protocols.ToString (", "); + headers["Sec-WebSocket-Protocol"] = _protocols.ToString (", "); var extensions = createExtensionsRequest (); if (extensions != null) - headers ["Sec-WebSocket-Extensions"] = extensions; + headers["Sec-WebSocket-Extensions"] = extensions; - headers ["Sec-WebSocket-Version"] = _version; + headers["Sec-WebSocket-Version"] = _version; AuthenticationResponse authRes = null; if (_authChallenge != null && _credentials != null) { @@ -939,7 +939,7 @@ namespace WebSocketSharp } if (authRes != null) - headers ["Authorization"] = authRes.ToString (); + headers["Authorization"] = authRes.ToString (); if (_cookies.Count > 0) req.SetCookies (_cookies); @@ -953,13 +953,13 @@ namespace WebSocketSharp var res = HttpResponse.CreateWebSocketResponse (); var headers = res.Headers; - headers ["Sec-WebSocket-Accept"] = CreateResponseKey (_base64Key); + headers["Sec-WebSocket-Accept"] = CreateResponseKey (_base64Key); if (_protocol != null) - headers ["Sec-WebSocket-Protocol"] = _protocol; + headers["Sec-WebSocket-Protocol"] = _protocol; if (_extensions != null) - headers ["Sec-WebSocket-Extensions"] = _extensions; + headers["Sec-WebSocket-Extensions"] = _extensions; if (_cookies.Count > 0) res.SetCookies (_cookies); @@ -1045,58 +1045,7 @@ namespace WebSocketSharp } } - // As client - private HttpResponse receiveHandshakeResponse () - { - var res = _stream.ReadHttpResponse (90000); - _logger.Debug ("A response to this WebSocket connection request:\n" + res.ToString ()); - - return res; - } - - private bool send (byte [] frame) - { - lock (_forConn) { - if (_readyState != WebSocketState.Open) { - _logger.Warn ("Sending has been interrupted."); - return false; - } - - return _stream.WriteBytes (frame); - } - } - - // As client - private void send (HttpRequest request) - { - _logger.Debug ( - String.Format ("A WebSocket connection request to {0}:\n{1}", _uri, request)); - - _stream.WriteBytes (request.ToByteArray ()); - } - - // As server - private bool send (HttpResponse response) - { - _logger.Debug ( - "A response to the WebSocket connection request:\n" + response.ToString ()); - - return _stream.WriteBytes (response.ToByteArray ()); - } - - private bool send (WebSocketFrame frame) - { - lock (_forConn) { - if (_readyState != WebSocketState.Open) { - _logger.Warn ("Sending has been interrupted."); - return false; - } - - return _stream.WriteBytes (frame.ToByteArray ()); - } - } - - private bool send (Opcode opcode, byte [] data) + private bool send (Opcode opcode, byte[] data) { lock (_forSend) { var sent = false; @@ -1108,7 +1057,8 @@ namespace WebSocketSharp } var mask = _client ? Mask.Mask : Mask.Unmask; - sent = send (WebSocketFrame.CreateFrame (Fin.Final, opcode, mask, data, compressed)); + sent = sendWebSocketFrame ( + WebSocketFrame.CreateFrame (Fin.Final, opcode, mask, data, compressed)); } catch (Exception ex) { _logger.Fatal (ex.ToString ()); @@ -1149,9 +1099,9 @@ namespace WebSocketSharp } } - private void sendAsync (Opcode opcode, byte [] data, Action completed) + private void sendAsync (Opcode opcode, byte[] data, Action completed) { - Func sender = send; + Func sender = send; sender.BeginInvoke ( opcode, data, @@ -1196,43 +1146,47 @@ namespace WebSocketSharp var rem = (int) (len % FragmentLength); var times = rem == 0 ? quo - 2 : quo - 1; - byte [] buffer = null; + byte[] buff = null; // Not fragmented if (quo == 0) { - buffer = new byte [rem]; - return stream.Read (buffer, 0, rem) == rem && - send (WebSocketFrame.CreateFrame (Fin.Final, opcode, mask, buffer, compressed)); + buff = new byte[rem]; + return stream.Read (buff, 0, rem) == rem && + sendWebSocketFrame ( + WebSocketFrame.CreateFrame (Fin.Final, opcode, mask, buff, compressed)); } - buffer = new byte [FragmentLength]; + buff = new byte[FragmentLength]; // First - if (stream.Read (buffer, 0, FragmentLength) != FragmentLength || - !send (WebSocketFrame.CreateFrame (Fin.More, opcode, mask, buffer, compressed))) + if (stream.Read (buff, 0, FragmentLength) != FragmentLength || + !sendWebSocketFrame ( + WebSocketFrame.CreateFrame (Fin.More, opcode, mask, buff, compressed))) return false; // Mid for (long i = 0; i < times; i++) { - if (stream.Read (buffer, 0, FragmentLength) != FragmentLength || - !send (WebSocketFrame.CreateFrame (Fin.More, Opcode.Cont, mask, buffer, compressed))) + if (stream.Read (buff, 0, FragmentLength) != FragmentLength || + !sendWebSocketFrame ( + WebSocketFrame.CreateFrame (Fin.More, Opcode.Cont, mask, buff, compressed))) return false; } // Final var tmpLen = FragmentLength; if (rem != 0) - buffer = new byte [tmpLen = rem]; + buff = new byte[tmpLen = rem]; - return stream.Read (buffer, 0, tmpLen) == tmpLen && - send (WebSocketFrame.CreateFrame (Fin.Final, Opcode.Cont, mask, buffer, compressed)); + return stream.Read (buff, 0, tmpLen) == tmpLen && + sendWebSocketFrame ( + WebSocketFrame.CreateFrame (Fin.Final, Opcode.Cont, mask, buff, compressed)); } // As client private HttpResponse sendHandshakeRequest () { var req = createHandshakeRequest (); - var res = sendHandshakeRequest (req); + var res = sendHandshakeRequest (req, 90000); if (res.IsUnauthorized) { _authChallenge = res.AuthenticationChallenge; if (_credentials != null && @@ -1244,8 +1198,8 @@ namespace WebSocketSharp var authRes = new AuthenticationResponse (_authChallenge, _credentials, _nonceCount); _nonceCount = authRes.NonceCount; - req.Headers ["Authorization"] = authRes.ToString (); - res = sendHandshakeRequest (req); + req.Headers["Authorization"] = authRes.ToString (); + res = sendHandshakeRequest (req, 15000); } } @@ -1253,17 +1207,60 @@ namespace WebSocketSharp } // As client - private HttpResponse sendHandshakeRequest (HttpRequest request) + private HttpResponse sendHandshakeRequest (HttpRequest request, int millisecondsTimeout) { - send (request); - return receiveHandshakeResponse (); + _logger.Debug ( + String.Format ("A WebSocket connection request to {0}:\n{1}", _uri, request)); + + var res = _stream.SendHttpRequest (request, millisecondsTimeout); + _logger.Debug ("A response to this WebSocket connection request:\n" + res.ToString ()); + + return res; + } + + // As server + private bool sendHandshakeResponse (HttpResponse response) + { + _logger.Debug ( + "A response to the WebSocket connection request:\n" + response.ToString ()); + + return _stream.WriteHttp (response); + } + + private bool sendWebSocketFrame (byte[] data) + { + lock (_forConn) { + if (_readyState != WebSocketState.Open) { + _logger.Warn ("Sending has been interrupted."); + return false; + } + + return _stream.WriteBytes (data); + } + } + + private bool sendWebSocketFrame (WebSocketFrame frame) + { + lock (_forConn) { + if (_readyState != WebSocketState.Open) { + _logger.Warn ("Sending has been interrupted."); + return false; + } + + return _stream.WriteWebSocketFrame (frame); + } } // As client private void setClientStream () { + var proxy = _proxyUri != null; + _tcpClient = proxy + ? new TcpClient (_proxyUri.DnsSafeHost, _proxyUri.Port) + : new TcpClient (_uri.DnsSafeHost, _uri.Port); + _stream = WebSocketStream.CreateClientStream ( - _uri, _proxyUri, _proxyCredentials, _secure, _certValidationCallback, out _tcpClient); + _tcpClient, proxy, _uri, _proxyCredentials, _secure, _certValidationCallback); } private void startReceiving () @@ -1376,7 +1373,7 @@ namespace WebSocketSharp { _readyState = WebSocketState.Closing; - send (response); + sendHandshakeResponse (response); closeServerResources (); _readyState = WebSocketState.Closed; @@ -1389,7 +1386,7 @@ namespace WebSocketSharp } // As server - internal void Close (CloseEventArgs e, byte [] frame, int timeout) + internal void Close (CloseEventArgs e, byte[] data, int millisecondsTimeout) { lock (_forConn) { if (_readyState == WebSocketState.Closing || _readyState == WebSocketState.Closed) { @@ -1400,7 +1397,7 @@ namespace WebSocketSharp _readyState = WebSocketState.Closing; } - e.WasClean = closeHandshake (frame, timeout, closeServerResources); + e.WasClean = closeHandshake (data, millisecondsTimeout, closeServerResources); _readyState = WebSocketState.Closed; try { @@ -1428,7 +1425,7 @@ namespace WebSocketSharp // As client internal static string CreateBase64Key () { - var src = new byte [16]; + var src = new byte[16]; var rand = new Random (); rand.NextBytes (src); @@ -1437,22 +1434,22 @@ namespace WebSocketSharp internal static string CreateResponseKey (string base64Key) { - var buffer = new StringBuilder (base64Key, 64); - buffer.Append (_guid); + var buff = new StringBuilder (base64Key, 64); + buff.Append (_guid); SHA1 sha1 = new SHA1CryptoServiceProvider (); - var src = sha1.ComputeHash (Encoding.UTF8.GetBytes (buffer.ToString ())); + var src = sha1.ComputeHash (Encoding.UTF8.GetBytes (buff.ToString ())); return Convert.ToBase64String (src); } - internal bool Ping (byte [] frame, int timeout) + internal bool Ping (byte[] data, int millisecondsTimeout) { try { AutoResetEvent pong; return _readyState == WebSocketState.Open && - send (frame) && + sendWebSocketFrame (data) && (pong = _receivePong) != null && - pong.WaitOne (timeout); + pong.WaitOne (millisecondsTimeout); } catch (Exception ex) { _logger.Fatal ("An exception has occurred while Ping:\n" + ex.ToString ()); @@ -1461,7 +1458,7 @@ namespace WebSocketSharp } // As server, used to broadcast - internal void Send (Opcode opcode, byte [] data, Dictionary cache) + internal void Send (Opcode opcode, byte[] data, Dictionary cache) { lock (_forSend) { lock (_forConn) { @@ -1469,7 +1466,7 @@ namespace WebSocketSharp return; try { - byte [] cached; + byte[] cached; if (!cache.TryGetValue (_compression, out cached)) { cached = WebSocketFrame.CreateFrame ( Fin.Final, @@ -1537,15 +1534,15 @@ namespace WebSocketSharp } /// - /// Closes the WebSocket connection with the specified , and releases all - /// associated resources. + /// Closes the WebSocket connection with the specified , + /// and releases all associated resources. /// /// - /// This method emits a event if isn't in the - /// allowable range of the WebSocket close status code. + /// This method emits a event if + /// isn't in the allowable range of the WebSocket close status code. /// /// - /// A that represents the status code indicating the reason for closure. + /// A that represents the status code indicating the reason for the close. /// public void Close (ushort code) { @@ -1553,12 +1550,12 @@ namespace WebSocketSharp } /// - /// Closes the WebSocket connection with the specified , and - /// releases all associated resources. + /// Closes the WebSocket connection with the specified , + /// and releases all associated resources. /// /// - /// One of the enum values, represents the status code indicating - /// the reason for closure. + /// One of the enum values, represents the status code + /// indicating the reason for the close. /// public void Close (CloseStatusCode code) { @@ -1566,23 +1563,23 @@ namespace WebSocketSharp } /// - /// Closes the WebSocket connection with the specified and - /// , and releases all associated resources. + /// Closes the WebSocket connection with the specified + /// and , and releases all associated resources. /// /// - /// This method emits a event if isn't in the - /// allowable range of the WebSocket close status code or the size of - /// is greater than 123 bytes. + /// This method emits a event if + /// isn't in the allowable range of the WebSocket close status code or the size + /// of is greater than 123 bytes. /// /// - /// A that represents the status code indicating the reason for closure. + /// A that represents the status code indicating the reason for the close. /// /// - /// A that represents the reason for closure. + /// A that represents the reason for the close. /// public void Close (ushort code, string reason) { - byte [] data = null; + byte[] data = null; var msg = _readyState.CheckIfClosable () ?? code.CheckIfValidCloseStatusCode () ?? (data = code.Append (reason)).CheckIfValidControlData ("reason"); @@ -1599,23 +1596,23 @@ namespace WebSocketSharp } /// - /// Closes the WebSocket connection with the specified and - /// , and releases all associated resources. + /// Closes the WebSocket connection with the specified + /// and , and releases all associated resources. /// /// - /// This method emits a event if the size of is - /// greater than 123 bytes. + /// This method emits a event if the size + /// of is greater than 123 bytes. /// /// - /// One of the enum values, represents the status code indicating - /// the reason for closure. + /// One of the enum values, represents the status code + /// indicating the reason for the close. /// /// - /// A that represents the reason for closure. + /// A that represents the reason for the close. /// public void Close (CloseStatusCode code, string reason) { - byte [] data = null; + byte[] data = null; var msg = _readyState.CheckIfClosable () ?? (data = ((ushort) code).Append (reason)).CheckIfValidControlData ("reason"); @@ -1659,12 +1656,12 @@ namespace WebSocketSharp /// This method doesn't wait for the close to be complete. /// /// - /// This method emits a event if isn't in the - /// allowable range of the WebSocket close status code. + /// This method emits a event if + /// isn't in the allowable range of the WebSocket close status code. /// /// /// - /// A that represents the status code indicating the reason for closure. + /// A that represents the status code indicating the reason for the close. /// public void CloseAsync (ushort code) { @@ -1679,8 +1676,8 @@ namespace WebSocketSharp /// This method doesn't wait for the close to be complete. /// /// - /// One of the enum values, represents the status code indicating - /// the reason for closure. + /// One of the enum values, represents the status code + /// indicating the reason for the close. /// public void CloseAsync (CloseStatusCode code) { @@ -1688,8 +1685,8 @@ namespace WebSocketSharp } /// - /// Closes the WebSocket connection asynchronously with the specified and - /// , and releases all associated resources. + /// Closes the WebSocket connection asynchronously with the specified + /// and , and releases all associated resources. /// /// /// @@ -1702,14 +1699,14 @@ namespace WebSocketSharp /// /// /// - /// A that represents the status code indicating the reason for closure. + /// A that represents the status code indicating the reason for the close. /// /// - /// A that represents the reason for closure. + /// A that represents the reason for the close. /// public void CloseAsync (ushort code, string reason) { - byte [] data = null; + byte[] data = null; var msg = _readyState.CheckIfClosable () ?? code.CheckIfValidCloseStatusCode () ?? (data = code.Append (reason)).CheckIfValidControlData ("reason"); @@ -1735,20 +1732,20 @@ namespace WebSocketSharp /// This method doesn't wait for the close to be complete. /// /// - /// This method emits a event if the size of - /// is greater than 123 bytes. + /// This method emits a event if the size + /// of is greater than 123 bytes. /// /// /// - /// One of the enum values, represents the status code indicating - /// the reason for closure. + /// One of the enum values, represents the status code + /// indicating the reason for the close. /// /// - /// A that represents the reason for closure. + /// A that represents the reason for the close. /// public void CloseAsync (CloseStatusCode code, string reason) { - byte [] data = null; + byte[] data = null; var msg = _readyState.CheckIfClosable () ?? (data = ((ushort) code).Append (reason)).CheckIfValidControlData ("reason"); @@ -1854,7 +1851,7 @@ namespace WebSocketSharp /// /// An array of that represents the binary data to send. /// - public void Send (byte [] data) + public void Send (byte[] data) { var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData (); if (msg != null) { @@ -1930,7 +1927,7 @@ namespace WebSocketSharp /// 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 SendAsync (byte[] data, Action completed) { var msg = _readyState.CheckIfOpen () ?? data.CheckIfValidSendData (); if (msg != null) { diff --git a/websocket-sharp/WebSocketStream.cs b/websocket-sharp/WebSocketStream.cs index e478a01d..aa483bdf 100644 --- a/websocket-sharp/WebSocketStream.cs +++ b/websocket-sharp/WebSocketStream.cs @@ -182,23 +182,29 @@ namespace WebSocketSharp return readHttp (stream, HttpResponse.Parse, millisecondsTimeout); } + private static bool writeBytes (Stream stream, byte[] data) + { + try { + stream.Write (data, 0, data.Length); + return true; + } + catch { + return false; + } + } + #endregion #region Internal Methods internal static WebSocketStream CreateClientStream ( + TcpClient tcpClient, + bool proxy, Uri targetUri, - Uri proxyUri, NetworkCredential proxyCredentials, bool secure, - System.Net.Security.RemoteCertificateValidationCallback validationCallback, - out TcpClient tcpClient) + System.Net.Security.RemoteCertificateValidationCallback validationCallback) { - var proxy = proxyUri != null; - tcpClient = proxy - ? new TcpClient (proxyUri.DnsSafeHost, proxyUri.Port) - : new TcpClient (targetUri.DnsSafeHost, targetUri.Port); - var netStream = tcpClient.GetStream (); if (proxy) { var req = HttpRequest.CreateConnectRequest (targetUri); @@ -270,17 +276,26 @@ namespace WebSocketSharp WebSocketFrame.ParseAsync (_innerStream, true, completed, error); } + internal HttpResponse SendHttpRequest (HttpRequest request, int millisecondsTimeout) + { + return sendHttpRequest (_innerStream, request, millisecondsTimeout); + } + internal bool WriteBytes (byte[] data) { - lock (_forWrite) { - try { - _innerStream.Write (data, 0, data.Length); - return true; - } - catch { - return false; - } - } + lock (_forWrite) + return writeBytes (_innerStream, data); + } + + internal bool WriteHttp (HttpBase http) + { + return writeBytes (_innerStream, http.ToByteArray ()); + } + + internal bool WriteWebSocketFrame (WebSocketFrame frame) + { + lock (_forWrite) + return writeBytes (_innerStream, frame.ToByteArray ()); } #endregion