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);
     }
 }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        /// <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;
            }
        }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
 /// <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);