Beispiel #1
0
        internal void timerMyHeartbeatTimer()
        {
            if (mInHeartBeatTimer)
            {
                // This should never happen: we are running this under a lock
                TheBaseAssets.MySYSLOG.WriteToLog(248, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("QueuedSender", $"QSender {MyTargetNodeChannel?.ToMLString()}: Internal error (timer reentered)", eMsgLevel.l2_Warning), true);
                return;
            }
            if (!TheBaseAssets.MasterSwitch || !IsQSenderReadyForHB || IsInWSPost || IsInPost || MyREST?.IsPosting > 0)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(248, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("QueuedSender", $"QSender {MyTargetNodeChannel?.ToMLString()} suspended due to: MS:{TheBaseAssets.MasterSwitch} IA:{IsAlive} ISSRFHB:{IsQSenderReadyForHB} INWSP:{IsInWSPost} INP:{IsInPost} RPCNT:{MyREST?.IsPosting}", eMsgLevel.l6_Debug), true);
                return; //New in 4.205: HB is not checked if QSender is in post (for example during a large telegram going to a browser)
            }

            if (MyTargetNodeChannel.IsWebSocket && !IsConnecting)
            {
                if (!TheCommonUtils.IsDeviceSenderType(MyTargetNodeChannel.SenderType)) //IDST-OK: Only update session state for none-devices
                {
                    TheBaseAssets.MySession.WriteSession(MyTargetNodeChannel.MySessionState);
                }
            }
            mInHeartBeatTimer = true;

            try
            {
                if (!IsConnecting && !IsConnected)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(248, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("QueuedSender", $"QSender {MyTargetNodeChannel?.ToMLString()} in illegal state (not connected AND not connecting) for Heartbeat!", eMsgLevel.l2_Warning), false);
                    FireSenderProblem(new TheRequestData()
                    {
                        ErrorDescription = "1304:Heartbeat found !Connected and !IsConnecting"
                    });
                    return;
                }
                if (!IsConnected && IsConnecting)
                {
                    ConnectRetries++;
                    if (ConnectRetries > TheBaseAssets.MyServiceHostInfo.TO.HeartBeatMissed)
                    {
                        TSM tMsg = new TSM("QueuedSender", $"Initial Connection failed. {MyTargetNodeChannel?.ToMLString()} might be down!", eMsgLevel.l2_Warning);
                        HeartBeatCnt = 0;
                        //FlushQueue();
                        tMsg.ORG = MyTargetNodeChannel.cdeMID.ToString();
                        TheBaseAssets.MySYSLOG.WriteToLog(248, tMsg, true);
                        FireSenderProblem(new TheRequestData()
                        {
                            ErrorDescription = $"1305:Connecting failed for {ConnectRetries} retries"
                        });
                        ConnectRetries = 0;
                        IsConnecting   = false;
                    }
                }
                else
                {
                    if (IsConnecting)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(248, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("QueuedSender", $"QSender {MyTargetNodeChannel?.ToMLString()} in illegal state (Connected AND Connecting) for Heartbeat!", eMsgLevel.l2_Warning), false);
                        return;
                    }
                    TheBaseAssets.MySYSLOG.WriteToLog(248, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("QueuedSender", "Enter HeartBeatTick for " + MyTargetNodeChannel, eMsgLevel.l6_Debug), true);
                    int Misses = TheBaseAssets.MyServiceHostInfo.TO.OnAdrenalin ? 2 : 1;
                    if (HeartBeatCnt > TheBaseAssets.MyServiceHostInfo.TO.HeartBeatMissed * Misses)
                    {
                        TSM tMsg = new TSM("QueuedSender", $"Too Many Heartbeats ({HeartBeatCnt}) missed - {MyTargetNodeChannel?.ToMLString()} might be down!", eMsgLevel.l2_Warning);
                        HeartBeatCnt = 0;
                        tMsg.ORG     = MyTargetNodeChannel.cdeMID.ToString();
                        TheBaseAssets.MySYSLOG.WriteToLog(248, tMsg, true);
                        FireSenderProblem(new TheRequestData()
                        {
                            ErrorDescription = "1306:Heartbeat failure!!"
                        });
                    }
                    else
                    {
                        if (HeartBeatCnt > TheBaseAssets.MyServiceHostInfo.TO.HeartBeatWarning)
                        {
                            TSM tMsg = new TSM("QueuedSender", $"More than {TheBaseAssets.MyServiceHostInfo.TO.HeartBeatWarning} ({HeartBeatCnt}) Heartbeats from {MyTargetNodeChannel?.ToMLString()} missed", eMsgLevel.l2_Warning)
                            {
                                ORG = MyTargetNodeChannel.cdeMID.ToString()
                            };
                            TheBaseAssets.MySYSLOG.WriteToLog(248, tMsg, true);
                        }
                        if (MyTargetNodeChannel != null) // && MyTargetNodeChannel.References > 0)  legacy
                        {
                            SendPickupMessage();
                        }
                        HeartBeatCnt++;
                    }
                }
            }
            catch (Exception e)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(248, new TSM("QueuedSender", $"Exception in Healthtimer for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l1_Error, e.ToString()), true);
            }
            finally
            {
                TheBaseAssets.MySYSLOG.WriteToLog(248, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("QueuedSender", $"Leave HeartBeatTick for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l6_Debug), false);
                mInHeartBeatTimer = false;
            }
        }
Beispiel #2
0
        private void sinkHeartBeatTimer(long NOTUSED)
        {
            try
            {
                TheDiagnostics.SetThreadName("HeartbeatTimer", true);
                mHeartBeatTicker++;
                TheBaseAssets.MySYSLOG.WriteToLog(2803, TSM.L(eDEBUG_LEVELS.EVERYTHING) ? null : new TSM("QSender", $"Enter HearbeatTimer for ORG:{MyTargetNodeChannel}", eMsgLevel.l7_HostDebugMessage));
                TheTimeouts tTO = TheBaseAssets.MyServiceHostInfo.TO;

                if (!IsHeartBeatAlive(tTO.DeviceCleanSweepTimeout * 2) && TheCommonUtils.IsDeviceSenderType(MyTargetNodeChannel?.SenderType ?? cdeSenderType.NOTSET) && MyTargetNodeChannel?.IsWebSocket == false)  //IDST-OK: Remove dead devices that might have hard disconnected (no correct disconnect) i.e. http browsers were just closed
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(2820, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("QSender", $"Forced Removal of QSender {MyTargetNodeChannel.ToMLString()} due to DeviceCleanSweep", eMsgLevel.l4_Message));
                    Guid?tTarget = MyTargetNodeChannel?.cdeMID;
                    DisposeSender(true);
                    if (tTarget.HasValue)
                    {
                        TheQueuedSenderRegistry.RemoveOrphan(tTarget.Value);
                        TheCommCore.PublishCentral(new TSM(eEngineName.ContentService, "CDE_DELETEORPHAN", tTarget.ToString()));
                    }
                    return;
                }
                if (!IsAlive && !MyTargetNodeChannel?.IsWebSocket == true)
                {
                    return;                                                        //NEW:V3 2013/12/13 allow for cloud reconnect if WebSockets
                }
                if ((mHeartBeatTicker % (tTO.HeartBeatRate * 2)) == 0)
                {
                    if (MyTargetNodeChannel?.SenderType != cdeSenderType.CDE_LOCALHOST)
                    {
                        timerMyHeartbeatTimer();
                    }
                    if (MyTargetNodeChannel?.SenderType == cdeSenderType.CDE_CLOUDROUTE && ((!IsConnected && !IsConnecting) || !IsAlive) && (mHeartBeatTicker % (tTO.HeartBeatRate * 10)) == 0) //tQ.MyTargetNodeChannel.IsWebSocket &&  NOW ALWAYS RECONNECT
                    {
                        TheCommonUtils.cdeRunAsync("ReconnectCloud", true, (o) => ReconnectCloud());
                    }
                    if (MyTargetNodeChannel?.SenderType != cdeSenderType.CDE_LOCALHOST && IsAlive && IsConnected) //!TheBaseAssets.MyServiceHostInfo.IsCloudService && !tQ.MyTargetNodeChannel.IsWebSocket &&
                    {
                        if (MyTargetNodeChannel?.IsWebSocket != true)
                        {
                            if (GetQueLength() == 0)
                            {
                                TheBaseAssets.MyServiceHostInfo.TO.MakeHeartPump(); // CODE REVIEW Markus: Isn't this backwards: we should pump faster while we have more work to do?
                                SendPickupMessage();                                //Pickup
                            }
                            else
                            {
                                TheBaseAssets.MyServiceHostInfo.TO.MakeHeartNormal();
                            }
                        }
                        else
                        {
                            SendPickupMessage(); //Pickup
                        }
                    }
                }
            }
            catch (Exception e)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(2821, new TSM("QSRegistry", $"Fatal Error in HealthTimer for QS:{this.cdeMID} and MTNC:{MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l1_Error, e.ToString()));
            }
        }
        internal static void SetResponseBuffer(TheRequestData pRequestData, TheChannelInfo pChannelInfo, bool pSendPulse, string NopTopic, Guid owner, string pRefreshToken)
        {
            if (string.IsNullOrEmpty(NopTopic))
            {
                TheQueuedSender tQ = null;
                if (pChannelInfo != null && pChannelInfo.cdeMID != Guid.Empty)    //Send to Device First
                {
                    tQ = TheQueuedSenderRegistry.GetSenderByGuid(pChannelInfo.cdeMID);
                }
                if (tQ != null)
                {
                    if (pRequestData.WebSocket != null)
                    {
                        if (tQ.GetQueLength() == 0)
                        {
                            tQ.SendPickupMessage();
                        }
                        return;
                    }
                    tQ.GetNextBackChannelBuffer(pRequestData);
                }
            }
            if (string.IsNullOrEmpty(NopTopic) && pRequestData.WebSocket != null)
            {
                return;                                                                   //NEW:3.084  && !pSendPulse removed          NEW:V3B3:2014-7-22 removed && pRequestData.ResponseBuffer != null
            }
            if (pRequestData.ResponseBuffer == null && pChannelInfo != null && (pSendPulse || (pChannelInfo.cdeMID != Guid.Empty || TheQueuedSenderRegistry.IsNodeIdInSenderList(pChannelInfo.cdeMID))))
            {
                TheDeviceMessage tDev = new TheDeviceMessage {
                    CNT = 0
                };
                //tDev.MET = 0;
                if (!string.IsNullOrEmpty(NopTopic))
                {
                    tDev.MSG = new TSM();   //Can be set without ORG and SID
                    if (owner != Guid.Empty)
                    {
                        tDev.MSG.OWN = owner.ToString();
                    }
                    if (NopTopic == "CDE_WSINIT")
                    {
                        NopTopic = TheCommCore.SetConnectingBufferStr(pChannelInfo, null);
                    }
                }
                if (pChannelInfo.SenderType != cdeSenderType.CDE_JAVAJASON) //4.209: No longer sending SID to Browser;
                {
                    if (TheBaseAssets.MyServiceHostInfo.EnableFastSecurity)
                    {
                        tDev.SID = pRequestData.SessionState.SScopeID;  //SECURITY: All responses will have same Scrambled ScopeID - but ok because this is init telegram or HB
                    }
                    else
                    {
                        tDev.SID = TheBaseAssets.MyScopeManager.GetScrambledScopeID(pRequestData.SessionState.SScopeID, false); //GRSI: high frequency
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(pRefreshToken))
                    {
                        tDev.SID = pRefreshToken;
                    }
                }
                tDev.FID = pRequestData.SessionState.GetNextSerial().ToString();
                if (TheCommonUtils.IsDeviceSenderType(pChannelInfo.SenderType)) //IDST-OK: Must create RSA for Devices
                {
                    TheCommonUtils.CreateRSAKeys(pRequestData.SessionState);
                    tDev.RSA = pRequestData.SessionState.RSAPublic;
                }
                tDev.NPA = TheBaseAssets.MyScopeManager.GetISBPath(TheBaseAssets.MyServiceHostInfo.RootDir, pChannelInfo.SenderType, TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType, pRequestData.SessionState.FID, pRequestData.SessionState.cdeMID, pRequestData.WebSocket != null);
                tDev.CNT = pSendPulse ? 1 : 0;
                tDev.TOP = NopTopic;
                tDev.DID = pChannelInfo.SenderType == cdeSenderType.CDE_JAVAJASON ? pChannelInfo.cdeMID.ToString() : TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString();

                //There will be only one Message here - single poke or Mini Command or NOP Pickup
                List <TheDeviceMessage> tDevList = new List <TheDeviceMessage> {
                    tDev
                };
                if (pChannelInfo.SenderType == cdeSenderType.CDE_JAVAJASON || TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType == cdeSenderType.CDE_MINI || pChannelInfo.SenderType == cdeSenderType.CDE_MINI || pRequestData.WebSocket != null)
                {
                    pRequestData.ResponseBuffer   = TheCommonUtils.CUTF8String2Array(TheCommonUtils.SerializeObjectToJSONString(tDevList));
                    pRequestData.ResponseMimeType = "application/json";
                }
                else
                {
                    pRequestData.ResponseBuffer   = TheCommonUtils.cdeCompressString(TheCommonUtils.SerializeObjectToJSONString(tDevList));
                    pRequestData.ResponseMimeType = "application/x-gzip";
                }
            }
            if (pRequestData.ResponseBuffer == null && pChannelInfo != null && pChannelInfo.cdeMID != Guid.Empty)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(290, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"Nothing to Send Back to {pChannelInfo?.ToMLString()}", eMsgLevel.l7_HostDebugMessage));
            }
        }
        private void TheWSSenderThread()
        {
            if (IsSenderThreadRunning /*|| MyTargetNodeChannel==null*/)
            {
                return;
            }
            if (MyTargetNodeChannel == null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(2371, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("WSQueuedSender", $"WSSender Thread could not be started because MTNC is null", eMsgLevel.l4_Message));
                return;
            }
            TheDiagnostics.SetThreadName($"QSender:{MyTargetNodeChannel} WSSenderThread", true);
            IsSenderThreadRunning = true;
            mre = new ManualResetEvent(false);

            CloudCounter++;
            StringBuilder tSendBufferStr = new StringBuilder(TheBaseAssets.MyServiceHostInfo?.IsMemoryOptimized == true ? 1024 : TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType] * 2);
            int           QDelay         = TheCommonUtils.CInt(TheBaseAssets.MySettings.GetSetting("ThrottleWS"));

            if (QDelay < 2)
            {
                QDelay = 2;
            }
            if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON && TheBaseAssets.MyServiceHostInfo.WsJsThrottle > QDelay)
            {
                QDelay = TheBaseAssets.MyServiceHostInfo.WsJsThrottle;
            }
            if (eventSenderThreadRunning != null)
            {
                TheCommonUtils.cdeRunAsync("EventSenderThreadRunning", true, (p) => { eventSenderThreadRunning(this); });
            }
            MyISBlock?.FireEvent("SenderThreadCreated");
            try
            {
                while (TheBaseAssets.MasterSwitch && IsAlive && MyWebSocketProcessor.IsActive && IsSenderThreadRunning)
                {
                    while (TheBaseAssets.MasterSwitch && IsAlive && MyWebSocketProcessor.IsActive && IsSenderThreadRunning && (MyTargetNodeChannel.MySessionState == null || IsConnecting || IsInWSPost || !MyWebSocketProcessor.ProcessingAllowed || MyCoreQueue.Count == 0))
                    {
                        if (IsInWSPost && MyCoreQueue.Count > 200)
                        {
                            TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("WSQueuedSender", $"IsInWSPost was still on and has been reset for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l2_Warning));
                            IsInWSPost = false;
                        }
                        if (MyTargetNodeChannel.MySessionState == null && !IsConnecting && MyCoreQueue.Count > 0)
                        {
                            break;
                        }
                        mre.WaitOne(QDelay);
                        // System.Diagnostics.Debug.WriteLine($"Waiting :{IsAlive} {MyCoreQueue.Count} {IsConnected} {IsConnecting} {IsInWSPost} {MyWebSocketProcessor.ProcessingAllowed}");
                    }
                    if (!TheBaseAssets.MasterSwitch || !IsAlive || !MyWebSocketProcessor.IsActive || MyTargetNodeChannel.MySessionState == null)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("WSQueuedSender", $"WSSender Thread Condition failed - Ending SenderThread IsAlive:{IsAlive} MyWSProccAlive:{(MyWebSocketProcessor == null ? false : MyWebSocketProcessor.IsActive)},SessionState:{(MyTargetNodeChannel?.MySessionState != null)} IsConnecting:{IsConnecting} IsConnected:{IsConnected}", eMsgLevel.l2_Warning));
                        break;
                    }
                    IsInWSPost = true;

                    int MCQCount  = 0;
                    int IsBatchOn = 0;
                    int FinalCnt  = 0;
#if CDE_NET35
                    tSendBufferStr = new StringBuilder(TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType] * 2);
