// Register for history on our Thing
 public void ConsumeHistory()
 {
     if (testThing != null)
     {
         TheHistoryParameters historyParameters = new TheHistoryParameters
         {
             Properties                = properties,
             SamplingWindow            = TimeSpan.FromMilliseconds(5000), // Every 5 seconds
             ReportUnchangedProperties = true,
             ReportInitialValues       = true,
             Persistent                = true,
             MaintainHistoryStore      = false,
             ComputeAvg                = true,
             ComputeMax                = true,
             ComputeMin                = true
         };
         historyToken = testThing.RegisterForUpdateHistory(historyParameters);
         TheQueuedSenderRegistry.RegisterHealthTimer((l) =>
         {
             // Every 6 seconds, log the aggregated values. Sampling window for historian is 5 seconds.
             if (l % 6 == 0)
             {
                 LogChanges(true);
             }
         });
     }
 }
        /// <summary>
        /// Construtor for network related events
        /// </summary>
        /// <param name="onNewInterfaceSink"></param>
        /// <param name="onDeletedInterfaceSink"></param>
        public TheNetworkInfo(Action <object, TheIPDef> onNewInterfaceSink, Action <object, TheIPDef> onDeletedInterfaceSink)
        {
            TheBaseAssets.MySYSLOG.WriteToLog(138, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("UPnP", "Enter NetworkInfo"));

            TheQueuedSenderRegistry.RegisterHealthTimer(PollInterface);
            MyHostName = cdeGetHostName();
            TheBaseAssets.MySYSLOG.WriteToLog(139, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("UPnP", "NetworkInfo - HostName :" + MyHostName));
            GetLocalIPs(true);
            if (onNewInterfaceSink != null)
            {
                OnNewInterfaceEvent += onNewInterfaceSink;
                foreach (TheIPDef address in AddressTable.Values)
                {
                    if (address.IsDnsEnabled)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(141, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("UPnP", string.Format("NetworkInfo - Init-Address: {0} of {1}", address, AddressTable.Count), eMsgLevel.l3_ImportantMessage));
                        OnNewInterfaceEvent?.Invoke(this, address);
                    }
                }
            }
            if (OnInterfaceDisabledEvent != null)
            {
                OnInterfaceDisabledEvent += onDeletedInterfaceSink;
            }
            TheBaseAssets.MySYSLOG.WriteToLog(144, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("UPnP", "NetworkInfo - All Interfaces Initialized"));
        }
Beispiel #3
0
        internal static TheNodeInfoHeader GetInfoHeaderJSON()
        {
            var tHead = new TheNodeInfoHeader {
                CloudRoutes    = new List <TheServiceRouteInfo>(),
                NodeID         = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID,
                NodeName       = TheBaseAssets.MyServiceHostInfo.NodeName,
                BuildVersion   = TheBaseAssets.BuildVersion,
                CurrentVersion = TheBaseAssets.CurrentVersionInfo,
                ScopeHash      = TheBaseAssets.MyScopeManager.IsScopingEnabled ? TheBaseAssets.MyScopeManager.ScopeID.Substring(0, 4).ToUpper() : "unscoped",
                OSInfo         = TheBaseAssets.MyServiceHostInfo.OSInfo
            };
            var CNs = TheQueuedSenderRegistry.GetCloudNodes(true);

            if (CNs.Count > 0)
            {
                foreach (var tQ in CNs)
                {
                    var tInfo = new TheServiceRouteInfo
                    {
                        Url            = tQ.MyTargetNodeChannel.TargetUrl,
                        IsConnected    = tQ.IsConnected,
                        IsConnecting   = tQ.IsConnecting,
                        LastError      = tQ.GetLastError(),
                        ErrorCode      = tQ.GetLastErrorCode(),
                        LastHB         = (tQ.GetLastHeartBeat() == DateTimeOffset.MinValue ? "not yet" : $"{TheCommonUtils.GetDateTimeString(tQ.GetLastHeartBeat(), -1)}"),
                        ConnectedSince = (tQ.MyLastConnectTime == DateTimeOffset.MinValue ? "not yet" : $"{TheCommonUtils.GetDateTimeString(tQ.MyLastConnectTime, -1)}"),
                        IsAlive        = tQ.IsAlive,
                        UsesWS         = tQ.HasWebSockets()
                    };
                    tInfo.Status = $"{tInfo.Url} (Connected: {(tInfo.IsConnected ? "Yes, all is good" : (tInfo.IsConnecting ? "Not, yet - trying to connect" : "No, and not yet trying to connect again!"))}{(!string.IsNullOrEmpty(tInfo.LastError) ? $" Last Error: {tInfo.LastError}" : "")})";
                    tHead.CloudRoutes.Add(tInfo);
                }
            }
            return(tHead);
        }
Beispiel #4
0
        internal void StartHeartBeat()
        {
            if (IsQSenderReadyForHB)
            {
                return;
            }
            IsQSenderReadyForHB = true;
            if (MyTSMHistory == null)
            {
                MyTSMHistory = new TheMirrorCache <TheSentRegistryItem>(TheBaseAssets.MyServiceHostInfo.TO.QSenderDejaSentTime);
            }

            if (!TheBaseAssets.MyServiceHostInfo.UseHBTimerPerSender)
            {
                TheQueuedSenderRegistry.RegisterHBTimer(sinkHeartBeatTimer);
            }
            else
            {
                lock (lockStartLock)
                {
                    if (mMyHeartBeatTimer == null)
                    {
                        mMyHeartBeatTimer = new Timer(sinkHeartBeatTimerLocal, null, TheBaseAssets.MyServiceHostInfo.TO.QSenderHealthTime, TheBaseAssets.MyServiceHostInfo.TO.QSenderHealthTime);
                    }
                }
            }
            InitHeartbeatTimer();
        }
        public override bool Init()
        {
            if (!mIsInitStarted)
            {
                mIsInitStarted          = true;
                MyBaseThing.StatusLevel = 4;
                MyBaseThing.LastMessage = "Logger Service has started";

                MyBaseThing.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessage);
                MyBaseEngine.RegisterEvent(eEngineEvents.ThingDeleted, OnThingDeleted);

                cdeP tP = null;
                if (TheBaseAssets.MyServiceHostInfo.DisableConsole)
                {
                    TheThing.SetSafePropertyBool(MyBaseThing, "DisableStandardLog", TheBaseAssets.MyServiceHostInfo.DisableConsole);
                }
                else
                {
                    tP = GetProperty("DisableStandardLog", true);
                }
                tP.RegisterEvent(eThingEvents.PropertyChanged, sinkDisableChanged);
                if (TheCommonUtils.CBool(tP.ToString()))
                {
                    TheBaseAssets.MyServiceHostInfo.DisableConsole = true;
                }

                if (TheBaseAssets.MyServiceHostInfo.UseGELFLoggingFormat)
                {
                    tP = TheThing.SetSafePropertyBool(MyBaseThing, "UseGELF", TheBaseAssets.MyServiceHostInfo.UseGELFLoggingFormat);
                }
                else
                {
                    tP = GetProperty("UseGELF", true);
                }
                tP.RegisterEvent(eThingEvents.PropertyChanged, sinkGELF);
                if (TheCommonUtils.CBool(tP.ToString()))
                {
                    TheBaseAssets.MyServiceHostInfo.UseGELFLoggingFormat = true;
                }

                bool DoLogKPIs = TheCommonUtils.CBool(TheBaseAssets.MySettings.GetSetting("LogKPIs"));
                if (DoLogKPIs)
                {
                    TheThing.SetSafePropertyBool(MyBaseThing, "LogKPIs", true);
                }

                TheQueuedSenderRegistry.RegisterHealthTimer(sinkTimer);
                // If not lengthy initialized you can remove cdeRunasync and call this synchronously
                TheCommonUtils.cdeRunAsync(MyBaseEngine.GetEngineName() + " Init Services", true, (o) =>
                {
                    // Perform any long-running initialization (i.e. network access, file access) here
                    InitServices();
                    MyBaseEngine.ProcessInitialized(); //Set the status of the Base Engine according to the status of the Things it manages
                    mIsInitCompleted = true;
                });
            }
            return(false);
        }
 /// <summary>
 /// Connect to the Thing
 /// </summary>
 public void Connect()
 {
     if (MyIsolator == null)
     {
         return;
     }
     readBytesSec = new PerformanceCounter("Process", "IO Other Bytes/sec", MyIsolator.ProcessName);
     TheThing.SetSafePropertyBool(MyBaseThing, "IsConnected", true);
     TheQueuedSenderRegistry.RegisterHealthTimer(sinkTimer);
 }
 private void sinkRequestMeshInfo(TheRequestData request)
 {
     if (request != null)
     {
         request.ResponseMimeType = "application/json";
         string errorText = "";
         Dictionary <string, string> tQ = TheCommonUtils.ParseQueryString(request.RequestUri?.Query);
         if (tQ != null)
         {
             tQ.TryGetValue("MESHINFOTOKEN", out string meshInfoToken);
             if (tQ.TryGetValue("ORG", out string tOrg))
             {
                 Guid requestorMID = TheCommonUtils.CGuid(tOrg);
                 if (requestorMID != Guid.Empty)
                 {
                     TheMeshInfoStatus meshInfoStatus = TheQueuedSenderRegistry.GetMeshInfoForNodeID(requestorMID, meshInfoToken);
                     if (string.IsNullOrEmpty(meshInfoStatus?.StatusMessage))
                     {
                         request.StatusCode     = (int)eHttpStatusCode.OK;
                         request.ResponseBuffer = TheCommonUtils.CUTF8String2Array(TheCommonUtils.SerializeObjectToJSONString(meshInfoStatus.MeshInfo));
                     }
                     else
                     {
                         request.StatusCode = meshInfoStatus.StatusCode; //Better if meshInfoStatus also defines this as there are different messages (wrong MIT, too frequent tests etc)
                         errorText          = meshInfoStatus.StatusMessage;
                     }
                 }
                 else
                 {
                     request.StatusCode = 400;
                     errorText          = "Invalid or badly formed ORG parameter.";
                 }
             }
             else
             {
                 request.StatusCode = 400;
                 errorText          = "No ORG parameter found for mesh info request.";
             }
         }
         else
         {
             request.StatusCode = (int)eHttpStatusCode.AccessDenied;
             errorText          = "Access denied";
         }
         if (!string.IsNullOrEmpty(errorText))
         {
             TheErrorResponse errorResponse = new TheErrorResponse {
                 Error = errorText, CTIM = DateTimeOffset.Now
             };
             request.ResponseBuffer = TheCommonUtils.CUTF8String2Array(TheCommonUtils.SerializeObjectToJSONString(errorResponse));
         }
     }
 }
