private async Task ProcessRequest <TWebSocketBehavior>(HttpListenerContext listenerContext, Func <TWebSocketBehavior> behaviorBuilder) where TWebSocketBehavior : WebSocketServerBehavior { WebSocketContext webSocketContext = null; WebSocketServerBehavior behavior = null; string clientId; try { webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol : null); behavior = behaviorBuilder(); int statusCode = 500; var statusDescription = "BadContext"; if (!behavior.OnValidateContext(webSocketContext, ref statusCode, ref statusDescription)) { listenerContext.Response.StatusDescription = statusDescription; listenerContext.Response.StatusCode = statusCode; listenerContext.Response.Close(); return; } clientId = behavior.GetClientId(webSocketContext); _clients.TryAdd(clientId, webSocketContext); Interlocked.Increment(ref count); _logInfo($"Client id:{clientId} accepted now there are {count} clients"); behavior.OnClientConnected(clientId); } catch (Exception e) { listenerContext.Response.StatusCode = 500; listenerContext.Response.Close(); this._logError($"Exception: {e}"); return; } try { await RecieveLoop(webSocketContext.WebSocket, behavior.OnBinaryMessage, behavior.OnStringMessage, (e) => { Interlocked.Decrement(ref count); this._logInfo($"Client disconnected. now {count} connected clients"); behavior.OnClose(new WebSocketClosedEventArgs(clientId, e.ReceivedResult)); }); } finally { if (webSocketContext.WebSocket != null) { webSocketContext.WebSocket.Dispose(); } // _cleanup(); if (!string.IsNullOrEmpty(clientId)) { _clients.TryRemove(clientId, out webSocketContext); } } }
private async Task HandleClient <TWebSocketBehavior>(HttpListenerContext listenerContext, Func <TWebSocketBehavior> behaviorBuilder, CancellationToken token) where TWebSocketBehavior : WebSocketServerBehavior { WebSocketContext webSocketContext = null; WebSocketServerBehavior behavior = null; string clientId; try { webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol : null); behavior = behaviorBuilder(); int statusCode = 500; var statusDescription = "BadContext"; if (!behavior.OnValidateContext(webSocketContext, ref statusCode, ref statusDescription)) { listenerContext.Response.StatusDescription = statusDescription; listenerContext.Response.StatusCode = statusCode; listenerContext.Response.Close(); _logError($"Failed to validate client context. Closing connection. Status: {statusCode}. Description: {statusDescription}."); return; } clientId = behavior.GetClientId(webSocketContext); _clients.TryAdd(clientId, webSocketContext); Interlocked.Increment(ref count); _logInfo($"Client id:{clientId} accepted now there are {count} clients"); var safeconnected = MakeSafe <string>(behavior.OnClientConnected, "behavior.OnClientConnected"); safeconnected(clientId); } catch (Exception e) { listenerContext.Response.StatusCode = 500; listenerContext.Response.Close(); _logError($"Exception: {e}"); return; } try { using (webSocketContext.WebSocket) { var closeBeh = MakeSafe <WebSocketClosedEventArgs>(behavior.OnClose, "behavior.OnClose"); var strBeh = MakeSafe <StringMessageReceivedEventArgs>(behavior.OnStringMessage, "behavior.OnStringMessage"); var binBeh = MakeSafe <BinaryMessageReceivedEventArgs>(behavior.OnBinaryMessage, "behavior.OnBinaryMessage"); //recieve Loop var buff = new byte[1048576]; while (true) { var msg = await webSocketContext.WebSocket.ReceiveMessageAsync(buff, clientId, token).ConfigureAwait(false); if (msg.BinData != null) { binBeh(new BinaryMessageReceivedEventArgs(msg.BinData, webSocketContext.WebSocket)); } else if (msg.StringData != null) { strBeh(new StringMessageReceivedEventArgs(msg.StringData, webSocketContext.WebSocket)); } else if (msg.Exception != null) { _logError($"Exception in read thread {msg.Exception}"); } else { Interlocked.Decrement(ref count); this._logInfo($"Client {clientId} disconnected. now {count} connected clients"); closeBeh(new WebSocketClosedEventArgs(clientId, msg.WebSocketCloseStatus, msg.CloseStatDesc)); break; } } } } finally { if (!string.IsNullOrEmpty(clientId)) { _clients.TryRemove(clientId, out webSocketContext); } _logInfo($"Completed Receive Loop for clientid {clientId}"); } }