#else
                    tSendBufferStr.Clear();
#endif
                    tSendBufferStr.Append("[");
                    do
                    {
                        TheCoreQueueContent tQueued = GetNextMessage(out MCQCount);
                        if (tQueued != null)
                        {
                            TheDeviceMessage tDev = new TheDeviceMessage();
                            if (tQueued.OrgMessage != null)
                            {
                                if (tQueued.OrgMessage.ToCloudOnly() && MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE)
                                {
                                    tQueued.OrgMessage.SetToCloudOnly(false);
                                }

                                tQueued.OrgMessage.GetNextSerial(tQueued.SubMsgCnt);
                                tDev.MSG = tQueued.OrgMessage;
                            }
                            var tCurSessState = MyTargetNodeChannel.MySessionState;
                            if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON)
                            {
                                if (tDev.MSG == null)
                                {
                                    // we have a pickup: never send to browser
                                    if (IsBatchOn > 0)
                                    {
                                        continue;   //ignore HB as other messages are already in the queue
                                    }
                                    else
                                    {
                                        IsInWSPost = false;
                                        continue;   //dont sent empty Message to Browser - HB not necessary
                                    }
                                }
                                else
                                {
                                    tDev.MSG.SEID = null; //SECURITY: Don't send SEID to Browser
                                    tDev.MSG.UID  = null; //SECURITY: Don't send SEID to Browser
                                    tDev.MSG.SID  = null; //SECURITY: Don't send SID to Browser
                                }
                                tDev.DID = MyTargetNodeChannel.cdeMID.ToString();
                            }
                            else
                            {
                                if (tDev.MSG == null) // CODE REVIEW: DO we also need to detect other simple topics with response message and ensure they get into their own batch?
                                {
                                    // we have a pickup (only to be sent if nothing else is being sent)
                                    if (IsBatchOn > 0)
                                    {
                                        // Ignore pickups if another message is already being sent (can happen with race condition between check before pickup enqueue and dequeue here - another TSM could be enqueue in that time)
                                        continue;
                                    }
                                    else
                                    {
                                        // Close the batch here so that no other TSM gets into the same batch
                                        // Possible optimization: check if other TSMs are available and skip the pickup here as well
                                        IsBatchOn = -1; // IsInWSPost = false;
                                    }
                                }
                                tDev.DID = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString();
                                if (!string.IsNullOrEmpty(tQueued?.OrgMessage?.SID))
                                {
                                    tDev.SID = tQueued.OrgMessage.SID;
                                }
                                else
                                {
                                    if (TheBaseAssets.MyServiceHostInfo.EnableFastSecurity)
                                    {
                                        tDev.SID = tCurSessState.SScopeID;  //SECURITY: All tDevs will have same Session Scrambled ScopeID - 4.209: SID from TSM if set.
                                    }
                                    else
                                    {
                                        tDev.SID = TheBaseAssets.MyScopeManager.GetScrambledScopeID(tCurSessState.SScopeID, false);  //GRSI: high frequency
                                    }
                                }
                            }

                            TheCDEKPIs.IncrementKPI(eKPINames.QSSent);
                            tDev.TOP = tQueued.Topic;
                            tDev.FID = tCurSessState.GetNextSerial().ToString();
                            if (TheCommonUtils.IsDeviceSenderType(MyTargetNodeChannel.SenderType))  //IDST-OK: Must create RSA for Devices
                            {
                                TheCommonUtils.CreateRSAKeys(tCurSessState);
                                if (TheBaseAssets.MyServiceHostInfo.SecurityLevel > 3)
                                {
                                    tDev.RSA = tCurSessState.RSAPublic;  //TODO: Make depending on switch (HighSecurity=RSAGeneration every three seconds
                                }
                            }
                            if (MyTargetNodeChannel.SenderType != cdeSenderType.CDE_CLOUDROUTE) //CODE-REVIEW: 4.0113 is this still valid: Must not reset HB if talking to cloud due to Cloud-Disconnect issue
                            {
                                ResetHeartbeatTimer(false, tCurSessState);
                            }
                            if (!cdeSenderType.CDE_JAVAJASON.Equals(MyTargetNodeChannel.SenderType))
                            {
                                tDev.NPA = TheBaseAssets.MyScopeManager.GetISBPath(TheBaseAssets.MyServiceHostInfo.RootDir, MyTargetNodeChannel.SenderType, TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType, tCurSessState.FID, tCurSessState.cdeMID, true);
                            }
                            if (MyTargetNodeChannel.MySessionState == null || MyTargetNodeChannel.MySessionState.HasExpired)
                            {
                                throw new Exception($"Session was deleted or has expired ({MyTargetNodeChannel?.MySessionState?.HasExpired})");
                            }
                            #region Batch Serialization
                            IsBatchOn++;
                            FinalCnt++;
                            var tToAdd = TheCommonUtils.SerializeObjectToJSONString(tDev);
                            if (MCQCount == 0 || tQueued.IsChunked || IsBatchOn > TheBaseAssets.MyServiceHostInfo.MaxBatchedTelegrams)
                            {
                                if (MCQCount != 0)
                                {
                                    tDev.CNT = MCQCount;
                                }
                                IsBatchOn = 0;
                            }
                            else
                            {
                                if (tSendBufferStr.Length + tToAdd.Length > TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType])
                                {
                                    tDev.CNT  = MCQCount;
                                    IsBatchOn = 0;
                                }
                            }
                            if (tSendBufferStr.Length > 1)
                            {
                                tSendBufferStr.Append(",");
                            }
                            tSendBufferStr.Append(tToAdd);
                            #endregion
                        }
                        else
                        {
                            IsBatchOn = 0;
                        }
                    } while (IsBatchOn > 0 && IsInWSPost && TheBaseAssets.MasterSwitch);
                    if (!IsInWSPost || tSendBufferStr.Length < 2)
                    {
                        IsInWSPost = false;
                        continue;
                    }
                    tSendBufferStr.Append("]");
                    if (FinalCnt > 1)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("WSQueuedSender", $"Batched:{FinalCnt}", eMsgLevel.l3_ImportantMessage));
                    }

                    if (!cdeSenderType.CDE_JAVAJASON.Equals(MyTargetNodeChannel.SenderType))
                    {
                        MyWebSocketProcessor.PostToSocket(null, TheCommonUtils.cdeCompressString(tSendBufferStr.ToString()), true, false);
                    }
                    else
                    {
                        MyWebSocketProcessor.PostToSocket(null, TheCommonUtils.CUTF8String2Array(tSendBufferStr.ToString()), false, false);
                    }
                    IsInWSPost = false;
                }
                TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("WSQueuedSender", $"WSQSenderThread was closed for {MyTargetNodeChannel?.ToMLString()} IsAlive:{IsAlive} MyWSProccAlive:{(MyWebSocketProcessor == null ? "Is Null" : MyWebSocketProcessor?.IsActive.ToString())},SessionState:{(MyTargetNodeChannel?.MySessionState != null)} IsConnecting:{IsConnecting} IsConnected:{IsConnected}", eMsgLevel.l1_Error));
            }
            catch (Exception e)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("WSQueuedSender", "Exception in WSSenderThread.", eMsgLevel.l1_Error, "Error:" + e));
            }
            finally
            {
                IsInWSPost            = false;
                IsSenderThreadRunning = false;
                StopHeartBeat();
            }
            if (IsAlive || (MyWebSocketProcessor != null && MyWebSocketProcessor.IsActive))
            {
                IsAlive = false;
                if (MyWebSocketProcessor != null)
                {
                    MyWebSocketProcessor.Shutdown(true, "1310:SenderThread Closed");
                }
            }
            CloudCounter--;
        }
