예제 #1
0
        internal void Startup()
        {
            TheDiagnostics.SetThreadName("WSStartup");
            if (TheBaseAssets.MyServiceHostInfo.MyStationWSPort == 0) return;
            Uri tUri = new Uri(TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false));
            MyHttpUrl = tUri.Scheme + "://*"; // +tUri.Host;
            MyHttpUrl += ":" + TheBaseAssets.MyServiceHostInfo.MyStationWSPort;
            MyHttpUrl += "/";
            appServer = new WebSocketServer();

            //Setup the appServer
            if (!appServer.Setup(new ServerConfig() { Port = TheBaseAssets.MyServiceHostInfo.MyStationWSPort, MaxRequestLength = 400000 })) //Setup with listening port
            {
                TheBaseAssets.MySYSLOG.WriteToLog(4343, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSServer", "Error During Startup", eMsgLevel.l1_Error));
                return;
            }

            appServer.NewMessageReceived += new SessionHandler<WebSocketSession, string>(appServer_NewMessageReceived);
            appServer.NewDataReceived += appServer_NewDataReceived;
            appServer.NewSessionConnected += appServer_NewSessionConnected;
            appServer.SessionClosed += appServer_SessionClosed;
            //Try to start the appServer
            if (!appServer.Start())
            {
                TheBaseAssets.MySYSLOG.WriteToLog(4343, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSServer", "Failed to start Super-Web-Socket Server", eMsgLevel.l1_Error));
                IsActive = false;
                return;
            }
            IsActive = true;
            TheBaseAssets.MySYSLOG.WriteToLog(4343, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheWSServer", "New Super-Web-Socket Server started ", eMsgLevel.l4_Message));
        }
예제 #2
0
 public static async Task WaitForWSAccept(HttpListenerContext pContext)
 {
     TheDiagnostics.SetThreadName("WSWait4Accept");
     var wsc = await pContext.AcceptWebSocketAsync(null);
     if (wsc != null)
     {
         TheRequestData tRequestData = new TheRequestData
         {
             RequestUri = pContext.Request.Url,
             UserAgent = pContext.Request.UserAgent,
             HttpMethod = pContext.Request.HttpMethod,
             Header = TheCommonUtils.cdeNameValueToDirectory(pContext.Request.Headers),
             ResponseMimeType = pContext.Request.ContentType,
             ServerTags = null,
             ClientCert = pContext.Request.GetClientCertificate()
         };
         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 (!string.IsNullOrEmpty(err))
             {
                 pContext.Response.StatusCode = (int)eHttpStatusCode.AccessDenied;
                 pContext.Response.OutputStream.Close();
                 return;
             }
         }
         TheWSProcessor8 tProcessor = new TheWSProcessor8(wsc.WebSocket);
         tProcessor.SetRequest(tRequestData);
         await tProcessor.ProcessWS();
     }
 }
예제 #3
0
 private void PollTelnetServer()
 {
     TheDiagnostics.SetThreadName("Telnet-Server", true);
     while (telnetClient.Connected && TheBaseAssets.MasterSwitch)
     {
         PollServer();
         Thread.Sleep(50);
     }
     if (telnetClient.Connected)
     {
         telnetClient.Disconnect();
     }
     eventClosed?.Invoke("Ended");
 }
예제 #4
0
        internal void CheckOnHealthTimer(long tTimerVal)
        {
            if (mDisableCollection)
            {
                return;
            }
            if ((tTimerVal % HealthUpdateCycle) != 0)
            {
                return;
            }
            if (TheCommonUtils.cdeIsLocked(lockCheckTimer))
            {
                return;
            }
            lock (lockCheckTimer)
            {
                if (!AreCounterInit)
                {
                    return;
                }
                TheBaseAssets.MySYSLOG.WriteToLog(8005, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("jcHealth", "Enter CheckOnHealthTimer", eMsgLevel.l7_HostDebugMessage));
                TheDiagnostics.SetThreadName("C-MyComputer-HealthTimer", true);
                if (!IsEnergyRegistered)
                {
                    TheThing tThing = TheThingRegistry.GetBaseEngineAsThing("CDMyEnergy.TheCDMyEnergyEngine");
                    if (tThing != null)
                    {
                        IsEnergyRegistered = true;
                        tThing.RegisterEvent(eEngineEvents.MessageProcessed, sinkEnergyFound);
                    }
                }
                SendHealthInfo(Guid.Empty);

                if (MyServiceHealthDataStore != null)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(8006, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("jcHealth", "Storing HealthInfo", eMsgLevel.l7_HostDebugMessage, MyHealthData.cdeUptime.ToString()));
                    if (!MyServiceHealthDataStore.IsReady)
                    {
                        MyServiceHealthDataStore.InitializeStore(false);
                        TheBaseAssets.MySYSLOG.WriteToLog(8006, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("jcHealth", "Storing HealthInfo- Initializing store", eMsgLevel.l4_Message));
                    }
                    MyServiceHealthDataStore.AddAnItem(TheThingStore.CloneFromTheThing(MyHealthData, true));
                }

                TheBaseAssets.MySYSLOG.WriteToLog(8006, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("jcHealth", "Leave CheckOnHealthTimer", eMsgLevel.l7_HostDebugMessage));
            }
        }