Beispiel #8
0
        /// <summary>
        /// This event is fired when the scope was changed
        /// </summary>
        public virtual void EventScopeChanged(bool SetReq)
        {
            if (TheBaseAssets.MyApplication != null && TheBaseAssets.MyApplication.MyCommonDisco != null)
            {
                TheBaseAssets.MyApplication.MyCommonDisco.UpdateContextID();
            }
            TheQueuedSenderRegistry.UpdateLocalHostScope();

            if (TheBaseAssets.MyServiceHostInfo.AreAllEnginesStarted)
            {
                TheQueuedSenderRegistry.ReinitCloudRoutes();
                TheUserManager.ResetUserScopes(true);
            }
        }
Beispiel #9
0
        public void ProcessRequest(HttpContext context)
        {
            try
            {
                var tRequestUri = HttpContext.Current.Request.Url;
                if (tRequestUri.PathAndQuery.ToLower().StartsWith("/wstest"))
                {
                    ProcessRequest(new HttpContextWrapper(context));
                    return;
                }

                context.AcceptWebSocketRequest(async wsContext =>
                {
                    TheRequestData tRequestData = new TheRequestData
                    {
                        RequestUri       = HttpContext.Current.Request.Url,
                        HttpMethod       = HttpContext.Current.Request.HttpMethod,
                        UserAgent        = HttpContext.Current.Request.UserAgent,
                        ServerTags       = TheCommonUtils.cdeNameValueToDirectory(HttpContext.Current.Request.ServerVariables),
                        Header           = TheCommonUtils.cdeNameValueToDirectory(HttpContext.Current.Request.Headers),
                        ResponseMimeType = "cde/ws",
                        ClientCert       = HttpContext.Current.Request.ClientCertificate?.Count > 0 ? new System.Security.Cryptography.X509Certificates.X509Certificate2(HttpContext.Current.Request.ClientCertificate?.Certificate) : null
                                                                                                                         //Verified that this works with no private key. Since C-DEngineCloud only works on Windows in IIS and MUST run as Administrator there is no linux check required here
                    };
                    if (TheCommCore.MyHttpService != null && TheBaseAssets.MyServiceHostInfo.ClientCertificateUsage > 1) //If CDE requires a certificate, terminate all incoming requests before any processing
                    {
                        var err = TheCommCore.MyHttpService.ValidateCertificateRoot(tRequestData);
                        if (TheBaseAssets.MyServiceHostInfo.DisableNMI && !string.IsNullOrEmpty(err))
                        {
                            var terr = $"WebSocket Access with worng Client Certificate root - access is denied: {err}";
                            TheBaseAssets.MySYSLOG.WriteToLog(423, new TSM("TheCloudWSockets", terr, eMsgLevel.l1_Error));
                            return;
                        }
                    }
                    await TheQueuedSenderRegistry.ProcessCloudRequest(wsContext.WebSocket, tRequestData);
                });
            }
            catch (Exception ex)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(423, new TSM("TheCloudWSockets", "Processing Error 500", ex.ToString()));
                context.Response.StatusCode        = 500;
                context.Response.StatusDescription = ex.Message;
                context.Response.End();
            }
        }
 internal void sinkExpired(TheSessionState pState)
 {
     if (pState != null)
     {
         if (pState.CID != Guid.Empty)
         {
             TheUserManager.RemoveTempUser(pState.CID);
         }
         TheQueuedSender tQSend = TheQueuedSenderRegistry.GetSenderBySEID(pState.cdeMID);
         if (tQSend != null)
         {
             tQSend.FireSenderProblem(new TheRequestData()
             {
                 ErrorDescription = "1500:Session for this QSender expired"
             });
         }
     }
 }
Beispiel #11
0
        public TheHealthMonitor(int pHealthCycle, TheCDMyComputerEngine pEngineName, bool DisableCollection)
        {
            if (pEngineName != null)
            {
                MyEngineName = pEngineName.GetBaseEngine().GetEngineName();
                MyBaseEngine = pEngineName;
            }

            if (pHealthCycle > 0)
            {
                HealthUpdateCycle = pHealthCycle;
            }

            mDisableCollection = DisableCollection;
            TheBaseEngine.WaitForStorageReadiness(StorageHasStarted, true);
            InitHealthCollection();
            TheQueuedSenderRegistry.RegisterHealthTimer(CheckOnHealthTimer);
        }
Beispiel #12
0
        /// <summary>
        /// Processes the WebSockets request.
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <param name="ws">The incoming WebSockets.</param>
        public async Task ProcessWSRequest(HttpContext context, WebSocket ws)
        {
            try
            {
                TheRequestData tRequestData = cdeASPNetCommon.CreateRequest(context);
                if (tRequestData == null)
                {
                    return;
                }
                tRequestData.ResponseMimeType = "cde/ws";

                await TheQueuedSenderRegistry.ProcessCloudRequest(ws, tRequestData);
            }
            catch (Exception ex)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(423, new TSM("TheCloudWSockets", "Processing Error 500", ex.ToString()));
                context.Response.StatusCode = 500;
            }
        }
        public bool Init()
        {
            if (mIsInitCalled)
            {
                return(false);
            }
            mIsInitCalled = true;

            MyBaseThing.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessage);
            if (TheThing.GetSafePropertyString(MyBaseThing, "VisitorCount") == "")
            {
                VisitorCount = 0;
            }
            MyNodePrintsName = $"NodePrints{TheThing.GetSafeThingGuid(MyBaseThing, "NodePrints")}";
            TheBaseEngine.WaitForStorageReadiness(OnStorageReady, true);
            MyBaseThing.SetPublishThrottle(15000);
            TheCommCore.RegisterRelayEvents(null, null, sinkNewConnection);

            if (MyVisitorLog == null)
            {
                MyVisitorLog = new TheVisitorLog(MyBaseThing);
            }
            TheQueuedSenderRegistry.RegisterHealthTimer(GetSystemInfo);
            TheCDEngines.MyNMIService.RegisterEvent("NMI_MY_LOCATION", (sender2, para) =>
            {
                var t = para as TheNMILocationInfo;
                if (t != null)
                {
                    var NewEntry = new TheVisitorLogData {
                        cdeN = t.cdeN, latitude = t.Latitude, longitude = t.Longitude, ip = t.ClientInfo?.UserID.ToString(), LastVisit = DateTimeOffset.Now, Description = t.ClientInfo != null && t.ClientInfo.UserID != Guid.Empty ? TheUserManager.GetUserFullName(t.ClientInfo.UserID) : "Unknown user"
                    };
                    MyVisitorLog.LogVisitor(NewEntry);
                    myGoogleMap?.SetUXProperty(Guid.Empty, $"AddMarker={TheCommonUtils.SerializeObjectToJSONString(NewEntry)}");
                }
            });
            TheCommCore.MyHttpService.RegisterHttpInterceptorB4("/cdemeshinfo.aspx", sinkRequestMeshInfo);
            MyBaseEngine.ProcessInitialized();
            MyBaseEngine.SetEngineReadiness(true, null);
            MyBaseEngine.SetStatusLevel(1);
            mIsInitialized = true;
            return(true);
        }