Beispiel #5
0
 internal ICollection <string> CombineSubscriptions(List <string> pTopics, out bool WasUpdated, bool AreOwnedSubs = false)
 {
     WasUpdated = false;
     if (pTopics == null)                 //pTopics = new List<string>();
     {
         return(MySubscriptions.TheKeys); //4.1042: Tuning
     }
     lock (CombineSubscriptionLock)
     {
         for (int i = 0; i < pTopics.Count; i++)
         {
             string tSubTopicRealScope = TheBaseAssets.MyScopeManager.GetRealScopeIDFromTopic(pTopics[i], out string tTopicName);       //Medium Frequency
             if (string.IsNullOrEmpty(tTopicName))
             {
                 continue;
             }
             if (MyTargetNodeChannel?.HasRScope(tSubTopicRealScope) != true)
             {
                 TheBaseAssets.MySYSLOG.WriteToLog(296, string.IsNullOrEmpty(tTopicName) || TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("QueuedSender", $"New Subscription to Topic={pTopics[i]} not allowed due to different Scope", eMsgLevel.l2_Warning));
                 continue;
             }
             if (string.IsNullOrEmpty(tSubTopicRealScope) && !TheBaseAssets.MyServiceHostInfo.AllowUnscopedMesh)
             {
                 if (TheBaseAssets.MyScopeManager.IsScopingEnabled && !string.IsNullOrEmpty(MyTargetNodeChannel.RealScopeID) && !TheCommonUtils.IsDeviceSenderType(MyTargetNodeChannel.SenderType))  //RScope-OK //IDST-??: check of unscoped telegrams - might need to go to unscoped devices?
                 {
                     TheBaseAssets.MySYSLOG.WriteToLog(296, string.IsNullOrEmpty(tTopicName) || TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("QueuedSender", $"New Subscription to UNSCOPED Topic={pTopics[i]} not allowed as current node is Scoped!", eMsgLevel.l2_Warning));
                     continue;
                 }
                 //Coming later for more security: No more Unscoped subscriptions except the plugin service has "IsAllowedUnscopedProcessing" enabled
                 //if (!TheBaseAssets.MyScopeManager.IsScopingEnabled && string.IsNullOrEmpty(tChannelRealScope) && pTopics[i] != eEngineName.ContentService && pTopics[i] != eEngineName.NMIService)
                 //{
                 //    TheBaseAssets.MySYSLOG.WriteToLog(296, string.IsNullOrEmpty(tTopicName) || TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("QueuedSender", $"New Subscription to UNSCOPED Topic={pTopics[i]} not allowed on unscoped Node!", eMsgLevel.l2_Warning));
                 //    continue;
                 //}
             }
             bool WasFound = false;
             foreach (string t in MySubscriptions.TheKeys)
             {
                 if (!string.IsNullOrEmpty(tSubTopicRealScope))
                 {
                     if (tSubTopicRealScope.Equals(MySubscriptions.MyRecords[t].RScopeID) && tTopicName.Equals(MySubscriptions.MyRecords[t].Topic))
                     {
                         WasFound = true;
                         break;
                     }
                 }
                 else
                 {
                     if (pTopics[i].Equals(t))
                     {
                         WasFound = true;
                         break;
                     }
                 }
             }
             if (!WasFound)
             {
                 MySubscriptions.AddOrUpdateItemKey(pTopics[i], new TheSubscriptionInfo()
                 {
                     RScopeID = tSubTopicRealScope, Topic = tTopicName, ToServiceOnly = AreOwnedSubs
                 }, null);
                 WasUpdated = true;
             }
         }
         return(MySubscriptions.TheKeys);
     }
 }