예제 #5
0
        private static void sinkRequestFailed(object state)
        {
            TheDiagnostics.SetThreadName("TimedRequestFailed", true);
            TheTimedRequest <T> req = state as TheTimedRequest <T>;

            if (state != null)
            {
                TheTimedRequest <T> tReq = req;
                lock (MyStoreRequestsLock)
                {
                    if (MyStoreRequests.ContainsKey(tReq.MagicID.ToString()))
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(472, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheTimedCallbacks", "Timed-Request Timed Out", eMsgLevel.l2_Warning));
                        MyStoreRequests.RemoveNoCare(tReq.MagicID.ToString());
                        tReq.MyRequest("Timed-Request Timed Out", (T)tReq.Cookie);
                    }
                }
            }
        }
예제 #6
0
 internal void Startup()
 {
     TheDiagnostics.SetThreadName("WSStartup");
     if (TheBaseAssets.MyServiceHostInfo.MyStationWSPort == 0) return;
     try
     {
         if (TheBaseAssets.MyServiceHostInfo.MyStationPort == TheBaseAssets.MyServiceHostInfo.MyStationWSPort)
             TheBaseAssets.MyServiceHostInfo.MyStationWSPort =(ushort)(TheBaseAssets.MyServiceHostInfo.MyStationPort + 1);
         appServer = new WebSocketServer(TheBaseAssets.MyServiceHostInfo.MyStationWSPort) { ReuseAddress = true }; // tUri.ToString());
         appServer.AddWebSocketService<CDEWSBehavior>(TheBaseAssets.MyServiceHostInfo.RootDir + "/ISB");
         appServer.Log.Level = LogLevel.Fatal;
         appServer.Log.Output = sinkLog;
         appServer.Start();
         IsActive = true;
         TheBaseAssets.MySYSLOG.WriteToLog(4378, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheWSServer", "New WebSocket-sharp Server started ", eMsgLevel.l4_Message, $"Port: {appServer.Port}"));
     }
     catch (Exception ee)
     {
         TheBaseAssets.MySYSLOG.WriteToLog(4378, new TSM("TheWSServer", "WebSocket-sharp could not start!", eMsgLevel.l1_Error, $"Port: {TheBaseAssets.MyServiceHostInfo.MyStationWSPort} {ee.ToString()}"));
     }
 }
예제 #7
0
 public bool RegisterDevice(TheUPnPDeviceInfo pNewDevice, bool ForceUpdate)
 {
     TheDiagnostics.SetThreadName("UPnP-Notify", true);
     if (!TheBaseAssets.MasterSwitch || (TheCommonUtils.cdeIsLocked(LockNotify) && !ForceUpdate) || string.IsNullOrEmpty(pNewDevice?.LocationURL))
     {
         return(false);
     }
     lock (LockNotify)
     {
         TheUPnPDeviceInfo tHistory = null;
         //tHistory = MyUPnPDiscoveryPast.MyMirrorCache.GetEntryByFunc((s) => s.LocationURL.Equals(pNewDevice.LocationURL, StringComparison.OrdinalIgnoreCase)); //
         string[] tUsn    = pNewDevice.USN.Split(':');
         string   tNewUsn = pNewDevice.USN;
         if (tUsn.Length > 2)
         {
             tNewUsn = tUsn[0] + ':' + tUsn[1];
         }
         tHistory = MyUPnPDiscoveryPast.MyMirrorCache.GetEntryByFunc((s) => s.USN.StartsWith(tNewUsn, StringComparison.OrdinalIgnoreCase)); //
         if (tHistory != null)                                                                                                              //gUSN
         {
             try
             {
                 tHistory.SourceIP    = IPAddress.TryParse(pNewDevice.LocationURL.Split(':')[0], out IPAddress tIp) ? pNewDevice.LocationURL : new Uri(pNewDevice.LocationURL).Host;
                 tHistory.LocationURL = pNewDevice.LocationURL;
                 if (DateTimeOffset.Now.Subtract(tHistory.LastSeenAt).TotalSeconds < tHistory.MaxAge)
                 {
                     MyUPnPDiscoveryPast.MyMirrorCache.AddOrUpdateItem(tHistory); //gUSN
                     if (tHistory.IsCDEngine)
                     {
                         ProcessCDEngine(tHistory, TheCommonUtils.CUri(tHistory.LocationURL, false));
                     }
                     else
                     {
                         CheckForDeviceMatch(tHistory, null);
                     }
                     return(true);
                 }
                 tHistory.LastSeenAt = DateTimeOffset.Now;
             }
             catch (Exception e)
             {
                 TheBaseAssets.MySYSLOG.WriteToLog(111, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("UPnP", string.Format("UPnP {0} Invalid Device URL", pNewDevice), eMsgLevel.l1_Error, e.ToString()));
                 return(false);
             }
         }
         if (tHistory == null)
         {
             tHistory = pNewDevice;
         }
         MyUPnPDiscoveryPast.MyMirrorCache.AddOrUpdateItem(tHistory); //gUSN
         Uri tLocationUrl;
         try
         {
             tLocationUrl = TheCommonUtils.CUri(tHistory.LocationURL, false);
             TheBaseAssets.MySYSLOG.WriteToLog(111, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("UPnP", string.Format("UPnP {0} Device Found", tHistory), eMsgLevel.l3_ImportantMessage));
             CheckForDeviceMatch(tHistory, tLocationUrl);
         }
         catch (Exception eee)
         {
             TheBaseAssets.MySYSLOG.WriteToLog(111, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("UPnP", string.Format("Non UPnP conform device found: {0}", tHistory), eMsgLevel.l7_HostDebugMessage, eee.ToString()));
             return(false);
         }
         if (tHistory.IsCDEngine)
         {
             ProcessCDEngine(tHistory, tLocationUrl);
         }
     }
     return(true);
 }
예제 #8
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()));
            }
        }