Beispiel #14
0
        public bool Init()
        {
            if (mIsInitCalled)
            {
                return(false);
            }

            mIsInitCalled           = true;
            MyBaseThing.StatusLevel = 1;

            MyBaseThing.Version      = TheBaseAssets.MyAppInfo.CurrentVersion.ToString(CultureInfo.InvariantCulture);
            MyBaseThing.Capabilities = TheBaseAssets.MyAppInfo.Capabilities;
            MyBaseThing.Address      = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false);
            TheThing.SetSafePropertyString(MyBaseThing, "Description", TheBaseAssets.MyAppInfo.LongDescription);
            mIsInitialized = true;

            TheThing.SetSafePropertyBool(MyBaseThing, "EnableKPIs", TheCommonUtils.CBool(TheBaseAssets.MySettings.GetSetting("EnableKPIs")));

            if (TheBaseAssets.MyServiceHostInfo.EnableTaskKPIs)
            {
                var taskKpiThread = new System.Threading.Thread(() =>
                {
                    TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: NodeHost starting Task KPI thread");
                    do
                    {
                        Thread.Sleep(1000); // Keeping it simple here, to minimize interference on task scheduler/thread scheduler etc. (Assumption: not used on production systems) // TheCommonUtils.SleepOneEye(1000, 1000);
                        var kpis = TheCommonUtils.GetTaskKpis(null);
                        TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: {TheCommonUtils.SerializeObjectToJSONString(kpis)}");
                    } while (TheBaseAssets.MasterSwitch && TheBaseAssets.MyServiceHostInfo.EnableTaskKPIs);
                    TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: NodeHost ending Task KPI thread");
                });
                taskKpiThread.Start();
            }
            KPIHarvestInterval = TheCommonUtils.CInt(TheBaseAssets.MySettings.GetAppSetting("KPIHarvestIntervalInSeconds", "5", false, true));
            if (KPIHarvestInterval > 0)
            {
                TheQueuedSenderRegistry.RegisterHealthTimer(sinkCyclic);
            }
            return(true);
        }
 void sinkTimer(long t)
 {
     if (MyIsolator == null)
     {
         return;
     }
     if (MyIsolator.HasExited)
     {
         TheQueuedSenderRegistry.UnregisterHealthTimer(sinkTimer);
         MyBaseThing.StatusLevel = 0;
         MyBaseThing.LastMessage = "Plugin no longer running";
         return;
     }
     try
     {
         TheThing.SetSafePropertyString(MyBaseThing, "IORead", string.Format("{0:0.00}", readBytesSec?.NextValue()));
         //if ((t%15)!=0) return;
         TheThing.SetSafePropertyString(MyBaseThing, "CPUTime", string.Format("{0:0.00}", MyIsolator.TotalProcessorTime.TotalSeconds));
         TheThing.SetSafePropertyNumber(MyBaseThing, "WorkingSet", MyIsolator.WorkingSet64 / 1024);
         TheThing.SetSafePropertyNumber(MyBaseThing, "Handles", MyIsolator.HandleCount);
         TheThing.SetSafePropertyNumber(MyBaseThing, "Threads", MyIsolator.Threads.Count);
         TimeSpan ts = DateTime.Now.Subtract(MyIsolator.StartTime);
         TheThing.SetSafePropertyNumber(MyBaseThing, "UpTime", ts.TotalMinutes);
         using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", $"SELECT * FROM Win32_PerfFormattedData_PerfProc_Process where IDProcess='{MyIsolator.Id}'"))
         {
             foreach (ManagementObject queryObj in searcher.Get())
             {
                 TheThing.SetSafePropertyString(MyBaseThing, "CPU", queryObj["PercentProcessorTime"].ToString());
                 MyBaseThing.Value = queryObj["PercentProcessorTime"].ToString();
                 //foreach (var ttt in queryObj.Properties)
                 //{
                 //    Console.WriteLine($"{ttt.Name}: {ttt.Value}");
                 //}
             }
         }
     }
     catch (Exception)
     {
     }
 }
        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));
            }
        }
Beispiel #17
0
        private void StartUPnPDiscovery(string pLiveEngines)
        {
            if (MyUPnPDiscoveryPast != null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(109, new TSM("UPnP", "DISCO aready running!"));
                return;
            }
            MyUPnPDiscoveryPast = new TheStorageMirror <TheUPnPDeviceInfo>(Engines.TheCDEngines.MyIStorageService)
            {
                IsRAMStore = true, BlockWriteIfIsolated = true
            };
            MyUPnPDiscoveryPast.SetRecordExpiration(DISCOExpireTime, sinkDeviceExpired);
            //MyUPnPDiscoveryPast.CacheStoreInterval = 60;
            //MyUPnPDiscoveryPast.IsStoreIntervalInSeconds = true;
            //MyUPnPDiscoveryPast.IsCachePersistent = true;
            MyUPnPDiscoveryPast.InitializeStore(true, true);

            var tCDEConnectUrl = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false);

            TheBaseAssets.MySYSLOG.WriteToLog(107, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("UPnP", "Starting Device", eMsgLevel.l3_ImportantMessage));
            MyDeviceUPnPInfo = new TheUPnPDeviceInfo()
            {
                FriendlyName    = TheBaseAssets.MyServiceHostInfo.ApplicationTitle + " at: " + tCDEConnectUrl + " - Services:" + pLiveEngines,// pStationEngines;
                Manufacturer    = TheBaseAssets.MyServiceHostInfo.VendorName,
                ManufacturerUrl = TheBaseAssets.MyServiceHostInfo.VendorUrl,
                ModelName       = TheBaseAssets.MyServiceHostInfo.ApplicationName,
                ModelNumber     = string.Format("V{0:0.0000}", TheBaseAssets.MyServiceHostInfo.CurrentVersion),
                SerialNumber    = TheBaseAssets.CurrentVersionInfo,
                PacketString    = "",
                RawMetaXml      = "",
                LocationURL     = tCDEConnectUrl,
                ST            = "C-DEngine",
                CDEConnectUrl = tCDEConnectUrl,
                CDENodeID     = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID,
                UUID          = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(),
                USN           = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(),
                IsCDEngine    = true
            };
            if (!TheBaseAssets.MyServiceHostInfo.RequiresConfiguration)
            {
                MyDeviceUPnPInfo.CDEContextID = TheBaseAssets.MyScopeManager.GetScrambledScopeID();     //GRSI: rare
            }
            if (TheCommonUtils.IsHostADevice())
            {
                MyDeviceUPnPInfo.HasPresentation = false;
            }
            else
            {
                if (!TheBaseAssets.MyServiceHostInfo.DisableWebSockets && TheBaseAssets.MyServiceHostInfo.MyStationWSPort > 0)
                {
                    var builder = new UriBuilder(TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false));
                    builder.Scheme = builder.Scheme == "https" ? "wss" : "ws";
                    builder.Port   = TheBaseAssets.MyServiceHostInfo.MyStationWSPort;
                    MyDeviceUPnPInfo.CDEConnectWsUrl = TheCommonUtils.TruncTrailingSlash(builder.Uri.ToString());
                }
                MyDeviceUPnPInfo.HasPresentation = true;
            }
            eventDiscoReady?.Invoke(true);

            TheQueuedSenderRegistry.RegisterHealthTimer(DoScan4Devices);
            TheBaseAssets.MySYSLOG.WriteToLog(108, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("UPnP", "DISCO engine ready..."));
        }
Beispiel #18
0
        internal static void InitAssets(TheBaseApplication pApp)
        {
            if (IsInitialized)
            {
                return;
            }
            IsInitialized = true;
            if (MyServiceHostInfo == null || !(MySecrets?.IsApplicationIDValid() == true))
            {
                MasterSwitch = false;
                return;
            }
            MyApplication = pApp;

            #region step 1: Moved from StartApplication to here as all the following code is updating TheBaseAssets
            //The following section are "app.config" only settings required before cdeTPI is loaded. These settings cannot be set via the Provisioning Service
            int delay = TheCommonUtils.CInt(MySettings.GetSetting("StartupDelay"));
            if (delay > 0)
            {
                TheCommonUtils.SleepOneEye((uint)(delay * 1000), 100);
            }

            string temp = MySettings.GetSetting("AllowEnvironmentVarsToOverrideConfig");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.AllowEnvironmentVarsToOverrideConfig = TheCommonUtils.CBool(temp);
            }
            temp = MySettings.GetSetting("AllowEnvironmentVars");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.AllowEnvironmentVars = TheCommonUtils.CBool(temp);
            }
            temp = MySettings.GetSetting("DEBUGLEVEL");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.DebugLevel = (eDEBUG_LEVELS)TheCommonUtils.CInt(temp);
            }
            //Clouds have special behavior and the CDE needs to know this upfront
            temp = MySettings.GetSetting("IsCloudService");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.IsCloudService = TheCommonUtils.CBool(temp);
            }
            temp = MySettings.GetSetting("ISOEN");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.IsIsolated  = true;
                MyServiceHostInfo.IsoEngine   = temp;
                MyServiceHostInfo.cdeNodeType = cdeNodeType.Active;
            }
            else
            {
                temp = MySettings.GetSetting("UseRandomDeviceID");
                if (!string.IsNullOrEmpty(temp))
                {
                    MyServiceHostInfo.UseRandomDeviceID = TheCommonUtils.CBool(temp);
                }
            }

            //Step 2: Restore from backup if exists
