/// <summary> /// Processes initial web socket connection request, sends unreceived messages and keeps websocket connection alive /// </summary> /// <param name="context">HttpContext</param> /// <param name="socketId">Web Socket Id</param> /// <param name="socketInfo">Web Socket item info</param> /// <param name="topic">Message topic</param> /// <returns></returns> private async Task ProcessRequest(HttpContext context, Guid socketId, WebSocketItemInfo socketInfo, string topic) { // Send old messages var oldMessages = _persistanceService.Get(topic, socketInfo.CreationDT); foreach (var message in oldMessages) { await PushMessageToClient(message, socketInfo.Socket); } // Wait in a loop var buffer = new byte[1024 * 4]; WebSocketReceiveResult result = await socketInfo.Socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { result = await socketInfo.Socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); } // Close connection await socketInfo.Socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); // Remove from dictionary ConcurrentDictionary <Guid, WebSocketItemInfo> socketList; _sockets.TryGetValue(topic, out socketList); WebSocketItemInfo dummyVar; socketList.TryRemove(socketId, out dummyVar); }
/// <summary> /// Handles web socket requests /// </summary> /// <param name="context">HttpContext</param> /// <param name="options">Middleware options</param> /// <returns></returns> public async Task HandleRequest(HttpContext context, LWMessagePushMiddlewareOptions options) { try { if (context.WebSockets.IsWebSocketRequest) { if (!context.Request.Query.ContainsKey("topic")) { string err = "Topic is required."; options.LogListener.Log(string.Format("WebSocket handler error: {0}", err), Logging.LogLevel.Error); throw new ArgumentNullException(err); } string topic = context.Request.Query["topic"]; Guid socketId = Guid.NewGuid(); string lastReceive = context.Request.Query["lastr"]; DateTime lastReceivedMsgDT = DateTime.UtcNow; options.LogListener.Log(string.Format("WebSocket connection request is received at {0} UTC for {1}", lastReceivedMsgDT.ToString(), topic), Logging.LogLevel.Verbose); if (lastReceive != null) { DateTime.TryParse(lastReceive, out lastReceivedMsgDT); } WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); WebSocketItemInfo socketInfo = new WebSocketItemInfo(webSocket, lastReceivedMsgDT); var newTopicDict = new ConcurrentDictionary <Guid, WebSocketItemInfo>(); newTopicDict.TryAdd(socketId, socketInfo); _sockets.AddOrUpdate(topic, newTopicDict, (a, b) => { b.TryAdd(socketId, socketInfo); return(b); }); await ProcessRequest(context, socketId, socketInfo, topic); } else { context.Response.StatusCode = 400; } } catch (Exception e) { options.LogListener.Log(string.Format("WebSocket handler error: {0}", e.Message), Logging.LogLevel.Error); throw e; } }