/// <summary> /// Processes incoming Messages /// If a Batch comes in, only the first message must have a valid NPA Path /// </summary> internal static void ProcessClientDeviceMessage(TheQueuedSender MyQSender, TheRequestData pRequestData, List <TheDeviceMessage> tDevList) { var toRemove = new List <TheDeviceMessage>(); foreach (TheDeviceMessage tDev in tDevList) { if (string.IsNullOrEmpty(tDev.NPA)) { return; // CODE REVIEW: Really stop processing all subsequent TDMs here (malformed TDM -> security)? } string NPA = tDev.NPA.Substring(4); if (NPA.EndsWith(".ashx", StringComparison.OrdinalIgnoreCase)) { NPA = NPA.Substring(0, NPA.Length - 5); } if (TheBaseAssets.MyScopeManager.ParseISBPath(NPA, out Guid? ttSessionID, out cdeSenderType tSenderType, out long tFID, out string tVersion)) { Guid tSessionID = TheCommonUtils.CGuid(ttSessionID); Guid tDeviceID = TheCommonUtils.CGuid(tDev.DID); lock (TheBaseAssets.MySession.GetLock()) //CODE-REVIEW: VERY expensive lock! Really necessary? { var myTargetNodeChannel = MyQSender.MyTargetNodeChannel; if (MyQSender.IsConnected && myTargetNodeChannel.MySessionState != null) //!=null new in 3.2 { if (!tSessionID.Equals(myTargetNodeChannel.MySessionState.cdeMID)) { Guid tOldID = myTargetNodeChannel.MySessionState.cdeMID; myTargetNodeChannel.MySessionState = TheBaseAssets.MySession.ValidateSEID(tSessionID); //Measure Frequency if (myTargetNodeChannel.MySessionState == null) { TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("CoreComm", $"No exiting session for remote node found. Using new session (possible reason: fast cloud reconnect) ...new: {tSessionID} old: {tOldID}", eMsgLevel.l2_Warning), true); myTargetNodeChannel.MySessionState = pRequestData.SessionState; } else { TheBaseAssets.MySession.RemoveSessionByID(tOldID); } } } if (tDeviceID != Guid.Empty && tDeviceID != myTargetNodeChannel.cdeMID) { if (myTargetNodeChannel.SenderType == cdeSenderType.CDE_CUSTOMISB) { if (myTargetNodeChannel.TruDID != tDeviceID) { myTargetNodeChannel.TruDID = tDeviceID; TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", $"Custom ISB sets TruDID to: {TheCommonUtils.GetDeviceIDML(tDeviceID)} for MTNC: {myTargetNodeChannel.ToMLString()}", eMsgLevel.l4_Message), true); } } else { TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", $"Different DeviceIDs received ...new: {TheCommonUtils.GetDeviceIDML(tDeviceID)} old: {TheCommonUtils.GetDeviceIDML(myTargetNodeChannel.cdeMID)} {(myTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE ? "For CloudRoute and Service normal" : "")}", eMsgLevel.l2_Warning), true); TheBaseAssets.MySession.RemoveSessionsByDeviceID(myTargetNodeChannel.cdeMID, Guid.Empty); TheQueuedSenderRegistry.UpdateQSenderID(myTargetNodeChannel.cdeMID, tDeviceID); myTargetNodeChannel.cdeMID = tDeviceID; if (pRequestData.DeviceID != tDeviceID) { TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", $"Different DeviceIDs in DID and Request ...DID: {TheCommonUtils.GetDeviceIDML(tDeviceID)} Request: {TheCommonUtils.GetDeviceIDML(myTargetNodeChannel.cdeMID)}", eMsgLevel.l2_Warning), true); pRequestData.DeviceID = tDeviceID; } switch (pRequestData.ResponseMimeType) { case "cde/mini": myTargetNodeChannel.SenderType = cdeSenderType.CDE_MINI; break; } } } if (myTargetNodeChannel.MySessionState == null) { myTargetNodeChannel.MySessionState = TheBaseAssets.MySession.GetOrCreateSessionState(tSessionID, pRequestData); } myTargetNodeChannel.MySessionState.SiteVersion = tVersion; myTargetNodeChannel.MySessionState.cdeMID = tSessionID; myTargetNodeChannel.MySessionState.CurrentURL = myTargetNodeChannel.TargetUrl; // Keep the RSA public key of the other party, so we can use it to encrypt data when sending to that party in the future if (!String.IsNullOrEmpty(tDev.RSA)) { myTargetNodeChannel.MySessionState.RSAPublicSend = tDev.RSA; } if (MyQSender.IsConnecting && !MyQSender.IsConnected) { MyQSender.IsConnected = true; if (myTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE) { if (TheBaseAssets.MyServiceHostInfo.IsIsolated && TheBaseAssets.MyServiceHostInfo.MasterNode == Guid.Empty) { TheBaseAssets.MyServiceHostInfo.MasterNode = myTargetNodeChannel.cdeMID; TheQueuedSenderRegistry.SendMasterNodeQueue(); } MyQSender.StartHeartBeat(); TheBaseAssets.MySYSLOG.WriteToLog(23055, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("CoreComm", $"Cloud Route is back up to {myTargetNodeChannel.ToMLString()}", eMsgLevel.l4_Message)); if (TheQueuedSenderRegistry.eventCloudIsBackUp != null) { TheCommonUtils.cdeRunAsync("QS-StartEngineNU", true, o => { TheQueuedSenderRegistry.eventCloudIsBackUp(TheCDEngines.MyContentEngine, myTargetNodeChannel); }); } } if (MyQSender.eventConnected != null) { TheCommonUtils.cdeRunAsync("QueueConnected", true, (p) => { MyQSender.eventConnected(MyQSender, myTargetNodeChannel); }); } MyQSender.MyISBlock?.FireEvent("Connected"); } pRequestData.SessionState = myTargetNodeChannel.MySessionState; MyQSender?.SetLastHeartbeat(myTargetNodeChannel.MySessionState); } if (!string.IsNullOrEmpty(tDev.TOP) && tDev.TOP.StartsWith("CDE_CONNECT")) { string[] tP = TheCommonUtils.cdeSplit(tDev.TOP, ";:;", true, true); if (tP.Length > 1) { string tEngs = tP[1]; TheCommonUtils.cdeRunAsync("QS-StartEngineNU", false, o => { TheCDEngines.StartEngineWithNewUrl(MyQSender?.MyTargetNodeChannel, tEngs); }); } if (tDevList.Count > 1) { if (toRemove == null) { toRemove = new List <TheDeviceMessage>(); } toRemove.Add(tDev); continue; } else { return; } } if (string.IsNullOrEmpty(tDev.TOP) || tDev.TOP.StartsWith("CDE_PICKUP") || tDev.TOP.StartsWith("CDE_WSINIT")) { TheBaseAssets.MySYSLOG.WriteToLog(23056, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"Heartbeat received {MyQSender?.MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l4_Message)); if (tDevList.Count > 1) { if (toRemove == null) { toRemove = new List <TheDeviceMessage>(); } toRemove.Add(tDev); continue; } else { return; } } break; //Found valid path and can go out } } if (toRemove != null) { foreach (var tDev in toRemove) { tDevList.Remove(tDev); } } TheCommonUtils.cdeRunAsync("QS-UpCo2Exec", false, o => { pRequestData.ResponseBuffer = null; DoExecuteCommand(null, MyQSender, false, pRequestData, tDevList); }, tDevList); }