예제 #9
0
        private void TheWSSenderThread()
        {
            if (IsSenderThreadRunning /*|| MyTargetNodeChannel==null*/)
            {
                return;
            }
            if (MyTargetNodeChannel == null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(2371, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("WSQueuedSender", $"WSSender Thread could not be started because MTNC is null", eMsgLevel.l4_Message));
                return;
            }
            TheDiagnostics.SetThreadName($"QSender:{MyTargetNodeChannel} WSSenderThread", true);
            IsSenderThreadRunning = true;
            mre = new ManualResetEvent(false);

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

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

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

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

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

                    if (!cdeSenderType.CDE_JAVAJASON.Equals(MyTargetNodeChannel.SenderType))
                    {
                        MyWebSocketProcessor.PostToSocket(null, TheCommonUtils.cdeCompressString(tSendBufferStr.ToString()), true, false);
                    }
                    else
                    {
                        MyWebSocketProcessor.PostToSocket(null, TheCommonUtils.CUTF8String2Array(tSendBufferStr.ToString()), false, false);
                    }
                    IsInWSPost = false;
                }
                TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("WSQueuedSender", $"WSQSenderThread was closed for {MyTargetNodeChannel?.ToMLString()} IsAlive:{IsAlive} MyWSProccAlive:{(MyWebSocketProcessor == null ? "Is Null" : MyWebSocketProcessor?.IsActive.ToString())},SessionState:{(MyTargetNodeChannel?.MySessionState != null)} IsConnecting:{IsConnecting} IsConnected:{IsConnected}", eMsgLevel.l1_Error));
            }
            catch (Exception e)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("WSQueuedSender", "Exception in WSSenderThread.", eMsgLevel.l1_Error, "Error:" + e));
            }
            finally
            {
                IsInWSPost            = false;
                IsSenderThreadRunning = false;
                StopHeartBeat();
            }
            if (IsAlive || (MyWebSocketProcessor != null && MyWebSocketProcessor.IsActive))
            {
                IsAlive = false;
                if (MyWebSocketProcessor != null)
                {
                    MyWebSocketProcessor.Shutdown(true, "1310:SenderThread Closed");
                }
            }
            CloudCounter--;
        }
