Skip to content

Commit eba9a8b

Browse files
muenchrisChris MuenchberndbrMarkusHorstmannChris Muench
authored
December 2024 release PR (#101)
* Many Sonarcloud code smell fixes * Only keep SendBuffer in memory in case there are messages to send * Force Dispose of ASP.NET Core WebSocket * Avoid ArgumentOutOfRangeException in DateTimeOffset initialization * More code smells removed * Removal of WSCS no longer inside CDE * More SonarCloud Cleanup * Fix for propert update of Sub-Properties in NMI Screens; Fix for creation of properties from class if class contains collections; * security fix for scopid on page checking for known scope * Beginning of support for Wildernesslabs.co Meadow board * OPC UA Attributes for UAVariable and UAHAVariable * More support for Meadow * Drop WR and disable config files for Meadow * IsFeather option * Fx to ensure UA Attributes are applied to non-mandatory properties; new cdeFOC flag to prevent ThingRegistry writes to disk for highspeed properties. * Null pointer fix; EngineName added to DeviceTypeAttribute - used by OPC UA NodeSet Client * new OPC UA Twin Base Thing for things with dual Connectors * Access to OldValue in cdeP; OPCUA Attributes for write and hidefromanonymous * TXT for HandleMessage as consts * OldValue not serialized * Fix for SetSetting() not applied correctly * New event b4 Form Meta Sending to Browser * Typo fix and prep for NMI editor * Better support for ReloadAfterLogout; NMI Model support for DefaultPortal of Plugin; Support for Portal Page Faceplates * Set default HomeScreen in User Profile * FitToScreen option * Inner Form ClassName * More flexible FacePlate Macros * Copyright update * Copyright * New event fired before a resource is sent to the NMI allowing plugins to modify static pages before sending to the NMI * Fix for HomeScreen by CDEDL Url Path * New ThingGroup for Group Screens and Overviews * Fix for Pin based Login * Pin connection API * New Pins, Groups and Thing extensions * New NMI Editor Coming * NMI Update for saving online NMI Screen modifications * Bigger property table * Better support for Dynamic Model Changes in preperation of the new NMI Editor Pin Connector Model for NMI Runtime in Preview New Reference to ThingBase in TheThing in order to manage Things based on TheThiingBase - required for NMI Editor * Thing Group improv * Redpillshift * new Numeric Html Macro with Digits option * New OPCUABaseAttribute - base for all UA Types * FlexibleNMI Screen API optimization; cdeASPNET for net6 and net7 * NMI Group API, Allow delete rule by RuleMID * Small possible Null Pointer exception during shutdown * Change of OPC UA Namespace for Pins * UAAttributes for UA Property Definition now on Classes allowed Breaking change: UANodeId changed to UATypeNodeId * new NMI Log option for ThingBase; fix for Properties-from-Class * Fix for PropertyChange event with forms containing multiple elements with same DataItem; Fix for Storage Historian Chart reference; Typo fixes in Documentation * Fix for duplicate cdeFixupFileName * New ICDEProperty Interface for better Properties of Properties management * New NMI Editor: Add and Delete of Controls to GroupThing in Preview Support for update of Fields with different Owner Thing in Forms new OPC UA Thing - moved all OPC UA releated classes to new cdeUAThing.cs Preview of TheThingGroup: HMI Screen Support within the NMI * fix for cdeASPNET only NET6 support for now * Update dotnetcore.yml: .Net 7 * cdeASPNet: Build for .Net7 again * Fix aspnetcore.csproj * Fix for licensing * NMI Editor improvements * Fix for Bernd; Fix for NMI no longer updating table content; new Pin Functions * NMI Editor improvements * Some minor exception fixes in TheQueuedSender; NMI Editor Improvements new eventPluginStarted event allowing to wait for a specific Engine to start * NMI Updates * Fix for reset of content-type if in header and property * NMI Code Cleanup; Removed depreciated methods; Disable NMI Editor in Cloud * Code Cleanup; Disable NMI Editor in Cloud * New Rule options for triggering rules only every xx seconds * Updater support for .NET7 * Depreciation of Loging in Rules engine - moved to ICDELoggerEngine * Stage One Removal of depreciated Methods (Commented out. in stage 2 we will remove the code completely) Support for TimeSpan Property * NMI Editor Cleanup and better handling * Support for backup of Cache folder for NetStandard * Cleanup of Obsolete code * Removal of old NET45 pragmas; SonarCloud Warnings removed; * Test: add SerializeObjectToJSONStringWithCycleTest * RecordsLock cleanup * NMI Editor Enhancements; Code Cleanup; Improvements in conjunctio with Provisioning Service and Mesh Manager * fix for custom plugins from host not loading * WriteToNMILog adjusted to same parameters as SetMessage for easier transition; Update to latest Nuget References * Added .net8 to workflow * Code Cleanup * ASPNET to .net8 * Solve ArgumentOutOfRangeException calling TheCDEEngines.StartEngines * Gitignor * Azure Key Vault Signing Support for future HSMaaS * typo fix * Improved Pin Management * Fix for FitToScreen calculation Pin Lines in ThingGroup * Pin NMI Tuning * pin tuning * PinStyle tuning (not final) * style fix * Better Startup logging on errors NMI Model Improvments * Safe Settings Management * Imrpoved Certificate logging * using cleanup * Proper Locking for ThePropertyBag * Automatic Pin line drawing in ThinGroups * Remove of AzureSign Folder * fixed signme * signme fix * signme * Fix for Linux plugin Updates * Fix for Backup/Restore under linux * Getting ready for .NET Standard 2.1 * Initial Drop for CDE 6.0 with .NET Standard 2.1 * Build Targets to 6.* * Update dotnetcore.yml removed .NET4.8 updater * update of Worflow packaging of CDE * Update dotnetcore.yml Temporary disable tests * Nuget fix * Pins can be stored and restored Pins can be deleted * Tests: Migrate to NUnit 4 * Reenable test in build * Support for Pin Line Drawing correction after Dragging * Fix for Pin Setup * Pin Line Fixes * Support for NMI Edtor OnHide Event; Support for Pin Property Overrides; * Update Pin Management Improved Pin Line Drawing * Pin Improvements * Pin Fix * Pin Update Events * Fix for Screen option Override * Support for custom WebSocket Hook Fixes for Pins and NMI * fix for pin flow animation * Sonar fixes * Pin update for ESP chips Allow to set a XIndex on FacePlates * Latest Updates * New Pin IsOnline flag * Pin Quality * spacing for faceplate template * Shutdown log improvement * latest nuget * Drop support for .NET7 * new macro for SVG * New Red-Alert events any thing can subscribe to * Macro fix * Fix for a bug in the settingsd reader if the first char is a { * PropertyMapper for ThingGroups * Set Default Portal Page to NMIAUTO for proper sunset/sunrise setting * New Code sign cert * Group Update * Setting Always push to FacePlace Properties * new way to detect mobile devices * Fix for Mobile CryptoLib in Release Mode * Update dotnetcore.yml * Update dotnetcore.yml * Update dotnetcore.yml * Update dotnetcore.yml --------- Co-authored-by: Chris Muench <chris.muench@live.com> Co-authored-by: Bernd Brachmaier | AUNOVIS <brachmaier@aunovis.de> Co-authored-by: MarkusHorstmann <markus.horstmann@c-labs.com> Co-authored-by: Markus Horstmann <markushorstmann@hotmail.com> Co-authored-by: Chris Muench <muenchris@c-labs.com> Co-authored-by: Chris Muench <chris@hyviva.com>
1 parent bd76ac0 commit eba9a8b

File tree

22 files changed

+463
-85
lines changed

22 files changed

+463
-85
lines changed

.github/workflows/dotnetcore.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,15 @@ jobs:
2727
- uses: actions/checkout@v2
2828

2929
- name: Setup Python
30-
uses: actions/setup-python@v2
30+
uses: actions/setup-python@v4
3131
with:
3232
python-version: '3.x'
3333

3434
- name: Setup .NET Core
35-
uses: actions/setup-dotnet@v1
35+
uses: actions/setup-dotnet@v4
3636
with:
3737
dotnet-version: |
38-
3.1.201
3938
8.0
40-
7.0
41-
6.0
42-
5.0
4339
source-url: https://api.nuget.org/v3/index.json
4440
config-file: .\nuget.config
4541
owner: ${{secrets.NUGETORG_APIKEY_OWNER}}
@@ -95,7 +91,7 @@ jobs:
9591
echo "CommitDate: ${{ steps.gitversion.outputs.commitDate }}"
9692
9793
- name: Install AzureSignTool
98-
run: dotnet tool install --global AzureSignTool
94+
run: dotnet tool install --global --version 5.0.0 AzureSignTool
9995

10096
- name: Enable code signing for build
10197
run: |
@@ -128,7 +124,7 @@ jobs:
128124
run: (robocopy .\src\nugets .\artifacts\ *.nupkg *.snupkg /s /np) ^& IF %ERRORLEVEL% LEQ 1 exit 0
129125
shell: cmd
130126
- name: Upload artifacts
131-
uses: actions/upload-artifact@v1
127+
uses: actions/upload-artifact@v4
132128
with:
133129
name: C-DEngine
134130
path: ./artifacts

src/C-DEngine/C-DBaseClasses/cde_BaseApplication.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public virtual void Shutdown(string pReason, bool force, bool waitIfPending = fa
336336
case cdeHostType.IIS: iis = " (Hosted in IIS)"; break;
337337
case cdeHostType.ASPCore: iis = " (Hosted in ASP.NET Core)"; break;
338338
}
339-
TheBaseAssets.MySYSLOG.WriteToLog(3, new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, TheBaseAssets.MyServiceHostInfo.ApplicationTitle + iis + " Stopped at : " + TheCommonUtils.GetDateTimeString(DateTimeOffset.Now), eMsgLevel.l4_Message)); //Log Entry that service has been started
339+
TheBaseAssets.MySYSLOG.WriteToLog(3, new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName,$"{TheBaseAssets.MyServiceHostInfo.ApplicationTitle}{iis} {(force?"forced":"")} Stopped at : {TheCommonUtils.GetDateTimeString(DateTimeOffset.Now)}", eMsgLevel.l4_Message)); //Log Entry that service has been started
340340
TheBaseAssets.MySYSLOG.Shutdown();
341341
}
342342
}

