public static bool TryParse(ReadableBuffer payload, out WebSocketCloseResult result, out ushort?actualCloseCode) { if (payload.Length == 0) { // Empty payload is OK actualCloseCode = null; result = new WebSocketCloseResult(WebSocketCloseStatus.Empty, string.Empty); return(true); } else if (payload.Length < 2) { actualCloseCode = null; result = default(WebSocketCloseResult); return(false); } else { var status = payload.ReadBigEndian <ushort>(); actualCloseCode = status; var description = string.Empty; payload = payload.Slice(2); if (payload.Length > 0) { description = payload.GetUtf8String(); } result = new WebSocketCloseResult((WebSocketCloseStatus)status, description); return(true); } }
private async Task <WebSocketCloseResult> CloseFromProtocolError(CancellationToken cancellationToken, int payloadLen, ReadableBuffer payload, string reason, WebSocketCloseStatus statusCode = WebSocketCloseStatus.ProtocolError) { // Non-continuation non-control message during fragmented message if (payloadLen > 0) { _inbound.Advance(payload.End); } var closeResult = new WebSocketCloseResult( statusCode, reason); await CloseAsync(closeResult, cancellationToken); Dispose(); return(closeResult); }
private WebSocketCloseResult HandleCloseFrame(ReadableBuffer payload, WebSocketFrame frame, out ushort?actualStatusCode) { // Update state if (State == WebSocketConnectionState.CloseSent) { State = WebSocketConnectionState.Closed; } else { State = WebSocketConnectionState.CloseReceived; } // Process the close frame WebSocketCloseResult closeResult; if (!WebSocketCloseResult.TryParse(frame.Payload, out closeResult, out actualStatusCode)) { closeResult = WebSocketCloseResult.Empty; } return(closeResult); }
/// <summary> /// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame. /// </summary> /// <remarks> /// If the other party does not respond with a close frame, the connection will remain open and the <see cref="Task{WebSocketCloseResult}"/> /// will remain active. Call the <see cref="IDisposable.Dispose"/> method on this instance to forcibly terminate the connection. /// </remarks> /// <param name="result">A <see cref="WebSocketCloseResult"/> with the payload for the close frame</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> that indicates when/if the send is cancelled.</param> /// <returns>A <see cref="Task"/> that completes when the close frame has been sent</returns> public async Task CloseAsync(WebSocketCloseResult result, CancellationToken cancellationToken) { if (State == WebSocketConnectionState.Closed) { throw new ObjectDisposedException(nameof(WebSocketConnection)); } else if (State == WebSocketConnectionState.Created) { throw new InvalidOperationException("Cannot send close frame when the connection hasn't been started"); } else if (State == WebSocketConnectionState.CloseSent) { throw new InvalidOperationException("Cannot send multiple close frames"); } var payloadSize = result.GetSize(); await SendCoreAsync( fin : true, opcode : WebSocketOpcode.Close, payloadAllocLength : payloadSize, payloadLength : payloadSize, payloadWriter : CloseResultPayloadWriter, payload : result, cancellationToken : cancellationToken); _timerCts.Cancel(); _pinger?.Dispose(); if (State == WebSocketConnectionState.CloseReceived) { State = WebSocketConnectionState.Closed; } else { State = WebSocketConnectionState.CloseSent; } }
private static void CloseResultPayloadWriter(WritableBuffer output, Span <byte> maskingKey, int payloadLength, WebSocketCloseResult result) { // Write the close payload out var payload = output.Memory.Slice(0, payloadLength).Span; result.WriteTo(ref output); if (maskingKey.Length > 0) { MaskingUtilities.ApplyMask(payload, maskingKey); } }
/// <summary> /// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame. /// </summary> /// <param name="result">A <see cref="WebSocketCloseResult"/> with the payload for the close frame.</param> /// <returns>A <see cref="Task"/> that completes when the close frame has been sent</returns> public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseResult result) => self.CloseAsync(result, CancellationToken.None);