#if CDE_NET45 // Backup/Restore only support on NET45
            // To ensure that restored backups are not overwritten during shutdown, we write them to a temp directory and move them into place on start up
            if (!MyServiceHostInfo.UseRandomDeviceID && !MyServiceHostInfo.IsIsolated)
            {
                string cacheParentPath = TheCommonUtils.GetCurrentAppDomainBaseDirWithTrailingSlash() + "ClientBin\\";
                if (Directory.Exists(cacheParentPath + "__CacheToRestore"))
                {
                    // Keep the old Cache around just in case
                    try
                    {
                        // First make space for the old copy, in case there was one already
                        if (Directory.Exists(cacheParentPath + "__CacheOld"))
                        {
                            Directory.Delete(cacheParentPath + "__CacheOld", true);
                        }
                    }
                    catch
                    {
                        //ignored
                    }
                    try
                    {
                        Directory.Move(cacheParentPath + "Cache", cacheParentPath + "__CacheOld");
                    }
                    catch
                    {
                        //ignored
                    }

                    // Now move the restored cache into place
                    try
                    {
                        Directory.Move(cacheParentPath + "__CacheToRestore", cacheParentPath + "Cache");
                    }
                    catch
                    {
                        TheSystemMessageLog.ToCo("Failure while restoring backup");
                    }
                }
            }
#endif

            MyServiceHostInfo.EnableTaskKPIs = TheCommonUtils.CBool(MySettings.GetSetting("EnableTaskKPIs"));
            if (MyServiceHostInfo.EnableTaskKPIs)
            {
                var taskKpiThread = new Thread(() =>
                {
                    do
                    {
                        var kpis = TheCommonUtils.GetTaskKpis(null);
                        TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: {TheCommonUtils.SerializeObjectToJSONString(kpis)}");
                        Thread.Sleep(1000); // Keeping it simple here, to minimize interference on task scheduler/thread scheduler etc. (Assumption: not used on production systems) // TheCommonUtils.SleepOneEye(1000, 1000);
                    } while (MasterSwitch && !Engines.TheCDEngines.IsHostReady && MyServiceHostInfo.EnableTaskKPIs);
                    TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: KPIs Handoff to NodeHost");
                });
                taskKpiThread.Start();
            }
            #endregion

            if (MyActivationManager == null)
            {
                MyActivationManager = new TheDefaultActivationManager(MySecrets, MySYSLOG);
            }


            #region step 3: analyse os environment information
            OperatingSystem os           = Environment.OSVersion;
            var             osInfoForLog = $"C-DEngine version: {BuildVersion} OS:{Environment.OSVersion} OS Version:{os.VersionString} OS Version Numbers: {os.Version.Major}.{os.Version.Minor}.{os.Version.Build}.{os.Version.Revision} Platform:{os.Platform} SP:{os.ServicePack} Processor Count: {Environment.ProcessorCount} IsMono:{(Type.GetType("Mono.Runtime") != null)} IsNetCore:{TheCommonUtils.IsNetCore()} Product: {TheCommonUtils.GetAssemblyProduct(typeof(TheBaseAssets))} ";
            TheSystemMessageLog.ToCo(osInfoForLog);
            MyServiceHostInfo.OSInfo = osInfoForLog;
            string dotNetInfoForLog = string.Empty;
