From c1a117f0382752c888b77874a6eebd926d35245d Mon Sep 17 00:00:00 2001 From: Maxson Ramon dos Anjos Medeiros Date: Tue, 8 Jul 2025 14:37:06 +0200 Subject: [PATCH] SetDirectoryAccessHandler added --- dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs | 62 ++++++++++++++++++- .../server_example_access_control/Program.cs | 23 +++++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 825f7709..d1b7acc3 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -2396,7 +2396,10 @@ namespace IEC61850 /// a user provided parameter that is passed to the handler [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] public static extern void IedServer_setDataSetAccessHandler(IntPtr self, IedServer_DataSetAccessHandler handler, IntPtr parameter); - + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + public static extern void IedServer_setDirectoryAccessHandler(IntPtr self, IedServer_DirectoryAccessHandler handler, IntPtr parameter); + /// /// callback handler to control client read access to data attributes /// User provided callback function to control MMS client read access to IEC 61850 @@ -2441,6 +2444,9 @@ namespace IEC61850 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate bool IedServer_ControlBlockAccessHandler(IntPtr parameter, IntPtr connection, int acsiClass, IntPtr ld, IntPtr ln, string objectName, string subObjectName, int accessType); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool IedServer_DirectoryAccessHandler(IntPtr parameter, IntPtr connection, int category, IntPtr logicalDevice); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate bool IedServer_ListObjectsAccessHandler(IntPtr parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice ld, LogicalNode ln, string objectName, string subObjectName, FunctionalConstraint fc); @@ -2779,7 +2785,7 @@ namespace IEC61850 private MmsDataAccessError InternalReadHandlerImplementation(IntPtr ld, IntPtr ln, IntPtr dataObject, int fc, IntPtr connection, IntPtr parameter) { - if (internalReadAccessHandler != null && ld != IntPtr.Zero && ln != IntPtr.Zero) + if (internalReadAccessHandler != null && ld != IntPtr.Zero && ln != IntPtr.Zero && connection != IntPtr.Zero) { ClientConnection con = null; @@ -2787,7 +2793,10 @@ namespace IEC61850 ModelNode ldModelNode = iedModel.GetModelNodeFromNodeRef(ld); ModelNode lnModelNode = iedModel.GetModelNodeFromNodeRef(ln); - ModelNode doModelNode = iedModel.GetModelNodeFromNodeRef(dataObject); + ModelNode doModelNode = null; + + if(dataObject != IntPtr.Zero) + doModelNode = iedModel.GetModelNodeFromNodeRef(dataObject); return internalReadAccessHandler(ldModelNode as LogicalDevice, lnModelNode as LogicalNode, doModelNode as DataObject, (FunctionalConstraint)fc, con, internalReadAccessHandlerParameter); } @@ -2795,6 +2804,53 @@ namespace IEC61850 return MmsDataAccessError.UNKNOWN; } + public enum IedServer_DirectoryCategory + { + DIRECTORY_CAT_LD_LIST, + DIRECTORY_CAT_DATA_LIST, + DIRECTORY_CAT_DATASET_LIST, + DIRECTORY_CAT_LOG_LIST + } + + public delegate bool InternalDirectoryAccessHandler(object parameter, ClientConnection connection, IedServer_DirectoryCategory category,LogicalDevice ld); + + private InternalDirectoryAccessHandler internalDirectoryAccessHandler = null; + + private object internalDirectoryAccessHandlerParameter = null; + + private IedServer_DirectoryAccessHandler directoryAccessHandler = null; + + public void SetDirectoryAccessHandler(InternalDirectoryAccessHandler handler, object parameter) + { + internalDirectoryAccessHandler = handler; + internalDirectoryAccessHandlerParameter = parameter; + + if (directoryAccessHandler == null) + { + directoryAccessHandler = new IedServer_DirectoryAccessHandler(DirectoryAccessHandler); + + IedServer_setDirectoryAccessHandler(self, directoryAccessHandler, IntPtr.Zero); + } + } + + private bool DirectoryAccessHandler(IntPtr parameter, IntPtr connection, int category, IntPtr logicalDevice) + { + if (internalDirectoryAccessHandler != null && connection != IntPtr.Zero) + { + ClientConnection con = null; + + this.clientConnections.TryGetValue(connection, out con); + + ModelNode ldModelNode = null; + + if(logicalDevice != IntPtr.Zero) + ldModelNode = iedModel.GetModelNodeFromNodeRef(logicalDevice); + + return internalDirectoryAccessHandler(internalDirectoryAccessHandlerParameter, con, (IedServer_DirectoryCategory)category, ldModelNode as LogicalDevice); + } + + return false; + } private Dictionary writeAccessHandlers = new Dictionary (); diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs index c56a4a75..be4b400d 100644 --- a/dotnet/server_example_access_control/Program.cs +++ b/dotnet/server_example_access_control/Program.cs @@ -192,6 +192,29 @@ namespace server_access_control iedServer.SetReadAccessHandler(readAccessHandler, null); + bool directoryAccessHandler(object parameter, ClientConnection connection, IedServer_DirectoryCategory category, LogicalDevice ld) + { + switch (category) + { + case IedServer_DirectoryCategory.DIRECTORY_CAT_LD_LIST: + + Console.WriteLine("Get list of logical devices from "+ connection.GetPeerAddress()+"\n"); + break; + case IedServer_DirectoryCategory.DIRECTORY_CAT_DATASET_LIST: + Console.WriteLine("Get list of datasets for LD "+ ld.GetName() + " from "+ connection.GetPeerAddress()+"\n"); + break; + case IedServer_DirectoryCategory.DIRECTORY_CAT_DATA_LIST: + Console.WriteLine("Get list of data for LD " + ld.GetName() + " from " + connection.GetPeerAddress() + "\n"); + break; + case IedServer_DirectoryCategory.DIRECTORY_CAT_LOG_LIST: + Console.WriteLine("Get list of logs for LD" + ld.GetName() + " from " + connection.GetPeerAddress() + "\n"); + return false; + } + + return true; + } + + iedServer.SetDirectoryAccessHandler(directoryAccessHandler, null); iedServer.Start(102);