public void Close(WebSocketCloseCode closeCode, string closeReason) { if (State == WebSocketState.Closed || State == WebSocketState.None) { return; } var priorState = Interlocked.Exchange(ref _state, _closing); switch (priorState) { case _connected: { var closingHandshake = new CloseFrame(closeCode, closeReason).ToArray(_frameBuilder); try { if (_stream.CanWrite) { StartClosingTimer(); var ar = _stream.BeginWrite(closingHandshake, 0, closingHandshake.Length, null, _stream); if (!ar.AsyncWaitHandle.WaitOne(ConnectTimeout)) { InternalClose(true); throw new TimeoutException(string.Format( "Closing handshake with remote [{0}] timeout [{1}].", RemoteEndPoint, ConnectTimeout)); } } } catch (Exception ex) { if (ShouldThrow(ex)) { throw; } } return; } case _connecting: case _closing: { InternalClose(true); return; } case _disposed: case _none: default: return; } }
public async Task Close(WebSocketCloseCode closeCode, string closeReason) { if (State == WebSocketState.Closed || State == WebSocketState.None) { return; } var priorState = Interlocked.Exchange(ref _state, _closing); switch (priorState) { case _connected: { var closingHandshake = new CloseFrame(closeCode, closeReason, false).ToArray(_frameBuilder); try { if (_stream.CanWrite) { await _stream.WriteAsync(closingHandshake, 0, closingHandshake.Length); StartClosingTimer(); #if DEBUG _log.DebugFormat("Session [{0}] sends server side close frame [{1}] [{2}].", this, closeCode, closeReason); #endif } } catch (Exception ex) when(!ShouldThrow(ex)) { } return; } case _connecting: case _closing: { await Close(); return; } case _disposed: case _none: default: return; } }
public byte[] EncodeFrame(CloseFrame frame) { // The Close frame MAY contain a body (the "Application data" portion of // the frame) that indicates a reason for closing, such as an endpoint // shutting down, an endpoint having received a frame too large, or an // endpoint having received a frame that does not conform to the format // expected by the endpoint. If there is a body, the first two bytes of // the body MUST be a 2-byte unsigned integer (in network byte order) // representing a status code with value /code/ defined in Section 7.4. // Following the 2-byte integer, the body MAY contain UTF-8-encoded data // with value /reason/, the interpretation of which is not defined by // this specification. This data is not necessarily human readable but // may be useful for debugging or passing information relevant to the // script that opened the connection. As the data is not guaranteed to // be human readable, clients MUST NOT show it to end users. int payloadLength = (string.IsNullOrEmpty(frame.CloseReason) ? 0 : Encoding.UTF8.GetMaxByteCount(frame.CloseReason.Length)) + 2; if (payloadLength > 125) { throw new WebSocketException("All control frames must have a payload length of 125 bytes or less."); } byte[] payload = new byte[payloadLength]; int higherByte = (int)frame.CloseCode / 256; int lowerByte = (int)frame.CloseCode % 256; payload[0] = (byte)higherByte; payload[1] = (byte)lowerByte; if (!string.IsNullOrEmpty(frame.CloseReason)) { int count = Encoding.UTF8.GetBytes(frame.CloseReason, 0, frame.CloseReason.Length, payload, 2); return(Encode(frame.OpCode, payload, 0, 2 + count, isMasked: frame.IsMasked)); } else { return(Encode(frame.OpCode, payload, 0, payload.Length, isMasked: frame.IsMasked)); } }
public byte[] EncodeFrame(CloseFrame frame) { // The Close frame MAY contain a body (the "Application data" portion of // the frame) that indicates a reason for closing, such as an endpoint // shutting down, an endpoint having received a frame too large, or an // endpoint having received a frame that does not conform to the format // expected by the endpoint. If there is a body, the first two bytes of // the body MUST be a 2-byte unsigned integer (in network byte order) // representing a status code with value /code/ defined in Section 7.4. // Following the 2-byte integer, the body MAY contain UTF-8-encoded data // with value /reason/, the interpretation of which is not defined by // this specification. This data is not necessarily human readable but // may be useful for debugging or passing information relevant to the // script that opened the connection. As the data is not guaranteed to // be human readable, clients MUST NOT show it to end users. int payloadLength = (string.IsNullOrEmpty(frame.CloseReason) ? 0 : Encoding.UTF8.GetMaxByteCount(frame.CloseReason.Length)) + 2; if (payloadLength > 125) throw new WebSocketException("All control frames must have a payload length of 125 bytes or less."); byte[] payload = new byte[payloadLength]; int higherByte = (int)frame.CloseCode / 256; int lowerByte = (int)frame.CloseCode % 256; payload[0] = (byte)higherByte; payload[1] = (byte)lowerByte; if (!string.IsNullOrEmpty(frame.CloseReason)) { int count = Encoding.UTF8.GetBytes(frame.CloseReason, 0, frame.CloseReason.Length, payload, 2); return Encode(frame.OpCode, payload, 0, 2 + count, isMasked: frame.IsMasked); } else { return Encode(frame.OpCode, payload, 0, payload.Length, isMasked: frame.IsMasked); } }
public async Task Close(WebSocketCloseCode closeCode, string closeReason) { if (State == WebSocketState.Closed || State == WebSocketState.None) return; var priorState = Interlocked.Exchange(ref _state, _closing); switch (priorState) { case _connected: { var closingHandshake = new CloseFrame(closeCode, closeReason, false).ToArray(_frameBuilder); try { if (_stream.CanWrite) { await _stream.WriteAsync(closingHandshake, 0, closingHandshake.Length); StartClosingTimer(); #if DEBUG _log.DebugFormat("Session [{0}] sends server side close frame [{1}] [{2}].", this, closeCode, closeReason); #endif } } catch (Exception ex) when (!ShouldThrow(ex)) { } return; } case _connecting: case _closing: { await Close(); return; } case _disposed: case _none: default: return; } }
public async Task Close(WebSocketCloseCode closeCode, string closeReason) { if (State == WebSocketState.Closed || State == WebSocketState.None) return; var priorState = Interlocked.Exchange(ref _state, _closing); switch (priorState) { case _connected: { var closingHandshake = new CloseFrame(closeCode, closeReason).ToArray(_frameBuilder); try { if (_stream.CanWrite) { StartClosingTimer(); #if DEBUG _log.DebugFormat("Send client side close frame [{0}] [{1}].", closeCode, closeReason); #endif var awaiter = _stream.WriteAsync(closingHandshake, 0, closingHandshake.Length); if (!awaiter.Wait(ConnectTimeout)) { await InternalClose(true); throw new TimeoutException(string.Format( "Closing handshake with [{0}] timeout [{1}].", _remoteEndPoint, ConnectTimeout)); } } } catch (Exception ex) when (!ShouldThrow(ex)) { } return; } case _connecting: case _closing: { await InternalClose(true); return; } case _disposed: case _none: default: return; } }
public void Close(WebSocketCloseCode closeCode, string closeReason) { if (State == WebSocketState.Closed || State == WebSocketState.None) return; var priorState = Interlocked.Exchange(ref _state, _closing); switch (priorState) { case _connected: { var closingHandshake = new CloseFrame(closeCode, closeReason).ToArray(_frameBuilder); try { if (_stream.CanWrite) { StartClosingTimer(); var ar = _stream.BeginWrite(closingHandshake, 0, closingHandshake.Length, null, _stream); if (!ar.AsyncWaitHandle.WaitOne(ConnectTimeout)) { InternalClose(true); throw new TimeoutException(string.Format( "Closing handshake with remote [{0}] timeout [{1}].", RemoteEndPoint, ConnectTimeout)); } } } catch (Exception ex) { if (ShouldThrow(ex)) throw; } return; } case _connecting: case _closing: { InternalClose(true); return; } case _disposed: case _none: default: return; } }