private async Task Echo(HttpContext context, IWebSocketConnection webSocket, ILogger logger) { var lastFrameOpcode = WebSocketOpcode.Continuation; var closeResult = await webSocket.ExecuteAsync(frame => { if (frame.Opcode == WebSocketOpcode.Ping || frame.Opcode == WebSocketOpcode.Pong) { // Already handled return(Task.CompletedTask); } LogFrame(logger, lastFrameOpcode, ref frame); // If the client send "ServerClose", then they want a server-originated close to occur string content = "<<binary>>"; if (frame.Opcode == WebSocketOpcode.Text) { // Slooooow content = Encoding.UTF8.GetString(frame.Payload.ToArray()); if (content.Equals("ServerClose")) { logger.LogDebug($"Sending Frame Close: {WebSocketCloseStatus.NormalClosure} Closing from Server"); return(webSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure, "Closing from Server"))); } else if (content.Equals("ServerAbort")) { context.Abort(); } } if (frame.Opcode != WebSocketOpcode.Continuation) { lastFrameOpcode = frame.Opcode; } logger.LogDebug($"Sending {frame.Opcode}: Len={frame.Payload.Length}, Fin={frame.EndOfMessage}: {content}"); return(webSocket.SendAsync(frame)); }); if (webSocket.State == WebSocketConnectionState.CloseReceived) { // Close the connection from our end await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure); logger.LogDebug("Socket closed"); } else if (webSocket.State != WebSocketConnectionState.Closed) { logger.LogError("WebSocket closed but not closed?"); } }
/// <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);
/// <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="status">A <see cref="WebSocketCloseStatus"/> value to be sent to the client in the close frame</param>. /// <param name="description">A textual description of the reason for closing the connection.</param> /// <returns>A <see cref="Task"/> that completes when the close frame has been sent</returns> public static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseStatus status, string description) => self.CloseAsync(new WebSocketCloseResult(status, description), CancellationToken.None);
/// <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="status">A <see cref="WebSocketCloseStatus"/> value to be sent to the client in 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 static Task CloseAsync(this IWebSocketConnection self, WebSocketCloseStatus status, CancellationToken cancellationToken) => self.CloseAsync(new WebSocketCloseResult(status), cancellationToken);