src/C-DEngine/C-DBaseClasses/cde_BaseAssets.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Reflection;
1919
using System.Text.RegularExpressions;
2020
using System.Threading;
21+
using System.Xml.Linq;
2122

2223
namespace nsCDEngine.BaseClasses
2324
{
@@ -52,7 +53,10 @@ public static string LoadCrypto(string pDLLName, ICDESystemLog pMySYSLOG = null,
5253
Dictionary<string, string> tL = new();
5354
Assembly tCryptoAssembly = null;
5455
string codeSignThumb;
55-
if (AppDomain.CurrentDomain?.FriendlyName != "RootDomain" && AppDomain.CurrentDomain?.FriendlyName != "MonoTouch" && AppDomain.CurrentDomain?.FriendlyName != "Meadow.dll") //Android and IOS
56+
var types = AppDomain.CurrentDomain.GetAssemblies();
57+
if (pDLLName.ToLower().EndsWith(".dll"))
58+
tCryptoAssembly = types.FirstOrDefault(g => g.Location.Contains(pDLLName.Substring(0,pDLLName.Length-4)));//new way of detecting mobile devices
59+
if (tCryptoAssembly == null) // AppDomain.CurrentDomain?.FriendlyName != "RootDomain" && AppDomain.CurrentDomain?.FriendlyName != "MonoTouch" && AppDomain.CurrentDomain?.FriendlyName != "Meadow.dll") //Android and IOS
5660
{
5761
TheSystemMessageLog.ToCo($"Starting CodeSign-Verifier in ({pDLLName}) with DVT:{bDontVerifyTrust} VTP:{bVerifyTrustPath} DVI:{bDontVerifyIntegrity}");
5862
MyCodeSigner ??= new TheDefaultCodeSigning(MySecrets, pMySYSLOG);
@@ -71,25 +75,21 @@ public static string LoadCrypto(string pDLLName, ICDESystemLog pMySYSLOG = null,
7175
}
7276
else
7377
{
74-
var types = AppDomain.CurrentDomain.GetAssemblies();
75-
tCryptoAssembly = types.FirstOrDefault(g => g.Location.Contains(pDLLName));
76-
if (tCryptoAssembly != null)
78+
TheSystemMessageLog.ToCo($"Crypto-Lib ({pDLLName}) preloaded with DVT:{bDontVerifyTrust} VTP:{bVerifyTrustPath} DVI:{bDontVerifyIntegrity}");
79+
var CDEPlugins = from t in tCryptoAssembly.GetTypes()
80+
let ifs = t.GetInterfaces()
81+
where ifs != null && ifs.Length > 0 && (ifs.Any(s => _KnownInterfaces.Contains(s.Name)))
82+
select new { Type = t, t.Namespace, t.Name, t.FullName };
83+
foreach (var Plugin in CDEPlugins)
7784
{
78-
var CDEPlugins = from t in tCryptoAssembly.GetTypes()
79-
let ifs = t.GetInterfaces()
80-
where ifs != null && ifs.Length > 0 && (ifs.Any(s => _KnownInterfaces.Contains(s.Name)))
81-
select new { Type = t, t.Namespace, t.Name, t.FullName };
82-
foreach (var Plugin in CDEPlugins)
85+
if (Plugin?.Type?.IsAbstract == false)
8386
{
84-
if (Plugin?.Type?.IsAbstract == false)
87+
var ints = Plugin.Type.GetInterfaces();
88+
foreach (var tI in ints)
8589
{
86-
var ints = Plugin.Type.GetInterfaces();
87-
foreach (var tI in ints)
90+
if (_KnownInterfaces.Contains(tI.Name))
8891
{
89-
if (_KnownInterfaces.Contains(tI.Name))
90-
{
91-
tL[tI.Name] = Plugin.FullName;
92-
}
92+
tL[tI.Name] = Plugin.FullName;
9393
}
9494
}
9595
}

src/C-DEngine/C-DBaseClasses/cde_SystemMessagesCore.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ public static class eEngineEvents
168168
/// Any Message sent to the Content-Relay Service that was not handled by the Content Service will be forwarded to this event
169169
/// </summary>
170170
public const string CustomTSMMessage = "CustomTSMMessage";
171+
/// <summary>
172+
/// Sent by the content Engine if a sever alert is issued. All subscribers should do the appropriate response
173+
/// </summary>
174+
public const string RedAlert = "RedAlert";
175+
/// <summary>
176+
/// Sent by the content Engine once the alert has been cleared. All subscribers should do the appropriate response
177+
/// </summary>
178+
public const string AllClear = "AllClear";
171179

172180
/// <summary>
173181
/// Engine received a Blob Object

src/C-DEngine/C-DCommunication/Protocols/HTTP/Service/cde_HttpService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ internal static void ProcessRequest(TheRequestData pRequestData)
377377
string Query = pRequestData.RequestUri.Query;
378378
if (Query.StartsWith("?"))
379379
Query = Query.Substring(1);
380-
if (string.IsNullOrEmpty(Query)) Query = "NMIPortal";
380+
if (string.IsNullOrEmpty(Query)) Query = "NMIAUTO";
381381
TheBaseAssets.MySession.EndSession(pRequestData);
382382
pRequestData.AllowStatePush = false;
383383
pRequestData.ResponseMimeType = "text/html";
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2009-2020 TRUMPF Laser GmbH, authors: C-Labs
2+
//
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
using nsCDEngine.BaseClasses;
6+
using nsCDEngine.ViewModels;
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Net.WebSockets;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
13+
namespace nsCDEngine.Communication
14+
{
15+
public class TheWebSocketHooks: TheDataBase
16+
{
17+
public void PostToSocket(object sender, byte[] data, bool SendAsBinary)
18+
{
19+
(sender as TheWSCustomProcessor)?.PostToSocket(null,data, SendAsBinary, false);
20+
}
21+
}
22+
23+
internal class TheWSCustomProcessor : TheWSProcessorBase
24+
{
25+
private static bool IsSocketReady(WebSocket ws)
26+
{
27+
return ws != null && (ws.State == WebSocketState.Open || ws.State == WebSocketState.Connecting);
28+
}
29+
30+
public TheWSCustomProcessor(WebSocket pWS) :base()
31+
{
32+
websocket = pWS;
33+
mCancelToken = new();
34+
}
35+
36+
readonly WebSocket websocket;
37+
/// <summary>
38+
/// new in CDE 6.0: Allows to intercept WebSocket Calls other than ISB requests
39+
/// </summary>
40+
/// <param name="pRequestData"></param>
41+
/// <returns></returns>
42+
public async Task<string> ProcessWS(TheRequestData pRequestData)
43+
{
44+
int tMaxMsgSize = 0;
45+
ArraySegment<byte> buffer;
46+
byte[] receiveBuffer;
47+
try
48+
{
49+
tMaxMsgSize = TheCommonUtils.GetMaxMessageSize(TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType);
50+
receiveBuffer = new byte[tMaxMsgSize];
51+
buffer = new ArraySegment<byte>(receiveBuffer);
52+
TheBaseAssets.MySYSLOG.WriteToLog(4367, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSProcessor", "New CustomProcessWS thread started ", eMsgLevel.l4_Message));
53+
}
54+
catch (Exception e)
55+
{
56+
TheBaseAssets.MySYSLOG.WriteToLog(4367, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheWSProcessor", "Failure while starting new CustomProcessWS thread", eMsgLevel.l4_Message, e.ToString()));
57+
return "Failure";
58+
}
59+
60+
bool hasFaulted = false;
61+
string tCause = "1604:Thread ended";
62+
try
63+
{
64+
while (TheBaseAssets.MasterSwitch && IsSocketReady(websocket))
65+
{
66+
WebSocketReceiveResult receiveResult = await websocket.ReceiveAsync(buffer, mCancelToken.Token);
67+
if (receiveResult.MessageType == WebSocketMessageType.Close)
68+
{
69+
tCause = "1605:WebSocket Closed";
70+
break;
71+
}
72+
73+
int offset = receiveResult.Count;
74+
bool IsUsingTArray = false;
75+
byte[] tPostData = null;
76+
if (!receiveResult.EndOfMessage)
77+
{
78+
List<byte[]> tTelList = new();
79+
byte[] tArray = null;
80+
while (!receiveResult.EndOfMessage)
81+
{
82+
if (IsUsingTArray)
83+
{
84+
var arraySeg = new ArraySegment<byte>(tArray, offset, tMaxMsgSize - offset);
85+
receiveResult = await websocket.ReceiveAsync(arraySeg, CancellationToken.None);
86+
}
87+
else
88+
{
89+
var arraySeg = new ArraySegment<byte>(receiveBuffer, offset, tMaxMsgSize - offset);
90+
receiveResult = await websocket.ReceiveAsync(arraySeg, CancellationToken.None);
91+
}
92+
93+
if (receiveResult.Count == 0)
94+
{
95+
if (receiveResult.Count + offset != tMaxMsgSize)
96+
TheBaseAssets.MySYSLOG.WriteToLog(4369,
97+
TSM.L(eDEBUG_LEVELS.OFF)
98+
? null
99+
: new TSM("ProcessWS",
100+
string.Format("WS Buffer count wrong: Max={0} Offset={1} Count={2}",
101+
tMaxMsgSize, offset, receiveResult.Count), eMsgLevel.l1_Error));
102+
tArray = new byte[tMaxMsgSize];
103+
if (!IsUsingTArray)
104+
tTelList.Add(receiveBuffer);
105+
tTelList.Add(tArray);
106+
IsUsingTArray = true;
107+
offset = 0;
108+
}
109+
else
110+
offset += receiveResult.Count;
111+
}
112+
113+
if (tTelList.Count > 0)
114+
tPostData = new byte[((tTelList.Count - 1) * tMaxMsgSize) + offset];
115+
for (int i = 0; i < tTelList.Count - 1; i++)
116+
{
117+
byte[] tb = tTelList[i];
118+
TheCommonUtils.cdeBlockCopy(tb, 0, tPostData, i * tMaxMsgSize, tMaxMsgSize);
119+
}
120+
121+
if (IsUsingTArray && offset > 0 && tTelList.Count > 0 && tPostData != null)
122+
{
123+
TheCommonUtils.cdeBlockCopy(tTelList[tTelList.Count - 1], 0, tPostData,
124+
(tTelList.Count - 1) * tMaxMsgSize, offset);
125+
}
126+
}
127+
128+
if (!IsUsingTArray)
129+
{
130+
tPostData = new byte[offset];
131+
TheCommonUtils.cdeBlockCopy(receiveBuffer, 0, tPostData, 0, offset);
132+
}
133+
TheCommCore.CustomWSHooks.FireEvent(pRequestData.RequestUri.PathAndQuery,
134+
new TheProcessMessage { ClientInfo = null, Message=new TSM(eEngineName.ContentService,"INCOMING_WS") { PLB=tPostData }, Topic = pRequestData.RequestUri.PathAndQuery, Cookie = this }, true);
135+
}
136+
}
137+
catch (OperationCanceledException)
138+
{
139+
hasFaulted = true;
140+
}
141+
catch (Exception eee)
142+
{
143+
hasFaulted = true;
144+
if (TheBaseAssets.MasterSwitch)
145+
{
146+
TheBaseAssets.MySYSLOG.WriteToLog(4369, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("ProcessWS", $"CustomProcessWS Loop has failed because WebSocket was closed during ReceiveAsync. {eee.Message}", eMsgLevel.l1_Error));
147+
}
148+
}
149+
if (hasFaulted || (websocket != null && websocket.State != WebSocketState.Closed))
150+
{
151+
tCause = $"1607:WebSocket Faulted:{hasFaulted} WS State:{(websocket != null ? websocket.State.ToString() : "is null")}";
152+
}
153+
return tCause;
154+
}
155+
156+
private readonly object _postToSocketLock = new();
157+
158+
internal override void PostToSocket(TheDeviceMessage pMsg, byte[] pPostBuffer, bool pSendAsBinary, bool IsInitialConnect)
159+
{
160+
if (!TheBaseAssets.MasterSwitch || pPostBuffer == null || pPostBuffer.Length == 0)
161+
return;
162+
bool HasFaulted = false;
163+
lock (_postToSocketLock)
164+
{
165+
string errorMsg = "";
166+
try
167+
{
168+
if (!IsSocketReady(websocket))
169+
{
170+
HasFaulted = true;
171+
errorMsg = "Socket Not Ready";
172+
}
173+
else
174+
{
175+
ArraySegment<byte> outputBuffer = new ArraySegment<byte>(pPostBuffer);
176+
Task tTask = websocket.SendAsync(outputBuffer, pSendAsBinary ? WebSocketMessageType.Binary : WebSocketMessageType.Text, true, TheBaseAssets.MasterSwitchCancelationToken);
177+
tTask.Wait(TheBaseAssets.MyServiceHostInfo.TO.WsTimeOut * 10);
178+
if (!tTask.IsCompleted)
179+
{
180+
var timeoutValue = TheBaseAssets.MyServiceHostInfo.TO.WsTimeOut * 10;
181+
TheBaseAssets.MySYSLOG.WriteToLog(43610, new TSM("TheWSProcessor", $"WebSocketServer-PostToSocket error: PostAsync Timeout {tTask.Status} after {timeoutValue} ms for {MyQSender?.MyTargetNodeChannel}", eMsgLevel.l1_Error));
182+
errorMsg = $"SendAsync timed out after {timeoutValue} ms";
183+
HasFaulted = true;
184+
}
185+
}
186+
}
187+
catch (Exception e)
188+
{
189+
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)));
190+
errorMsg = $"PostToSocket failed: {e.Message}";
191+
HasFaulted = true;
192+
}
193+
if (HasFaulted)
194+
{
195+
Shutdown(true, $"1610:{errorMsg}");
196+
}
197+
}
198+
}
199+
}
200+
}

src/C-DEngine/C-DCommunication/Protocols/WS/cde_WSServer.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,19 @@ public static async Task WaitForWSAccept(HttpListenerContext pContext)
106106
return;
107107
}
108108
}
109-
TheWSProcessor8 tProcessor = new (wsc.WebSocket);
110-
tProcessor.SetRequest(tRequestData);
111-
await tProcessor.ProcessWS();
109+
if (tRequestData.RequestUri.PathAndQuery.StartsWith("/ISB"))
110+
{
111+
TheWSProcessor8 tProcessor = new(wsc.WebSocket);
112+
tProcessor.SetRequest(tRequestData);
113+
await tProcessor.ProcessWS();
114+
}
115+
else
116+
{
117+
if (!TheCommCore.CustomWSHooks.IsEventRegistered(tRequestData.RequestUri.PathAndQuery))
118+
return;
119+
TheWSCustomProcessor tProcessor = new TheWSCustomProcessor(wsc.WebSocket);
120+
await tProcessor.ProcessWS(tRequestData);
121+
}
112122
}
113123
}
114124