예제 #10
0
        public void TheRESTSenderThread()
        {
            if (IsSenderThreadRunning)
            {
                return;
            }
            try
            {
                TheDiagnostics.SetThreadName($"QSender:{MyTargetNodeChannel} SenderThread", true);
                MyREST = new TheREST();
                IsSenderThreadRunning = true;
                StringBuilder tSendBufferStr = new StringBuilder(TheBaseAssets.MyServiceHostInfo?.IsMemoryOptimized == true ? 1024 : TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType] * 2);
                TargetUri     = TheCommonUtils.CUri(MyTargetNodeChannel.TargetUrl, true);
                TargetUriPath = TargetUri.AbsolutePath;

                int QDelay = TheCommonUtils.CInt(TheBaseAssets.MySettings.GetSetting("ThrottleWS"));
                if (QDelay < 2)
                {
                    QDelay = 2;
                }
                if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON && TheBaseAssets.MyServiceHostInfo.WsJsThrottle > QDelay)
                {
                    QDelay = TheBaseAssets.MyServiceHostInfo.WsJsThrottle;
                }
                mre = new ManualResetEvent(false);
                if (eventSenderThreadRunning != null)
                {
                    TheCommonUtils.cdeRunAsync("EventSenderThreadRunning", true, (p) => { eventSenderThreadRunning(this); });
                }
                MyISBlock?.FireEvent("SenderThreadCreated");
                while (TheBaseAssets.MasterSwitch && IsAlive && IsSenderThreadRunning)
                {
                    if (QDelay > 2)
                    {
                        mre.WaitOne(QDelay);    //Throtteling should be here not in the wait loop
                    }
                    int WaitCounter = 0;
                    while (TheBaseAssets.MasterSwitch && IsAlive && IsSenderThreadRunning && ((MyCoreQueue.Count == 0 && IsConnected) || IsConnecting || IsInPost || MyREST.IsPosting > (IsConnected?TheBaseAssets.MyServiceHostInfo.ParallelPosts:0)))
                    {
                        // CODE REVIEW: This was seen looping after service route to local node was closed (due to node shutdown): IsCOnnecting/IsConnected/IsInPost were false; ISAlive true. MyREST.IsPosting was 8. Queue count ~345
                        //              This should be fixed now with IsSenderThreadRunning in the loop (I was wrong :) this happens only with cloud connections where POST fails and the IsPosting was not reset properly).
                        // Update: If found the same problem. Sometime IsPosting is not reduced properly when a Timeout or other error occured during Posting
                        if (IsInPost && MyCoreQueue.Count > 100)
                        {
                            TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"IsInPost was still on and has been reset for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l2_Warning));
                            IsInPost = false;
                        }
                        if (!IsConnected)
                        {
                            if (IsConnecting && MyREST.IsPosting == 0)
                            {
                                TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"IsConnecting is set but no Pending Post {MyTargetNodeChannel?.ToMLString()} - resetting IsConnecting", eMsgLevel.l2_Warning));
                                IsConnecting = false;
                            }
                            if (!IsConnecting && MyREST.IsPosting > (IsConnected ? 10 : 0))
                            {
                                WaitCounter++;
                                if (WaitCounter > (10000 / QDelay))
                                {
                                    TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"MyREST.IsPosting ({MyREST.IsPosting}) was higher then expected...possible POST problem. Resetting POST Counter for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l2_Warning));
                                    MyREST.IsPosting = 0;
                                }
                            }
                        }

                        mre.WaitOne(QDelay);
                    }
                    if (!TheBaseAssets.MasterSwitch || !IsAlive || !IsSenderThreadRunning)
                    {
                        IsInPost = false;
                        break;
                    }
                    IsInPost = true;
                    if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_BACKCHANNEL ||
                        MyTargetNodeChannel.SenderType == cdeSenderType.CDE_PHONE ||
                        MyTargetNodeChannel.SenderType == cdeSenderType.CDE_DEVICE ||
                        MyTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"QSender Should NEVER GO HERE because SenderType is {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l1_Error));
                        IsInPost = false;
                        IsSenderThreadRunning = false;
                        return;
                    }
                    //NEW3.124: Sender Loop has to terminate if Cloud was Disabled.
                    if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE && (TheBaseAssets.MyServiceHostInfo.IsCloudDisabled || string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) || !TheBaseAssets.MyServiceHostInfo.HasServiceRoute(TargetUri)))  //ServiceRoute can contain multiple routes...
                    {
                        break;
                    }
                    TheCoreQueueContent tQueued = null;
                    int MCQCount  = 0;
                    int IsBatchOn = 0;
#if CDE_NET35
                    tSendBufferStr = new StringBuilder(TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType] * 2);
#else
                    tSendBufferStr.Clear();
