Exemplo n.º 1
0
        static async Task WhenConnectionIsEstablishedAsync(this ManagedWebSocket websocket)
        {
            // update status
            websocket.SetStatus("Initializing");
            var correlationID = UtilityService.NewUUID;

            // prepare session
            try
            {
                var query   = websocket.RequestUri.ParseQuery();
                var session = Global.GetSession(websocket.Headers, query, $"{(websocket.RemoteEndPoint as IPEndPoint).Address}");

                // update session identity
                session.SessionID = query.TryGetValue("x-session-id", out var sessionID) ? sessionID.Url64Decode() : "";
                if (string.IsNullOrWhiteSpace(session.SessionID))
                {
                    throw new InvalidRequestException("Session identity is not found");
                }

                // update device identity
                session.DeviceID = query.TryGetValue("x-device-id", out var deviceID) ? deviceID.Url64Decode() : "";
                if (string.IsNullOrWhiteSpace(session.DeviceID))
                {
                    throw new InvalidRequestException("Device identity is not found");
                }

                // update session
                websocket.Set("Session", session);
                await websocket.PrepareConnectionInfoAsync(correlationID, session, Global.CancellationTokenSource.Token, RTU.Logger).ConfigureAwait(false);

                // wait for few times before connecting to API Gateway Router because RxNET needs that
                if (query.ContainsKey("x-restart"))
                {
                    await Task.WhenAll(
                        websocket.SendAsync(new UpdateMessage {
                        Type = "Knock"
                    }),
                        Task.Delay(345, Global.CancellationTokenSource.Token)
                        ).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                await RTU.WebSocket.CloseWebSocketAsync(websocket, ex is InvalidRequestException?WebSocketCloseStatus.InvalidPayloadData : WebSocketCloseStatus.InternalServerError, ex is InvalidRequestException?$"Request is invalid => {ex.Message}" : ex.Message).ConfigureAwait(false);

                return;
            }

            // subscribe an updater to push messages to client device
            websocket.Set("Updater", Services.Router.IncomingChannel.RealmProxy.Services
                          .GetSubject <UpdateMessage>("messages.update")
                          .Subscribe(
                              async message => await websocket.PushAsync(message).ConfigureAwait(false),
                              async exception => await Global.WriteLogsAsync(RTU.Logger, "Http.InternalAPIs", $"Error occurred while fetching an updating message => {exception.Message}", exception).ConfigureAwait(false)
                              )
                          );

            // subscribe a communicator to update related information
            websocket.Set("Communicator", Services.Router.IncomingChannel.RealmProxy.Services
                          .GetSubject <CommunicateMessage>("messages.services.apigateway")
                          .Subscribe(
                              async message => await websocket.CommunicateAsync(message).ConfigureAwait(false),
                              async exception => await Global.WriteLogsAsync(RTU.Logger, "Http.InternalAPIs", $"Error occurred while fetching an inter-communicating message => {exception.Message}", exception).ConfigureAwait(false)
                              )
                          );

            // update status
            websocket.SetStatus("Connected");
            if (Global.IsVisitLogEnabled)
            {
                await Global.WriteLogsAsync(RTU.Logger, "Http.Visits", $"The real-time updater (RTU) is started" + "\r\n" + websocket.GetConnectionInfo() + "\r\n" + $"- Status: {websocket.GetStatus()}", null, Global.ServiceName, LogLevel.Information, correlationID).ConfigureAwait(false);
            }
        }
Exemplo n.º 2
0
        static async Task WhenMessageIsReceivedAsync(this ManagedWebSocket websocket, WebSocketReceiveResult result, byte[] data)
        {
            // receive continuous messages
            object message;

            if (!result.EndOfMessage)
            {
                websocket.Extra["Message"] = websocket.Extra.TryGetValue("Message", out message) ? (message as byte[]).Concat(data) : data;
                return;
            }

            // last message or single small message
            var stopwatch     = Stopwatch.StartNew();
            var correlationID = UtilityService.NewUUID;

            if (websocket.Extra.TryGetValue("Message", out message))
            {
                message = (message as byte[]).Concat(data);
                websocket.Extra.Remove("Message");
            }
            else
            {
                message = data;
            }

            // check message
            var requestMsg = result.MessageType.Equals(WebSocketMessageType.Text) ? (message as byte[]).GetString() : null;

            if (string.IsNullOrWhiteSpace(requestMsg))
            {
                return;
            }

            // wait for the initializing process is completed
            while ("Initializing".IsEquals(websocket.GetStatus()))
            {
                await Task.Delay(UtilityService.GetRandomNumber(123, 456), Global.CancellationTokenSource.Token).ConfigureAwait(false);
            }

            // check session
            var session = websocket.Get <Session>("Session");

            if (session == null)
            {
                await Task.WhenAll
                (
                    Global.WriteLogsAsync(RTU.Logger, "Http.InternalAPIs", $"No session is attached - Request: {requestMsg}", null, Global.ServiceName, LogLevel.Critical, correlationID),
                    RTU.WebSocket.CloseWebSocketAsync(websocket, WebSocketCloseStatus.PolicyViolation, "No session")
                ).ConfigureAwait(false);

                return;
            }

            // prepare
            var requestObj  = requestMsg.ToExpandoObject();
            var serviceName = requestObj.Get("ServiceName", "");
            var objectName  = requestObj.Get("ObjectName", "");
            var verb        = requestObj.Get("Verb", "GET").ToUpper();
            var query       = new Dictionary <string, string>(requestObj.Get("Query", new Dictionary <string, string>()), StringComparer.OrdinalIgnoreCase);

            query.TryGetValue("object-identity", out var objectIdentity);

            // visit logs
            if (Global.IsVisitLogEnabled)
            {
                await Global.WriteLogsAsync(RTU.Logger, "Http.Visits",
                                            $"Request starting {verb} " + $"/{serviceName}{(string.IsNullOrWhiteSpace(objectName) ? "" : $"/{objectName}")}{(string.IsNullOrWhiteSpace(objectIdentity) ? "" : $"/{objectIdentity}")}".ToLower() + (query.TryGetValue("x-request", out var xrequest) ? $"?x-request={xrequest}" : "") + " HTTPWS/1.1" + " \r\n" +