#if !CDE_NET35 && !CDE_NET4
            try
            {
                string frameworkDescription = null;
                string osDescription        = null;
                string processArchitecture  = null;
                string osArchitecture       = null;

#if CDE_STANDARD
                frameworkDescription = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
                osDescription        = System.Runtime.InteropServices.RuntimeInformation.OSDescription;
                processArchitecture  = System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString();
                osArchitecture       = System.Runtime.InteropServices.RuntimeInformation.OSArchitecture.ToString();
#else
                var rtInfoType = Type.GetType("System.Runtime.InteropServices.RuntimeInformation, System.Runtime.InteropServices.RuntimeInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                if (rtInfoType != null)
                {
                    frameworkDescription = rtInfoType.GetProperty("FrameworkDescription").GetValue(null).ToString();
                    osDescription        = rtInfoType.GetProperty("OSDescription").GetValue(null).ToString();
                    processArchitecture  = rtInfoType.GetProperty("ProcessArchitecture").GetValue(null).ToString();
                    osArchitecture       = rtInfoType.GetProperty("OSArchitecture").GetValue(null).ToString();
                }
#endif
                if (!string.IsNullOrEmpty(frameworkDescription))
                {
                    dotNetInfoForLog = $"NetFrameWork:{frameworkDescription} Processor:{processArchitecture} OS:{osDescription } OS Arch:{osArchitecture}";
                    TheSystemMessageLog.ToCo(dotNetInfoForLog);
                    MyServiceHostInfo.OSInfo += $" {dotNetInfoForLog}";
                }
            }
            catch
            {
            }
#endif
            if (TheCommonUtils.IsMono()) // CODE REVIEW: Need to clean this up - do we mean Mono or Linux or case-insensitive file systems? CM: No- here we need this to find out if we are running in the MONO Runtime
            {
                MyServiceHostInfo.cdePlatform = cdePlatform.MONO_V3;
            }
            else
            {
#if CDE_NET35
                MyServiceHostInfo.cdePlatform = cdePlatform.X32_V3;
#elif CDE_NET4
                MyServiceHostInfo.cdePlatform = Environment.Is64BitProcess ? cdePlatform.NETV4_64 : cdePlatform.NETV4_32;
#elif CDE_STANDARD
                MyServiceHostInfo.cdePlatform = cdePlatform.NETSTD_V20;
#else
                MyServiceHostInfo.cdePlatform = TheCommonUtils.GetAssemblyPlatform(Assembly.GetEntryAssembly(), false, out var empty);// old: Environment.Is64BitProcess ? cdePlatform.X64_V3 : cdePlatform.X32_V4;
#endif
            }
            TheSystemMessageLog.ToCo("BaseDir: " + MyServiceHostInfo.BaseDirectory);
            #endregion

            #region step 4: Prepare essential Subsystems (Syslog, ScopeManager, Diagnostics, Caches, AppInfo)
            MySYSLOG = new TheSystemMessageLog(500); // No more ToCo after this point (will be ignored)
            TheCDEKPIs.Reset();

            MyServiceHostInfo.MiniHostInfo.MySYSLOG = MySYSLOG;
            MyServiceHostInfo.MiniHostInfo.MyKPIs   = new TheKPIs();
            if (MyScopeManager == null)
            {
                MyScopeManager = new TheDefaultScopeManager();
            }
            MyScopeManager.SetMiniHSI(MyServiceHostInfo.MiniHostInfo);
            MyScopeManager.RegisterScopeChanged(localEventScopeChanged);

            TheDiagnostics.InitDiagnostics();
            TheDiagnostics.SetThreadName("MAIN THREAD");
            TheQueuedSenderRegistry.Startup();

            MyBlobCache     = new TheMirrorCache <TheBlobData>(MyServiceHostInfo.TO.StorageCleanCycle);
            MyReceivedParts = new TheMirrorCache <TheReceivedParts>(MyServiceHostInfo.TO.StorageCleanCycle);
            //TODO: I hope there is a better way to do this for Metro!
            MyServiceTypes.Add(typeof(TheBaseAssets));

            MyServiceHostInfo.TO.MakeHeartNormal();

            MyAppInfo = new ThePluginInfo
            {
                cdeMID             = MyServiceHostInfo.cdeMID,
                CurrentVersion     = MyServiceHostInfo.CurrentVersion,
                Developer          = MyServiceHostInfo.VendorName,
                DeveloperUrl       = MyServiceHostInfo.VendorUrl,
                HomeUrl            = MyServiceHostInfo.SiteName,
                IconUrl            = MyServiceHostInfo.UPnPIcon,
                LongDescription    = MyServiceHostInfo.Description,
                Platform           = MyServiceHostInfo.cdePlatform,
                Copyrights         = MyServiceHostInfo.Copyrights,
                Price              = 0,
                ServiceDescription = MyServiceHostInfo.Title,
                ServiceName        = MyServiceHostInfo.ApplicationName,
                Capabilities       = new List <eThingCaps> {
                    eThingCaps.Host
                },
                Categories    = new List <string>(),
                FilesManifest = new List <string>()
            };
            if (MyServiceHostInfo.ManifestFiles != null)
            {
                MyAppInfo.FilesManifest.AddRange(MyServiceHostInfo.ManifestFiles);
            }
            #endregion

            //Now load provisioning and local settings then parse them
#pragma warning disable CS0618 // Type or member is obsolete - its allowed here
            if (!TheCDESettings.ParseSettings(MyCmdArgs, true, false))
#pragma warning restore CS0618 // Type or member is obsolete
            {
                MasterSwitch = false;
                return;
            }

            if (MyCodeSigner == null)
            {
                MyCodeSigner = new TheDefaultCodeSigning(MySecrets, MySYSLOG);
            }
            string tBaseDir = MyServiceHostInfo.BaseDirectory;
            if (MyServiceHostInfo.cdeHostingType == cdeHostType.IIS)
            {
                tBaseDir += "bin\\";
            }
            string uDir = tBaseDir;
            if (!string.IsNullOrEmpty(MyServiceHostInfo.ISMMainExecutable))
            {
                uDir += MyServiceHostInfo.ISMMainExecutable;
                if (MyServiceHostInfo.cdeHostingType != cdeHostType.IIS)
                {
                    var hostPath = uDir + ".exe";
                    if (!File.Exists(hostPath))
                    {
                        // We may be running under .Net Core with a .dll-based host
                        hostPath = uDir + ".dll";
                    }
                    uDir = hostPath;
                }
            }
            else
            {
                uDir += "C-DEngine.dll";
            }
            MyServiceHostInfo.CodeSignThumb = MyCodeSigner.GetAppCert(MyServiceHostInfo.DontVerifyTrust, uDir, MyServiceHostInfo.VerifyTrustPath, MyServiceHostInfo.DontVerifyIntegrity);  //Must be loaded here to set trust level in HSI

            if (MyLoc as TheDefaultLocalizationUtils != null)
            {
                (MyLoc as TheDefaultLocalizationUtils).DoPseudoLoc = TheCommonUtils.CBool(MySettings.GetSetting("DoPseudoLoc"));
            }

            #region step 5: output some system information
            if (MyServiceHostInfo.IsMemoryOptimized)
            {
                MySYSLOG.SetMaxLogEntries(10);
            }
            MySYSLOG.WriteToLog(4151, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", osInfoForLog, eMsgLevel.l4_Message));

            if (!string.IsNullOrEmpty(dotNetInfoForLog))
            {
                MySYSLOG.WriteToLog(4152, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", dotNetInfoForLog, eMsgLevel.l4_Message));
            }
            MySYSLOG.WriteToLog(4153, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheBaseAssets", "BaseDir: " + MyServiceHostInfo.BaseDirectory, eMsgLevel.l4_Message));
            #endregion

            #region step 6: determine WebSocket8 vs. WebSocketsSharp
            var ws8FlagTemp = MySettings.GetSetting("DisallowWebSocket8");
            if (!string.IsNullOrEmpty(ws8FlagTemp))
            {
                MyServiceHostInfo.IsWebSocket8Active = !TheCommonUtils.CBool(ws8FlagTemp);
                MySYSLOG.WriteToLog(4154, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", $"Setting IsWebSocket8Active to {MyServiceHostInfo.IsWebSocket8Active} due to config", eMsgLevel.l4_Message));
            }
            else
            {
                MyServiceHostInfo.IsWebSocket8Active = true;
            }
            if ((os.Platform != PlatformID.Win32NT && !TheCommonUtils.IsNetCore()) || (os.Platform == PlatformID.Win32NT && (os.Version.Major < 6 || (os.Version.Major == 6 && os.Version.Minor < 2))))
            {
                MyServiceHostInfo.IsWebSocket8Active = false;
                string tWSMsg = "Older Windows or non-Windows OS Detected - No OS Support for WebSockets Found: ";
#if !CDE_USECSWS //OK
                TheBaseAssets.MyServiceHostInfo.DisableWebSockets = true;
                tWSMsg += "WebSockets are turned Off";
#else
                tWSMsg += "Switching to WebSockets-Sharp";
#endif
                MySYSLOG.WriteToLog(4155, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", tWSMsg, eMsgLevel.l4_Message));
            }
            #endregion

            #region step 7: Initialize Localization subsystem (ILocalizationHooks)
            bool bLocInitialized = false;
            try
            {
                var entryAssembly = Assembly.GetEntryAssembly();    //This does not work in IIS!
                if (entryAssembly != null)
                {
                    var CDEPlugins = from t in entryAssembly.GetTypes()
                                     let ifs = t.GetInterfaces()
                                               where ifs != null && ifs.Length > 0 && (ifs.Contains(typeof(ILocalizationHooks)))
                                               select new { Type = t, t.Namespace, t.Name, t.FullName };
                    if (CDEPlugins != null && CDEPlugins.Any())
                    {
                        MyLoc = Activator.CreateInstance(CDEPlugins.First().Type) as ILocalizationHooks;
                    }
                    bLocInitialized = true;
                }
            }
            catch
            {
            }
            if (!bLocInitialized)
            {
                MySYSLOG.WriteToLog(4156, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", "3rd Party ILocalization Hooks not found - using built-in", eMsgLevel.l4_Message));
            }
            #endregion

            #region step 8: Set MyStationUrl
            switch (MyServiceHostInfo.cdeHostingType)
            {
            case cdeHostType.Phone:
            case cdeHostType.Metro:
                MyServiceHostInfo.MyDeviceMoniker = "CDEV://";
                break;

            case cdeHostType.Silverlight:
                MyServiceHostInfo.MyDeviceMoniker = "CDES://";
                break;

            case cdeHostType.Device:
                MyServiceHostInfo.MyDeviceMoniker = "CDEC://";
                break;

            case cdeHostType.Mini:
                MyServiceHostInfo.MyDeviceMoniker = "CDEM://";
                break;

            default:     //Services
                MyServiceHostInfo.MyDeviceMoniker = "CDEB://";
                break;
            }
            if (TheCommonUtils.IsHostADevice())
            {
                MyServiceHostInfo.MyStationURL = MyServiceHostInfo.MyDeviceMoniker + "{" + MyServiceHostInfo.MyDeviceInfo.DeviceID + "}".ToUpper(); //MSU-OK
            }
            else
            {
                if (MyServiceHostInfo.MyAltStationURLs.Count(s => s.StartsWith("CDEB")) == 0)
                {
                    MyServiceHostInfo.MyAltStationURLs.Add("CDEB://{" + MyServiceHostInfo.MyDeviceInfo.DeviceID + "}"); //TODO: Backchannel Possibly save to Config File
                }
            }
            #endregion

            #region step 9: Start Localhost QSender and SessionStateManager
            MySession        = new TheSessionStateManager(MyServiceHostInfo);
            LocalHostQSender = new TheQueuedSender();                                                                                                                                                                                 //NO connected or Error Event necessary
            LocalHostQSender.StartSender(new TheChannelInfo(MyServiceHostInfo.MyDeviceInfo.DeviceID, MyScopeManager.ScopeID, MyServiceHostInfo.MyDeviceInfo.SenderType, MyServiceHostInfo.GetPrimaryStationURL(false)), null, false); //NEW:2.06 Setting Realscope here ///null correct - no subs on LocalhostQS in beginning //RScope-OK
            if ((MyServiceHostInfo.DisableWebSockets || MyServiceHostInfo.MyStationWSPort == 0) && !TheCommonUtils.IsHostADevice())
            {
                MySYSLOG.WriteToLog(4157, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", $"WebSockets Disabled - no WSPort specified {MyServiceHostInfo.MyStationWSPort} or DisableWebSocket={MyServiceHostInfo.DisableWebSockets}", eMsgLevel.l4_Message));
            }
            #endregion

            // Post Device ID settings

            //Step 10: Save all settings to local cdeTPI
            MySettings.UpdateLocalSettings();
        }
Beispiel #19
0
        static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Main thread";  // Helps Debugging

            //SDK Non-Commercial ID. FOR COMMERCIAL APP GET THIS ID FROM C-LABS!
            TheScopeManager.SetApplicationID("/cVjzPfjlO;{@QMj:jWpW]HKKEmed[llSlNUAtoE`]G?");

            //
            //  Establish service parameters
            //
            TheBaseAssets.MyServiceHostInfo = new TheServiceHostInfo(cdeHostType.Application)
            {
                // TODO: Generate host service unique ID
                cdeMID = TheCommonUtils.CGuid("{AE1F4BBB-B9E3-47D5-B08A-FE71A5697D20}"),

                // TCP/IP Port Assignments
                MyStationPort = 8713,                     // Port for REST access to this node.
                                                          // If your PC already uses port 80 for another webserver, change this port.
                                                          // We recommend using Port 8700 and higher for UPnP to work properly.

                MyStationWSPort = 8714,                   // Enables WebSockets on the station port.
                                                          // If UseRandomDeviceID is false, this Value cannot be changed here once the
                                                          // app runs for the first time.
                                                          // On Windows 8 and later, MyStationPort and MyStationWSPort
                                                          // can be the same port if running as Administrator.

                ISMMainExecutable = "MyTestHost",         // Name of the executable (without .exe)
                ApplicationName   = "My-Relay",           // Friendly Name of Application
                Title             = "My-Relay (C) 2020 ", // Title of this Host Service
                ApplicationTitle  = "My-Relay Portal",    // Title visible in the NMI Portal

                SiteName = "http://cloud.c-labs.com",     // Link to the main Cloud Node of this host.
                                                          // Not required, for documentation only

                CurrentVersion = 1.0001,                  // Service version of this Service.
                                                          // Increase when you publish a new version so the
                                                          // online store can display the correct update icon
                DebugLevel   = eDEBUG_LEVELS.ESSENTIALS,  // Define a DebugLevel for the SystemLog output.
                ServiceRoute = "wss://cloud.c-labs.com",  // Points at the cloud
            };

            // Generate random Scope ID every time we run.
            strScope = TheScopeManager.GenerateNewScopeID();   // TIP: instead of creating a new random ID every
                                                               // time your host starts, you can put a breakpoint in the
                                                               // next line, record the ID and feed it in the "SetScopeIDFromEasyID".
                                                               // Or even set a fixed ScopeID here. (FOR TESTING ONLY!!)

            TheScopeManager.SetScopeIDFromEasyID("1234");      // Set a ScopeID - the security context of this node.
                                                               // Replace strScope with any random 8 characters or numbers

            //
            // Create dictionary to hold configuration settings.
            //
            #region Args Parsing
            ArgList = new Dictionary <string, string>();
            for (int i = 0; i < args.Length; i++)
            {
                string[] tArgs = args[i].Split('=');
                if (tArgs.Length == 2)
                {
                    string key = tArgs[0].ToUpper();
                    ArgList[key] = tArgs[1];
                }
            }
            #endregion

            ArgList["DontVerifyTrust"] = "True";       // When "false", all plugins have to be signed with the
                                                       // same certificate as the host application or C-DEngine.DLL.
                                                       // When "true", ignore code signing security check (dev only!)

            ArgList["UseRandomDeviceID"] = "True";     // When "true", assigns a new device ID everytime
                                                       // the host starts. No configuration data retained on disk.
                                                       // When "false", enables persistence between system starts

            ArgList["ScopeUserLevel"] = "255";         // Set the Scope Access Level

            // Create a new Base (C-DEngine IoT) Application
            MyBaseApplication = new TheBaseApplication();

            // Start the C-DEngine Host Application.
            // If a PluginService class is added DIRECTLY to the host project you can
            // instantiate the Service here. Replace null with "new cdePluginService1()"
            if (!MyBaseApplication.StartBaseApplication(null, ArgList))
            {
                // If the Application fails to start, quit the app.
                // StartBaseApplication returns very fast because all
                // C-DEngine code is running asynchronously
                return;
            }

            // (Optional) Whether to use Universal Plug
            // and Play (UPnP) to find devices.
            // MyBaseApplication.MyCommonDisco.RegisterUPnPUID("*", null);

            // Set up URL for our node.
            string strStationURL = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false);
            strStationURL = String.Format("{0}/lnmi", strStationURL);

            // Set up messaging (for basic sample)
            TheCDEngines.RegisterPubSubTopic("MyTestEngine2");                  // The engine for MyTestHost2
            IBaseEngine eng = TheCDEngines.RegisterPubSubTopic("MyTestEngine"); // The engine for THIS host
            eng.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessage);
            TheQueuedSenderRegistry.RegisterHealthTimer(SinkTimer);

            #region Waiting for ESC Key pressed
            try
            {
                // User input loop
                while (true)
                {
                    Console.WriteLine("\r\nStation URL: " + strStationURL);
                    Console.WriteLine("\r\nScope ID: " + strScope);
                    Console.WriteLine("\r\n[Esc] key to quit. 'B' (or 'b') to launch browser");

                    // Loop until (1) C-DEngine master switch, or (2) Keyboard input
                    while (TheBaseAssets.MasterSwitch && Console.KeyAvailable == false) // Console.KeyAvailable throws exception in Docker
                    {
                        Thread.Sleep(250);
                    }

                    // Check C-DEngine master switch.
                    if (!TheBaseAssets.MasterSwitch)
                    {
                        // Exit user input loop.
                        break;
                    }

                    ConsoleKeyInfo key = Console.ReadKey();
                    if (key.Key == ConsoleKey.Escape)
                    {
                        break;
                    }
                    if (key.KeyChar == 'b' || key.KeyChar == 'B')
                    {
                        try
                        {
                            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                            {
                                strStationURL = strStationURL.Replace("&", "^&");
                                Process.Start(new ProcessStartInfo("cmd.exe", $"/c start {strStationURL}")
                                {
                                    CreateNoWindow = true
                                });
                            }
                            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                            {
                                System.Diagnostics.Process.Start("xdg-open", strStationURL);
                            }
                            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                            {
                                System.Diagnostics.Process.Start("open", strStationURL);
                            }
                            else
                            {
                                Console.WriteLine($"Error launching browser for URL {strStationURL}");
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"Error launching browser for URL {strStationURL}");
                            Console.WriteLine($"Exception details: {e.ToString()}");
                        }
                    }
                } // while (true)
            }
            catch (InvalidOperationException)
            {
                TheBaseAssets.MasterSwitchCancelationToken.WaitHandle.WaitOne();
            }

            MyBaseApplication.Shutdown(true);
            #endregion
        }
Beispiel #20
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()));
            }
        }
        /// <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);
        }