#endif
                    tSendBufferStr.Append("[");
                    byte[] BinSendBuffer = null;
                    do
                    {
                        if (!IsConnected)
                        {
                            tQueued        = new TheCoreQueueContent();
                            IsConnecting   = true;
                            ConnectRetries = 0;
                            if (CloudInRetry)
                            {
                                var count = Interlocked.Increment(ref CloudRetryCount);
                                if (count > 10)
                                {
                                    int delaySeconds = TheBaseAssets.MyServiceHostInfo.HeartbeatDelay * TheBaseAssets.MyServiceHostInfo.TO.HeartBeatRate;
                                    TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("QueuedSender", $"Too many retries for {MyTargetNodeChannel?.ToMLString()}: {count}. Waiting {delaySeconds} seconds.", eMsgLevel.l2_Warning));
                                    TheCommonUtils.SleepOneEye((uint)delaySeconds * 1000, 100);
                                    Interlocked.Exchange(ref CloudRetryCount, 0);
                                }
                                if (!TheBaseAssets.MasterSwitch || !IsAlive || !IsSenderThreadRunning || (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE &&
                                                                                                          (TheBaseAssets.MyServiceHostInfo.IsCloudDisabled || string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) || !TheBaseAssets.MyServiceHostInfo.HasServiceRoute(TargetUri))))
                                {
                                    //Very rare but required after Sleep
                                    throw new Exception("QSender had to be terminated in Cloud Retry due to disabling of ServiceRoute or C-DEngine Shutdown");
                                }
                            }//NEW3.124: Sender Loop has to terminate if Cloud was Disabled.
                            if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE && (TheBaseAssets.MyServiceHostInfo.IsCloudDisabled || string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) || !TheBaseAssets.MyServiceHostInfo.HasServiceRoute(TargetUri)))
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (CloudInRetry)
                            {
                                CloudInRetry = false;
                                IsInPost     = false;
                                continue;
                            }
                            tQueued = GetNextMessage(out MCQCount);
                        }
                        if (tQueued != null)
                        {
                            TheCDEKPIs.IncrementKPI(eKPINames.QSSent);

                            if (tQueued.OrgMessage == null && !IsConnecting)
                            {
                                if (MySubscriptions.Count == 0)
                                {
                                    if (IsBatchOn == 0) //Only jump out if no telegrams are in batch..
                                    {
                                        IsInPost = false;
                                        continue;
                                    }
                                }
                                if (IsBatchOn == 0) //If telegrams are in the batch dont send short message
                                {
                                    BinSendBuffer    = new byte[1];
                                    BinSendBuffer[0] = (byte)((int)(TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType)).ToString()[0];
                                    break;
                                }
                            }
                            if (tQueued.OrgMessage != null && tQueued.OrgMessage.ToCloudOnly() && MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE)
                            {
                                tQueued.OrgMessage.SetToCloudOnly(false);
                            }

                            TheDeviceMessage tDev = new TheDeviceMessage
                            {
                                DID = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString() // MyTargetNodeChannel.cdeMID.ToString();
                            };

                            if (MyTargetNodeChannel.MySessionState != null)
                            {
                                //BUGFIX: After fast Cloud Disconnect/reconnect-Relay lost Scopeing because it Scope was not properly stored in SessionState
                                if (string.IsNullOrEmpty(MyTargetNodeChannel.MySessionState.SScopeID) && TheBaseAssets.MyScopeManager.IsScopingEnabled)
                                {
                                    MyTargetNodeChannel.MySessionState.SScopeID = TheBaseAssets.MyScopeManager.GetScrambledScopeID();       //GRSI: rare
                                }
                                if (TheBaseAssets.MyServiceHostInfo.EnableFastSecurity)
                                {
                                    tDev.SID = MyTargetNodeChannel.MySessionState.SScopeID;
                                }
                                else
                                {
                                    tDev.SID = TheBaseAssets.MyScopeManager.GetScrambledScopeID(MyTargetNodeChannel.MySessionState.SScopeID, false); //GRSI: high frequency!
                                }
                            }
                            else
                            {
                                tDev.SID = TheBaseAssets.MyScopeManager.GetScrambledScopeID();      //GRSI: rare
                            }
                            tDev.MSG = tQueued.OrgMessage;
                            tDev.FID = "1";
                            if (IsConnecting)
                            {
                                tDev.TOP = TheCommCore.SetConnectingBufferStr(MyTargetNodeChannel, null);
                            }
                            else
                            {
                                tDev.TOP = tQueued.Topic;
                                tQueued.OrgMessage?.GetNextSerial(tQueued.SubMsgCnt);
                                if (MyTargetNodeChannel.MySessionState != null)
                                {
                                    tDev.FID = MyTargetNodeChannel.MySessionState.GetNextSerial().ToString(); //(SendCounter + 1).ToString();    //V3B3: New was empty //V4.1010: Same as WS now
                                }
                            }

                            #region Batch Serialization
                            IsBatchOn++;
                            if (MCQCount == 0 || IsBatchOn > TheBaseAssets.MyServiceHostInfo.MaxBatchedTelegrams || tQueued.IsChunked)
                            {
                                if (MCQCount != 0)
                                {
                                    tDev.CNT = MCQCount;
                                }
                                IsBatchOn = 0;
                            }
                            else
                            {
                                if (tSendBufferStr.Length > TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType])
                                {
                                    tDev.CNT  = MCQCount;
                                    IsBatchOn = 0;
                                }
                            }
                            if (tSendBufferStr.Length > 1)
                            {
                                tSendBufferStr.Append(",");
                            }
                            tSendBufferStr.Append(TheCommonUtils.SerializeObjectToJSONString(tDev));
                            #endregion
                        }
                        else
                        {
                            IsBatchOn = 0;
                        }
                    } while (IsBatchOn > 0 && IsInPost && TheBaseAssets.MasterSwitch);
                    if ((!IsInPost || tSendBufferStr.Length < 2) && BinSendBuffer == null)
                    {
                        IsInPost = false;
                        continue;
                    }

                    string tMimeType = "application/octet-stream";
                    if (BinSendBuffer == null)
                    {
                        tSendBufferStr.Append("]");
                        if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_MINI || TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType == cdeSenderType.CDE_MINI)
                        {
                            tMimeType     = "application/json";
                            BinSendBuffer = TheCommonUtils.CUTF8String2Array(tSendBufferStr.ToString());
                        }
                        else
                        {
                            tMimeType     = "application/x-gzip";
                            BinSendBuffer = TheCommonUtils.cdeCompressString(tSendBufferStr.ToString());
                        }
                    }
                    if (MyTargetNodeChannel == null)
                    {
                        TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("QueuedSender", $"Channel was deleted - exiting SenderThread", eMsgLevel.l2_Warning));
                        IsInPost = false;
                        break;
                    }
                    string         ISBPath = new Uri(TargetUri, TheBaseAssets.MyScopeManager.GetISBPath(TargetUriPath, TheCommonUtils.GetOriginST(MyTargetNodeChannel), MyTargetNodeChannel.SenderType, MyTargetNodeChannel.MySessionState == null? 1: MyTargetNodeChannel.MySessionState.FID /*Interlocked.Increment(ref SendCounter)*/, (MyTargetNodeChannel.MySessionState == null || !IsConnected) ?Guid.Empty: MyTargetNodeChannel.MySessionState.cdeMID, MyTargetNodeChannel.IsWebSocket)).ToString(); //V3B4: changed from TheBaseAssets.MyServiceHostInfo.MyDeviceInfo
                    TheRequestData pData   = new TheRequestData
                    {
                        RemoteAddress    = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false),
                        RequestUri       = new Uri(ISBPath),
                        PostData         = BinSendBuffer,
                        ResponseMimeType = tMimeType,
                        DeviceID         = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID,
                        HttpMethod       = "POST"
                    };
                    if (!TheCertificates.SetClientCert(pData, MyTargetNodeChannel?.ClientCertificateThumb))
                    {
                        throw new Exception("Client Certificate could not be added");
                    }
                    MyREST.PostRESTAsync(pData, sinkUploadDataCompleted, FireSenderProblem);
                    if (BinSendBuffer != null)
                    {
                        TheCDEKPIs.IncrementKPI(eKPINames.QKBSent, BinSendBuffer.Length);
                    }

                    IsInPost = false;
                }
                FlushQueue();
                TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("QueuedSender", $"QSenderThread was closed for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l6_Debug));
            }
            catch (Exception e)
            {
                IsInPost = false;
                TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("QueuedSender", "Exception in jcSenderThread.", eMsgLevel.l1_Error, "Error:" + e));
                if (MyTargetNodeChannel?.SenderType != cdeSenderType.CDE_BACKCHANNEL)
                {
                    FireSenderProblem(new TheRequestData()
                    {
                        ErrorDescription = $"1308:{e}"
                    });
                }
            }
            finally
            {
                IsSenderThreadRunning = false;
                IsAlive      = false;
                IsInPost     = false;
                CloudInRetry = false;
                StopHeartBeat();
            }
        }
