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);
                }
            }
        }
Exemple #2
0
        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}");
            }
        }