src/C-DEngine/C-DCommunication/cde_QueuedSenderRegistry.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,32 @@ public static async Task ProcessCloudRequest(System.Net.WebSockets.WebSocket wsS
11861186
}
11871187
TheCDEKPIs.DecrementKPI(eKPINames.KPI3);
11881188
}
1189+
1190+
/// <summary>
1191+
/// new in CDE 6.0: Allows to intercept WebSocket Calls other than ISB requests
1192+
/// </summary>
1193+
/// <param name="wsSocket"></param>
1194+
/// <param name="pRequestData"></param>
1195+
/// <returns></returns>
1196+
public static async Task<string> ProcessWSRequest(System.Net.WebSockets.WebSocket wsSocket, TheRequestData pRequestData)
1197+
{
1198+
TheWSCustomProcessor tProcessor = null;
1199+
try
1200+
{
1201+
if (!TheCommCore.CustomWSHooks.IsEventRegistered(pRequestData.RequestUri.PathAndQuery))
1202+
return null;
1203+
1204+
tProcessor = new TheWSCustomProcessor(wsSocket);
1205+
return await tProcessor.ProcessWS(pRequestData);
1206+
}
1207+
catch (Exception ex)
1208+
{
1209+
TheBaseAssets.MySYSLOG.WriteToLog(2828, new TSM("ASHXHandler", "Processing Error", ex.ToString()));
1210+
if (tProcessor != null)
1211+
tProcessor.Shutdown(true, "ASHX Handler encountered Error");
1212+
}
1213+
return null;
1214+
}
11891215
#endif
11901216

11911217
/// <summary>

src/C-DEngine/C-DCommunication/cde_TheCommCore.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ namespace nsCDEngine.Communication
2020
/// </summary>
2121
public static class TheCommCore
2222
{
23+
/// <summary>
24+
/// Register new WebSocket hooks with the Path+Query
25+
/// i.e: CustomWSHooks.RegisterEvent2("/mypath", sinkTelegrams);
26+
/// </summary>
27+
public static TheWebSocketHooks CustomWSHooks = new TheWebSocketHooks();
28+
2329
internal static List<string> GetQueueInformation(bool ShowQueueDetails)
2430
{
2531
return TheQueuedSenderRegistry.ShowQSenderDetails(ShowQueueDetails);

0 commit comments

Comments
 (0)