예제 #11
0
        internal override void PostToSocket(TheDeviceMessage pMsg, byte[] pPostBuffer, bool PostAsBinary, bool IsInitialConnect)
        {
            TheDiagnostics.SetThreadName("WSPostToSocketCSWS:" + (MyQSender.MyTargetNodeChannel?.ToString() ?? "DEAD"));

            if (MyQSender != null && !MyQSender.IsConnected && !IsInitialConnect)
            {
                Shutdown(true, "1653:QSenderCSWS not connected but Posting in illegal state");
                return;
            }

            if (!ProcessingAllowed)         //NEW:V3BETA2: New Waiting Algorythm
                WaitUntilProcessingAllowed();

            if (!IsActive || !TheBaseAssets.MasterSwitch)
                return;

            if (websocket == null && webSocketSession==null)
            {
                eventClosed?.Invoke("1654:WebSockets are down");
                return;
            }
            ProcessingAllowed = false;

            try
            {
                if (pPostBuffer != null)
                {
                    TheCDEKPIs.IncrementKPI(eKPINames.QKBSent, pPostBuffer.Length);
                    if (PostAsBinary)
                    {
                        if (webSocketSession != null)
                            webSocketSession.SendB(pPostBuffer);
                        else
                        {
                            websocket?.Send(pPostBuffer);
                        }
                    }
                    else
                    {
                        if (webSocketSession != null)
                            webSocketSession.SendB(TheCommonUtils.CArray2UTF8String(pPostBuffer));
                        else
                        {
                            websocket?.Send(TheCommonUtils.CArray2UTF8String(pPostBuffer));
                        }
                    }
                }
                else
                {
                    string toSend = TheCommonUtils.SerializeObjectToJSONString(pMsg);
                    if (PostAsBinary)
                    {
                        byte[] toSendb = TheCommonUtils.CUTF8String2Array(toSend);
                        TheCDEKPIs.IncrementKPI(eKPINames.QKBSent, toSendb.Length);
                        if (webSocketSession != null)
                            webSocketSession.SendB(toSendb);
                        else
                        {
                            websocket?.Send(toSendb);
                        }
                    }
                    else
                    {
                        if (webSocketSession != null)
                            webSocketSession.SendB(toSend);
                        else
                        {
                            websocket?.Send(toSend);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Shutdown(true, "1655:DoPostToSocketCSWS had a fault: "+e);
            }

            if (mre != null)
                ProcessingAllowed = true;
        }
예제 #12
0
        internal override void PostToSocket(TheDeviceMessage pMsg, byte[] pPostBuffer, bool SendAsBinary, bool IsInitialConnect)
        {
            TheDiagnostics.SetThreadName("WSPostToSocket:" + ((MyQSender?.MyTargetNodeChannel != null) ? MyQSender.MyTargetNodeChannel.ToString():"DEAD"));
            if (MyQSender?.MyTargetNodeChannel == null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("ProcessWS", $"QSender8 not Has not QSender or TargetChannel {MyQSender}", eMsgLevel.l1_Error));
                Shutdown(true, "1608:WS8 has not QSender but is Posting - illegal state");
                return;
            }

            if (MyQSender != null && !MyQSender.IsConnected && !IsInitialConnect)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("ProcessWS", "QSender8 not connected but Posting - illegal state", eMsgLevel.l1_Error));
                Shutdown(true, "1609:QSender8 not connected but Posting - illegal state");
                return;
            }

            bool HasFaulted = false;

            lock (_postToSocketLock)
            // The lock needs to be at the websocket level: assumption is that there is at most one WSProcessor per socket!
            {
                if (!IsActive || !TheBaseAssets.MasterSwitch)
                {
                    return;
                }

                ProcessingAllowed = false;
                string errorMsg = "";
                try
                {
                    if (!IsSocketReady(websocket))
                    {
                        HasFaulted = true;
                        errorMsg   = "Socket Not Ready";
                    }
                    else
                    {
                        // TODO MH - Move this outside of the lock so we can minimize the lock time? Or are there ordering constraints on the serialization for some reason?
                        ArraySegment <byte> outputBuffer;
                        if (pPostBuffer != null)
                        {
                            TheCDEKPIs.IncrementKPI(eKPINames.QKBSent, pPostBuffer.Length);
                            outputBuffer = new ArraySegment <byte>(pPostBuffer);
                        }
                        else
                        {
                            string tStr = TheCommonUtils.SerializeObjectToJSONString(pMsg);
                            TheCDEKPIs.IncrementKPI(eKPINames.QKBSent, tStr.Length);
                            outputBuffer = new ArraySegment <byte>(Encoding.UTF8.GetBytes(tStr));
                        }
                        //LogBufferToFile("wsoutputputlog", outputBuffer.Array, outputBuffer.Offset, outputBuffer.Count);
                        Task tTask = websocket.SendAsync(outputBuffer, SendAsBinary ? WebSocketMessageType.Binary : WebSocketMessageType.Text, true, TheBaseAssets.MasterSwitchCancelationToken);
                        tTask.Wait(TheBaseAssets.MyServiceHostInfo.TO.WsTimeOut * 10);
                        if (!tTask.IsCompleted)
                        {
                            var timeoutValue = TheBaseAssets.MyServiceHostInfo.TO.WsTimeOut * 10;
                            TheBaseAssets.MySYSLOG.WriteToLog(43610, new TSM("TheWSProcessor", $"WebSocketServer-PostToSocket error: PostAsync Timeout {tTask.Status} after {timeoutValue} ms for {MyQSender?.MyTargetNodeChannel}", eMsgLevel.l1_Error));
                            errorMsg   = $"SendAsync timed out after {timeoutValue} ms";
                            HasFaulted = true;
                        }
                    }
                }
                catch (Exception e)
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(43610, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSProcessor", "WebSocketServer-PostToSocket Error:", eMsgLevel.l1_Error, ((int)TheBaseAssets.MyServiceHostInfo.DebugLevel > 1? e.ToString():e.Message)));
                    errorMsg   = $"PostToSocket failed: {e.Message}";
                    HasFaulted = true;
                }
                if (HasFaulted)
                {
                    Shutdown(true, $"1610:{errorMsg}");
                }
                //IsPosting = false;
                if (mre != null)
                {
                    ProcessingAllowed = true;
                }
            }
        }
