Example #1
0
        public async Task WebSocketRequestHandler(AspNetWebSocketContext webSocketContext)
        {
            socket = webSocketContext.WebSocket as AspNetWebSocket;
            open   = true;
            var receivedDataBuffer = new ArraySegment <Byte>(new Byte[MAX_DATA_SIZE]);

            cancellationToken = new CancellationToken();

            if (socket.State == WebSocketState.Open)
            {
                if (openCallback != null)
                {
                    openCallback.Invoke(uid);
                }
            }

            while (socket.State == WebSocketState.Open)
            {
                WebSocketReceiveResult result;
                var messageString = "";
                do
                {
                    result = await socket.ReceiveAsync(receivedDataBuffer, CancellationToken.None);

                    messageString = Encoding.UTF8.GetString(receivedDataBuffer.Array, 0, result.Count);
                } while (!result.EndOfMessage && readAll);

                if (receiveCallback != null)
                {
                    receiveCallback.Invoke(uid, messageString);
                }
            }
            if (socket.State == WebSocketState.Closed)
            {
                NotifyClosed();
            }
        }
        private async Task<AspNetWebSocket> ProcessRequestImplAsync() {
            AspNetWebSocket webSocket = null;

            try {
                // SendResponse and other asynchronous notifications cannot be process by ASP.NET after this point.
                _root.WorkerRequest.SuppressSendResponseNotifications();

                // A flush is necessary to activate the WebSocket module so that we can get its pointer.
                //
                // DevDiv #401948: We can't allow a flush failure to propagate out, otherwise the rest of
                // this method doesn't run, which could leak resources (by not invoking the user callback)
                // or cause weird behavior (by not calling CompleteTransitionToWebSocket, which could corrupt
                // server state). If the flush fails, we'll wait to propagate the exception until a safe
                // point later in this method.
                ExceptionDispatchInfo flushExceptionDispatchInfo = DoFlush();

                // Create the AspNetWebSocket. There's a chance that the client disconnected before we
                // hit this code. If this is the case, we'll pass a null WebSocketPipe to the
                // AspNetWebSocket ctor, which immediately sets the socket into an aborted state.
                UnmanagedWebSocketContext unmanagedWebSocketContext = _root.WorkerRequest.GetWebSocketContext();
                WebSocketPipe pipe = (unmanagedWebSocketContext != null) ? new WebSocketPipe(unmanagedWebSocketContext, PerfCounters.Instance) : null;
                webSocket = new AspNetWebSocket(pipe, _subProtocol);

                // slim down the HttpContext as much as possible to allow the GC to reclaim memory
                _httpContext.CompleteTransitionToWebSocket();

                // always install a new SynchronizationContext, even if the user is running in legacy SynchronizationContext mode
                AspNetSynchronizationContext syncContext = new AspNetSynchronizationContext(this);
                _httpContext.SyncContext = syncContext;

                bool webSocketRequestSucceeded = false;
                try {
                    // need to keep track of this in the manager so that we can abort if it the AppDomain goes down
                    AspNetWebSocketManager.Current.Add(webSocket);

                    // bump up the total count (the currently-executing count is recorded separately)
                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TOTAL_WEBSOCKETS);

                    // Release the reference to the user delegate (which might just be a simple initialization routine) so that
                    // the GC can claim it. The only thing that needs to remain alive is the Task itself, which we're referencing.
                    Task task = null;
                    syncContext.Send(_ => {
                        task = _userFunc(new AspNetWebSocketContextImpl(new HttpContextWrapper(_httpContext), _root.WorkerRequest, webSocket));
                    }, null);

                    // Was there an exception from user code? If so, rethrow (which logs).
                    ExceptionDispatchInfo exception = syncContext.ExceptionDispatchInfo;
                    if (exception != null) {
                        exception.Throw();
                    }

                    _userFunc = null;
                    await task.ConfigureAwait(continueOnCapturedContext: false);

                    // Was there an exception from the earlier call to DoFlush? If so, rethrow (which logs).
                    // This needs to occur after the user's callback finishes, otherwise ASP.NET could try
                    // to complete the request while the callback is still accessing it.
                    if (flushExceptionDispatchInfo != null) {
                        flushExceptionDispatchInfo.Throw();
                    }

                    // Any final state except Aborted is marked as 'success'.
                    // It's possible execution never reaches this point, e.g. if the user's
                    // callback throws an exception. In that case, 'webSocketRequestSucceeded'
                    // will keep its default value of false, and the performance counter
                    // will mark this request as having failed.

                    if (webSocket.State != WebSocketState.Aborted) {
                        webSocketRequestSucceeded = true;
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_SUCCEEDED_WEBSOCKETS);
                    }
                }
                finally {
                    // we need to make sure the user can't call the WebSocket any more after this point
                    _isProcessingComplete = true;
                    webSocket.DisposeInternal();
                    AspNetWebSocketManager.Current.Remove(webSocket);

                    if (!webSocketRequestSucceeded) {
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED_WEBSOCKETS);
                    }
                }
            }
            catch (Exception ex) {
                // don't let the exception propagate upward; just log it instead
                WebBaseEvent.RaiseRuntimeError(ex, null);
            }

            return webSocket;
        }
 public AspNetWebSocketContextImpl(HttpContextBase httpContext = null, HttpWorkerRequest workerRequest = null, AspNetWebSocket webSocket = null) {
     _httpContext = httpContext;
     _workerRequest = workerRequest;
     _webSocket = webSocket;
 }
        public async Task Receiver(AspNetWebSocketContext context)
        {
            try
            {
                socket = context.WebSocket as AspNetWebSocket;
                key    = context.SecWebSocketKey;
                #region ADD CLIENT
                if (LIST_CLIENT == null)
                {
                    LIST_CLIENT    = new Dictionary <string, AspNetWebSocketContext>();
                    LIST_MAP_TOKEN = new Dictionary <string, string>();
                }
                LIST_CLIENT.Add(key, context);
                LIST_MAP_TOKEN.Add(key, userData.token);

                //if (!LIST_CLIENT.ContainsKey(userData.token))
                //{
                //    LIST_CLIENT.Add(key, context);
                //    LIST_MAP_TOKEN.Add(key, userData.token);
                //}
                //else
                //{
                //    //var client = LIST_CLIENT[userData.token];
                //    //client = context;
                //    //var clientKey = LIST_MAP_TOKEN.SingleOrDefault(x => x.Value == userData.token).Key;
                //    //if(clientKey != null)
                //    //    LIST_MAP_TOKEN.Remove(clientKey);
                //    //LIST_MAP_TOKEN.Add(key, userData.token);
                //}
                if (!string.IsNullOrEmpty(userData.tokenOld))
                {
                    var listTokenOld = LIST_MAP_TOKEN.Where(x => x.Value == userData.tokenOld);
                    foreach (var item in listTokenOld)
                    {
                        await KickUser(item.Key, Constants.WEBSOCKET_STATUS.KICK_USER);
                    }
                }
                #endregion
                init();
                while (socket.State == WebSocketState.Open)
                {
                    await ProcessSendDataPacket();
                    await ProcessSendBroadCast();

                    while (ListDataSend.Count > 0)
                    {
                        await SendMessage(ListDataSend[0]);

                        ListDataSend.RemoveAt(0);
                    }
                    WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), CancellationToken.None);

                    //disconnect client
                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        LIST_MAP_TOKEN.Remove(key);
                        await Disconnect(Constants.WEBSOCKET_STATUS.DISCONNECT_CLIENT);

                        //await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
                    }
                    else if (receiveResult.MessageType == WebSocketMessageType.Binary)
                    {
                        await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Cannot accept binary frame", CancellationToken.None);
                    }
                    else
                    {
                        int count = receiveResult.Count;

                        while (receiveResult.EndOfMessage == false)
                        {
                            if (count >= maxMessageSize)
                            {
                                await Disconnect(Constants.WEBSOCKET_STATUS.DISCONNECT_SERVER);

                                return;
                            }
                            receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer, count, maxMessageSize - count), CancellationToken.None);

                            count += receiveResult.Count;
                        }
                        var receivedString = Encoding.UTF8.GetString(receiveBuffer, 0, count);
                        ProcessByDataPacket(receivedString);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLog("ERROR WEBSOCKET", ex);
                await Disconnect(Constants.WEBSOCKET_STATUS.DISCONNECT_SERVER);

                return;
            }
        }