Beispiel #22
0
        internal static void ToThingProperties(TheThing pThing, bool bReset)
        {
            lock (thingHarvestLock)
            {
                if (pThing == null)
                {
                    return;
                }
                if (KPIIndexes == null)
                {
                    CreateKPIIndexes();
                }
                if (KPIs == null)
                {
                    KPIs = new long[KPIIndexes.Count];
                }

                if (KPIs != null && KPIIndexes != null)
                {
                    TimeSpan timeSinceLastReset = DateTimeOffset.Now.Subtract(LastReset);
                    bool     resetReady         = timeSinceLastReset.TotalMilliseconds >= 1000;
                    foreach (var keyVal in KPIIndexes.GetDynamicEnumerable())
                    {
                        bool donres = doNotReset.Contains(keyVal.Key);
                        long kpiValue;
                        if (bReset && !donres && resetReady)
                        {
                            kpiValue = Interlocked.Exchange(ref KPIs[keyVal.Value], 0);
                        }
                        else
                        {
                            kpiValue = Interlocked.Read(ref KPIs[keyVal.Value]);
                        }

                        // LastReset not set yet - shouldn't happen since it is set in first call to Reset (TheBaseAssets.InitAssets)
                        if (LastReset == DateTimeOffset.MinValue || timeSinceLastReset.TotalSeconds <= 1 || donres)
                        {
                            pThing.SetProperty(keyVal.Key, kpiValue);
                        }
                        else
                        {
                            pThing.SetProperty(keyVal.Key, kpiValue / timeSinceLastReset.TotalSeconds); // Normalize value to "per second"
                        }
                        if (!doNotComputeTotals.Contains(keyVal.Key))
                        {
                            pThing.SetProperty(keyVal.Key + "Total", TheThing.GetSafePropertyNumber(pThing, keyVal.Key + "Total") + kpiValue);
                        }
                    }
                    if (bReset && resetReady)
                    {
                        LastReset = DateTimeOffset.Now;
                    }
                    // Grab some KPIs from sources - Workaround, this should be computed in the source instead
                    SetKPI(eKPINames.QSenders, TheQueuedSenderRegistry.GetSenderListNodes().Count);
                    SetKPI(eKPINames.QSenderInRegistry, TheQueuedSenderRegistry.Count());
                    SetKPI(eKPINames.SessionCount, TheBaseAssets.MySession.GetSessionCount());
                    SetKPI(eKPINames.UniqueMeshes, TheQueuedSenderRegistry.GetUniqueMeshCount());
                    SetKPI(eKPINames.UnsignedNodes, TheQueuedSenderRegistry.GetUnsignedNodeCount());
                    SetKPI(eKPINames.KnownNMINodes, Engines.NMIService.TheFormsGenerator.GetNMINodeCount());
                    SetKPI(eKPINames.StreamsNotFound, Communication.HttpService.TheHttpService.IsStreaming.Count);
                    SetKPI(eKPINames.BlobsNotFound, Engines.ContentService.TheContentServiceEngine.BlobsNotHere.Count);
                }
            }
        }
        internal static void DoExecuteCommand(string pInTopicBatch, TheQueuedSender pQSender, bool DoSendBackBuffer, TheRequestData pRequestData, List <TheDeviceMessage> pDevMessageList)
        {
            bool SendPulse = false;

            if (pDevMessageList != null && pDevMessageList.Count > 0)
            {
                foreach (TheDeviceMessage pDevMessage in pDevMessageList)
                {
                    TSM    recvMessage = null;
                    string tTopic      = "";
                    try
                    {
                        var    tTargetNodeChannel = pQSender?.MyTargetNodeChannel;
                        string pInTopic           = pInTopicBatch;
                        if (string.IsNullOrEmpty(pInTopic))
                        {
                            pInTopic = pDevMessage.TOP;
                        }
                        recvMessage = pDevMessage.MSG;
                        if (pQSender != null && tTargetNodeChannel != null && tTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON && recvMessage != null && string.IsNullOrEmpty(recvMessage.ORG))
                        {
                            recvMessage.ORG = tTargetNodeChannel.cdeMID.ToString();
                        }

                        #region ChunkResassembly
                        string[] CommandParts = null;
                        if (!string.IsNullOrEmpty(pInTopic))
                        {
                            CommandParts = TheCommonUtils.cdeSplit(pInTopic, ":,:", false, false);
                            tTopic       = CommandParts[0];
                        }
                        TheCDEKPIs.IncrementKPI(eKPINames.CCTSMsReceived);
                        if (CommandParts != null && CommandParts.Length == 4 && !CommandParts[2].Equals("1"))
                        {
                            if (!TheCommonUtils.ProcessChunkedMessage(CommandParts, recvMessage))
                            {
                                SendPulse = true;
                                continue;
                            }
                        }
                        #endregion

                        if (recvMessage != null)
                        {
                            if (((TheBaseAssets.MyServiceHostInfo.RejectIncomingSETP && recvMessage.TXT?.StartsWith("SETP:") == true) || TheBaseAssets.MyServiceHostInfo.DisableNMIMessages) && recvMessage.ENG?.StartsWith(eEngineName.NMIService) == true)
                            {
                                TheCDEKPIs.IncrementKPI(eKPINames.QSSETPRejected);
                                continue;
                            }
                            var tTopicSens  = tTopic.Split('@')[0]; //only topic - no ScopeID
                            var tTopicParts = tTopic.Split(';');
                            if (tTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON)
                            {
                                //4.209: JavaJason does no longer get the scope ID - hence telegrams coming from the browser have to be ammmended with SID here
                                if (string.IsNullOrEmpty(recvMessage.SID) && !string.IsNullOrEmpty(pRequestData?.SessionState?.SScopeID))
                                {
                                    recvMessage.SID = pRequestData?.SessionState?.SScopeID; //Set the ScopeID in the SID of the message
                                    if (tTopic.StartsWith("CDE_SYSTEMWIDE"))
                                    {
                                        tTopic = $"{tTopicParts[0]}@{recvMessage.SID}";
                                        if (tTopicParts.Length > 1)
                                        {
                                            tTopic += $";{tTopicParts[1]}"; //if a direct address is added use this too
                                        }
                                    }
                                    else if (!tTopic.Contains('@'))
                                    {
                                        tTopic += $"@{recvMessage.SID}";
                                    }
                                    if (recvMessage.TXT == "CDE_SUBSCRIBE" || recvMessage.TXT == "CDE_INITIALIZE")
                                    {
                                        string MsgNoSID = null;
                                        recvMessage.PLS = TheBaseAssets.MyScopeManager.AddScopeID(recvMessage.PLS, recvMessage.SID, ref MsgNoSID, false, false);
                                    }
                                }
                            }
                            if (tTopicParts.Length > 1)
                            {
                                tTopicSens += $";{tTopicParts[1]}";                                                                                                                                                                                                               //if a direct address is added use this too
                            }
                            if (TheQueuedSenderRegistry.WasTSMSeenBefore(recvMessage, pRequestData.SessionState.cdeMID, tTopicSens, tTargetNodeChannel?.RealScopeID))                                                                                                             //ATTENTION: RScope should come from pDevMessage
                            {
                                TheBaseAssets.MySYSLOG.WriteToLog(285, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", $"EnterExecuteCommand: Message was seen before ORG:{TheCommonUtils.GetDeviceIDML(recvMessage?.ORG)} Topic:{tTopicSens}", eMsgLevel.l2_Warning)); //ORG-OK
                                TheCDEKPIs.IncrementKPI(eKPINames.QSRejected);
                                continue;
                            }
                            if (tTargetNodeChannel.cdeMID == Guid.Empty)
                            {
                                tTargetNodeChannel.cdeMID = recvMessage.GetLastRelay();
                            }
                            if (tTargetNodeChannel.SenderType == cdeSenderType.NOTSET)
                            {
                                TheBaseAssets.MySYSLOG.WriteToLog(285, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", "Sender Type for the QSender is not set! WE SHOULD NEVER GET HERE", eMsgLevel.l1_Error));//ORG-OK
                                //3.218: Processing no longer allowed!!!
                                return;
                            }
                            // Enable upper layers to do RSA decryption. Force overwrite for Browser even if SEID already set (may have been initialized to some other value)
                            if (tTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON || String.IsNullOrEmpty(recvMessage.SEID))
                            {
                                recvMessage.SEID = pRequestData.SessionState.cdeMID.ToString();
                            }

                            if (pRequestData.SessionState != null && string.IsNullOrEmpty(pRequestData.SessionState.RemoteAddress))
                            {
                                pRequestData.SessionState.RemoteAddress = tTargetNodeChannel.cdeMID.ToString();
                            }

                            //NEW: User ID Management in Message after first node
                            if (string.IsNullOrEmpty(recvMessage.UID) && pRequestData.SessionState != null && pRequestData.SessionState.CID != Guid.Empty)
                            {
                                recvMessage.UID = TheCommonUtils.cdeEncrypt(pRequestData.SessionState.CID.ToByteArray(), TheBaseAssets.MySecrets.GetAI());     //3.083: Must be cdeAI
                            }
                        }
                    }
                    catch (Exception ee)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(319, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("CoreComm", "Execute Command Pre-Parsing Error", eMsgLevel.l1_Error, ee.ToString()));
                    }

                    if (recvMessage == null)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(286, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"No Message for Parsing: Topic:{tTopic} - {pRequestData.ResponseBufferStr}", eMsgLevel.l7_HostDebugMessage));
                    }
                    else
                    {
                        if (recvMessage.PLB != null && recvMessage.PLB.Length > 0 && string.IsNullOrEmpty(recvMessage.PLS))
                        {
                            try
                            {
                                recvMessage.PLS = TheCommonUtils.cdeDecompressToString(recvMessage.PLB);
                                recvMessage.PLB = null;
                            }
                            catch (Exception)
                            {
                                TheBaseAssets.MySYSLOG.WriteToLog(286, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", $"PLB to PLS decompress failed - Topic:{tTopic} Node:{pQSender?.MyTargetNodeChannel?.ToMLString()} ORG:{TheCommonUtils.GetDeviceIDML(recvMessage?.ORG)}", eMsgLevel.l7_HostDebugMessage, $"TXT:{recvMessage.TXT}"));//ORG-OK
                            }
                        }

                        TheBaseAssets.MySYSLOG.WriteToLog(286, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"PLB to PLS parsing done - Topic:{tTopic} Node:{pQSender?.MyTargetNodeChannel?.ToMLString()} ORG:{TheCommonUtils.GetDeviceIDML(recvMessage?.ORG)}", eMsgLevel.l7_HostDebugMessage, $"TXT:{recvMessage.TXT}"));//ORG-OK
                        if (!SendPulse)
                        {
                            SendPulse = recvMessage.SendPulse();
                        }
                        TheCDEKPIs.IncrementKPI(eKPINames.CCTSMsEvaluated);
                    }

                    try
                    {
                        if (recvMessage != null && !string.IsNullOrEmpty(tTopic)) // tTopic != null)
                        {
                            if (!ParseSimplex(tTopic, recvMessage, pQSender))     //NEW:2.06 - No More Local Host processing here
                            {
                                if (TheBaseAssets.MyServiceHostInfo.MaximumHops == 0 || recvMessage.HobCount() < TheBaseAssets.MyServiceHostInfo.MaximumHops)
                                {
                                    if (!tTopic.StartsWith("CDE_CONNECT") || !TheBaseAssets.MyServiceHostInfo.AllowMessagesInConnect) // Should never get here if AllowMessagesInConnect is false, but avoid global publish just in case...
                                    {
                                        TheCDEKPIs.IncrementKPI(eKPINames.CCTSMsRelayed);
                                        TheCommCore.PublishCentral(tTopic, recvMessage, false, null, false, pQSender?.MyTargetNodeChannel?.IsTrustedSender ?? false);
                                    }
                                    else
                                    {
                                        // Message is part of a CDE_CONNECT: Republish it to enable single-post message sending (i.e. MSB/Service Gateway scenario)
                                        TheCDEKPIs.IncrementKPI(eKPINames.CCTSMsRelayed); // TODO SHould we have a separate KPI for this
                                        TheCommCore.PublishCentral(recvMessage, true, pQSender.MyTargetNodeChannel.IsTrustedSender);
                                    }
                                }
                            }
                            else
                            {
                                if (pQSender?.MyTargetNodeChannel != null && pQSender?.MyTargetNodeChannel?.SenderType != cdeSenderType.CDE_JAVAJASON)
                                {
                                    SendPulse = true;
                                }
                            }
                        }
                    }
                    catch (Exception ee)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(319, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("CoreComm", "Execute Command Parsing Error", eMsgLevel.l1_Error, ee.ToString()));
                    }
                    TheBaseAssets.MySYSLOG.WriteToLog(286, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"Done with Do Execute Command for Topic:{tTopic}", eMsgLevel.l7_HostDebugMessage));
                }
            }
            if (pRequestData.WebSocket == null)
            {
                if (DoSendBackBuffer)
                {
                    SetResponseBuffer(pRequestData, pQSender.MyTargetNodeChannel, SendPulse, "");
                }
                else if (SendPulse)
                {
                    pQSender.SendPickupMessage(); //Pickup next message right away if pulse mode is on
                }
            }
            TheBaseAssets.MySYSLOG.WriteToLog(286, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", "Leave Do Execute Command", eMsgLevel.l7_HostDebugMessage));
        }
 public void Disconnect()
 {
     TheQueuedSenderRegistry.UnregisterHealthTimer(sinkTimer);
     TheThing.SetSafePropertyBool(MyBaseThing, "IsConnected", false);
 }