예제 #13
0
        public async Task ProcessWS()
        {
            TheDiagnostics.SetThreadName("WSProcessWS");
            if (MyQSender == null)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(4366, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSProcessor", "ProcessWS - no QSender Specified! ", eMsgLevel.l1_Error));
                return;
            }
            int tMaxMsgSize = 0;
            ArraySegment <byte> buffer;

            byte[] receiveBuffer;
            try
            {
                if (IsClient)
                {
                    tMaxMsgSize = TheCommonUtils.GetMaxMessageSize(MyQSender.MyTargetNodeChannel.SenderType);
                }
                else
                {
                    tMaxMsgSize = TheCommonUtils.GetMaxMessageSize(TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType);
                }
                receiveBuffer = new byte[tMaxMsgSize];
                buffer        = new ArraySegment <byte>(receiveBuffer);
                TheBaseAssets.MySYSLOG.WriteToLog(4367, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSProcessor", "New ProcessWS thread started ", eMsgLevel.l4_Message));
            }
            catch (Exception e)
            {
                TheBaseAssets.MySYSLOG.WriteToLog(4367, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSProcessor", "Failure while starting new ProcessWS thread", eMsgLevel.l4_Message, e.ToString()));
                return;
            }

            CloseFired = false;
            bool   HasFaulted = false;
            string tCause     = "1604:Thread ended";

            try
            {
                if (IsSocketReady(websocket))
                {
                    if (IsClient)
                    {
                        //MyQSender.IsConnected = true;
                        byte[] tSendBuffer = TheCommCore.SetConnectingBuffer(MyQSender);
                        PostToSocket(null, tSendBuffer, false, true);
                    }
                }

                while (TheBaseAssets.MasterSwitch && IsActive && IsSocketReady(websocket))
                {
                    WebSocketReceiveResult receiveResult = await websocket.ReceiveAsync(buffer, CancellationToken.None);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        tCause = "1605:WebSocket Closed";
                        break;
                    }
                    //LogBufferToFile("wsinputlog.dat", buffer.Array, buffer.Offset, receiveResult.Count);
                    if (MyQSender == null || !MyQSender.IsAlive)
                    {
                        tCause = "1606:QSender No longer alive";
                        break;
                    }

                    int    offset          = receiveResult.Count;
                    bool   IsUsingTArray   = false;
                    byte[] tPostData       = null;
                    int    tPostDataLength = 0;
                    if (receiveResult.EndOfMessage == false)
                    {
                        List <byte[]> tTelList = new List <byte[]>();
                        byte[]        tArray   = null;
                        while (receiveResult.EndOfMessage == false)
                        {
                            if (IsUsingTArray)
                            {
                                var arraySeg = new ArraySegment <byte>(tArray, offset, tMaxMsgSize - offset);
                                receiveResult = await websocket.ReceiveAsync(arraySeg, CancellationToken.None);

                                //LogBufferToFile("wsinputlog.dat", arraySeg.Array, arraySeg.Offset, receiveResult.Count);
                            }
                            else
                            {
                                var arraySeg = new ArraySegment <byte>(receiveBuffer, offset, tMaxMsgSize - offset);
                                receiveResult = await websocket.ReceiveAsync(arraySeg, CancellationToken.None);

                                //LogBufferToFile("wsinputlog.dat", arraySeg.Array, arraySeg.Offset, receiveResult.Count);
                            }
                            if (receiveResult.Count == 0)
                            {
                                if (receiveResult.Count + offset != tMaxMsgSize)
                                {
                                    TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("ProcessWS", string.Format("WS Buffer count wrong: Max={0} Offset={1} Count={2}", tMaxMsgSize, offset, receiveResult.Count), eMsgLevel.l1_Error));
                                }
                                tArray = new byte[tMaxMsgSize];
                                if (!IsUsingTArray)
                                {
                                    tTelList.Add(receiveBuffer);
                                }
                                tTelList.Add(tArray);
                                IsUsingTArray = true;
                                offset        = 0;
                            }
                            else
                            {
                                offset += receiveResult.Count;
                            }
                        }
                        if (tTelList.Count > 0)
                        {
                            tPostData = new byte[((tTelList.Count - 1) * tMaxMsgSize) + offset];
                        }
                        tPostDataLength = 0;
                        for (int i = 0; i < tTelList.Count - 1; i++)
                        {
                            byte[] tb = tTelList[i];
                            TheCommonUtils.cdeBlockCopy(tb, 0, tPostData, i * tMaxMsgSize, tMaxMsgSize);
                            tb = null;
                        }
                        if (IsUsingTArray && offset > 0 && tTelList.Count > 0 && tPostData != null)
                        {
                            TheCommonUtils.cdeBlockCopy(tTelList[tTelList.Count - 1], 0, tPostData, (tTelList.Count - 1) * tMaxMsgSize, offset);
                            tPostDataLength = tPostData.Length;
                        }
                        //tTelList.Clear();
                    }
                    if (!IsUsingTArray)
                    {
                        tPostData = new byte[offset];
                        TheCommonUtils.cdeBlockCopy(receiveBuffer, 0, tPostData, 0, offset);
                        tPostDataLength = offset;
                    }
                    //LogBufferToFile("wsinputbactchedlog.dat", tPostData, 0, tPostData.Length);
                    TheCommonUtils.cdeRunAsync("ProcessFromWS", true, (o) => ProcessIncomingData(null, (byte [])o, ((byte[])o).Length), tPostData);
                }
            }
            catch (Exception eee)
            {
                HasFaulted = true;
                if (eee.Source == "System")
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("ProcessWS", "ProcessWS Loop has failed because WebSocket was closed during ReceiveAsync.", eMsgLevel.l1_Error));
                }
                else
                {
                    TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("ProcessWS", "ProcessWS Loop has failed.", eMsgLevel.l1_Error, eee.ToString()));
                }
            }
            TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("ProcessWS", $"ProcessWS Loop for {OwnerNodeID} has ended. Faulted:{HasFaulted} HasWS:{websocket != null}", eMsgLevel.l3_ImportantMessage));
            ConnectSuccess = false;
            if (HasFaulted || (websocket != null && websocket.State != WebSocketState.Closed))
            {
                tCause = string.Format("1607:WebSocket Faulted:{0} WS State:{1}", HasFaulted, websocket != null?websocket.State.ToString():"is null");
            }
            Shutdown(true, tCause);
        }
예제 #14
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();
        }