예제 #1
0
        public async Task Invoke(
            HttpContext httpContext,
            IChatroomsManager chatroomsManager,
            ILogger <WebSocketSession> logger)
        {
            if (httpContext is null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            if (chatroomsManager is null)
            {
                throw new ArgumentNullException(nameof(chatroomsManager));
            }

            if (!httpContext.WebSockets.IsWebSocketRequest || httpContext.Request.Path != ChatClientEndpoint)
            {
                await _next(httpContext);

                return;
            }

            if (logger is null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            var webSocket = await httpContext.WebSockets.AcceptWebSocketAsync();

            using var webSocketSession = new WebSocketSession(webSocket, _messageParser, logger);

            var connectionRequest = webSocketSession.ReceivedMessages
                                    .Where(msg => msg is ConnectionRequestMessage)
                                    .Timeout(_connectionTimeout, Observable.Return(ClientMessageBase.Empty))
                                    .Take(1)
                                    .Wait() as ConnectionRequestMessage;

            if (connectionRequest is null)
            {
                httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
                await httpContext.Response.CompleteAsync();

                return;
            }

            httpContext.Request.Headers.Add(GetAuthorizationHeader(connectionRequest));
            var authResults = await Task.WhenAll(
                httpContext.AuthenticateAsync(JwtSchemes.Admin),
                httpContext.AuthenticateAsync(JwtSchemes.User));

            if (authResults.All(result => !result.Succeeded))
            {
                await httpContext.Response.CompleteAsync();

                return;
            }

            var sessionId = Guid.NewGuid();

            using var chatClient = new NotificationClient(
                      connectionRequest.UserId,
                      sessionId,
                      webSocketSession,
                      chatroomsManager,
                      _notificationsService);

            webSocketSession.EnqueueMessage(new ConnectedMessage {
                SessionId = sessionId,
            });

            await webSocketSession.Lifetime.Task;
        }