Example #5
0
        private async Task <AspNetWebSocket> ProcessRequestImplAsync()
        {
            AspNetWebSocket webSocket = null;

            try {
                // SendResponse and other asynchronous notifications cannot be process by ASP.NET after this point.
                _root.WorkerRequest.SuppressSendResponseNotifications();

                // A flush is necessary to activate the WebSocket module so that we can get its pointer.
                //
                // DevDiv #401948: We can't allow a flush failure to propagate out, otherwise the rest of
                // this method doesn't run, which could leak resources (by not invoking the user callback)
                // or cause weird behavior (by not calling CompleteTransitionToWebSocket, which could corrupt
                // server state). If the flush fails, we'll wait to propagate the exception until a safe
                // point later in this method.
                ExceptionDispatchInfo flushExceptionDispatchInfo = DoFlush();

                // Create the AspNetWebSocket. There's a chance that the client disconnected before we
                // hit this code. If this is the case, we'll pass a null WebSocketPipe to the
                // AspNetWebSocket ctor, which immediately sets the socket into an aborted state.
                UnmanagedWebSocketContext unmanagedWebSocketContext = _root.WorkerRequest.GetWebSocketContext();
                WebSocketPipe             pipe = (unmanagedWebSocketContext != null) ? new WebSocketPipe(unmanagedWebSocketContext, PerfCounters.Instance) : null;
                webSocket = new AspNetWebSocket(pipe, _subProtocol);

                // slim down the HttpContext as much as possible to allow the GC to reclaim memory
                _httpContext.CompleteTransitionToWebSocket();

                // always install a new SynchronizationContext, even if the user is running in legacy SynchronizationContext mode
                AspNetSynchronizationContext syncContext = new AspNetSynchronizationContext(this);
                _httpContext.SyncContext = syncContext;

                bool webSocketRequestSucceeded = false;
                try {
                    // need to keep track of this in the manager so that we can abort if it the AppDomain goes down
                    AspNetWebSocketManager.Current.Add(webSocket);

                    // bump up the total count (the currently-executing count is recorded separately)
                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TOTAL_WEBSOCKETS);

                    // Release the reference to the user delegate (which might just be a simple initialization routine) so that
                    // the GC can claim it. The only thing that needs to remain alive is the Task itself, which we're referencing.
                    Task task = null;
                    syncContext.Send(_ => {
                        task = _userFunc(new AspNetWebSocketContextImpl(new HttpContextWrapper(_httpContext), _root.WorkerRequest, webSocket));
                    }, null);

                    // Was there an exception from user code? If so, rethrow (which logs).
                    ExceptionDispatchInfo exception = syncContext.ExceptionDispatchInfo;
                    if (exception != null)
                    {
                        exception.Throw();
                    }

                    _userFunc = null;
                    await task.ConfigureAwait(continueOnCapturedContext : false);

                    // Was there an exception from the earlier call to DoFlush? If so, rethrow (which logs).
                    // This needs to occur after the user's callback finishes, otherwise ASP.NET could try
                    // to complete the request while the callback is still accessing it.
                    if (flushExceptionDispatchInfo != null)
                    {
                        flushExceptionDispatchInfo.Throw();
                    }

                    // Any final state except Aborted is marked as 'success'.
                    // It's possible execution never reaches this point, e.g. if the user's
                    // callback throws an exception. In that case, 'webSocketRequestSucceeded'
                    // will keep its default value of false, and the performance counter
                    // will mark this request as having failed.

                    if (webSocket.State != WebSocketState.Aborted)
                    {
                        webSocketRequestSucceeded = true;
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_SUCCEEDED_WEBSOCKETS);
                    }
                }
                finally {
                    // we need to make sure the user can't call the WebSocket any more after this point
                    _isProcessingComplete = true;
                    webSocket.DisposeInternal();
                    AspNetWebSocketManager.Current.Remove(webSocket);

                    if (!webSocketRequestSucceeded)
                    {
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED_WEBSOCKETS);
                    }
                }
            }
            catch (Exception ex) {
                // don't let the exception propagate upward; just log it instead
                WebBaseEvent.RaiseRuntimeError(ex, null);
            }

            return(webSocket);
        }