Beispiel #25
0
        internal static string InfoHeader(bool IsSmall)
        {
            //string ret = $"<h3>{TheBaseAssets.MyServiceHostInfo.MyAppPresenter}</h3><h1>{TheBaseAssets.MyServiceHostInfo.ApplicationTitle} V{TheBaseAssets.MyServiceHostInfo.CurrentVersion}</h1><h3>Hosted at: {TheBaseAssets.LocalHostQSender.MyTargetNodeChannel}<br/>NodeName: {TheBaseAssets.MyServiceHostInfo.NodeName}</br>AppName:{TheBaseAssets.MyServiceHostInfo.ApplicationName}<br/>lcd: {TheBaseAssets.MyServiceHostInfo.BaseDirectory}</br>CDE:V{TheBaseAssets.CurrentVersionInfo} Drop: {TheBaseAssets.BuildVersion}</br>Started:{TheCommonUtils.GetDateTimeString(TheBaseAssets.MyServiceHostInfo.cdeCTIM, -1)}";
            string ret2 = $"<h3>{TheBaseAssets.MyServiceHostInfo.MyAppPresenter}</h3>"; //<div id=\"mainBox\" style=\"width-fixed:90%;display:flex; flex-flow: column wrap\">

            ret2 += $"<h1 id=\"title\">{TheBaseAssets.MyServiceHostInfo.ApplicationTitle} V{TheBaseAssets.MyServiceHostInfo.CurrentVersion}</h1>";
            if (TheBaseAssets.MyServiceHostInfo.ShowMarkupInLog)
            {
                ret2 += $"<script>var cdeCSOn; function cdeColorSpan(pContent, pColor) {{ var x = document.getElementsByClassName(\"cdeRSHash\");var i;for (i = 0; i < x.length; i++){{ if (!pContent) {{ if (!cdeCSOn) x[i].style.backgroundColor = \"transparent\"; }} else {{ if (pContent.innerText==x[i].innerText && !cdeCSOn) x[i].style.backgroundColor = pColor; }}}}}}</script>";
            }
            ret2 += $"<div class=\"cdeInfoBlock\" style=\"width:750px;\"><div class=\"cdeInfoBlockHeader cdeInfoBlockHeaderText\" id=\"nodeInfo\">Node Info</div><table style=\"margin-left:2%\">";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right; min-width:200px;\">Hosted at:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.LocalHostQSender.MyTargetNodeChannel.ToMLString(true)}</td></tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Node ID:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheCommonUtils.GetDeviceIDML(TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID)}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Node Name:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.MyServiceHostInfo.NodeName}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Station Name:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.MyServiceHostInfo.MyStationName}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Application Name:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.MyServiceHostInfo.ApplicationName}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">OS Info:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left;word-wrap: break-word;max-width:540px \">{TheBaseAssets.MyServiceHostInfo.OSInfo}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Local Dir:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.MyServiceHostInfo.BaseDirectory}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">CDE Info:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.CurrentVersionInfo}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">CDE Drop:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">V{TheBaseAssets.BuildVersion}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">CDE Crypto:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheBaseAssets.MySecrets.CryptoVersion()}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Unique Meshes Connected:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheQueuedSenderRegistry.GetUniqueMeshCount()}</td><tr>";
            string tScope = "";

            if (TheBaseAssets.MyScopeManager.IsScopingEnabled)
            {
                tScope = GetScopeHashML(TheBaseAssets.MyScopeManager.GetScopeHash(null));
            }
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Local Node-Scope:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{(TheBaseAssets.MyScopeManager.IsScopingEnabled ? $"A local Scope is set. Hash: {tScope}" : "Scoping is disabled")}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Client Cert Thumbprint:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{(TheBaseAssets.MyServiceHostInfo.ClientCertificateThumb?.Length > 3 ? $"{TheBaseAssets.MyServiceHostInfo.ClientCertificateThumb.Substring(0, 4)}" : $"No client certificate specified")}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Node Started at:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheCommonUtils.GetDateTimeString(TheBaseAssets.MyServiceHostInfo.cdeCTIM, -1)}</td><tr>";
            ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right\">Last Update at:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{TheCommonUtils.GetDateTimeString(DateTimeOffset.Now, -1)}</td><tr>";
            ret2 += "</table>";

            if (!IsSmall)
            {
                ret2 += $"<h2>Service Routes:</h2><table style=\"margin-left:2%\">";
                ret2 += $"<tr><th scope=\"rowgroup;\" style=\"background-color:rgba(90,90,90, 0.15); padding:3px; text-align:right; width:200px;\">Configured Routes:</th><td style=\"border-bottom:1px solid rgba(90, 90, 90, 0.25);padding:3px;text-align:left \">{(string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) ? "No Routes are configured" : $"{TheBaseAssets.MyServiceHostInfo.ServiceRoute}")}</td></tr>";
        internal static bool ParseSimplex(string pScopedTopic, TSM pMessage, TheQueuedSender pQSender) //, TheSessionState pSessionState, Action<TSM> pLocalCallback)
        {
            if (pMessage == null)
            {
                return(false);
            }
#if !JC_COMMDEBUG
            try
            {
#endif
            if (pMessage?.TXT?.Equals("CDE_DELETEORPHAN") == true)
            {
                TheQueuedSenderRegistry.RemoveOrphan(TheCommonUtils.CGuid(pMessage.PLS));
                return(false);
            }

            if (pQSender == null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(291, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", $"QSender not found! Received from ORG:{TheCommonUtils.GetDeviceIDML(pMessage?.ORG)}", eMsgLevel.l1_Error, pMessage?.PLS));
                return(false);
            }

            //SECURITY-REVIEW: This cannot be permitted without extra tokens and Encryption! otherwise it can be used to change a nodes scope on the fly!
            //if ("CDE_UPDATESCOPE".Equals(pMessage.TXT))
            //{
            //    pQSender.UpdateSubscriptionScope(TheBaseAssets.MyScopeManager.GetRealScopeID(pMessage.SID));     //GRSI: rare
            //    return true;
            //}
            if (pQSender != null && pMessage.ENG?.StartsWith(eEngineName.ContentService) == true && pMessage?.TXT == "CDE_SERVICE_INFO" && pQSender.MyTargetNodeChannel?.RealScopeID == TheBaseAssets.MyScopeManager.GetRealScopeID(pMessage.SID))
            {
                try
                {
                    pQSender.SetNodeInfo(TheCommonUtils.DeserializeJSONStringToObject <TheNodeInfoClone>(pMessage?.PLS));
                }
                catch (Exception e)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(23056, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"Error decoding SystemInfo {pQSender?.MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l1_Error, e.ToString()));
                }
            }

            if (pMessage.TXT?.Equals("CDE_SUBSCRIBE") == true || pMessage.TXT?.Equals("CDE_INITIALIZE") == true) //9-9-2012 CDEC Did not work right on CDE_INIT
            {
                TheBaseAssets.MySYSLOG.WriteToLog(292, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", $"Parse-Simplex Subscribe from {pQSender?.MyTargetNodeChannel?.ToMLString()} Parsed: {pMessage?.PLS}", eMsgLevel.l7_HostDebugMessage));
                if (pQSender?.MyISBlock != null && !TheBaseAssets.MyServiceHostInfo.IsCloudService)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(292, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", "Parse-Simplex Subscribe rejected for Custom ISBConnect", eMsgLevel.l7_HostDebugMessage));
                    return(true);
                }
                ParseSubscribe(pMessage.PLS, pQSender);
                if (pMessage.ENG.Equals("CLOUDSYNC"))
                {
                    string[] tTopics = pMessage.PLS.Split(';');
                    foreach (string t in tTopics)
                    {
                        TSM.GetScrambledIDFromTopic(t, out string tEng);
                        if (TheThingRegistry.IsEngineRegistered(tEng))
                        {
                            IBaseEngine tsBase = TheThingRegistry.GetBaseEngine(tEng);
                            tsBase?.GetBaseThing()?.FireEvent(eEngineEvents.NewSubscription, tsBase.GetBaseThing(), pQSender.MyTargetNodeChannel, true);
                        }
                    }
                    return(true);
                }
                else
                {
                    TheThing tBase2 = TheThingRegistry.GetBaseEngineAsThing(pMessage.ENG);
                    if (tBase2 != null)
                    {
                        tBase2.FireEvent(eEngineEvents.NewSubscription, tBase2, pQSender.MyTargetNodeChannel, true);
                    }
                }
                if (pMessage.TXT.Equals("CDE_SUBSCRIBE"))       //NEW:2.06 Make sure Subscribe and Unsubscribe only go to first node
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            if (pMessage.TXT?.Equals("CDE_UNSUBSCRIBE") == true)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(292, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", $"Parse-Simplex Unsubscribe from {pQSender.MyTargetNodeChannel?.ToMLString()} Parsed: {pMessage.PLS}", eMsgLevel.l7_HostDebugMessage));
                ParseUnsubscribe(pMessage.PLS, pQSender);
                return(true);       //NEW:2.06 Make sure Subscribe and Unsubscribe only go to first node
            }
#if !JC_COMMDEBUG
        }

        catch (Exception ee)
        {
            TheBaseAssets.MySYSLOG.WriteToLog(316, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", "Parse-Simplex", eMsgLevel.l1_Error, ee.ToString()));
        }
#endif
            return(false);
        }