You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iot/projects/Infrastructure/Web/WebSockets/WebSocketManager.cs

88 lines
3.6 KiB

using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Infrastructure.WebSockets
{
public class WebSocketManager
{
private readonly RequestDelegate _next;
public delegate void SendHandler(ArraySegment<byte> buffer, WebSocketMessageType messageType, Func<WebSocketWrapper, bool> condition);
public static event SendHandler SendMessage;
public WebSocketManager(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path.StartsWithSegments("/ws"))
{
if (context.Request.Path.StartsWithSegments("/ws"))
{
if (context.WebSockets.IsWebSocketRequest)
{
try
{
var sec = "Sec-WebSocket-Protocol";
if (context.Request.Headers.ContainsKey(sec))
{
context.Response.Headers.Add(sec, context.Request.Headers[sec]);
}
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
var key = Guid.NewGuid();
var wrapper = new WebSocketWrapper { Context = context, WebSocket = webSocket };
SendMessage += wrapper.Send;
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = null;
while (webSocket.State == WebSocketState.Open)
{
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result == null || result.CloseStatus.HasValue || result.MessageType == WebSocketMessageType.Close)
{
break;
}
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
wrapper.OnReceived(message);
}
SendMessage -= wrapper.Send;
if (webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
}
catch (Exception ex)
{
Console.WriteLine("^Exception at WebSocket Close");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.ToString());
Console.WriteLine("$Exception at WebSocket Close");
}
}
else
{
context.Response.StatusCode = 400;
}
}
}
else
{
await this._next(context);
}
}
public static async Task Send(ArraySegment<byte> data, WebSocketMessageType messageType, Func<WebSocketWrapper, bool> condition)
{
await Task.Run(() =>
{
SendMessage?.Invoke(data, messageType, condition);
});
}
}
}