diff --git a/config/stack_config.h b/config/stack_config.h
index 3cd3e771..37e663e3 100644
--- a/config/stack_config.h
+++ b/config/stack_config.h
@@ -170,7 +170,7 @@
/* allow application to set server identity (for MMS identity service) at runtime */
#define CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY 1
-/* Force memory alignment - required for some platforms (required more memory for buffered reporting) */
+/* Force memory alignment - required for some platforms (requires more memory for buffered reporting) */
#define CONFIG_IEC61850_FORCE_MEMORY_ALIGNMENT 1
/* compile with support for R-GOOSE (mbedtls requried) */
@@ -249,10 +249,24 @@
/* enable to configure MmsServer at runtime */
#define CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME 1
+/* Define the default number of the maximum outstanding calls allowed by the caller (client) */
+#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING 5
+
+/* Define the default number of the maximum outstanding calls allowed by the calling endpoint (server) */
+#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED 5
+
/************************************************************************************
* Check configuration for consistency - DO NOT MODIFY THIS PART!
************************************************************************************/
+#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING < 1)
+#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING must be greater than 0!"
+#endif
+
+#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED < 1)
+#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED must be greater than 0!"
+#endif
+
#if (MMS_JOURNAL_SERVICE != 1)
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
diff --git a/config/stack_config.h.cmake b/config/stack_config.h.cmake
index 52017dc2..28521f25 100644
--- a/config/stack_config.h.cmake
+++ b/config/stack_config.h.cmake
@@ -169,7 +169,7 @@
/* allow application to set server identity (for MMS identity service) at runtime */
#define CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY 1
-/* Force memory alignment - required for some platforms (required more memory for buffered reporting) */
+/* Force memory alignment - required for some platforms (requires more memory for buffered reporting) */
#define CONFIG_IEC61850_FORCE_MEMORY_ALIGNMENT 1
/* default results for MMS identify service */
@@ -238,10 +238,24 @@
/* enable to configure MmsServer at runtime */
#define CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME 1
+/* Define the default number of the maximum outstanding calls allowed by the caller (client) */
+#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING 5
+
+/* Define the default number of the maximum outstanding calls allowed by the calling endpoint (server) */
+#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED 5
+
/************************************************************************************
* Check configuration for consistency - DO NOT MODIFY THIS PART!
************************************************************************************/
+#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING < 1)
+#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING must be greater than 0!"
+#endif
+
+#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED < 1)
+#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED must be greater than 0!"
+#endif
+
#if (MMS_JOURNAL_SERVICE != 1)
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index 16d79a56..38db124c 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -431,6 +431,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 IedConnection_getRequestTimeout(IntPtr self);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedConnection_setMaxOutstandingCalls(IntPtr self, int calling, int called);
+
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setTimeQuality(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool leapSecondKnown, [MarshalAs(UnmanagedType.I1)] bool clockFailure, [MarshalAs(UnmanagedType.I1)] bool clockNotSynchronized, int subsecondPrecision);
@@ -559,6 +562,12 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_installStateChangedHandler(IntPtr connection, InternalStateChangedHandler handler, IntPtr parameter);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_ignoreReadAccess(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool ignore);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_ignoreClientRequests(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool ignore);
+
/*********************
* Async functions
*********************/
@@ -815,6 +824,16 @@ namespace IEC61850
}
}
+ ///
+ /// Set the maximum number outstanding calls allowed for this connection
+ ///
+ /// the maximum outstanding calls allowed by the caller (client)
+ /// the maximum outstanding calls allowed by the called endpoint (server)
+ public void SetMaxOutstandingCalls(int calling, int called)
+ {
+ IedConnection_setMaxOutstandingCalls(connection, calling, called);
+ }
+
///
/// Gets or sets the maximum size if a PDU (has to be set before calling connect!).
///
@@ -1175,6 +1194,9 @@ namespace IEC61850
private static List WrapNativeLogQueryResult(IntPtr linkedList)
{
+ if (linkedList == IntPtr.Zero)
+ return null;
+
List journalEntries = new List();
IntPtr element = LinkedList_getNext(linkedList);
@@ -1945,6 +1967,24 @@ namespace IEC61850
}
}
+ ///
+ /// Ignore all MMS requests from clients (for testing purposes)
+ ///
+ /// when true all requests from clients will be ignored
+ public void IgnoreClientRequests(bool ignore)
+ {
+ IedServer_ignoreClientRequests(connection, ignore);
+ }
+
+ ///
+ /// Temporarily ignore read requests (for testing purposes)
+ ///
+ /// true to ignore read requests, false to handle read requests.
+ public void IgnoreReadAccess(bool ignore)
+ {
+ IedServer_ignoreReadAccess(connection, ignore);
+ }
+
///
/// Read the values of a data set (GetDataSetValues service).
///
@@ -2238,22 +2278,27 @@ namespace IEC61850
GetDataSetDirectoryHandler handler = callbackInfo.Item1;
object handlerParameter = callbackInfo.Item2;
- IntPtr element = LinkedList_getNext(dataSetDirectory);
-
handle.Free();
- List newList = new List();
+ List newList = null;
- while (element != IntPtr.Zero)
+ if (dataSetDirectory != IntPtr.Zero)
{
- string dataObject = Marshal.PtrToStringAnsi(LinkedList_getData(element));
+ newList = new List();
- newList.Add(dataObject);
+ IntPtr element = LinkedList_getNext(dataSetDirectory);
- element = LinkedList_getNext(element);
- }
+ while (element != IntPtr.Zero)
+ {
+ string dataObject = Marshal.PtrToStringAnsi(LinkedList_getData(element));
- LinkedList_destroy(dataSetDirectory);
+ newList.Add(dataObject);
+
+ element = LinkedList_getNext(element);
+ }
+
+ LinkedList_destroy(dataSetDirectory);
+ }
handler.Invoke(invokeId, handlerParameter, (IedClientError)err, newList, isDeletable);
}
@@ -2428,11 +2473,9 @@ namespace IEC61850
dataSet = new DataSet(nativeDataSet);
}
-
handler(invokeId, handlerParameter, clientError, dataSet);
}
-
public delegate void ReadDataSetHandler(UInt32 invokeId,object parameter,IedClientError err,DataSet dataSet);
///
@@ -2566,7 +2609,6 @@ namespace IEC61850
{
handler(invokeId, handlerParameter, clientError, null, moreFollows);
}
-
}
///
@@ -2632,7 +2674,6 @@ namespace IEC61850
return GetLogicalDeviceDataSetsAsync(null, ldName, continueAfter, handler, parameter);
}
-
public UInt32 GetLogicalDeviceDataSetsAsync(List result, string ldName, string continueAfter, GetNameListHandler handler, object parameter)
{
int error;
@@ -2977,6 +3018,19 @@ namespace IEC61850
IED_STATE_CLOSING = 3
}
+ public static class IedClientErrorExtension
+ {
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr IedClientError_toString(int err);
+
+ public static string ToString(this IedClientError err)
+ {
+ string stringVal = Marshal.PtrToStringAnsi(IedClientError_toString((int)err));
+
+ return stringVal;
+ }
+ }
+
///
/// Error codes for client side functions
///
@@ -3062,6 +3116,9 @@ namespace IEC61850
/** Received an invalid response message from the server */
IED_ERROR_MALFORMED_MESSAGE = 34,
+ /** Service was not executed because required resource is still in use */
+ IED_ERROR_OBJECT_CONSTRAINT_CONFLICT = 35,
+
/** Service not implemented */
IED_ERROR_SERVICE_NOT_IMPLEMENTED = 98,
diff --git a/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs b/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs
index 818276c4..980d9ceb 100644
--- a/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs
@@ -1,7 +1,7 @@
/*
* IEC61850CommonAPI.cs
*
- * Copyright 2014-2017 Michael Zillgith
+ * Copyright 2014-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -454,6 +454,9 @@ namespace IEC61850
SetByMmsUtcTime (mmsUtcTime);
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
public Timestamp()
{
self = Timestamp_create ();
@@ -461,6 +464,19 @@ namespace IEC61850
responsibleForDeletion = true;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Timestamp(Timestamp other) : this()
+ {
+ SetTimeInSeconds (other.GetTimeInSeconds ());
+ SetSubsecondPrecision (other.GetSubsecondPrecision ());
+ SetFractionOfSecondPart (other.GetFractionOfSecondPart ());
+ SetLeapSecondKnow(other.IsLeapSecondKnown());
+ SetClockFailure(other.HasClockFailure());
+ SetClockNotSynchronized(other.IsClockNotSynchronized());
+ }
+
public Timestamp(byte[] value)
{
self = Timestamp_createFromByteArray (value);
diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index b0d2c054..8a0c5bf3 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -1874,6 +1874,9 @@ namespace IEC61850
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ControlAction_getInterlockCheck(IntPtr self);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr ControlAction_getT(IntPtr self);
+
private IntPtr self;
private IedServer.ControlHandlerInfo info;
private IedServer iedServer;
@@ -2003,6 +2006,18 @@ namespace IEC61850
{
return ControlAction_getInterlockCheck(self);
}
+
+ ///
+ /// Gets the time (paramter T) of the control action
+ ///
+ public Timestamp GetT()
+ {
+ IntPtr tPtr = ControlAction_getT(self);
+
+ Timestamp t = new Timestamp(tPtr, false);
+
+ return new Timestamp(t);
+ }
}
public delegate void GoCBEventHandler(MmsGooseControlBlock goCB, int cbEvent, object parameter);
@@ -2247,6 +2262,10 @@ namespace IEC61850
static extern void IedServer_handleWriteAccessForComplexAttribute(IntPtr self, IntPtr dataAttribute,
InternalWriteAccessHandler handler, IntPtr parameter);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_handleWriteAccessForDataObject(IntPtr self, IntPtr dataObject, int fc,
+ InternalWriteAccessHandler handler, IntPtr parameter);
+
public delegate void ConnectionIndicationHandler(IedServer iedServer, ClientConnection clientConnection, bool connected, object parameter);
private ConnectionIndicationHandler connectionHandler = null;
@@ -2713,12 +2732,27 @@ namespace IEC61850
}
}
+ private void AddHandlerInfoForDataObjectRecursive(DataObject dataObject, FunctionalConstraint fc, WriteAccessHandler handler, object parameter, InternalWriteAccessHandler internalHandler)
+ {
+ foreach (ModelNode child in dataObject.GetChildren())
+ {
+ if (child is DataAttribute && (child as DataAttribute).FC == fc)
+ {
+ AddHandlerInfoForDataAttributeRecursive(child as DataAttribute, handler, parameter, internalHandler);
+ }
+ else if (child is DataObject)
+ {
+ AddHandlerInfoForDataObjectRecursive(child as DataObject, fc, handler, parameter, internalHandler);
+ }
+ }
+ }
+
///
/// Install a WriteAccessHandler for a data attribute and for all sub data attributes
///
/// This instructs the server to monitor write attempts by MMS clients to specific
- /// data attributes.If a client tries to write to the monitored data attribute the
- /// handler is invoked.The handler can decide if the write access will be allowed
+ /// data attributes. If a client tries to write to the monitored data attribute the
+ /// handler is invoked. The handler can decide if the write access will be allowed
/// or denied.If a WriteAccessHandler is set for a specific data attribute - the
/// default write access policy will not be performed for that data attribute.
///
@@ -2738,6 +2772,27 @@ namespace IEC61850
IedServer_handleWriteAccessForComplexAttribute(self, dataAttr.self, internalHandler, IntPtr.Zero);
}
+ ///
+ /// Install a WriteAccessHandler for a data object and for all sub data objects and sub data attributes that have the same functional constraint
+ ///
+ /// This instructs the server to monitor write attempts by MMS clients to specific
+ /// data attributes. If a client tries to write to the monitored data attribute the
+ /// handler is invoked. The handler can decide if the write access will be allowed
+ /// or denied. If a WriteAccessHandler is set the
+ /// default write access policy will not be performed for the matching data attributes.
+ /// the data object to monitor
+ /// the functional constraint (FC) to monitor
+ /// the callback function that is invoked if a client tries to write to a monitored data attribute that is a child of the data object.
+ /// a user provided parameter that is passed to the WriteAccessHandler when called.
+ public void HandleWriteAccessForDataObject(DataObject dataObj, FunctionalConstraint fc, WriteAccessHandler handler, object parameter)
+ {
+ InternalWriteAccessHandler internalHandler = new InternalWriteAccessHandler(WriteAccessHandlerImpl);
+
+ AddHandlerInfoForDataObjectRecursive(dataObj, fc, handler, parameter, internalHandler);
+
+ IedServer_handleWriteAccessForDataObject(self, dataObj.self, (int)fc, internalHandler, IntPtr.Zero);
+ }
+
///
/// Set the defualt write access policy for a specific FC. The default policy is applied when no handler is installed for a data attribute
///
diff --git a/dotnet/example2/WriteValueExample.cs b/dotnet/example2/WriteValueExample.cs
index eb8b0228..b3ea3c04 100644
--- a/dotnet/example2/WriteValueExample.cs
+++ b/dotnet/example2/WriteValueExample.cs
@@ -36,7 +36,7 @@ namespace example2
}
catch (IedConnectionException e)
{
- Console.WriteLine("IED connection excepion: " + e.Message);
+ Console.WriteLine("IED connection exception: " + e.Message + " err: " + e.GetIedClientError().ToString());
}
// release all resources - do NOT use the object after this call!!
diff --git a/hal/ethernet/linux/ethernet_linux.c b/hal/ethernet/linux/ethernet_linux.c
index eaf1897a..bb989600 100644
--- a/hal/ethernet/linux/ethernet_linux.c
+++ b/hal/ethernet/linux/ethernet_linux.c
@@ -1,7 +1,7 @@
/*
* ethernet_linux.c
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -57,7 +57,8 @@ EthernetHandleSet_new(void)
{
EthernetHandleSet result = (EthernetHandleSet) GLOBAL_MALLOC(sizeof(struct sEthernetHandleSet));
- if (result != NULL) {
+ if (result != NULL)
+ {
result->handles = NULL;
result->nhandles = 0;
}
@@ -68,8 +69,8 @@ EthernetHandleSet_new(void)
void
EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock)
{
- if (self != NULL && sock != NULL) {
-
+ if (self != NULL && sock != NULL)
+ {
int i = self->nhandles++;
self->handles = realloc(self->handles, self->nhandles * sizeof(struct pollfd));
@@ -82,12 +83,14 @@ EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock)
void
EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock)
{
- if ((self != NULL) && (sock != NULL)) {
-
+ if ((self != NULL) && (sock != NULL))
+ {
int i;
- for (i = 0; i < self->nhandles; i++) {
- if (self->handles[i].fd == sock->rawSocket) {
+ for (i = 0; i < self->nhandles; i++)
+ {
+ if (self->handles[i].fd == sock->rawSocket)
+ {
memmove(&self->handles[i], &self->handles[i+1], sizeof(struct pollfd) * (self->nhandles - i - 1));
self->nhandles--;
return;
@@ -128,7 +131,8 @@ getInterfaceIndex(int sock, const char* deviceName)
strncpy(ifr.ifr_name, deviceName, IFNAMSIZ - 1);
- if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1) {
+ if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1)
+ {
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Failed to get interface index");
return -1;
@@ -157,7 +161,7 @@ Ethernet_getInterfaceMACAddress(const char* interfaceId, uint8_t* addr)
int i;
- for(i = 0; i < 6; i++ )
+ for (i = 0; i < 6; i++ )
{
addr[i] = (unsigned char)buffer.ifr_hwaddr.sa_data[i];
}
@@ -166,106 +170,112 @@ Ethernet_getInterfaceMACAddress(const char* interfaceId, uint8_t* addr)
EthernetSocket
Ethernet_createSocket(const char* interfaceId, uint8_t* destAddress)
{
- EthernetSocket ethernetSocket = GLOBAL_CALLOC(1, sizeof(struct sEthernetSocket));
+ EthernetSocket self = GLOBAL_CALLOC(1, sizeof(struct sEthernetSocket));
- if (ethernetSocket) {
- ethernetSocket->rawSocket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (self)
+ {
+ self->rawSocket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (ethernetSocket->rawSocket == -1) {
+ if (self->rawSocket == -1)
+ {
if (DEBUG_SOCKET)
printf("Error creating raw socket!\n");
- GLOBAL_FREEMEM(ethernetSocket);
+ GLOBAL_FREEMEM(self);
return NULL;
}
- ethernetSocket->socketAddress.sll_family = PF_PACKET;
- ethernetSocket->socketAddress.sll_protocol = htons(ETH_P_ALL);
+ self->socketAddress.sll_family = PF_PACKET;
+ self->socketAddress.sll_protocol = htons(ETH_P_ALL);
- int ifcIdx = getInterfaceIndex(ethernetSocket->rawSocket, interfaceId);
+ int ifcIdx = getInterfaceIndex(self->rawSocket, interfaceId);
- if (ifcIdx == -1) {
- Ethernet_destroySocket(ethernetSocket);
+ if (ifcIdx == -1)
+ {
+ Ethernet_destroySocket(self);
return NULL;
}
- ethernetSocket->socketAddress.sll_ifindex = ifcIdx;
+ self->socketAddress.sll_ifindex = ifcIdx;
- ethernetSocket->socketAddress.sll_hatype = ARPHRD_ETHER;
- ethernetSocket->socketAddress.sll_pkttype = PACKET_HOST | PACKET_MULTICAST;
+ self->socketAddress.sll_hatype = ARPHRD_ETHER;
+ self->socketAddress.sll_pkttype = PACKET_HOST | PACKET_MULTICAST;
- ethernetSocket->socketAddress.sll_halen = ETH_ALEN;
+ self->socketAddress.sll_halen = ETH_ALEN;
- memset(ethernetSocket->socketAddress.sll_addr, 0, 8);
+ memset(self->socketAddress.sll_addr, 0, 8);
if (destAddress != NULL)
- memcpy(ethernetSocket->socketAddress.sll_addr, destAddress, 6);
+ memcpy(self->socketAddress.sll_addr, destAddress, 6);
+
+ self->isBind = false;
- ethernetSocket->isBind = false;
+ Ethernet_setMode(self, ETHERNET_SOCKET_MODE_PROMISC);
}
- return ethernetSocket;
+ return self;
}
void
-Ethernet_setMode(EthernetSocket ethSocket, EthernetSocketMode mode)
+Ethernet_setMode(EthernetSocket self, EthernetSocketMode mode)
{
- if (ethSocket) {
-
- if (mode == ETHERNET_SOCKET_MODE_PROMISC) {
-
+ if (self)
+ {
+ if (mode == ETHERNET_SOCKET_MODE_PROMISC)
+ {
struct ifreq ifr;
- if (ioctl (ethSocket->rawSocket, SIOCGIFFLAGS, &ifr) == -1)
+ if (ioctl (self->rawSocket, SIOCGIFFLAGS, &ifr) == -1)
{
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Problem getting device flags");
return;
}
-
ifr.ifr_flags |= IFF_PROMISC;
- if (ioctl (ethSocket->rawSocket, SIOCSIFFLAGS, &ifr) == -1)
+ if (ioctl (self->rawSocket, SIOCSIFFLAGS, &ifr) == -1)
{
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Setting device to promiscuous mode failed");
return;
}
}
- else if (mode == ETHERNET_SOCKET_MODE_ALL_MULTICAST) {
+ else if (mode == ETHERNET_SOCKET_MODE_ALL_MULTICAST)
+ {
struct ifreq ifr;
- if (ioctl (ethSocket->rawSocket, SIOCGIFFLAGS, &ifr) == -1)
+ if (ioctl (self->rawSocket, SIOCGIFFLAGS, &ifr) == -1)
{
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Problem getting device flags");
return;
}
-
ifr.ifr_flags |= IFF_ALLMULTI;
- if (ioctl (ethSocket->rawSocket, SIOCSIFFLAGS, &ifr) == -1)
+ if (ioctl (self->rawSocket, SIOCSIFFLAGS, &ifr) == -1)
{
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Setting device to promiscuous mode failed");
return;
}
}
- else if (mode == ETHERNET_SOCKET_MODE_HOST_ONLY) {
- ethSocket->socketAddress.sll_pkttype = PACKET_HOST;
+ else if (mode == ETHERNET_SOCKET_MODE_HOST_ONLY)
+ {
+ self->socketAddress.sll_pkttype = PACKET_HOST;
}
- else if (mode == ETHERNET_SOCKET_MODE_MULTICAST) {
- ethSocket->socketAddress.sll_pkttype = PACKET_HOST | PACKET_MULTICAST;
+ else if (mode == ETHERNET_SOCKET_MODE_MULTICAST)
+ {
+ self->socketAddress.sll_pkttype = PACKET_HOST | PACKET_MULTICAST;
}
}
}
void
-Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress)
+Ethernet_addMulticastAddress(EthernetSocket self, uint8_t* multicastAddress)
{
struct packet_mreq mreq;
memset(&mreq, 0, sizeof(struct packet_mreq));
- mreq.mr_ifindex = ethSocket->socketAddress.sll_ifindex;
+ mreq.mr_ifindex = self->socketAddress.sll_ifindex;
mreq.mr_alen = ETH_ALEN;
mreq.mr_type = PACKET_MR_MULTICAST;
mreq.mr_address[0] = multicastAddress[0];
@@ -275,17 +285,17 @@ Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress
mreq.mr_address[4] = multicastAddress[4];
mreq.mr_address[5] = multicastAddress[5];
- int res = setsockopt(ethSocket->rawSocket, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+ int res = setsockopt(self->rawSocket, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
-
- if (res != 0) {
+ if (res != 0)
+ {
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Setting multicast address failed");
}
}
void
-Ethernet_setProtocolFilter(EthernetSocket ethSocket, uint16_t etherType)
+Ethernet_setProtocolFilter(EthernetSocket self, uint16_t etherType)
{
if (etherType == 0x88b8)
{
@@ -303,22 +313,22 @@ Ethernet_setProtocolFilter(EthernetSocket ethSocket, uint16_t etherType)
fprog.len = sizeof(filter) / sizeof(*filter);
fprog.filter = filter;
- if (setsockopt(ethSocket->rawSocket, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) == -1)
+ if (setsockopt(self->rawSocket, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) == -1)
if (DEBUG_SOCKET)
printf("ETHERNET_LINUX: Applying filter failed");
}
else
{
- ethSocket->socketAddress.sll_protocol = htons(etherType);
+ self->socketAddress.sll_protocol = htons(etherType);
}
}
-
/* non-blocking receive */
int
Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize)
{
- if (self->isBind == false) {
+ if (self->isBind == false)
+ {
if (bind(self->rawSocket, (struct sockaddr*) &self->socketAddress, sizeof(self->socketAddress)) == 0)
self->isBind = true;
else
@@ -329,17 +339,20 @@ Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize)
}
void
-Ethernet_sendPacket(EthernetSocket ethSocket, uint8_t* buffer, int packetSize)
+Ethernet_sendPacket(EthernetSocket self, uint8_t* buffer, int packetSize)
{
- sendto(ethSocket->rawSocket, buffer, packetSize,
- 0, (struct sockaddr*) &(ethSocket->socketAddress), sizeof(ethSocket->socketAddress));
+ sendto(self->rawSocket, buffer, packetSize,
+ 0, (struct sockaddr*) &(self->socketAddress), sizeof(self->socketAddress));
}
void
-Ethernet_destroySocket(EthernetSocket ethSocket)
+Ethernet_destroySocket(EthernetSocket self)
{
- close(ethSocket->rawSocket);
- GLOBAL_FREEMEM(ethSocket);
+ if (self)
+ {
+ close(self->rawSocket);
+ GLOBAL_FREEMEM(self);
+ }
}
bool
@@ -347,4 +360,3 @@ Ethernet_isSupported()
{
return true;
}
-
diff --git a/hal/socket/linux/socket_linux.c b/hal/socket/linux/socket_linux.c
index d53ed419..44b4cbef 100644
--- a/hal/socket/linux/socket_linux.c
+++ b/hal/socket/linux/socket_linux.c
@@ -1,7 +1,7 @@
/*
* socket_linux.c
*
- * Copyright 2013-2021 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@@ -907,7 +907,7 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
{
//TODO add support for IPv6
struct sockaddr_storage remoteAddress;
-
+ memset(&remoteAddress, 0, sizeof(struct sockaddr_storage));
socklen_t structSize = sizeof(struct sockaddr_storage);
int result = recvfrom(self->fd, msg, msgSize, MSG_DONTWAIT, (struct sockaddr*)&remoteAddress, &structSize);
diff --git a/hal/socket/win32/socket_win32.c b/hal/socket/win32/socket_win32.c
index f50ac05a..8976a825 100644
--- a/hal/socket/win32/socket_win32.c
+++ b/hal/socket/win32/socket_win32.c
@@ -843,6 +843,7 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
{
//TODO add support for IPv6
struct sockaddr_storage remoteAddress;
+ memset(&remoteAddress, 0, sizeof(struct sockaddr_storage));
socklen_t structSize = sizeof(struct sockaddr_storage);
if (address)
diff --git a/hal/tls/mbedtls/tls_mbedtls.c b/hal/tls/mbedtls/tls_mbedtls.c
index e2f152d0..06b98234 100644
--- a/hal/tls/mbedtls/tls_mbedtls.c
+++ b/hal/tls/mbedtls/tls_mbedtls.c
@@ -37,9 +37,9 @@
#endif
#if (CONFIG_DEBUG_TLS == 1)
-#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ## __VA_ARGS__);
+#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ## __VA_ARGS__)
#else
-#define DEBUG_PRINT(fmt, ...) {do {} while(0);}
+#define DEBUG_PRINT(fmt, ...) do {} while(0)
#endif
@@ -265,7 +265,7 @@ TLSConfiguration_create()
mbedtls_ssl_conf_authmode(&(self->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
- mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION);
+ mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_ENABLED);
/* static int hashes[] = {3,4,5,6,7,8,0}; */
/* mbedtls_ssl_conf_sig_hashes(&(self->conf), hashes); */
@@ -297,7 +297,7 @@ TLSConfiguration_create()
void
TLSConfiguration_setClientMode(TLSConfiguration self)
{
- self->conf.endpoint = MBEDTLS_SSL_IS_CLIENT;
+ mbedtls_ssl_conf_endpoint(&(self->conf), MBEDTLS_SSL_IS_CLIENT);
}
void
@@ -852,20 +852,26 @@ TLSSocket_performHandshake(TLSSocket self)
{
int ret = mbedtls_ssl_renegotiate(&(self->ssl));
- if (ret == 0) {
+ if (ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
+ ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS || ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) {
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
}
+
+ DEBUG_PRINT("TLS", "TLSSocket_performHandshake Success -> ret=%i\n", ret);
+ raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "TLS session renegotiation completed", self);
return true;
}
else {
DEBUG_PRINT("TLS", "TLSSocket_performHandshake failed -> ret=%i\n", ret);
- if (self->tlsConfig->eventHandler) {
- uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl));
+ raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Alarm: TLS session renegotiation failed", self);
- createSecurityEvents(self->tlsConfig, ret, flags, self);
+ /* mbedtls_ssl_renegotiate mandates to reset the ssl session in case of errors */
+ ret = mbedtls_ssl_session_reset(&(self->ssl));
+ if (ret != 0) {
+ DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -> ret: -0x%X\n", -ret);
}
return false;
@@ -898,16 +904,10 @@ startRenegotiationIfRequired(TLSSocket self)
if (Hal_getTimeInMs() <= self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs)
return true;
- raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Info: session renegotiation started", self);
-
- if (TLSSocket_performHandshake(self) == false) {
- DEBUG_PRINT("TLS", " renegotiation failed\n");
+ if (TLSSocket_performHandshake(self) == false)
return false;
- }
- DEBUG_PRINT("TLS", " started renegotiation\n");
self->lastRenegotiationTime = Hal_getTimeInMs();
-
return true;
}
@@ -920,22 +920,30 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
return -1;
}
- int ret = mbedtls_ssl_read(&(self->ssl), buf, size);
-
- if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE))
- return 0;
+ int len = 0;
+ while (len < size) {
+ int ret = mbedtls_ssl_read(&(self->ssl), (buf + len), (size - len));
+ if (ret > 0) {
+ len += ret;
+ continue;
+ }
- if (ret < 0) {
+ switch (ret) {
+ case 0: // falling through
+ case MBEDTLS_ERR_SSL_WANT_READ:
+ case MBEDTLS_ERR_SSL_WANT_WRITE:
+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
+ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
+ // Known "good" cases indicating the read is done
+ return len;
- switch (ret)
- {
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
DEBUG_PRINT("TLS", " connection was closed gracefully\n");
- return -1;
+ break;
case MBEDTLS_ERR_NET_CONN_RESET:
DEBUG_PRINT("TLS", " connection was reset by peer\n");
- return -1;
+ break;
default:
DEBUG_PRINT("TLS", " mbedtls_ssl_read returned -0x%x\n", -ret);
@@ -945,19 +953,23 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
createSecurityEvents(self->tlsConfig, ret, flags, self);
}
+ }
- return -1;
+ int reset_err = mbedtls_ssl_session_reset(&(self->ssl));
+ if (0 != reset_err) {
+ DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -0x%X\n", -reset_err);
}
+
+ return ret;
}
- return ret;
+ return len;
}
int
TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
{
- int ret;
- int len = size;
+ int len = 0;
checkForCRLUpdate(self);
@@ -965,22 +977,26 @@ TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
return -1;
}
- while ((ret = mbedtls_ssl_write(&(self->ssl), buf, len)) <= 0)
+ while (len < size)
{
- if (ret == MBEDTLS_ERR_NET_CONN_RESET)
- {
- DEBUG_PRINT("TLS", "peer closed the connection\n");
- return -1;
+ int ret = mbedtls_ssl_write(&(self->ssl), (buf + len), (size -len));
+ if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ||
+ (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) || (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)) {
+ continue;
}
- if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE))
- {
- DEBUG_PRINT("TLS", "mbedtls_ssl_write returned %d\n", ret);
+ if (ret < 0) {
+ DEBUG_PRINT("TLS", "mbedtls_ssl_write returned -0x%X\n", -ret);
+
+ if (0 != (ret = mbedtls_ssl_session_reset(&(self->ssl)))) {
+ DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -0x%X\n", -ret);
+ }
+
return -1;
}
- }
- len = ret;
+ len += ret;
+ }
return len;
}
@@ -1008,6 +1024,7 @@ TLSSocket_close(TLSSocket self)
if (self->peerCert)
GLOBAL_FREEMEM(self->peerCert);
+
GLOBAL_FREEMEM(self);
}
diff --git a/pyiec61850/CMakeLists.txt b/pyiec61850/CMakeLists.txt
index 159ef4bc..a42960f9 100644
--- a/pyiec61850/CMakeLists.txt
+++ b/pyiec61850/CMakeLists.txt
@@ -1,18 +1,22 @@
-# The SWIG functions/macros used in this module, swig_add_module and swig_add_library
-# are not available in CMake versions earlier than 3.8
-# cmake_minimum_required(VERSION 3.8)
+cmake_minimum_required(VERSION 3.12)
+
+cmake_policy(SET CMP0078 NEW)
+
+if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0")
+ cmake_policy(SET CMP0086 NEW)
+endif()
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
-find_package(PythonInterp ${BUILD_PYTHON_VERSION} REQUIRED)
-find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT REQUIRED)
+find_package(Python COMPONENTS Interpreter Development REQUIRED)
-include_directories(${PYTHON_INCLUDE_PATH})
+include_directories(${Python_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_SWIG_FLAGS "")
set_property(SOURCE iec61850.i PROPERTY CPLUSPLUS ON)
+set_property(SOURCE iec61850.i PROPERTY SWIG_MODULE_NAME pyiec61850)
if(WIN32)
set(LIBS iec61850 ws2_32)
@@ -20,25 +24,21 @@ else()
set(LIBS iec61850-shared)
endif()
-if(${CMAKE_VERSION} VERSION_LESS 3.8)
- swig_add_module(iec61850 python iec61850.i)
-else()
- swig_add_library(iec61850
- LANGUAGE python
- SOURCES iec61850.i
- )
-endif()
+swig_add_library(pyiec61850
+ LANGUAGE python
+ SOURCES iec61850.i
+)
-swig_link_libraries(iec61850 ${PYTHON_LIBRARIES} ${LIBS})
+swig_link_libraries(pyiec61850 ${LIBS})
# Finding python modules install path
execute_process(
- COMMAND ${PYTHON_EXECUTABLE} -c
- "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib())"
+ COMMAND ${Python_EXECUTABLE} -c
+ "from sysconfig import get_path; import sys; sys.stdout.write(get_path('platlib'))"
OUTPUT_VARIABLE PYTHON_SITE_DIR
)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/iec61850.py DESTINATION ${PYTHON_SITE_DIR})
-install(TARGETS _iec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR})
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pyiec61850.py DESTINATION ${PYTHON_SITE_DIR})
+install(TARGETS pyiec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR})
-add_test(test_pyiec61850 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test_pyiec61850.py)
+add_test(test_pyiec61850 ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test_pyiec61850.py)
diff --git a/pyiec61850/README.md b/pyiec61850/README.md
new file mode 100644
index 00000000..b2398919
--- /dev/null
+++ b/pyiec61850/README.md
@@ -0,0 +1,95 @@
+# Python wrapper for libIEC61850
+
+## Building
+Before building you should install SWIG and Python
+(see the '[Setup development environment on Linux](#setup-development-environment-on-linux-ubuntu)' section for help).
+
+To build the Python bindings you have to turn on the BUILD\_PYTHON\_BINDINGS flag in CMake from cmake-gui or in command line:
+```sh
+$ mkdir build && cd build
+$ cmake -DBUILD_PYTHON_BINDINGS=ON ..
+```
+
+Then compile the library and install it:
+```sh
+$ make
+$ sudo make install
+```
+(Eventually, update your ld cache with: `sudo ldconfig`)
+
+CMake and SWIG will automatically detect your Python version and install the Python library in Python library directories.
+
+For running the integrated tests:
+```sh
+$ make test
+```
+
+pyiec61850 library is to be imported calling:
+```python
+import pyiec61850 as iec61850
+```
+
+## Client tutorial
+
+The Python bindings works similarly to the basic C library. However there are some differences:
+
+* a specific function is to be called to cast variables from one type to another
+* arguments passed by pointer are to be removed from arguments and append to the return list
+
+
+For example to create a connection, call:
+```python
+ con = iec61850.IedConnection_create()
+ error = iec61850.IedConnection_connect(con, "localhost", 102)
+ if (error == iec61850.IED_ERROR_OK):
+ # Do some work
+ iec61850.IedConnection_close(con)
+ iec61850.IedConnection_destroy(con)
+```
+
+To iterate over a list of logical devices, the code becomes:
+```python
+[deviceList, error] = iec61850.IedConnection_getLogicalDeviceList(con)
+device = iec61850.LinkedList_getNext(deviceList)
+
+while device:
+ print("LD: %s" % iec61850.toCharP(device.data))
+ [logicalNodes, error] = iec61850.IedConnection_getLogicalDeviceDirectory(
+ con, iec61850.toCharP(device.data))
+ device = iec61850.LinkedList_getNext(device)
+iec61850.LinkedList_destroy(deviceList)
+```
+
+Reading and writing operations can be performed using this syntax:
+```python
+[floatValue, error] = iec61850.IedConnection_readFloatValue(con,
+ "simpleIOGenericIO/GGIO1.AnIn1.mag.f", iec61850.IEC61850_FC_MX)
+err = iec61850.IedConnection_writeFloatValue(con,
+ "simpleIOGenericIO/GGIO1.AnIn1.mag.f", iec61850.IEC61850_FC_MX, 10.0)
+```
+
+## Appendix
+
+## Setup development environment on Linux Ubuntu
+
+_[Tested on Ubuntu 20.04 LTS, Ubuntu 22.04 LTS, Ubuntu 23.10]_
+
+Here the minimum required packages for compiling libiec61850 and the Python
+wrapper (without TLS, SQlite, ...):
+
+```sh
+$ sudo apt-get update
+$ sudo apt-get install g++ cmake swig git python3 python3-all-dev
+```
+
+## Setup development environment on Linux Alpine
+
+_[Tested on Alpine 3.18]_
+
+Here the minimum required packages for compiling libiec61850 and the Python
+wrapper (without TLS, SQlite, ...):
+
+```sh
+$ apk update
+$ apk add git g++ swig make cmake python3 python3-dev linux-headers
+```
diff --git a/pyiec61850/examples/dispServerStruct.py b/pyiec61850/examples/dispServerStruct.py
index aea02b4f..2b49479b 100755
--- a/pyiec61850/examples/dispServerStruct.py
+++ b/pyiec61850/examples/dispServerStruct.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
import os,sys
-import iec61850
+import pyiec61850 as iec61850
if __name__=="__main__":
hostname = "localhost";
tcpPort = 102
diff --git a/pyiec61850/examples/rcbSubscriptionExample.py b/pyiec61850/examples/rcbSubscriptionExample.py
index d4d05aa5..7d1243be 100644
--- a/pyiec61850/examples/rcbSubscriptionExample.py
+++ b/pyiec61850/examples/rcbSubscriptionExample.py
@@ -27,7 +27,7 @@ The user needs to:
import time
import sys
-import iec61850
+import pyiec61850 as iec61850
def open_connection(ip_address, mms_port):
diff --git a/pyiec61850/iec61850.i b/pyiec61850/iec61850.i
index 254fec64..4cdbe0ea 100644
--- a/pyiec61850/iec61850.i
+++ b/pyiec61850/iec61850.i
@@ -1,5 +1,5 @@
/* File : iec61850.i */
-%module(directors="1") iec61850
+%module(directors="1") pyiec61850
%ignore ControlObjectClient_setTestMode(ControlObjectClient self);
%ignore CDA_OperBoolean(ModelNode* parent, bool isTImeActivated);
%ignore LogicalNode_hasBufferedReports(LogicalNode* node);
diff --git a/pyiec61850/test_pyiec61850.py b/pyiec61850/test_pyiec61850.py
index aceb3fdb..6f6d8cdd 100755
--- a/pyiec61850/test_pyiec61850.py
+++ b/pyiec61850/test_pyiec61850.py
@@ -6,7 +6,7 @@ import traceback
import signal
import sys
sys.path.append('.')
-import iec61850
+import pyiec61850 as iec61850
def signal_handler(signal, frame):
global running
running =0
diff --git a/pyiec61850/tutorial.md b/pyiec61850/tutorial.md
deleted file mode 100644
index ce766cab..00000000
--- a/pyiec61850/tutorial.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Building
-Before building you should install swig and python.
-To build python bindings you have to turn on the BUILD\_PYTHON\_BINDINGS flag in CMake from cmake-gui or in command line:
-```sh
-$ cmake -DBUILD_PYTHON_BINDINGS=ON .
-```
-Then compile the library and install it. CMake and swig will automatically detect your python version and install the python library in python library directories.
-
-pyiec61850 library is to be imported calling
-```python
-import iec61850
-```
-# Client tutorial
-
-The python bindings works similarly to the basic C library. However there are some differences:
-
-* a specific function is to be called to cast variables from one type to another
-* arguments passed by pointer are to be removed from arguments and append to the return list
-
-
-For example to create a connection, call:
-```python
- con = iec61850.IedConnection_create()
- error = iec61850.IedConnection_connect(con, "localhost", 102)
- if (error == iec61850.IED_ERROR_OK):
- # Do some work
- iec61850.IedConnection_close(con)
- iec61850.IedConnection_destroy(con)
-```
-
-To iterate over a list of logical devices, the code becomes:
-```python
-[deviceList, error] = iec61850.IedConnection_getLogicalDeviceList(con)
-device = iec61850.LinkedList_getNext(deviceList)
-
-while device:
- print("LD: %s" % iec61850.toCharP(device.data))
- [logicalNodes, error] = iec61850.IedConnection_getLogicalDeviceDirectory(
- con, iec61850.toCharP(device.data))
- device = iec61850.LinkedList_getNext(device)
-iec61850.LinkedList_destroy(deviceList)
-```
-
-Reading and writing operations can be performed using this syntax:
-```python
-[floatValue, error] = iec61850.IedConnection_readFloatValue(con,
- "simpleIOGenericIO/GGIO1.AnIn1.mag.f", iec61850.IEC61850_FC_MX)
-err = iec61850.IedConnection_writeFloatValue(con,
- "simpleIOGenericIO/GGIO1.AnIn1.mag.f", iec61850.IEC61850_FC_MX, 10.0)
-```
diff --git a/src/common/string_utilities.c b/src/common/string_utilities.c
index 2f659e6f..1608f964 100644
--- a/src/common/string_utilities.c
+++ b/src/common/string_utilities.c
@@ -90,14 +90,14 @@ StringUtils_copyStringToBufferAndReplace(const char* str, char* buffer, char old
char*
StringUtils_createStringFromBuffer(const uint8_t* buf, int size)
{
- char* newStr = (char*) GLOBAL_MALLOC(size + 1);
+ char* newStr = (char*) GLOBAL_MALLOC(size + 1);
- if (newStr) {
- memcpy(newStr, buf, size);
- newStr[size] = 0;
- }
+ if (newStr) {
+ memcpy(newStr, buf, size);
+ newStr[size] = 0;
+ }
- return newStr;
+ return newStr;
}
char*
@@ -429,11 +429,11 @@ getCharWeight(int c)
{
static bool initialized = false;
static char lookupTable[LT_MAX_CHARS + 1];
+ static const char* charOrder = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz$_0123456789";
if (!initialized) {
int ltIndex;
int weight = 1;
- const char* charOrder = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz$_0123456789";
for (ltIndex = 1; ltIndex < LT_MAX_CHARS; ltIndex++) {
if (strchr(charOrder, ltIndex)) continue;
diff --git a/src/goose/goose_publisher.c b/src/goose/goose_publisher.c
index a8023807..094881a5 100644
--- a/src/goose/goose_publisher.c
+++ b/src/goose/goose_publisher.c
@@ -1,7 +1,7 @@
/*
* goose_publisher.c
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -106,12 +106,14 @@ GoosePublisher_createEx(CommParameters* parameters, const char* interfaceID, boo
if (self)
{
- if (prepareGooseBuffer(self, parameters, interfaceID, useVlanTag)) {
+ if (prepareGooseBuffer(self, parameters, interfaceID, useVlanTag))
+ {
self->timestamp = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs());
GoosePublisher_reset(self);
}
- else {
+ else
+ {
GoosePublisher_destroy(self);
self = NULL;
}
@@ -257,71 +259,84 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char*
uint16_t vlanId;
uint16_t appId;
- if (parameters) {
- dstAddr = defaultDstAddr;
- priority = CONFIG_GOOSE_DEFAULT_PRIORITY;
- vlanId = CONFIG_GOOSE_DEFAULT_VLAN_ID;
- appId = CONFIG_GOOSE_DEFAULT_APPID;
- }
- else {
+ if (parameters)
+ {
dstAddr = parameters->dstAddress;
priority = parameters->vlanPriority;
vlanId = parameters->vlanId;
appId = parameters->appId;
}
+ else
+ {
+ dstAddr = defaultDstAddr;
+ priority = CONFIG_GOOSE_DEFAULT_PRIORITY;
+ vlanId = CONFIG_GOOSE_DEFAULT_VLAN_ID;
+ appId = CONFIG_GOOSE_DEFAULT_APPID;
+ }
if (interfaceID)
self->ethernetSocket = Ethernet_createSocket(interfaceID, dstAddr);
else
self->ethernetSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, dstAddr);
- if (self->ethernetSocket) {
+ if (self->ethernetSocket)
+ {
self->buffer = (uint8_t*) GLOBAL_MALLOC(GOOSE_MAX_MESSAGE_SIZE);
- memcpy(self->buffer, dstAddr, 6);
- memcpy(self->buffer + 6, srcAddr, 6);
+ if (self->buffer)
+ {
+ memcpy(self->buffer, dstAddr, 6);
+ memcpy(self->buffer + 6, srcAddr, 6);
- int bufPos = 12;
+ int bufPos = 12;
- if (useVlanTags) {
- /* Priority tag - IEEE 802.1Q */
- self->buffer[bufPos++] = 0x81;
- self->buffer[bufPos++] = 0x00;
+ if (useVlanTags)
+ {
+ /* Priority tag - IEEE 802.1Q */
+ self->buffer[bufPos++] = 0x81;
+ self->buffer[bufPos++] = 0x00;
- uint8_t tci1 = priority << 5;
- tci1 += vlanId / 256;
+ uint8_t tci1 = priority << 5;
+ tci1 += vlanId / 256;
- uint8_t tci2 = vlanId % 256;
+ uint8_t tci2 = vlanId % 256;
- self->buffer[bufPos++] = tci1; /* Priority + VLAN-ID */
- self->buffer[bufPos++] = tci2; /* VLAN-ID */
- }
+ self->buffer[bufPos++] = tci1; /* Priority + VLAN-ID */
+ self->buffer[bufPos++] = tci2; /* VLAN-ID */
+ }
- /* EtherType GOOSE */
- self->buffer[bufPos++] = 0x88;
- self->buffer[bufPos++] = 0xB8;
+ /* EtherType GOOSE */
+ self->buffer[bufPos++] = 0x88;
+ self->buffer[bufPos++] = 0xB8;
- /* APPID */
- self->buffer[bufPos++] = appId / 256;
- self->buffer[bufPos++] = appId % 256;
+ /* APPID */
+ self->buffer[bufPos++] = appId / 256;
+ self->buffer[bufPos++] = appId % 256;
- self->lengthField = bufPos;
+ self->lengthField = bufPos;
- /* Length */
- self->buffer[bufPos++] = 0x00;
- self->buffer[bufPos++] = 0x08;
+ /* Length */
+ self->buffer[bufPos++] = 0x00;
+ self->buffer[bufPos++] = 0x08;
- /* Reserved1 */
- self->buffer[bufPos++] = 0x00;
- self->buffer[bufPos++] = 0x00;
+ /* Reserved1 */
+ self->buffer[bufPos++] = 0x00;
+ self->buffer[bufPos++] = 0x00;
- /* Reserved2 */
- self->buffer[bufPos++] = 0x00;
- self->buffer[bufPos++] = 0x00;
+ /* Reserved2 */
+ self->buffer[bufPos++] = 0x00;
+ self->buffer[bufPos++] = 0x00;
- self->payloadStart = bufPos;
+ self->payloadStart = bufPos;
- return true;
+ return true;
+ }
+ else
+ {
+ if (DEBUG_GOOSE_PUBLISHER)
+ printf("GOOSE_PUBLISHER: Failed to allocate buffer\n");
+ return false;
+ }
}
else {
return false;
@@ -329,8 +344,8 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char*
}
static int32_t
-createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffer, size_t maxPayloadSize) {
-
+createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffer, size_t maxPayloadSize)
+{
/* Step 1 - calculate length fields */
uint32_t goosePduLength = 0;
@@ -365,13 +380,16 @@ createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffe
LinkedList element = LinkedList_getNext(dataSetValues);
- while (element) {
+ while (element)
+ {
MmsValue* dataSetEntry = (MmsValue*) element->data;
- if (dataSetEntry) {
+ if (dataSetEntry)
+ {
dataSetSize += MmsValue_encodeMmsData(dataSetEntry, NULL, 0, false);
}
- else {
+ else
+ {
/* TODO encode MMS NULL */
if (DEBUG_GOOSE_PUBLISHER)
printf("GOOSE_PUBLISHER: NULL value in data set!\n");
@@ -438,7 +456,8 @@ createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffe
/* Encode data set entries */
element = LinkedList_getNext(dataSetValues);
- while (element) {
+ while (element)
+ {
MmsValue* dataSetEntry = (MmsValue*) element->data;
if (dataSetEntry) {
@@ -503,7 +522,7 @@ GoosePublisher_publishAndDump(GoosePublisher self, LinkedList dataSet, char *msg
int rc = GoosePublisher_publish(self, dataSet);
if (rc == 0)
- {
+ {
int copied = self->payloadStart + self->payloadLength;
if (bufSize < copied)
diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c
index 833fb2ff..6109eee9 100644
--- a/src/goose/goose_receiver.c
+++ b/src/goose/goose_receiver.c
@@ -1,7 +1,7 @@
/*
* goose_receiver.c
*
- * Copyright 2014-2022 Michael Zillgith
+ * Copyright 2014-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -73,7 +73,8 @@ GooseReceiver_createEx(uint8_t* buffer)
{
GooseReceiver self = (GooseReceiver) GLOBAL_MALLOC(sizeof(struct sGooseReceiver));
- if (self != NULL) {
+ if (self != NULL)
+ {
self->running = false;
self->stop = false;
self->interfaceId = NULL;
@@ -148,9 +149,20 @@ static void
createNewStringFromBufferElement(MmsValue* value, uint8_t* bufferSrc, int elementLength)
{
value->value.visibleString.buf = (char*) GLOBAL_MALLOC(elementLength + 1);
- memcpy(value->value.visibleString.buf, bufferSrc, elementLength);
- value->value.visibleString.buf[elementLength] = 0;
- value->value.visibleString.size = elementLength;
+
+ if (value->value.visibleString.buf)
+ {
+ memcpy(value->value.visibleString.buf, bufferSrc, elementLength);
+ value->value.visibleString.buf[elementLength] = 0;
+ value->value.visibleString.size = elementLength;
+ }
+ else
+ {
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ printf("GOOSE_SUBSCRIBER: failed to allocate memory for visible string\n");
+
+ value->value.visibleString.size = 0;
+ }
}
static GooseParseError
@@ -165,24 +177,28 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
GooseParseError pe = GOOSE_PARSE_ERROR_NO_ERROR;
uint8_t tag;
- while (bufPos < allDataLength) {
+ while (bufPos < allDataLength)
+ {
tag = buffer[bufPos++];
- if (elementIndex > maxIndex) {
+ if (elementIndex > maxIndex)
+ {
pe = GOOSE_PARSE_ERROR_OVERFLOW;
break; /* from while */
}
MmsValue* value = MmsValue_getElement(dataSetValues, elementIndex);
- if (value == NULL) {
+ if (value == NULL)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: type mismatch (element %i not found)\n", elementIndex);
return GOOSE_PARSE_ERROR_TYPE_MISMATCH;
}
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);
- if (bufPos < 0) {
+ if (bufPos < 0)
+ {
pe = GOOSE_PARSE_ERROR_TAGDECODE;
break; /* from while */
}
@@ -197,7 +213,8 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
case 0xa1: /* array */
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: found array\n");
- if (MmsValue_getType(value) == MMS_ARRAY) {
+ if (MmsValue_getType(value) == MMS_ARRAY)
+ {
if (parseAllData(buffer + bufPos, elementLength, value) != GOOSE_PARSE_ERROR_NO_ERROR)
pe = GOOSE_PARSE_ERROR_SUBLEVEL;
}
@@ -209,7 +226,8 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
case 0xa2: /* structure */
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: found structure\n");
- if (MmsValue_getType(value) == MMS_STRUCTURE) {
+ if (MmsValue_getType(value) == MMS_STRUCTURE)
+ {
if (parseAllData(buffer + bufPos, elementLength, value) != GOOSE_PARSE_ERROR_NO_ERROR)
pe = GOOSE_PARSE_ERROR_SUBLEVEL;
}
@@ -232,18 +250,23 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x84: /* BIT STRING */
- if (MmsValue_getType(value) == MMS_BIT_STRING) {
+ if (MmsValue_getType(value) == MMS_BIT_STRING)
+ {
int padding = buffer[bufPos];
- if (padding > 7) {
+ if (padding > 7)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: invalid bit-string (padding not plausible)\n");
pe = GOOSE_PARSE_ERROR_INVALID_PADDING;
}
- else {
+ else
+ {
int bitStringLength = (8 * (elementLength - 1)) - padding;
- if (bitStringLength == value->value.bitString.size) {
+
+ if (bitStringLength == value->value.bitString.size)
+ {
memcpy(value->value.bitString.buf, buffer + bufPos + 1,
elementLength - 1);
}
@@ -258,8 +281,10 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x85: /* integer */
- if (MmsValue_getType(value) == MMS_INTEGER) {
- if (elementLength <= value->value.integer->maxSize) {
+ if (MmsValue_getType(value) == MMS_INTEGER)
+ {
+ if (elementLength <= value->value.integer->maxSize)
+ {
value->value.integer->size = elementLength;
memcpy(value->value.integer->octets, buffer + bufPos, elementLength);
}
@@ -273,8 +298,10 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x86: /* unsigned integer */
- if (MmsValue_getType(value) == MMS_UNSIGNED) {
- if (elementLength <= value->value.integer->maxSize) {
+ if (MmsValue_getType(value) == MMS_UNSIGNED)
+ {
+ if (elementLength <= value->value.integer->maxSize)
+ {
value->value.integer->size = elementLength;
memcpy(value->value.integer->octets, buffer + bufPos, elementLength);
}
@@ -288,7 +315,8 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x87: /* Float */
- if (MmsValue_getType(value) == MMS_FLOAT) {
+ if (MmsValue_getType(value) == MMS_FLOAT)
+ {
if (elementLength == 9) {
MmsValue_setDouble(value, BerDecoder_decodeDouble(buffer, bufPos));
}
@@ -305,15 +333,19 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x89: /* octet string */
- if (MmsValue_getType(value) == MMS_OCTET_STRING) {
- if (elementLength <= abs(value->value.octetString.maxSize)) {
+ if (MmsValue_getType(value) == MMS_OCTET_STRING)
+ {
+ if (elementLength <= abs(value->value.octetString.maxSize))
+ {
value->value.octetString.size = elementLength;
memcpy(value->value.octetString.buf, buffer + bufPos, elementLength);
}
- else {
+ else
+ {
uint8_t* newBuf = (uint8_t*)GLOBAL_MALLOC(elementLength);
- if (newBuf) {
+ if (newBuf)
+ {
memcpy(newBuf, buffer + bufPos, elementLength);
uint8_t* oldBuf = value->value.octetString.buf;
@@ -324,7 +356,6 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
GLOBAL_FREEMEM(oldBuf);
}
-
}
}
else {
@@ -333,14 +364,17 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x8a: /* visible string */
- if (MmsValue_getType(value) == MMS_VISIBLE_STRING) {
-
- if (value->value.visibleString.buf != NULL) {
- if ((int32_t) value->value.visibleString.size >= elementLength) {
+ if (MmsValue_getType(value) == MMS_VISIBLE_STRING)
+ {
+ if (value->value.visibleString.buf != NULL)
+ {
+ if ((int32_t) value->value.visibleString.size >= elementLength)
+ {
memcpy(value->value.visibleString.buf, buffer + bufPos, elementLength);
value->value.visibleString.buf[elementLength] = 0;
}
- else {
+ else
+ {
GLOBAL_FREEMEM(value->value.visibleString.buf);
createNewStringFromBufferElement(value, buffer + bufPos, elementLength);
@@ -348,7 +382,6 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
}
else
createNewStringFromBufferElement(value, buffer + bufPos, elementLength);
-
}
else {
pe = GOOSE_PARSE_ERROR_TYPE_MISMATCH;
@@ -356,7 +389,8 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x8c: /* binary time */
- if (MmsValue_getType(value) == MMS_BINARY_TIME) {
+ if (MmsValue_getType(value) == MMS_BINARY_TIME)
+ {
if ((elementLength == 4) || (elementLength == 6)) {
memcpy(value->value.binaryTime.buf, buffer + bufPos, elementLength);
}
@@ -367,7 +401,8 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break;
case 0x91: /* Utctime */
- if (elementLength == 8) {
+ if (elementLength == 8)
+ {
if (MmsValue_getType(value) == MMS_UTC_TIME) {
MmsValue_setUtcTimeByBuffer(value, buffer + bufPos);
}
@@ -394,13 +429,15 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
elementIndex++;
}
- if (elementIndex <= maxIndex) {
+ if (elementIndex <= maxIndex)
+ {
if (pe == GOOSE_PARSE_ERROR_NO_ERROR) {
pe = GOOSE_PARSE_ERROR_UNDERFLOW;
}
}
- if (DEBUG_GOOSE_SUBSCRIBER) {
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ {
switch (pe) {
case GOOSE_PARSE_ERROR_UNKNOWN_TAG:
printf("GOOSE_SUBSCRIBER: Found unkown tag %02x!\n", tag);
@@ -443,11 +480,14 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
MmsValue* dataSetValues = NULL;
- while (bufPos < allDataLength) {
+ while (bufPos < allDataLength)
+ {
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);
- if (bufPos < 0) {
+
+ if (bufPos < 0)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
@@ -498,11 +538,14 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
elementIndex = 0;
bufPos = 0;
- while (bufPos < allDataLength) {
+ while (bufPos < allDataLength)
+ {
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);
- if (bufPos < 0) {
+
+ if (bufPos < 0)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
@@ -552,22 +595,26 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
case 0x84: /* BIT STRING */
{
- if (elementLength > 1) {
+ if (elementLength > 1)
+ {
int padding = buffer[bufPos];
int rawBitLength = (elementLength - 1) * 8;
- if (padding > 7) {
+ if (padding > 7)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: invalid bit-string (padding not plausible)\n");
goto exit_with_error;
}
- else {
+ else
+ {
value = MmsValue_newBitString(rawBitLength - padding);
memcpy(value->value.bitString.buf, buffer + bufPos + 1, elementLength - 1);
}
}
- else {
+ else
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: invalid bit-string\n");
@@ -577,13 +624,15 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
break;
case 0x85: /* integer */
- if (elementLength > 8) {
- if (DEBUG_GOOSE_SUBSCRIBER)
- printf("GOOSE_SUBSCRIBER: unsupported integer size(%i)\n", elementLength);
+ if (elementLength > 8)
+ {
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ printf("GOOSE_SUBSCRIBER: unsupported integer size(%i)\n", elementLength);
- goto exit_with_error;
+ goto exit_with_error;
}
- else {
+ else
+ {
value = MmsValue_newInteger(elementLength * 8);
memcpy(value->value.integer->octets, buffer + bufPos, elementLength);
value->value.integer->size = elementLength;
@@ -592,13 +641,15 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
break;
case 0x86: /* unsigned integer */
- if (elementLength > 8) {
+ if (elementLength > 8)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: unsupported unsigned size(%i)\n", elementLength);
goto exit_with_error;
}
- else {
+ else
+ {
value = MmsValue_newUnsigned(elementLength * 8);
memcpy(value->value.integer->octets, buffer + bufPos, elementLength);
value->value.integer->size = elementLength;
@@ -634,13 +685,16 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
break;
case 0x91: /* Utctime */
- if (elementLength == 8) {
+ if (elementLength == 8)
+ {
value = MmsValue_newUtcTime(0);
MmsValue_setUtcTimeByBuffer(value, buffer + bufPos);
}
else
- if (DEBUG_GOOSE_SUBSCRIBER)
- printf("GOOSE_SUBSCRIBER: UTCTime element is of wrong size!\n");
+ {
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ printf("GOOSE_SUBSCRIBER: UTCTime element is of wrong size!\n");
+ }
break;
default:
@@ -651,7 +705,8 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
bufPos += elementLength;
- if (value != NULL) {
+ if (value != NULL)
+ {
MmsValue_setElement(dataSetValues, elementIndex, value);
elementIndex++;
}
@@ -686,10 +741,12 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
uint32_t numberOfDatSetEntries = 0;
- if (buffer[bufPos++] == 0x61) {
+ if (buffer[bufPos++] == 0x61)
+ {
int gooseLength;
bufPos = BerDecoder_decodeLength(buffer, &gooseLength, bufPos, apduLength);
- if (bufPos < 0) {
+ if (bufPos < 0)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
@@ -697,12 +754,14 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
int gooseEnd = bufPos + gooseLength;
- while (bufPos < gooseEnd) {
+ while (bufPos < gooseEnd)
+ {
int elementLength;
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength);
- if (bufPos < 0) {
+ if (bufPos < 0)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
@@ -720,16 +779,19 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
{
LinkedList element = LinkedList_getNext(self->subscriberList);
- while (element != NULL) {
+ while (element)
+ {
GooseSubscriber subscriber = (GooseSubscriber) LinkedList_getData(element);
if (subscriber->isObserver)
{
- if (elementLength > 129) {
+ if (elementLength > 129)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: gocbRef too long!\n");
}
- else {
+ else
+ {
memcpy(subscriber->goCBRef, buffer + bufPos, elementLength);
subscriber->goCBRef[elementLength] = 0;
}
@@ -737,8 +799,10 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
matchingSubscriber = subscriber;
break;
}
- else if (subscriber->goCBRefLen == elementLength) {
- if (memcmp(subscriber->goCBRef, buffer + bufPos, elementLength) == 0) {
+ else if (subscriber->goCBRefLen == elementLength)
+ {
+ if (memcmp(subscriber->goCBRef, buffer + bufPos, elementLength) == 0)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: gocbRef is matching!\n");
matchingSubscriber = subscriber;
@@ -768,12 +832,15 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Found dataSet\n");
{
- if (matchingSubscriber) {
- if (elementLength > 129) {
+ if (matchingSubscriber)
+ {
+ if (elementLength > 129)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: datSet too long!\n");
}
- else {
+ else
+ {
memcpy(matchingSubscriber->datSet, buffer + bufPos, elementLength);
matchingSubscriber->datSet[elementLength] = 0;
}
@@ -785,12 +852,15 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Found goId\n");
{
- if (matchingSubscriber) {
- if (elementLength > 129) {
+ if (matchingSubscriber)
+ {
+ if (elementLength > 129)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: goId too long!\n");
}
- else {
+ else
+ {
memcpy(matchingSubscriber->goId, buffer + bufPos, elementLength);
matchingSubscriber->goId[elementLength] = 0;
}
@@ -856,15 +926,17 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
bufPos += elementLength;
}
- if (matchingSubscriber != NULL) {
-
+ if (matchingSubscriber != NULL)
+ {
matchingSubscriber->timeAllowedToLive = timeAllowedToLive;
matchingSubscriber->ndsCom = ndsCom;
matchingSubscriber->simulation = simulation;
- if (matchingSubscriber->dataSetValuesSelfAllocated) {
+ if (matchingSubscriber->dataSetValuesSelfAllocated)
+ {
/* when confRev changed replaced old data set */
- if ((matchingSubscriber->dataSetValues != NULL) && (matchingSubscriber->confRev != confRev)) {
+ if ((matchingSubscriber->dataSetValues != NULL) && (matchingSubscriber->confRev != confRev))
+ {
MmsValue_delete(matchingSubscriber->dataSetValues);
matchingSubscriber->dataSetValues = NULL;
}
@@ -874,14 +946,16 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
if (timestampBufPos)
MmsValue_setUtcTimeByBuffer(matchingSubscriber->timestamp, timestampBufPos);
- else {
+ else
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: GOOSE message has no time stamp\n");
MmsValue_setUtcTime(matchingSubscriber->timestamp, 0);
}
- if (matchingSubscriber->isObserver && matchingSubscriber->dataSetValues != NULL) {
+ if (matchingSubscriber->isObserver && matchingSubscriber->dataSetValues != NULL)
+ {
MmsValue_delete(matchingSubscriber->dataSetValues);
matchingSubscriber->dataSetValues = NULL;
}
@@ -890,7 +964,8 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
if (matchingSubscriber->dataSetValues == NULL)
matchingSubscriber->dataSetValues = parseAllDataUnknownValue(matchingSubscriber, dataSetBufferAddress, dataSetBufferLength, false);
- else {
+ else
+ {
GooseParseError parseError = parseAllData(dataSetBufferAddress, dataSetBufferLength, matchingSubscriber->dataSetValues);
if (parseError != GOOSE_PARSE_ERROR_NO_ERROR) {
@@ -900,7 +975,8 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
matchingSubscriber->parseError = parseError;
}
- if (matchingSubscriber->stNum == stNum) {
+ if (matchingSubscriber->stNum == stNum)
+ {
if (matchingSubscriber->sqNum >= sqNum) {
isValid = false;
}
@@ -944,13 +1020,18 @@ parseGooseMessage(GooseReceiver self, uint8_t* buffer, int numbytes)
uint8_t priority = 0;
uint16_t vlanId = 0;
bool vlanSet = false;
+
/* check for VLAN tag */
- if ((buffer[bufPos] == 0x81) && (buffer[bufPos + 1] == 0x00)) {
+ if ((buffer[bufPos] == 0x81) && (buffer[bufPos + 1] == 0x00))
+ {
priority = buffer[bufPos + 2] & 0xF8 >> 5;
vlanId = ((buffer[bufPos + 2] & 0x07) << 8) + buffer[bufPos + 3];
vlanSet = true;
bufPos += 4; /* skip VLAN tag */
headerLength += 4;
+
+ if (numbytes < (22 + 4))
+ return;
}
/* check for GOOSE Ethertype */
@@ -980,13 +1061,22 @@ parseGooseMessage(GooseReceiver self, uint8_t* buffer, int numbytes)
int apduLength = length - 8;
- if (numbytes < length + headerLength) {
+ if (apduLength < 0)
+ {
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ printf("GOOSE_SUBSCRIBER: Invalid length field\n");
+ return;
+ }
+
+ if (numbytes < length + headerLength)
+ {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Invalid PDU size\n");
return;
}
- if (DEBUG_GOOSE_SUBSCRIBER) {
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ {
printf("GOOSE_SUBSCRIBER: GOOSE message:\nGOOSE_SUBSCRIBER: ----------------\n");
printf("GOOSE_SUBSCRIBER: DST-MAC: %02x:%02x:%02x:%02x:%02X:%02X\n",
dstMac[0], dstMac[1], dstMac[2], dstMac[3], dstMac[4], dstMac[5]);
@@ -998,7 +1088,8 @@ parseGooseMessage(GooseReceiver self, uint8_t* buffer, int numbytes)
/* check if there is an interested subscriber */
LinkedList element = LinkedList_getNext(self->subscriberList);
- while (element != NULL) {
+ while (element)
+ {
GooseSubscriber subscriber = (GooseSubscriber) LinkedList_getData(element);
if (subscriber->isObserver)
@@ -1014,7 +1105,8 @@ parseGooseMessage(GooseReceiver self, uint8_t* buffer, int numbytes)
}
if (((subscriber->appId == -1) || (subscriber->appId == appId)) &&
- (!subscriber->dstMacSet || (memcmp(subscriber->dstMac, dstMac,6) == 0))) {
+ (!subscriber->dstMacSet || (memcmp(subscriber->dstMac, dstMac,6) == 0)))
+ {
subscriberFound = true;
break;
}
@@ -1036,41 +1128,48 @@ gooseReceiverLoop(void *threadParameter)
{
GooseReceiver self = (GooseReceiver) threadParameter;
- if (self->ethSocket) {
+ if (self->ethSocket)
+ {
EthernetHandleSet handleSet = EthernetHandleSet_new();
EthernetHandleSet_addSocket(handleSet, self->ethSocket);
- if (self->running) {
-
- while (self->running) {
- switch (EthernetHandleSet_waitReady(handleSet, 100))
- {
- case -1:
- if (DEBUG_GOOSE_SUBSCRIBER)
- printf("GOOSE_SUBSCRIBER: EhtnernetHandleSet_waitReady() failure\n");
- break;
- case 0:
- break;
- default:
- GooseReceiver_tick(self);
- }
+ bool running = true;
- if (self->stop)
- break;
+ while (running)
+ {
+ switch (EthernetHandleSet_waitReady(handleSet, 100))
+ {
+ case -1:
+ if (DEBUG_GOOSE_SUBSCRIBER)
+ printf("GOOSE_SUBSCRIBER: EhtnernetHandleSet_waitReady() failure\n");
+ break;
+ case 0:
+ break;
+ default:
+ GooseReceiver_tick(self);
}
- GooseReceiver_stopThreadless(self);
+ if (self->stop)
+ break;
+
+ running = self->running;
}
+ GooseReceiver_stopThreadless(self);
+
EthernetHandleSet_destroy(handleSet);
}
-#if (CONFIG_IEC61850_R_GOOSE == 1)
- else if (self->session) {
+#if (CONFIG_IEC61850_R_GOOSE == 0)
+ else if (self->session)
+ {
HandleSet handleSet = Handleset_new();
Handleset_addSocket(handleSet, RSession_getSocket(self->session));
- while (self->running) {
+ bool running = true;
+
+ while (running)
+ {
switch (Handleset_waitReady(handleSet, 100))
{
case -1:
@@ -1085,6 +1184,8 @@ gooseReceiverLoop(void *threadParameter)
if (self->stop)
break;
+
+ running = self->running;
}
GooseReceiver_stopThreadless(self);
@@ -1102,7 +1203,8 @@ void
GooseReceiver_start(GooseReceiver self)
{
#if (CONFIG_MMS_THREADLESS_STACK == 0)
- if (GooseReceiver_startThreadless(self)) {
+ if (GooseReceiver_startThreadless(self))
+ {
self->thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, false);
if (self->thread != NULL) {
@@ -1160,7 +1262,8 @@ GooseReceiver_stop(GooseReceiver self)
void
GooseReceiver_destroy(GooseReceiver self)
{
- if (self) {
+ if (self)
+ {
#if (CONFIG_MMS_THREADLESS_STACK == 0)
if ((self->thread != NULL) && (GooseReceiver_isRunning(self)))
GooseReceiver_stop(self);
@@ -1185,12 +1288,14 @@ GooseReceiver_startThreadless(GooseReceiver self)
{
#if (CONFIG_IEC61850_R_GOOSE == 1)
if (self->session) {
- if (RSession_start(self->session) == R_SESSION_ERROR_OK) {
+ if (RSession_start(self->session) == R_SESSION_ERROR_OK)
+ {
self->running = true;
return (EthernetSocket)1;
}
- else {
+ else
+ {
self->running = false;
return (EthernetSocket)0;
@@ -1204,7 +1309,8 @@ GooseReceiver_startThreadless(GooseReceiver self)
else
self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL);
- if (self->ethSocket != NULL) {
+ if (self->ethSocket != NULL)
+ {
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_GOOSE);
/* set multicast addresses for subscribers */
@@ -1212,14 +1318,17 @@ GooseReceiver_startThreadless(GooseReceiver self)
LinkedList element = LinkedList_getNext(self->subscriberList);
- while (element != NULL) {
+ while (element != NULL)
+ {
GooseSubscriber subscriber = (GooseSubscriber) LinkedList_getData(element);
- if (subscriber->dstMacSet == false) {
+ if (subscriber->dstMacSet == false)
+ {
/* no destination MAC address defined -> we have to switch to all multicast mode */
Ethernet_setMode(self->ethSocket, ETHERNET_SOCKET_MODE_ALL_MULTICAST);
}
- else {
+ else
+ {
Ethernet_addMulticastAddress(self->ethSocket, subscriber->dstMac);
}
@@ -1262,18 +1371,20 @@ bool
GooseReceiver_tick(GooseReceiver self)
{
#if (CONFIG_IEC61850_R_GOOSE == 1)
- if (self->session) {
+ if (self->session)
+ {
if (RSession_receiveMessage(self->session, handleSessionPayloadElement, (void*) self) == R_SESSION_ERROR_OK)
return true;
else
return false;
}
- else {
+ else
+ {
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
-
int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH);
- if (packetSize > 0) {
+ if (packetSize > 0)
+ {
parseGooseMessage(self, self->buffer, packetSize);
return true;
}
diff --git a/src/goose/goose_subscriber.c b/src/goose/goose_subscriber.c
index 64227127..019c2b7e 100644
--- a/src/goose/goose_subscriber.c
+++ b/src/goose/goose_subscriber.c
@@ -1,7 +1,7 @@
/*
* goose_subscriber.c
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -40,7 +40,8 @@ GooseSubscriber_create(char* goCbRef, MmsValue* dataSetValues)
{
GooseSubscriber self = (GooseSubscriber) GLOBAL_CALLOC(1, sizeof(struct sGooseSubscriber));
- if (self) {
+ if (self)
+ {
StringUtils_copyStringMax(self->goCBRef, 130, goCbRef);
self->goCBRefLen = strlen(goCbRef);
@@ -97,7 +98,8 @@ GooseSubscriber_setAppId(GooseSubscriber self, uint16_t appId)
void
GooseSubscriber_destroy(GooseSubscriber self)
{
- if (self) {
+ if (self)
+ {
MmsValue_delete(self->timestamp);
if (self->dataSetValuesSelfAllocated)
@@ -120,19 +122,19 @@ GooseSubscriber_getAppId(GooseSubscriber self)
return self->appId;
}
-char *
+char*
GooseSubscriber_getGoId(GooseSubscriber self)
{
return self->goId;
}
-char *
+char*
GooseSubscriber_getGoCbRef(GooseSubscriber self)
{
return self->goCBRef;
}
-char *
+char*
GooseSubscriber_getDataSet(GooseSubscriber self)
{
return self->datSet;
diff --git a/src/iec61850/client/client_report.c b/src/iec61850/client/client_report.c
index af12d26a..321532e5 100644
--- a/src/iec61850/client/client_report.c
+++ b/src/iec61850/client/client_report.c
@@ -3,7 +3,7 @@
*
* Client implementation for IEC 61850 reporting.
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -283,14 +283,27 @@ lookupReportHandler(IedConnection self, const char* rcbReference)
return NULL;
}
+static void
+uninstallReportHandler(IedConnection self, const char* rcbReference)
+{
+ ClientReport report = lookupReportHandler(self, rcbReference);
+
+ if (report != NULL) {
+ LinkedList_remove(self->enabledReports, report);
+ ClientReport_destroy(report);
+ }
+}
+
void
IedConnection_installReportHandler(IedConnection self, const char* rcbReference, const char* rptId, ReportCallbackFunction handler,
void* handlerParameter)
{
+ Semaphore_wait(self->reportHandlerMutex);
+
ClientReport report = lookupReportHandler(self, rcbReference);
if (report != NULL) {
- IedConnection_uninstallReportHandler(self, rcbReference);
+ uninstallReportHandler(self, rcbReference);
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: Removed existing report callback handler for %s\n", rcbReference);
@@ -306,8 +319,8 @@ IedConnection_installReportHandler(IedConnection self, const char* rcbReference,
else
report->rptId = NULL;
- Semaphore_wait(self->reportHandlerMutex);
LinkedList_add(self->enabledReports, report);
+
Semaphore_post(self->reportHandlerMutex);
if (DEBUG_IED_CLIENT)
@@ -319,12 +332,7 @@ IedConnection_uninstallReportHandler(IedConnection self, const char* rcbReferenc
{
Semaphore_wait(self->reportHandlerMutex);
- ClientReport report = lookupReportHandler(self, rcbReference);
-
- if (report != NULL) {
- LinkedList_remove(self->enabledReports, report);
- ClientReport_destroy(report);
- }
+ uninstallReportHandler(self, rcbReference);
Semaphore_post(self->reportHandlerMutex);
}
@@ -367,6 +375,8 @@ IedConnection_triggerGIReport(IedConnection self, IedClientError* error, const c
void
iedConnection_handleReport(IedConnection self, MmsValue* value)
{
+ Semaphore_wait(self->reportHandlerMutex);
+
MmsValue* rptIdValue = MmsValue_getElement(value, 0);
if ((rptIdValue == NULL) || (MmsValue_getType(rptIdValue) != MMS_VISIBLE_STRING)) {
@@ -769,15 +779,14 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
matchingReport->reasonForInclusion[i] = IEC61850_REASON_NOT_INCLUDED;
}
}
-
- Semaphore_wait(self->reportHandlerMutex);
if (matchingReport->callback != NULL)
matchingReport->callback(matchingReport->callbackParameter, matchingReport);
+exit_function:
+
Semaphore_post(self->reportHandlerMutex);
-exit_function:
return;
}
diff --git a/src/iec61850/client/client_report_control.c b/src/iec61850/client/client_report_control.c
index 6affd50e..65967cdb 100644
--- a/src/iec61850/client/client_report_control.c
+++ b/src/iec61850/client/client_report_control.c
@@ -528,39 +528,44 @@ readObjectHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, MmsV
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_GetRCBValuesHandler handler = (IedConnection_GetRCBValuesHandler) call->callback;
ClientReportControlBlock updateRcb = (ClientReportControlBlock) call->specificParameter;
char* rcbReference = (char*) call->specificParameter2.pointer;
-
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), NULL);
}
- else {
-
- if (value == NULL) {
+ else
+ {
+ if (value == NULL)
+ {
handler(invokeId, call->callbackParameter, IED_ERROR_OBJECT_DOES_NOT_EXIST, NULL);
}
- else {
- if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) {
+ else
+ {
+ if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
+ {
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: getRCBValues returned data-access-error!\n");
handler(invokeId, call->callbackParameter, iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)), NULL);
}
- else {
-
+ else
+ {
ClientReportControlBlock returnRcb = updateRcb;
if (returnRcb == NULL)
returnRcb = ClientReportControlBlock_create(rcbReference);
- if (clientReportControlBlock_updateValues(returnRcb, value)) {
+ if (clientReportControlBlock_updateValues(returnRcb, value))
+ {
handler(invokeId, call->callbackParameter, IED_ERROR_OK, returnRcb);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: getRCBValues returned wrong type!\n");
@@ -569,19 +574,18 @@ readObjectHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, MmsV
if (updateRcb == NULL)
ClientReportControlBlock_destroy(returnRcb);
}
-
}
MmsValue_delete(value);
}
-
}
GLOBAL_FREEMEM(rcbReference);
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -598,7 +602,8 @@ IedConnection_getRCBValuesAsync(IedConnection self, IedClientError* error, const
char* domainName = MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId);
- if (domainName == NULL) {
+ if (domainName == NULL)
+ {
*error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
return 0;
}
@@ -608,7 +613,8 @@ IedConnection_getRCBValuesAsync(IedConnection self, IedClientError* error, const
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -627,7 +633,8 @@ IedConnection_getRCBValuesAsync(IedConnection self, IedClientError* error, const
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
GLOBAL_FREEMEM(call->specificParameter2.pointer);
iedConnection_releaseOutstandingCall(self, call);
return 0;
diff --git a/src/iec61850/client/ied_connection.c b/src/iec61850/client/ied_connection.c
index d64fc595..23ccf6ff 100644
--- a/src/iec61850/client/ied_connection.c
+++ b/src/iec61850/client/ied_connection.c
@@ -1,7 +1,7 @@
/*
* ied_connection.c
*
- * Copyright 2013-2023 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -33,7 +33,6 @@
#define DEFAULT_CONNECTION_TIMEOUT 10000
#define DATA_SET_MAX_NAME_LENGTH 64 /* is 32 according to standard! */
-#define OUTSTANDING_CALLS 12
typedef struct sICLogicalDevice
{
@@ -47,12 +46,107 @@ struct sClientDataSet
MmsValue* dataSetValues; /* MmsValue instance of type MMS_ARRAY */
};
-struct sFileDirectoryEntry {
+struct sFileDirectoryEntry
+{
char* fileName;
uint32_t fileSize;
uint64_t lastModified;
};
+const char*
+IedClientError_toString(IedClientError err)
+{
+ switch (err)
+ {
+ case IED_ERROR_OK:
+ return "ok";
+
+ case IED_ERROR_NOT_CONNECTED:
+ return "not-connected";
+
+ case IED_ERROR_ALREADY_CONNECTED:
+ return "already-connected";
+
+ case IED_ERROR_CONNECTION_LOST:
+ return "connection-lost";
+
+ case IED_ERROR_SERVICE_NOT_SUPPORTED:
+ return "service-not-supported";
+
+ case IED_ERROR_CONNECTION_REJECTED:
+ return "connection-rejected";
+
+ case IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED:
+ return "outstanding-call-limit-reached";
+
+ case IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT:
+ return "invalid-argument";
+
+ case IED_ERROR_ENABLE_REPORT_FAILED_DATASET_MISMATCH:
+ return "enable-report-failed-due-to-dataset-mismatch";
+
+ case IED_ERROR_OBJECT_REFERENCE_INVALID:
+ return "object-reference-invalid";
+
+ case IED_ERROR_UNEXPECTED_VALUE_RECEIVED:
+ return "unexpected-value-received";
+
+ case IED_ERROR_TIMEOUT:
+ return "timeout";
+
+ case IED_ERROR_ACCESS_DENIED:
+ return "access-denied";
+
+ case IED_ERROR_OBJECT_DOES_NOT_EXIST:
+ return "object-does-not-exist";
+
+ case IED_ERROR_OBJECT_EXISTS:
+ return "object-exists";
+
+ case IED_ERROR_OBJECT_ACCESS_UNSUPPORTED:
+ return "object-access-unsupported";
+
+ case IED_ERROR_TYPE_INCONSISTENT:
+ return "type-inconsistent";
+
+ case IED_ERROR_TEMPORARILY_UNAVAILABLE:
+ return "temporary-unavailable";
+
+ case IED_ERROR_OBJECT_UNDEFINED:
+ return "object-undefined";
+
+ case IED_ERROR_INVALID_ADDRESS:
+ return "invalid-address";
+
+ case IED_ERROR_HARDWARE_FAULT:
+ return "hardware-fault";
+
+ case IED_ERROR_TYPE_UNSUPPORTED:
+ return "type-unsupported";
+
+ case IED_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT:
+ return "object-attribute-inconsistent";
+
+ case IED_ERROR_OBJECT_VALUE_INVALID:
+ return "object-value-invalid";
+
+ case IED_ERROR_OBJECT_INVALIDATED:
+ return "object-invalidated";
+
+ case IED_ERROR_MALFORMED_MESSAGE:
+ return "malformed-message";
+
+ case IED_ERROR_OBJECT_CONSTRAINT_CONFLICT:
+ return "object-constraint-conflict";
+
+ case IED_ERROR_SERVICE_NOT_IMPLEMENTED:
+ return "service-not-implemented";
+
+ default:
+ return "unknown-error";
+ }
+}
+
IedClientError
iedConnection_mapMmsErrorToIedError(MmsError mmsError)
{
@@ -177,8 +271,10 @@ iedConnection_allocateOutstandingCall(IedConnection self)
int i = 0;
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
- if (self->outstandingCalls[i].used == false) {
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
+ if (self->outstandingCalls[i].used == false)
+ {
self->outstandingCalls[i].used = true;
call = &(self->outstandingCalls[i]);
break;
@@ -209,8 +305,10 @@ iedConnection_lookupOutstandingCall(IedConnection self, uint32_t invokeId)
int i = 0;
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
- if ((self->outstandingCalls[i].used) && (self->outstandingCalls[i].invokeId == invokeId)) {
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
+ if ((self->outstandingCalls[i].used) && (self->outstandingCalls[i].invokeId == invokeId))
+ {
call = &(self->outstandingCalls[i]);
break;
}
@@ -618,7 +716,8 @@ createNewConnectionObject(TLSConfiguration tlsConfig, bool useThreads)
self->reportHandlerMutex = Semaphore_create(1);
self->outstandingCallsLock = Semaphore_create(1);
- self->outstandingCalls = (IedConnectionOutstandingCall) GLOBAL_CALLOC(OUTSTANDING_CALLS, sizeof(struct sIedConnectionOutstandingCall));
+ self->maxOutstandingCalled = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ self->outstandingCalls = (IedConnectionOutstandingCall) GLOBAL_CALLOC(CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED, sizeof(struct sIedConnectionOutstandingCall));
self->connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
@@ -663,6 +762,29 @@ IedConnection_setLocalAddress(IedConnection self, const char* localIpAddress, in
IsoConnectionParameters_setLocalTcpParameters(isoP, localIpAddress, localPort);
}
+void
+IedConnection_setMaxOutstandingCalls(IedConnection self, int calling, int called)
+{
+ if (calling < 1)
+ calling = 1;
+
+ if (called < 1)
+ called = 1;
+
+ if (self->outstandingCalls)
+ {
+ GLOBAL_FREEMEM(self->outstandingCalls);
+ }
+
+ self->maxOutstandingCalled = called;
+ self->outstandingCalls = (IedConnectionOutstandingCall)GLOBAL_CALLOC(called, sizeof(struct sIedConnectionOutstandingCall));
+
+ if (self->connection)
+ {
+ MmsConnnection_setMaxOutstandingCalls(self->connection, calling, called);
+ }
+}
+
void
IedConnection_setConnectTimeout(IedConnection self, uint32_t timeoutInMs)
{
@@ -672,7 +794,8 @@ IedConnection_setConnectTimeout(IedConnection self, uint32_t timeoutInMs)
void
IedConnection_setRequestTimeout(IedConnection self, uint32_t timeoutInMs)
{
- if (self->connection) {
+ if (self->connection)
+ {
MmsConnection_setRequestTimeout(self->connection, timeoutInMs);
}
}
@@ -855,7 +978,7 @@ IedConnection_destroy(IedConnection self)
GLOBAL_FREEMEM(self->outstandingCalls);
- LinkedList_destroyStatic(self->clientControls);
+ LinkedList_destroyDeep(self->clientControls, (LinkedListValueDeleteFunction)ControlObjectClient_destroy);
Semaphore_destroy(self->clientControlsLock);
Semaphore_destroy(self->outstandingCallsLock);
@@ -1027,7 +1150,8 @@ IedConnection_getServerDirectoryAsync(IedConnection self, IedClientError* error,
MmsConnection_getDomainNamesAsync(self->connection, &(call->invokeId), &err, continueAfter, result, getNameListHandler, self);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(err);
iedConnection_releaseOutstandingCall(self, call);
@@ -1059,7 +1183,8 @@ IedConnection_getLogicalDeviceVariablesAsync(IedConnection self, IedClientError*
MmsConnection_getDomainVariableNamesAsync(self->connection, &(call->invokeId), &err, ldName, continueAfter, result, getNameListHandler, self);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(err);
iedConnection_releaseOutstandingCall(self, call);
@@ -1091,7 +1216,8 @@ IedConnection_getLogicalDeviceDataSetsAsync(IedConnection self, IedClientError*
MmsConnection_getDomainVariableListNamesAsync(self->connection, &(call->invokeId), &err, ldName, continueAfter, result, getNameListHandler, self);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(err);
iedConnection_releaseOutstandingCall(self, call);
@@ -1112,15 +1238,16 @@ readObjectHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, MmsV
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_ReadObjectHandler handler = (IedConnection_ReadObjectHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), value);
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -1141,14 +1268,16 @@ IedConnection_readObjectAsync(IedConnection self, IedClientError* error, const c
domainId = MmsMapping_getMmsDomainFromObjectReference(objRef, domainIdBuffer);
itemId = MmsMapping_createMmsVariableNameFromObjectReference(objRef, fc, itemIdBuffer);
- if ((domainId == NULL) || (itemId == NULL)) {
+ if ((domainId == NULL) || (itemId == NULL))
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -1161,15 +1290,18 @@ IedConnection_readObjectAsync(IedConnection self, IedClientError* error, const c
/* check if item ID contains an array "(..)" */
char* brace = strchr(itemId, '(');
- if (brace) {
+ if (brace)
+ {
char* secondBrace = strchr(brace, ')');
- if (secondBrace) {
+ if (secondBrace)
+ {
char* endPtr;
int index = (int) strtol(brace + 1, &endPtr, 10);
- if (endPtr == secondBrace) {
+ if (endPtr == secondBrace)
+ {
char* component = NULL;
if (strlen(secondBrace + 1) > 1)
@@ -1188,8 +1320,8 @@ IedConnection_readObjectAsync(IedConnection self, IedClientError* error, const c
else
MmsConnection_readVariableAsync(self->connection, &(call->invokeId), &err, domainId, itemId, readObjectHandlerInternal, self);
- if ((err != MMS_ERROR_NONE) || (*error != IED_ERROR_OK)) {
-
+ if ((err != MMS_ERROR_NONE) || (*error != IED_ERROR_OK))
+ {
if (err != MMS_ERROR_NONE) {
*error = iedConnection_mapMmsErrorToIedError(err);
}
@@ -1202,7 +1334,6 @@ IedConnection_readObjectAsync(IedConnection self, IedClientError* error, const c
return call->invokeId;
}
-
MmsValue*
IedConnection_readObject(IedConnection self, IedClientError* error, const char* objectReference,
FunctionalConstraint fc)
@@ -1217,7 +1348,8 @@ IedConnection_readObject(IedConnection self, IedClientError* error, const char*
domainId = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainIdBuffer);
itemId = MmsMapping_createMmsVariableNameFromObjectReference(objectReference, fc, itemIdBuffer);
- if ((domainId == NULL) || (itemId == NULL)) {
+ if ((domainId == NULL) || (itemId == NULL))
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -1227,15 +1359,18 @@ IedConnection_readObject(IedConnection self, IedClientError* error, const char*
/* check if item ID contains an array "(..)" */
char* brace = strchr(itemId, '(');
- if (brace) {
+ if (brace)
+ {
char* secondBrace = strchr(brace, ')');
- if (secondBrace) {
+ if (secondBrace)
+ {
char* endPtr;
int index = (int) strtol(brace + 1, &endPtr, 10);
- if (endPtr == secondBrace) {
+ if (endPtr == secondBrace)
+ {
char* component = NULL;
if (strlen(secondBrace + 1) > 1)
@@ -1269,10 +1404,12 @@ IedConnection_readBooleanValue(IedConnection self, IedClientError* error, const
bool retVal = false;
- if (value != NULL) {
+ if (value != NULL)
+ {
if (MmsValue_getType(value) == MMS_BOOLEAN)
retVal = MmsValue_getBoolean(value);
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1292,10 +1429,12 @@ IedConnection_readFloatValue(IedConnection self, IedClientError* error, const ch
float retVal = 0.f;
- if (value != NULL) {
+ if (value != NULL)
+ {
if (MmsValue_getType(value) == MMS_FLOAT)
retVal = MmsValue_toFloat(value);
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1315,10 +1454,12 @@ IedConnection_readStringValue(IedConnection self, IedClientError* error, const c
char* retVal = NULL;
- if (value != NULL) {
+ if (value != NULL)
+ {
if ((MmsValue_getType(value) == MMS_VISIBLE_STRING) || (MmsValue_getType(value) == MMS_STRING))
retVal = StringUtils_copyString(MmsValue_toString(value));
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1338,10 +1479,12 @@ IedConnection_readInt32Value(IedConnection self, IedClientError* error, const ch
int32_t retVal = 0;
- if (value != NULL) {
+ if (value != NULL)
+ {
if ((MmsValue_getType(value) == MMS_INTEGER) || (MmsValue_getType(value) == MMS_UNSIGNED))
retVal = MmsValue_toInt32(value);
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1361,10 +1504,12 @@ IedConnection_readUnsigned32Value(IedConnection self, IedClientError* error, con
uint32_t retVal = 0;
- if (value != NULL) {
+ if (value != NULL)
+ {
if ((MmsValue_getType(value) == MMS_INTEGER) || (MmsValue_getType(value) == MMS_UNSIGNED))
retVal = MmsValue_toUint32(value);
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1384,10 +1529,12 @@ IedConnection_readInt64Value(IedConnection self, IedClientError* error, const ch
int64_t retVal = 0;
- if (value != NULL) {
+ if (value != NULL)
+ {
if ((MmsValue_getType(value) == MMS_INTEGER) || (MmsValue_getType(value) == MMS_UNSIGNED))
retVal = MmsValue_toInt64(value);
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1408,15 +1555,17 @@ IedConnection_readTimestampValue(IedConnection self, IedClientError* error, cons
Timestamp* retVal = timeStamp;
- if (value != NULL) {
- if (MmsValue_getType(value) == MMS_UTC_TIME) {
-
+ if (value != NULL)
+ {
+ if (MmsValue_getType(value) == MMS_UTC_TIME)
+ {
if (retVal == NULL)
retVal = (Timestamp*) GLOBAL_MALLOC(sizeof(Timestamp));
memcpy(retVal->val, value->value.utcTime, 8);
}
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1437,12 +1586,13 @@ IedConnection_readQualityValue(IedConnection self, IedClientError* error, const
Quality quality = QUALITY_VALIDITY_GOOD;
- if (value != NULL) {
-
+ if (value != NULL)
+ {
if ((MmsValue_getType(value) == MMS_BIT_STRING) && (MmsValue_getBitStringSize(value) == 13)) {
quality = Quality_fromMmsValue(value);
}
- else {
+ else
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR)
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value));
else
@@ -1469,7 +1619,8 @@ IedConnection_writeObject(IedConnection self, IedClientError* error, const char*
domainId = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainIdBuffer);
itemId = MmsMapping_createMmsVariableNameFromObjectReference(objectReference, fc, itemIdBuffer);
- if ((domainId == NULL) || (itemId == NULL)) {
+ if ((domainId == NULL) || (itemId == NULL))
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return;
}
@@ -1479,15 +1630,18 @@ IedConnection_writeObject(IedConnection self, IedClientError* error, const char*
/* check if item ID contains an array "(..)" */
char* brace = strchr(itemId, '(');
- if (brace) {
+ if (brace)
+ {
char* secondBrace = strchr(brace, ')');
- if (secondBrace) {
+ if (secondBrace)
+ {
char* endPtr;
int index = (int) strtol(brace + 1, &endPtr, 10);
- if (endPtr == secondBrace) {
+ if (endPtr == secondBrace)
+ {
char* component = NULL;
if (strlen(secondBrace + 1) > 1)
@@ -1505,7 +1659,8 @@ IedConnection_writeObject(IedConnection self, IedClientError* error, const char*
else
*error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
}
- else {
+ else
+ {
MmsConnection_writeVariable(self->connection, &mmsError, domainId, itemId, value);
*error = iedConnection_mapMmsErrorToIedError(mmsError);
@@ -1519,8 +1674,8 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataAc
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler) call->callback;
IedClientError iedError = iedConnection_mapMmsErrorToIedError(err);
@@ -1532,7 +1687,8 @@ writeVariableHandler(uint32_t invokeId, void* parameter, MmsError err, MmsDataAc
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -1553,14 +1709,16 @@ IedConnection_writeObjectAsync(IedConnection self, IedClientError* error, const
domainId = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainIdBuffer);
itemId = MmsMapping_createMmsVariableNameFromObjectReference(objectReference, fc, itemIdBuffer);
- if ((domainId == NULL) || (itemId == NULL)) {
+ if ((domainId == NULL) || (itemId == NULL))
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -1574,7 +1732,8 @@ IedConnection_writeObjectAsync(IedConnection self, IedClientError* error, const
/* check if item ID contains an array "(..)" */
char* brace = strchr(itemId, '(');
- if (brace) {
+ if (brace)
+ {
char* secondBrace = strchr(brace, ')');
if (secondBrace) {
@@ -1582,7 +1741,8 @@ IedConnection_writeObjectAsync(IedConnection self, IedClientError* error, const
int index = (int) strtol(brace + 1, &endPtr, 10);
- if (endPtr == secondBrace) {
+ if (endPtr == secondBrace)
+ {
char* component = NULL;
if (strlen(secondBrace + 1) > 1)
@@ -1601,13 +1761,15 @@ IedConnection_writeObjectAsync(IedConnection self, IedClientError* error, const
else
*error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
}
- else {
+ else
+ {
MmsConnection_writeVariableAsync(self->connection, &(call->invokeId), &err, domainId, itemId, value, writeVariableHandler, self);
*error = iedConnection_mapMmsErrorToIedError(err);
}
- if (*error != IED_ERROR_OK) {
+ if (*error != IED_ERROR_OK)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -1648,7 +1810,6 @@ IedConnection_writeInt32Value(IedConnection self, IedClientError* error, const c
IedConnection_writeObject(self, error, objectReference, fc, &mmsValue);
}
-
void
IedConnection_writeUnsigned32Value(IedConnection self, IedClientError* error, const char* objectReference,
FunctionalConstraint fc, uint32_t value)
@@ -1717,9 +1878,10 @@ IedConnection_getDeviceModelFromServer(IedConnection self, IedClientError* error
LinkedList logicalDeviceNames = MmsConnection_getDomainNames(self->connection, &mmsError);
- if (logicalDeviceNames != NULL) {
-
- if (self->logicalDevices != NULL) {
+ if (logicalDeviceNames)
+ {
+ if (self->logicalDevices)
+ {
LinkedList_destroyDeep(self->logicalDevices, (LinkedListValueDeleteFunction) ICLogicalDevice_destroy);
self->logicalDevices = NULL;
}
@@ -1728,20 +1890,23 @@ IedConnection_getDeviceModelFromServer(IedConnection self, IedClientError* error
LinkedList logicalDevices = LinkedList_create();
- while (logicalDevice != NULL) {
+ while (logicalDevice)
+ {
char* name = (char*) logicalDevice->data;
LinkedList variables = MmsConnection_getDomainVariableNames(self->connection,
&mmsError, name);
- if (variables != NULL) {
+ if (variables)
+ {
ICLogicalDevice* icLogicalDevice = ICLogicalDevice_create(name);
ICLogicalDevice_setVariableList(icLogicalDevice, variables);
LinkedList_add(logicalDevices, icLogicalDevice);
}
- else {
+ else
+ {
if (error)
*error = iedConnection_mapMmsErrorToIedError(mmsError);
break;
@@ -1750,10 +1915,12 @@ IedConnection_getDeviceModelFromServer(IedConnection self, IedClientError* error
logicalDevice = LinkedList_getNext(logicalDevice);
}
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
LinkedList_destroyDeep(logicalDevices, (LinkedListValueDeleteFunction) ICLogicalDevice_destroy);
}
- else {
+ else
+ {
self->logicalDevices = logicalDevices;
}
@@ -1768,19 +1935,22 @@ IedConnection_getLogicalDeviceList(IedConnection self, IedClientError* error)
{
*error = IED_ERROR_OK;
- if (self->logicalDevices == NULL) {
+ if (self->logicalDevices == NULL)
+ {
IedConnection_getDeviceModelFromServer(self, error);
if (*error != IED_ERROR_OK)
return NULL;
}
- if (self->logicalDevices != NULL) {
+ if (self->logicalDevices)
+ {
LinkedList logicalDevice = LinkedList_getNext(self->logicalDevices);
LinkedList logicalDeviceList = LinkedList_create();
- while (logicalDevice != NULL) {
+ while (logicalDevice)
+ {
ICLogicalDevice* icLogicalDevice = (ICLogicalDevice*) logicalDevice->data;
char* logicalDeviceName = StringUtils_copyString(icLogicalDevice->name);
@@ -1790,11 +1960,16 @@ IedConnection_getLogicalDeviceList(IedConnection self, IedClientError* error)
logicalDevice = LinkedList_getNext(logicalDevice);
}
- *error = IED_ERROR_OK;
+ if (error)
+ *error = IED_ERROR_OK;
+
return logicalDeviceList;
}
- else {
- *error = IED_ERROR_UNKNOWN;
+ else
+ {
+ if (error)
+ *error = IED_ERROR_UNKNOWN;
+
return NULL;
}
}
@@ -1822,19 +1997,22 @@ IedConnection_getFileDirectory(IedConnection self, IedClientError* error, const
bool moreFollows = false;
- do {
+ do
+ {
moreFollows =
MmsConnection_getFileDirectory(self->connection, &mmsError, directoryName, continueAfter,
mmsFileDirectoryHandler, fileNames);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
return NULL;
}
- if (moreFollows) {
+ if (moreFollows)
+ {
FileDirectoryEntry lastDirectoryEntry = (FileDirectoryEntry)
LinkedList_getData(LinkedList_getLastElement(fileNames));
@@ -1859,7 +2037,8 @@ IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, cons
bool moreFollowsInternal = MmsConnection_getFileDirectory(self->connection, &mmsError, directoryName, continueAfter,
mmsFileDirectoryHandler, fileNames);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
@@ -1880,9 +2059,10 @@ fileDirectoryHandlerEx(uint32_t invokeId, void* parameter, MmsError err, char* f
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
- if (call->specificParameter2.getFileDirectory.cont) {
+ if (call)
+ {
+ if (call->specificParameter2.getFileDirectory.cont)
+ {
IedConnection_FileDirectoryEntryHandler handler = (IedConnection_FileDirectoryEntryHandler) call->callback;
call->specificParameter2.getFileDirectory.cont =
@@ -1892,7 +2072,8 @@ fileDirectoryHandlerEx(uint32_t invokeId, void* parameter, MmsError err, char* f
if (filename == NULL)
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -1906,7 +2087,8 @@ IedConnection_getFileDirectoryAsyncEx(IedConnection self, IedClientError* error,
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -1920,7 +2102,8 @@ IedConnection_getFileDirectoryAsyncEx(IedConnection self, IedClientError* error,
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -1960,7 +2143,8 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil
int32_t frsmId =
MmsConnection_fileOpen(self->connection, &mmsError, fileName, 0, &fileSize, NULL);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return 0;
}
@@ -1971,17 +2155,20 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil
clientFileReadHandler.retVal = true;
clientFileReadHandler.byteReceived = 0;
- while (true) {
+ while (true)
+ {
bool moreFollows =
MmsConnection_fileRead(self->connection, &mmsError, frsmId, mmsFileReadHandler,
&clientFileReadHandler);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return 0;
}
- if (clientFileReadHandler.retVal == false) {
+ if (clientFileReadHandler.retVal == false)
+ {
*error = IED_ERROR_UNKNOWN;
break;
}
@@ -2002,7 +2189,8 @@ mmsConnectionFileCloseHandler (uint32_t invokeId, void* parameter, MmsError mmsE
{
(void)success;
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: failed to close file error: %i (mms-error: %i)\n", iedConnection_mapMmsErrorToIedError(mmsError), mmsError);
}
@@ -2011,10 +2199,12 @@ mmsConnectionFileCloseHandler (uint32_t invokeId, void* parameter, MmsError mmsE
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
+ if (call)
+ {
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -2028,46 +2218,53 @@ mmsConnectionFileReadHandler (uint32_t invokeId, void* parameter, MmsError mmsEr
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_GetFileAsyncHandler handler = (IedConnection_GetFileAsyncHandler) call->callback;
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(call->specificParameter2.getFileInfo.originalInvokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
- if (mmsError != MMS_ERROR_SERVICE_TIMEOUT) {
+ if (mmsError != MMS_ERROR_SERVICE_TIMEOUT)
+ {
/* close file */
MmsConnection_fileCloseAsync(self->connection, &(call->invokeId), &mmsError, frsmId, mmsConnectionFileCloseHandler, self);
if (mmsError != MMS_ERROR_NONE)
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: getFile timeout -> stop download\n");
iedConnection_releaseOutstandingCall(self, call);
}
}
- else {
+ else
+ {
bool cont = handler(call->specificParameter2.getFileInfo.originalInvokeId, call->callbackParameter, IED_ERROR_OK, invokeId, buffer, byteReceived, moreFollows);
- if ((moreFollows == false) || (cont == false)) {
+ if ((moreFollows == false) || (cont == false))
+ {
/* close file */
MmsConnection_fileCloseAsync(self->connection, &(call->invokeId), &mmsError, frsmId, mmsConnectionFileCloseHandler, self);
if (mmsError != MMS_ERROR_NONE)
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
/* send next read request */
MmsConnection_fileReadAsync(self->connection, &(call->invokeId), &mmsError, frsmId,
mmsConnectionFileReadHandler, self);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(invokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
@@ -2075,16 +2272,16 @@ mmsConnectionFileReadHandler (uint32_t invokeId, void* parameter, MmsError mmsEr
/* close file */
MmsConnection_fileCloseAsync(self->connection, &(call->invokeId), &mmsError, frsmId, mmsConnectionFileCloseHandler, self);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
}
-
}
}
}
-
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -2100,24 +2297,27 @@ mmsConnectionFileOpenHandler (uint32_t invokeId, void* parameter, MmsError mmsEr
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_GetFileAsyncHandler handler = (IedConnection_GetFileAsyncHandler) call->callback;
call->specificParameter2.getFileInfo.originalInvokeId = invokeId;
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(invokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
call->specificParameter2.getFileInfo.originalInvokeId = invokeId;
MmsConnection_fileReadAsync(self->connection, &(call->invokeId), &mmsError, frsmId, mmsConnectionFileReadHandler, self);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
handler(invokeId, call->callbackParameter, err, invokeId, NULL, 0, false);
@@ -2129,9 +2329,9 @@ mmsConnectionFileOpenHandler (uint32_t invokeId, void* parameter, MmsError mmsEr
iedConnection_releaseOutstandingCall(self, call);
}
}
-
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -2146,7 +2346,8 @@ IedConnection_getFileAsync(IedConnection self, IedClientError* error, const char
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -2158,7 +2359,8 @@ IedConnection_getFileAsync(IedConnection self, IedClientError* error, const char
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -2200,14 +2402,16 @@ deleteFileAndSetFileHandler (uint32_t invokeId, void* parameter, MmsError mmsErr
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
+ if (call)
+ {
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(mmsError));
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -2221,7 +2425,8 @@ IedConnection_setFileAsync(IedConnection self, IedClientError* error, const char
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -2233,7 +2438,8 @@ IedConnection_setFileAsync(IedConnection self, IedClientError* error, const char
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -2273,7 +2479,8 @@ IedConnection_deleteFileAsync(IedConnection self, IedClientError* error, const c
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -2305,15 +2512,18 @@ IedConnection_getLogicalDeviceDirectory(IedConnection self, IedClientError* erro
LinkedList logicalDevice = LinkedList_getNext(self->logicalDevices);
- while (logicalDevice != NULL) {
+ while (logicalDevice)
+ {
ICLogicalDevice* device = (ICLogicalDevice*) logicalDevice->data;
- if (strcmp(device->name, logicalDeviceName) == 0) {
+ if (strcmp(device->name, logicalDeviceName) == 0)
+ {
LinkedList logicalNodeNames = LinkedList_create();
LinkedList variable = LinkedList_getNext(device->variables);
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
if (strchr(variableName, '$') == NULL)
@@ -2338,7 +2548,8 @@ addToStringSet(LinkedList set, char* string)
{
LinkedList element = set;
- while (LinkedList_getNext(element) != NULL) {
+ while (LinkedList_getNext(element) != NULL)
+ {
if (strcmp((char*) LinkedList_getNext(element)->data, string) == 0)
return false;
@@ -2354,21 +2565,25 @@ addVariablesWithFc(char* fc, char* lnName, LinkedList variables, LinkedList lnDi
{
LinkedList variable = LinkedList_getNext(variables);
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
char* fcPos = strchr(variableName, '$');
- if (fcPos != NULL) {
+ if (fcPos != NULL)
+ {
if (memcmp(fcPos + 1, fc, 2) != 0)
goto next_element;
int lnNameLen = (int)(fcPos - variableName);
- if (strncmp(variableName, lnName, lnNameLen) == 0) {
+ if (strncmp(variableName, lnName, lnNameLen) == 0)
+ {
char* fcEndPos = strchr(fcPos + 1, '$');
- if (fcEndPos != NULL) {
+ if (fcEndPos != NULL)
+ {
char* nameEndPos = strchr(fcEndPos + 1, '$');
if (nameEndPos == NULL)
@@ -2393,7 +2608,8 @@ getLogicalNodeDirectoryLogs(IedConnection self, IedClientError* error, const cha
LinkedList journals = MmsConnection_getDomainJournals(mmsCon, &mmsError, logicalDeviceName);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return NULL;
}
@@ -2402,17 +2618,19 @@ getLogicalNodeDirectoryLogs(IedConnection self, IedClientError* error, const cha
LinkedList journal = LinkedList_getNext(journals);
- while (journal != NULL) {
-
+ while (journal)
+ {
char* journalName = (char*) LinkedList_getData(journal);
char* logName = strchr(journalName, '$');
- if (logName != NULL) {
+ if (logName)
+ {
logName[0] = 0;
logName += 1;
- if (strcmp(journalName, logicalNodeName) == 0) {
+ if (strcmp(journalName, logicalNodeName) == 0)
+ {
char* log = StringUtils_copyString(logName);
LinkedList_add(logs, (void*) log);
}
@@ -2436,7 +2654,8 @@ getLogicalNodeDirectoryDataSets(IedConnection self, IedClientError* error, const
LinkedList dataSets = MmsConnection_getDomainVariableListNames(mmsCon, &mmsError, logicalDeviceName);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return NULL;
}
@@ -2445,16 +2664,19 @@ getLogicalNodeDirectoryDataSets(IedConnection self, IedClientError* error, const
LinkedList dataSet = LinkedList_getNext(dataSets);
- while (dataSet != NULL) {
+ while (dataSet)
+ {
char* dataSetName = (char*) LinkedList_getData(dataSet);
char* lnDataSetName = strchr(dataSetName, '$');
- if (lnDataSetName != NULL) {
+ if (lnDataSetName)
+ {
lnDataSetName[0] = 0;
lnDataSetName += 1;
- if (strcmp(dataSetName, logicalNodeName) == 0) {
+ if (strcmp(dataSetName, logicalNodeName) == 0)
+ {
char* lnDataSet = StringUtils_copyString(lnDataSetName);
LinkedList_add(lnDataSets, (void*) lnDataSet);
}
@@ -2474,7 +2696,8 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
{
*error = IED_ERROR_OK;
- if (strlen(logicalNodeReference) > 129) {
+ if (strlen(logicalNodeReference) > 129)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2485,7 +2708,8 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
char* ldSep = strchr(lnRefCopy, '/');
- if (ldSep == NULL) {
+ if (ldSep == NULL)
+ {
*error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
return NULL;
}
@@ -2514,10 +2738,12 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
ICLogicalDevice* ld = NULL;
- while (device != NULL) {
+ while (device)
+ {
ICLogicalDevice* ldCandidate = (ICLogicalDevice*) device->data;
- if (strcmp(logicalDeviceName, ldCandidate->name) == 0) {
+ if (strcmp(logicalDeviceName, ldCandidate->name) == 0)
+ {
ld = ldCandidate;
break;
}
@@ -2525,25 +2751,28 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
device = LinkedList_getNext(device);
}
- if (ld == NULL) {
+ if (ld == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
LinkedList lnDirectory = LinkedList_create();
- switch (acsiClass) {
-
+ switch (acsiClass)
+ {
case ACSI_CLASS_DATA_OBJECT:
{
LinkedList variable = LinkedList_getNext(ld->variables);
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
char* fcPos = strchr(variableName, '$');
- if (fcPos != NULL) {
+ if (fcPos)
+ {
if (memcmp(fcPos + 1, "RP", 2) == 0)
goto next_element;
@@ -2555,13 +2784,16 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
int lnNameLen = (int)(fcPos - variableName);
- if (strncmp(variableName, logicalNodeName, lnNameLen) == 0) {
+ if (strncmp(variableName, logicalNodeName, lnNameLen) == 0)
+ {
char* fcEndPos = strchr(fcPos + 1, '$');
- if (fcEndPos != NULL) {
+ if (fcEndPos)
+ {
char* nameEndPos = strchr(fcEndPos + 1, '$');
- if (nameEndPos == NULL) {
+ if (nameEndPos == NULL)
+ {
char* dataObjectName = StringUtils_copyString(fcEndPos + 1);
if (!addToStringSet(lnDirectory, dataObjectName))
@@ -2582,7 +2814,8 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
{
LinkedList variable = LinkedList_getNext(ld->variables);
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
if (strcmp(variableName, "LLN0$SP$SGCB") == 0)
@@ -2625,7 +2858,8 @@ IedConnection_getLogicalNodeVariables(IedConnection self, IedClientError* error,
{
*error = IED_ERROR_OK;
- if (strlen(logicalNodeReference) > 129) {
+ if (strlen(logicalNodeReference) > 129)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2642,7 +2876,8 @@ IedConnection_getLogicalNodeVariables(IedConnection self, IedClientError* error,
char* ldSep = strchr(lnRefCopy, '/');
- if (ldSep == NULL) {
+ if (ldSep == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2659,10 +2894,12 @@ IedConnection_getLogicalNodeVariables(IedConnection self, IedClientError* error,
ICLogicalDevice* ld = NULL;
- while (device != NULL) {
+ while (device)
+ {
ICLogicalDevice* ldCandidate = (ICLogicalDevice*) device->data;
- if (strcmp(logicalDeviceName, ldCandidate->name) == 0) {
+ if (strcmp(logicalDeviceName, ldCandidate->name) == 0)
+ {
ld = ldCandidate;
break;
}
@@ -2670,7 +2907,8 @@ IedConnection_getLogicalNodeVariables(IedConnection self, IedClientError* error,
device = LinkedList_getNext(device);
}
- if (ld == NULL) {
+ if (ld == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2682,15 +2920,18 @@ IedConnection_getLogicalNodeVariables(IedConnection self, IedClientError* error,
LinkedList lnDirectory = LinkedList_create();
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
char* fcPos = strchr(variableName, '$');
- if (fcPos != NULL) {
+ if (fcPos)
+ {
int lnNameLen = (int)(fcPos - variableName);
- if (strncmp(variableName, logicalNodeName, lnNameLen) == 0) {
+ if (strncmp(variableName, logicalNodeName, lnNameLen) == 0)
+ {
LinkedList_add(lnDirectory, StringUtils_copyString(fcPos + 1));
}
}
@@ -2708,7 +2949,8 @@ getDataDirectory(IedConnection self, IedClientError* error,
{
*error = IED_ERROR_OK;
- if (strlen(dataReference) > 129) {
+ if (strlen(dataReference) > 129)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2733,7 +2975,8 @@ getDataDirectory(IedConnection self, IedClientError* error,
char* logicalNodeNameEnd = strchr(logicalNodeName, '.');
- if (logicalNodeNameEnd == NULL) {
+ if (logicalNodeNameEnd == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2744,7 +2987,8 @@ getDataDirectory(IedConnection self, IedClientError* error,
int dataNamePartLen = (int)strlen(dataNamePart);
- if (dataNamePartLen < 1) {
+ if (dataNamePartLen < 1)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2757,10 +3001,12 @@ getDataDirectory(IedConnection self, IedClientError* error,
ICLogicalDevice* ld = NULL;
- while (device != NULL) {
+ while (device)
+ {
ICLogicalDevice* ldCandidate = (ICLogicalDevice*) device->data;
- if (strcmp(logicalDeviceName, ldCandidate->name) == 0) {
+ if (strcmp(logicalDeviceName, ldCandidate->name) == 0)
+ {
ld = ldCandidate;
break;
}
@@ -2768,7 +3014,8 @@ getDataDirectory(IedConnection self, IedClientError* error,
device = LinkedList_getNext(device);
}
- if (ld == NULL) {
+ if (ld == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2777,18 +3024,20 @@ getDataDirectory(IedConnection self, IedClientError* error,
LinkedList dataDirectory = LinkedList_create();
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
char* fcPos = strchr(variableName, '$');
- if (fcPos != NULL) {
+ if (fcPos)
+ {
int lnNameLen = (int)(fcPos - variableName);
- if (logicalNodeNameLen == lnNameLen) {
-
- if (memcmp(variableName, logicalNodeName, lnNameLen) == 0) {
-
+ if (logicalNodeNameLen == lnNameLen)
+ {
+ if (memcmp(variableName, logicalNodeName, lnNameLen) == 0)
+ {
/* ok we are in the correct logical node */
/* skip FC */
@@ -2804,10 +3053,10 @@ getDataDirectory(IedConnection self, IedClientError* error,
if (remainingLen <= dataNamePartLen)
goto next_variable;
- if (remainingPart[dataNamePartLen] == '$') {
-
- if (memcmp(dataNamePart, remainingPart, dataNamePartLen) == 0) {
-
+ if (remainingPart[dataNamePartLen] == '$')
+ {
+ if (memcmp(dataNamePart, remainingPart, dataNamePartLen) == 0)
+ {
char* subElementName = remainingPart + dataNamePartLen + 1;
char* subElementNameSep = strchr(subElementName, '$');
@@ -2817,7 +3066,8 @@ getDataDirectory(IedConnection self, IedClientError* error,
char* elementName;
- if (withFc) {
+ if (withFc)
+ {
int elementNameLen = (int)strlen(subElementName);
elementName = (char*) GLOBAL_MALLOC(elementNameLen + 5);
@@ -2846,7 +3096,6 @@ getDataDirectory(IedConnection self, IedClientError* error,
*error = IED_ERROR_OK;
return dataDirectory;
-
}
LinkedList
@@ -2867,14 +3116,16 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
{
*error = IED_ERROR_OK;
- if (strlen(dataReference) > 129) {
+ if (strlen(dataReference) > 129)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
char* fcString = FunctionalConstraint_toString(fc);
- if (fcString == NULL) {
+ if (fcString == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2899,7 +3150,8 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
char* logicalNodeNameEnd = strchr(logicalNodeName, '.');
- if (logicalNodeNameEnd == NULL) {
+ if (logicalNodeNameEnd == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2910,7 +3162,8 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
int dataNamePartLen = (int)strlen(dataNamePart);
- if (dataNamePartLen < 1) {
+ if (dataNamePartLen < 1)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2923,10 +3176,12 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
ICLogicalDevice* ld = NULL;
- while (device != NULL) {
+ while (device)
+ {
ICLogicalDevice* ldCandidate = (ICLogicalDevice*) device->data;
- if (strcmp(logicalDeviceName, ldCandidate->name) == 0) {
+ if (strcmp(logicalDeviceName, ldCandidate->name) == 0)
+ {
ld = ldCandidate;
break;
}
@@ -2934,7 +3189,8 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
device = LinkedList_getNext(device);
}
- if (ld == NULL) {
+ if (ld == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -2943,18 +3199,20 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
LinkedList dataDirectory = LinkedList_create();
- while (variable != NULL) {
+ while (variable)
+ {
char* variableName = (char*) variable->data;
char* fcPos = strchr(variableName, '$');
- if (fcPos != NULL) {
+ if (fcPos)
+ {
int lnNameLen = (int)(fcPos - variableName);
- if (logicalNodeNameLen == lnNameLen) {
-
- if (memcmp(variableName, logicalNodeName, lnNameLen) == 0) {
-
+ if (logicalNodeNameLen == lnNameLen)
+ {
+ if (memcmp(variableName, logicalNodeName, lnNameLen) == 0)
+ {
/* ok we are in the correct logical node */
/* skip FC */
@@ -2973,10 +3231,10 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
if (remainingLen <= dataNamePartLen)
goto next_variable;
- if (remainingPart[dataNamePartLen] == '$') {
-
- if (memcmp(dataNamePart, remainingPart, dataNamePartLen) == 0) {
-
+ if (remainingPart[dataNamePartLen] == '$')
+ {
+ if (memcmp(dataNamePart, remainingPart, dataNamePartLen) == 0)
+ {
char* subElementName = remainingPart + dataNamePartLen + 1;
char* subElementNameSep = strchr(subElementName, '$');
@@ -3005,7 +3263,6 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
*error = IED_ERROR_OK;
return dataDirectory;
-
}
@@ -3026,9 +3283,10 @@ IedConnection_createDataSet(IedConnection self, IedClientError* error, const cha
const char* itemId;
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
-
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3036,17 +3294,20 @@ IedConnection_createDataSet(IedConnection self, IedClientError* error, const cha
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
int domainIdLength = (int)strlen(domainId);
- if ((strlen(dataSetReference) - domainIdLength - 1) > 32) {
+ if ((strlen(dataSetReference) - domainIdLength - 1) > 32)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3056,7 +3317,8 @@ IedConnection_createDataSet(IedConnection self, IedClientError* error, const cha
itemId = itemIdRef;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
@@ -3067,12 +3329,13 @@ IedConnection_createDataSet(IedConnection self, IedClientError* error, const cha
LinkedList dataSetElement = LinkedList_getNext(dataSetElements);
- while (dataSetElement != NULL) {
-
+ while (dataSetElement)
+ {
MmsVariableAccessSpecification* dataSetEntry =
MmsMapping_ObjectReferenceToVariableAccessSpec((char*) dataSetElement->data);
- if (dataSetEntry == NULL) {
+ if (dataSetEntry == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto cleanup_list;
}
@@ -3110,8 +3373,10 @@ IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const cha
int dataSetReferenceLength = (int)strlen(dataSetReference);
- if (dataSetReference[0] != '@') {
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3119,16 +3384,18 @@ IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const cha
else
StringUtils_copyStringMax(itemId, DATA_SET_MAX_NAME_LENGTH + 1, dataSetReference);
}
- else {
-
- if (MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainId) == NULL) {
+ else
+ {
+ if (MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainId) == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
const char* itemIdString = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdString) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdString) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3138,8 +3405,10 @@ IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const cha
StringUtils_replace(itemId, '.', '$');
}
}
- else {
- if (dataSetReferenceLength > 33) {
+ else
+ {
+ if (dataSetReferenceLength > 33)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3169,13 +3438,14 @@ deleteNamedVariableListHandler(uint32_t invokeId, void* parameter, MmsError mmsE
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler)call->callback;
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
- if (err == IED_ERROR_OK) {
+ if (err == IED_ERROR_OK)
+ {
if (success == false)
err = IED_ERROR_ACCESS_DENIED;
}
@@ -3184,7 +3454,8 @@ deleteNamedVariableListHandler(uint32_t invokeId, void* parameter, MmsError mmsE
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -3203,9 +3474,10 @@ IedConnection_deleteDataSetAsync(IedConnection self, IedClientError* error, cons
int dataSetReferenceLength = (int)strlen(dataSetReference);
- if (dataSetReference[0] != '@') {
- if ((dataSetReference[0] == '/')
- || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3213,17 +3485,18 @@ IedConnection_deleteDataSetAsync(IedConnection self, IedClientError* error, cons
else
StringUtils_copyStringMax(itemId, DATA_SET_MAX_NAME_LENGTH + 1, dataSetReference);
}
- else {
-
- if (MmsMapping_getMmsDomainFromObjectReference(dataSetReference,
- domainId) == NULL) {
+ else
+ {
+ if (MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainId) == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
const char *itemIdString = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdString) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdString) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
@@ -3233,8 +3506,10 @@ IedConnection_deleteDataSetAsync(IedConnection self, IedClientError* error, cons
StringUtils_replace(itemId, '.', '$');
}
}
- else {
- if (dataSetReferenceLength > 33) {
+ else
+ {
+ if (dataSetReferenceLength > 33)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
@@ -3246,7 +3521,8 @@ IedConnection_deleteDataSetAsync(IedConnection self, IedClientError* error, cons
MmsError mmsError;
- if ((domainId == NULL) || (itemId[0] == 0)) {
+ if ((domainId == NULL) || (itemId[0] == 0))
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
@@ -3262,14 +3538,17 @@ IedConnection_deleteDataSetAsync(IedConnection self, IedClientError* error, cons
call->callbackParameter = parameter;
call->invokeId = 0;
- if (isAssociationSpecific) {
+ if (isAssociationSpecific)
+ {
MmsConnection_deleteAssociationSpecificNamedVariableListAsync(self->connection, &(call->invokeId), &mmsError, itemId, deleteNamedVariableListHandler, self);
}
- else {
+ else
+ {
MmsConnection_deleteNamedVariableListAsync(self->connection, &(call->invokeId), &mmsError, domainId, itemId, deleteNamedVariableListHandler, self);
}
- if (*error != IED_ERROR_OK) {
+ if (*error != IED_ERROR_OK)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -3284,13 +3563,14 @@ createDataSetAsyncHandler(uint32_t invokeId, void* parameter, MmsError mmsError,
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_GenericServiceHandler handler = (IedConnection_GenericServiceHandler)call->callback;
IedClientError err = iedConnection_mapMmsErrorToIedError(mmsError);
- if (err == IED_ERROR_OK) {
+ if (err == IED_ERROR_OK)
+ {
if (success == false)
err = IED_ERROR_ACCESS_DENIED;
}
@@ -3299,7 +3579,8 @@ createDataSetAsyncHandler(uint32_t invokeId, void* parameter, MmsError mmsError,
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -3313,9 +3594,10 @@ IedConnection_createDataSetAsync(IedConnection self, IedClientError* error, cons
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
- goto exit_function;
+ goto exit_function;
}
call->callback = handler;
@@ -3329,9 +3611,10 @@ IedConnection_createDataSetAsync(IedConnection self, IedClientError* error, cons
const char* itemId;
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
-
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3339,17 +3622,20 @@ IedConnection_createDataSetAsync(IedConnection self, IedClientError* error, cons
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
int domainIdLength = (int)strlen(domainId);
- if ((strlen(dataSetReference) - domainIdLength - 1) > 32) {
+ if ((strlen(dataSetReference) - domainIdLength - 1) > 32)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3359,7 +3645,8 @@ IedConnection_createDataSetAsync(IedConnection self, IedClientError* error, cons
itemId = itemIdRef;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
@@ -3368,12 +3655,13 @@ IedConnection_createDataSetAsync(IedConnection self, IedClientError* error, cons
LinkedList dataSetElement = LinkedList_getNext(dataSetElements);
- while (dataSetElement != NULL) {
-
+ while (dataSetElement)
+ {
MmsVariableAccessSpecification* dataSetEntry =
MmsMapping_ObjectReferenceToVariableAccessSpec((char*) dataSetElement->data);
- if (dataSetEntry == NULL) {
+ if (dataSetEntry == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto cleanup_list;
}
@@ -3383,11 +3671,13 @@ IedConnection_createDataSetAsync(IedConnection self, IedClientError* error, cons
dataSetElement = LinkedList_getNext(dataSetElement);
}
- if (isAssociationSpecific) {
+ if (isAssociationSpecific)
+ {
MmsConnection_defineNamedVariableListAssociationSpecificAsync(self->connection, &(call->invokeId),
&mmsError, itemId, dataSetEntries, createDataSetAsyncHandler, self);
}
- else {
+ else
+ {
MmsConnection_defineNamedVariableListAsync(self->connection, &(call->invokeId),
&mmsError, domainId, itemId, dataSetEntries, createDataSetAsyncHandler, self);
}
@@ -3400,8 +3690,10 @@ cleanup_list:
exit_function:
- if (*error != IED_ERROR_OK) {
- iedConnection_releaseOutstandingCall(self, call);
+ if (*error != IED_ERROR_OK)
+ {
+ if (call)
+ iedConnection_releaseOutstandingCall(self, call);
return 0;
}
@@ -3425,8 +3717,10 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3434,17 +3728,20 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
const char* itemIdRef = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdRef) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdRef) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3454,7 +3751,8 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
itemId = itemIdRefInBuffer;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
@@ -3470,13 +3768,14 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
entries = MmsConnection_readNamedVariableListDirectory(self->connection,
&mmsError, domainId, itemId, &deletable);
- if (mmsError == MMS_ERROR_NONE) {
-
+ if (mmsError == MMS_ERROR_NONE)
+ {
LinkedList entry = LinkedList_getNext(entries);
dataSetMembers = LinkedList_create();
- while (entry) {
+ while (entry)
+ {
MmsVariableAccessSpecification* varAccessSpec = (MmsVariableAccessSpecification*)LinkedList_getData(entry);
char* objectReference = MmsMapping_varAccessSpecToObjectReference(varAccessSpec);
@@ -3507,17 +3806,20 @@ getDataSetDirectoryAsyncHandler(uint32_t invokeId, void* parameter, MmsError mms
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
+ if (call)
+ {
LinkedList dataSetMembers = NULL;
if (mmsError != MMS_ERROR_NONE)
err = iedConnection_mapMmsErrorToIedError(mmsError);
- if (specs) {
+ if (specs)
+ {
dataSetMembers = LinkedList_create();
LinkedList specElem = LinkedList_getNext(specs);
- while (specElem) {
+ while (specElem)
+ {
MmsVariableAccessSpecification* varAccessSpec = (MmsVariableAccessSpecification*)LinkedList_getData(specElem);
char* objectReference = MmsMapping_varAccessSpecToObjectReference(varAccessSpec);
@@ -3548,7 +3850,8 @@ IedConnection_getDataSetDirectoryAsync(IedConnection self, IedClientError* error
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -3565,8 +3868,10 @@ IedConnection_getDataSetDirectoryAsync(IedConnection self, IedClientError* error
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3574,17 +3879,20 @@ IedConnection_getDataSetDirectoryAsync(IedConnection self, IedClientError* error
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
const char* itemIdRef = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdRef) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdRef) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3594,7 +3902,8 @@ IedConnection_getDataSetDirectoryAsync(IedConnection self, IedClientError* error
itemId = itemIdRefInBuffer;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
@@ -3609,12 +3918,14 @@ IedConnection_getDataSetDirectoryAsync(IedConnection self, IedClientError* error
exit_function:
- if (*error != IED_ERROR_OK) {
+ if (*error != IED_ERROR_OK)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
- else {
+ else
+ {
return call->invokeId;
}
}
@@ -3631,9 +3942,10 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
-
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3641,17 +3953,20 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3662,7 +3977,8 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
itemId = itemIdRef;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
@@ -3678,18 +3994,21 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
dataSetVal = MmsConnection_readNamedVariableListValues(self->connection, &mmsError,
domainId, itemId, true);
- if (dataSetVal == NULL) {
+ if (dataSetVal == NULL)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
goto exit_function;
}
else
*error = IED_ERROR_OK;
- if (dataSet == NULL) {
+ if (dataSet == NULL)
+ {
dataSet = ClientDataSet_create(dataSetReference);
ClientDataSet_setDataSetValues(dataSet, dataSetVal);
}
- else {
+ else
+ {
MmsValue* dataSetValues = ClientDataSet_getValues(dataSet);
MmsValue_update(dataSetValues, dataSetVal);
MmsValue_delete(dataSetVal);
@@ -3706,32 +4025,38 @@ getDataSetHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, MmsV
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_ReadDataSetHandler handler = (IedConnection_ReadDataSetHandler) call->callback;
ClientDataSet dataSet = (ClientDataSet) call->specificParameter;
char* dataSetReference = (char*) call->specificParameter2.pointer;
- if (value != NULL) {
-
- if (dataSet == NULL) {
+ if (value)
+ {
+ if (dataSet == NULL)
+ {
dataSet = ClientDataSet_create(dataSetReference);
- ClientDataSet_setDataSetValues(dataSet, value);
- GLOBAL_FREEMEM(dataSetReference);
+ ClientDataSet_setDataSetValues(dataSet, MmsValue_clone(value));
}
- else {
+ else
+ {
MmsValue* dataSetValues = ClientDataSet_getValues(dataSet);
MmsValue_update(dataSetValues, value);
- MmsValue_delete(value);
}
+
+ MmsValue_delete(value);
}
+ if (dataSetReference)
+ GLOBAL_FREEMEM(dataSetReference);
+
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), dataSet);
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -3749,9 +4074,10 @@ IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error,
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
-
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3759,17 +4085,20 @@ IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error,
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
@@ -3780,14 +4109,16 @@ IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error,
itemId = itemIdRef;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -3812,8 +4143,8 @@ IedConnection_readDataSetValuesAsync(IedConnection self, IedClientError* error,
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
-
+ if (err != MMS_ERROR_NONE)
+ {
GLOBAL_FREEMEM(call->specificParameter2.pointer);
iedConnection_releaseOutstandingCall(self, call);
@@ -3836,9 +4167,10 @@ IedConnection_writeDataSetValues(IedConnection self, IedClientError* error, cons
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
-
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3846,17 +4178,20 @@ IedConnection_writeDataSetValues(IedConnection self, IedClientError* error, cons
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
}
@@ -3867,7 +4202,8 @@ IedConnection_writeDataSetValues(IedConnection self, IedClientError* error, cons
itemId = itemIdRef;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
@@ -3889,15 +4225,16 @@ writeDataSetHandlerInternal(uint32_t invokeId, void* parameter, MmsError err, Li
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_WriteDataSetHandler handler = (IedConnection_WriteDataSetHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), accessResults);
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -3915,9 +4252,10 @@ IedConnection_writeDataSetValuesAsync(IedConnection self, IedClientError* error,
bool isAssociationSpecific = false;
- if (dataSetReference[0] != '@') {
-
- if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ if (dataSetReference[0] != '@')
+ {
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL))
+ {
domainId = NULL;
if (dataSetReference[0] == '/')
@@ -3925,17 +4263,20 @@ IedConnection_writeDataSetValuesAsync(IedConnection self, IedClientError* error,
else
itemId = dataSetReference;
}
- else {
+ else
+ {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
- if (domainId == NULL) {
+ if (domainId == NULL)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
- if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
+ if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH)
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
@@ -3946,14 +4287,16 @@ IedConnection_writeDataSetValuesAsync(IedConnection self, IedClientError* error,
itemId = itemIdRef;
}
}
- else {
+ else
+ {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
}
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -3967,7 +4310,8 @@ IedConnection_writeDataSetValuesAsync(IedConnection self, IedClientError* error,
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
@@ -3989,8 +4333,8 @@ IedConnection_queryLogByTime(IedConnection self, IedClientError* error, const ch
char* logDomain = logRef;
char* logName = strchr(logRef, '/');
- if (logName != NULL) {
-
+ if (logName)
+ {
logName[0] = 0;
logName++;
@@ -4006,18 +4350,19 @@ IedConnection_queryLogByTime(IedConnection self, IedClientError* error, const ch
MmsValue_delete(startTimeMms);
MmsValue_delete(endTimeMms);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return NULL;
}
else
return journalEntries;
}
- else {
+ else
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
-
}
static void
@@ -4027,15 +4372,16 @@ readJournalHandler(uint32_t invokeId, void* parameter, MmsError err, LinkedList
IedConnectionOutstandingCall call = iedConnection_lookupOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
IedConnection_QueryLogHandler handler = (IedConnection_QueryLogHandler) call->callback;
handler(invokeId, call->callbackParameter, iedConnection_mapMmsErrorToIedError(err), journalEntries, moreFollows);
iedConnection_releaseOutstandingCall(self, call);
}
- else {
+ else
+ {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: internal error - no matching outstanding call!\n");
}
@@ -4052,14 +4398,15 @@ IedConnection_queryLogByTimeAsync(IedConnection self, IedClientError* error, con
char* logDomain = logRef;
char* logName = strchr(logRef, '/');
- if (logName != NULL) {
-
+ if (logName != NULL)
+ {
logName[0] = 0;
logName++;
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -4083,18 +4430,19 @@ IedConnection_queryLogByTimeAsync(IedConnection self, IedClientError* error, con
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
return call->invokeId;
}
- else {
+ else
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
-
}
uint32_t
@@ -4108,14 +4456,15 @@ IedConnection_queryLogAfterAsync(IedConnection self, IedClientError* error, cons
char* logDomain = logRef;
char* logName = strchr(logRef, '/');
- if (logName != NULL) {
-
+ if (logName)
+ {
logName[0] = 0;
logName++;
IedConnectionOutstandingCall call = iedConnection_allocateOutstandingCall(self);
- if (call == NULL) {
+ if (call == NULL)
+ {
*error = IED_ERROR_OUTSTANDING_CALL_LIMIT_REACHED;
return 0;
}
@@ -4135,14 +4484,16 @@ IedConnection_queryLogAfterAsync(IedConnection self, IedClientError* error, cons
*error = iedConnection_mapMmsErrorToIedError(err);
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
iedConnection_releaseOutstandingCall(self, call);
return 0;
}
return call->invokeId;
}
- else {
+ else
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return 0;
}
@@ -4161,8 +4512,8 @@ IedConnection_queryLogAfter(IedConnection self, IedClientError* error, const cha
char* logDomain = logRef;
char* logName = strchr(logRef, '/');
- if (logName != NULL) {
-
+ if (logName)
+ {
logName[0] = 0;
logName++;
@@ -4174,14 +4525,16 @@ IedConnection_queryLogAfter(IedConnection self, IedClientError* error, const cha
MmsValue_delete(timeStampMms);
- if (mmsError != MMS_ERROR_NONE) {
+ if (mmsError != MMS_ERROR_NONE)
+ {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return NULL;
}
else
return journalEntries;
}
- else {
+ else
+ {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
return NULL;
}
@@ -4255,4 +4608,3 @@ FileDirectoryEntry_getLastModified(FileDirectoryEntry self)
{
return self->lastModified;
}
-
diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h
index 5e53efe2..5946bd00 100644
--- a/src/iec61850/inc/iec61850_client.h
+++ b/src/iec61850/inc/iec61850_client.h
@@ -1,7 +1,7 @@
/*
* iec61850_client.h
*
- * Copyright 2013-2021 Michael Zillgith
+ * Copyright 2013-2023 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -172,6 +172,14 @@ typedef enum {
IED_ERROR_UNKNOWN = 99
} IedClientError;
+/**
+ * \brief Convert error value to string
+ *
+ * \return string constant representing the error
+ */
+LIB61850_API const char*
+IedClientError_toString(IedClientError err);
+
/**************************************************
* Connection creation and destruction
**************************************************/
@@ -258,6 +266,16 @@ IedConnection_setLocalAddress(IedConnection self, const char* localIpAddress, in
LIB61850_API void
IedConnection_setConnectTimeout(IedConnection self, uint32_t timeoutInMs);
+/**
+ * \brief Set the maximum number outstanding calls allowed for this connection
+ *
+ * \param self the connection object
+ * \param calling the maximum outstanding calls allowed by the caller (client)
+ * \param called the maximum outstanding calls allowed by the called endpoint (server)
+ */
+LIB61850_API void
+IedConnection_setMaxOutstandingCalls(IedConnection self, int calling, int called);
+
/**
* \brief set the request timeout in ms
*
@@ -1154,15 +1172,6 @@ typedef int ReasonForInclusion;
/** the reason for inclusion is unknown (e.g. report is not configured to include reason-for-inclusion) */
#define IEC61850_REASON_UNKNOWN 32
-#define REASON_NOT_INCLUDED IEC61850_REASON_NOT_INCLUDED
-#define REASON_DATA_CHANGE IEC61850_REASON_DATA_CHANGE
-#define REASON_QUALITY_CHANGE IEC61850_REASON_QUALITY_CHANGE
-#define REASON_DATA_UPDATE IEC61850_REASON_DATA_UPDATE
-#define REASON_INTEGRITY IEC61850_REASON_INTEGRITY
-#define REASON_GI IEC61850_REASON_GI
-#define REASON_UNKNOWN IEC61850_REASON_UNKNOWN
-
-
/* Element encoding mask values for ClientReportControlBlock */
/** include the report ID into the setRCB request */
@@ -1259,9 +1268,11 @@ typedef void (*ReportCallbackFunction) (void* parameter, ClientReport report);
* Otherwise the internal data structures storing the received data set values will not be updated
* correctly.
*
- * When replacing a report handler you only have to call this function. There is no separate call to
+ * \note Replacing a report handler you only have to call this function. There is no separate call to
* IedConnection_uninstallReportHandler() required.
*
+ * \note Do not call this function inside of the ReportCallbackFunction. Doing so will cause a deadlock.
+ *
* \param self the connection object
* \param rcbReference object reference of the report control block
* \param rptId a string that identifies the report. If the rptId is not available then the
@@ -1276,6 +1287,8 @@ IedConnection_installReportHandler(IedConnection self, const char* rcbReference,
/**
* \brief uninstall a report handler function for the specified report control block (RCB)
*
+ * \note Do not call this function inside of the ReportCallbackFunction. Doing so will cause a deadlock.
+ *
* \param self the connection object
* \param rcbReference object reference of the report control block
*/
diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h
index b14bb6cb..6dc69524 100644
--- a/src/iec61850/inc/iec61850_server.h
+++ b/src/iec61850/inc/iec61850_server.h
@@ -3,7 +3,7 @@
*
* IEC 61850 server API for libiec61850.
*
- * Copyright 2013-2023 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -815,7 +815,9 @@ LIB61850_API void
IedServer_setConnectionIndicationHandler(IedServer self, IedConnectionIndicationHandler handler, void* parameter);
/**
- * \brief Ignore all requests from clients
+ * \brief Ignore all requests from clients (for testing purposes)
+ *
+ * NOTE: This function will block all client requests on MMS layer
*
* \param self the instance of IedServer to configure.
* \param enable when true all requests from clients will be ignored
@@ -1447,7 +1449,7 @@ LIB61850_API DataObject*
ControlAction_getControlObject(ControlAction self);
/**
- * \brief Gets the time of the control, if it's a timeActivatedControl, returns 0, if it's not.
+ * \brief Gets the time of the control (attribute "operTm"), if it's a timeActivatedControl, returns 0, if it's not.
*
* \param self the control action instance
*
@@ -1456,6 +1458,16 @@ ControlAction_getControlObject(ControlAction self);
LIB61850_API uint64_t
ControlAction_getControlTime(ControlAction self);
+/**
+ * \brief Gets the time (attribute "T") of the last received control action (Oper or Select)
+ *
+ * \param self the control action instance
+ *
+ * \return the time of the last received control action
+ */
+LIB61850_API Timestamp*
+ControlAction_getT(ControlAction self);
+
/**
* \brief Control model callback to perform the static tests (optional).
*
@@ -1845,6 +1857,19 @@ LIB61850_API void
IedServer_handleWriteAccessForComplexAttribute(IedServer self, DataAttribute* dataAttribute,
WriteAccessHandler handler, void* parameter);
+/**
+ * \brief Install a WriteAccessHandler for all data attributes of a data object with a specific FC
+ *
+ * \param self the instance of IedServer to operate on.
+ * \param dataObject the data object to monitor
+ * \param fc the functional constraint to monitor
+ * \param handler the callback function that is invoked if a client tries to write to
+ * the monitored data attribute.
+ * \param parameter a user provided parameter that is passed to the WriteAccessHandler when called.
+*/
+LIB61850_API void
+IedServer_handleWriteAccessForDataObject(IedServer self, DataObject* dataObject, FunctionalConstraint fc, WriteAccessHandler handler, void* parameter);
+
typedef enum {
ACCESS_POLICY_ALLOW,
ACCESS_POLICY_DENY
@@ -1997,6 +2022,15 @@ typedef bool
LIB61850_API void
IedServer_setControlBlockAccessHandler(IedServer self, IedServer_ControlBlockAccessHandler handler, void* parameter);
+/**
+ * \brief Temporarily ignore read requests (for testing purposes)
+ *
+ * \param self the instance of IedServer to operate on.
+ * \param ignore true to ignore read requests, false to handle read requests.
+*/
+LIB61850_API void
+IedServer_ignoreReadAccess(IedServer self, bool ignore);
+
/**@}*/
/**@}*/
diff --git a/src/iec61850/inc_private/control.h b/src/iec61850/inc_private/control.h
index 66cb6706..adf56731 100644
--- a/src/iec61850/inc_private/control.h
+++ b/src/iec61850/inc_private/control.h
@@ -1,7 +1,7 @@
/*
* control.h
*
- * Copyright 2013-2019 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -90,6 +90,8 @@ struct sControlObject
MmsValue* origin;
MmsValue* timestamp;
+ Timestamp T;
+
MmsValue* ctlNumSt;
MmsValue* originSt;
diff --git a/src/iec61850/inc_private/ied_connection_private.h b/src/iec61850/inc_private/ied_connection_private.h
index e571ca8e..52467747 100644
--- a/src/iec61850/inc_private/ied_connection_private.h
+++ b/src/iec61850/inc_private/ied_connection_private.h
@@ -1,7 +1,7 @@
/*
* ied_connection_private.h
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -34,14 +34,16 @@
typedef struct sIedConnectionOutstandingCall* IedConnectionOutstandingCall;
-struct sIedConnectionOutstandingCall {
+struct sIedConnectionOutstandingCall
+{
bool used;
uint32_t invokeId;
void* callback;
void* callbackParameter;
void* specificParameter; /* function/service specific parameter */
- union {
+ union
+ {
void* pointer;
struct {
uint32_t originalInvokeId;
@@ -69,6 +71,7 @@ struct sIedConnection
Semaphore outstandingCallsLock;
IedConnectionOutstandingCall outstandingCalls;
+ int maxOutstandingCalled;
IedConnectionClosedHandler connectionCloseHandler;
void* connectionClosedParameter;
@@ -81,7 +84,8 @@ struct sIedConnection
uint8_t timeQuality;
};
-struct sClientReportControlBlock {
+struct sClientReportControlBlock
+{
char* objectReference;
bool isBuffered;
diff --git a/src/iec61850/inc_private/ied_server_private.h b/src/iec61850/inc_private/ied_server_private.h
index d5555659..8dc5fede 100644
--- a/src/iec61850/inc_private/ied_server_private.h
+++ b/src/iec61850/inc_private/ied_server_private.h
@@ -81,10 +81,11 @@ struct sIedServer
uint8_t timeQuality; /* user settable time quality for internally updated times */
+ bool ignoreReadAccess; /* when true don't answer read request (for test purposes) */
+
bool running;
};
-
LIB61850_INTERNAL IEC61850_ServiceError
private_IedServer_convertMmsDataAccessErrorToServiceError(MmsDataAccessError mmsError);
diff --git a/src/iec61850/inc_private/logging.h b/src/iec61850/inc_private/logging.h
index 82ef712b..79c3f246 100644
--- a/src/iec61850/inc_private/logging.h
+++ b/src/iec61850/inc_private/logging.h
@@ -124,7 +124,7 @@ LIB61850_INTERNAL MmsValue*
LIBIEC61850_LOG_SVC_readAccessControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, MmsServerConnection connection);
LIB61850_INTERNAL MmsDataAccessError
-LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection);
#endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_ */
diff --git a/src/iec61850/inc_private/mms_mapping.h b/src/iec61850/inc_private/mms_mapping.h
index 63ec5742..340a2d81 100644
--- a/src/iec61850/inc_private/mms_mapping.h
+++ b/src/iec61850/inc_private/mms_mapping.h
@@ -149,7 +149,7 @@ LIB61850_INTERNAL void
MmsMapping_installReadAccessHandler(MmsMapping* self, ReadAccessHandler handler, void* paramter);
LIB61850_INTERNAL MmsDataAccessError
-Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection);
LIB61850_INTERNAL MmsValue*
diff --git a/src/iec61850/inc_private/mms_sv.h b/src/iec61850/inc_private/mms_sv.h
index 6f8663bf..a0bb0ded 100644
--- a/src/iec61850/inc_private/mms_sv.h
+++ b/src/iec61850/inc_private/mms_sv.h
@@ -41,7 +41,7 @@ LIB61850_INTERNAL MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig , MmsServerConnection connection);
LIB61850_INTERNAL MmsDataAccessError
-LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection);
LIB61850_INTERNAL void
diff --git a/src/iec61850/inc_private/reporting.h b/src/iec61850/inc_private/reporting.h
index 558343c2..eddeb2d1 100644
--- a/src/iec61850/inc_private/reporting.h
+++ b/src/iec61850/inc_private/reporting.h
@@ -126,7 +126,7 @@ LIB61850_INTERNAL void
ReportControl_valueUpdated(ReportControl* self, int dataSetEntryIndex, int flag, bool modelLocked);
LIB61850_INTERNAL MmsValue*
-ReportControl_getRCBValue(ReportControl* rc, char* elementName);
+ReportControl_getRCBValue(ReportControl* rc, const char* elementName);
LIB61850_INTERNAL MmsVariableSpecification*
Reporting_createMmsBufferedRCBs(MmsMapping* self, MmsDomain* domain,
@@ -137,7 +137,7 @@ Reporting_createMmsUnbufferedRCBs(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int reportsCount);
LIB61850_INTERNAL MmsDataAccessError
-Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* elementName, MmsValue* value,
+Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, const char* elementName, MmsValue* value,
MmsServerConnection connection);
LIB61850_INTERNAL bool
diff --git a/src/iec61850/server/impl/client_connection.c b/src/iec61850/server/impl/client_connection.c
index dbca770a..6eac160d 100644
--- a/src/iec61850/server/impl/client_connection.c
+++ b/src/iec61850/server/impl/client_connection.c
@@ -1,7 +1,7 @@
/*
* client_connection.c
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -32,8 +32,8 @@
#include "libiec61850_platform_includes.h"
-struct sClientConnection {
-
+struct sClientConnection
+{
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore tasksCountMutex;
#endif
@@ -47,7 +47,8 @@ private_ClientConnection_create(void* serverConnectionHandle)
{
ClientConnection self = (ClientConnection) GLOBAL_MALLOC(sizeof(struct sClientConnection));
- if (self) {
+ if (self)
+ {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
self->tasksCountMutex = Semaphore_create(1);
#endif
@@ -62,7 +63,8 @@ private_ClientConnection_create(void* serverConnectionHandle)
void
private_ClientConnection_destroy(ClientConnection self)
{
- if (self) {
+ if (self)
+ {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_destroy(self->tasksCountMutex);
#endif
@@ -123,7 +125,6 @@ private_ClientConnection_getServerConnectionHandle(ClientConnection self)
return self->serverConnectionHandle;
}
-
const char*
ClientConnection_getPeerAddress(ClientConnection self)
{
diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c
index 8a5c4baa..2acecedd 100644
--- a/src/iec61850/server/impl/ied_server.c
+++ b/src/iec61850/server/impl/ied_server.c
@@ -540,17 +540,18 @@ updateDataSetsWithCachedValues(IedServer self)
}
}
-
IedServer
IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguration, IedServerConfig serverConfiguration)
{
IedServer self = (IedServer) GLOBAL_CALLOC(1, sizeof(struct sIedServer));
- if (self) {
+ if (self)
+ {
self->model = dataModel;
self->running = false;
self->localIpAddress = NULL;
+ self->ignoreReadAccess = false;
#if (CONFIG_IEC61850_EDITION_1 == 1)
self->edition = IEC_61850_EDITION_1;
@@ -561,7 +562,8 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1)
self->logServiceEnabled = true;
- if (serverConfiguration) {
+ if (serverConfiguration)
+ {
self->logServiceEnabled = serverConfiguration->enableLogService;
self->edition = serverConfiguration->edition;
}
@@ -574,7 +576,8 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
#endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
- if (serverConfiguration) {
+ if (serverConfiguration)
+ {
self->reportBufferSizeBRCBs = serverConfiguration->reportBufferSize;
self->reportBufferSizeURCBs = serverConfiguration->reportBufferSizeURCBs;
self->enableBRCBResvTms = serverConfiguration->enableResvTmsForBRCB;
@@ -582,7 +585,8 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
self->syncIntegrityReportTimes = serverConfiguration->syncIntegrityReportTimes;
self->rcbSettingsWritable = serverConfiguration->reportSettingsWritable;
}
- else {
+ else
+ {
self->reportBufferSizeBRCBs = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE;
self->reportBufferSizeURCBs = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE;
self->enableOwnerForRCB = false;
@@ -602,11 +606,13 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
#endif
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
- if (serverConfiguration) {
+ if (serverConfiguration)
+ {
self->enableEditSG = serverConfiguration->enableEditSG;
self->hasSGCBResvTms = serverConfiguration->enableResvTmsForSGCB;
}
- else {
+ else
+ {
self->enableEditSG = true;
self->hasSGCBResvTms = true;
}
@@ -614,14 +620,15 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
self->mmsMapping = MmsMapping_create(dataModel, self);
- if (self->mmsMapping) {
-
+ if (self->mmsMapping)
+ {
self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping);
self->mmsServer = MmsServer_create(self->mmsDevice, tlsConfiguration);
#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1)
- if (serverConfiguration) {
+ if (serverConfiguration)
+ {
MmsServer_enableFileService(self->mmsServer, serverConfiguration->enableFileService);
MmsServer_enableDynamicNamedVariableListService(self->mmsServer, serverConfiguration->enableDynamicDataSetService);
MmsServer_setMaxAssociationSpecificDataSets(self->mmsServer, serverConfiguration->maxAssociationSpecificDataSets);
@@ -668,7 +675,8 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
IedServer_setTimeQuality(self, true, false, false, 10);
}
- else {
+ else
+ {
IedServer_destroy(self);
self = NULL;
}
@@ -1679,6 +1687,38 @@ IedServer_handleWriteAccessForComplexAttribute(IedServer self, DataAttribute* da
}
}
+void
+IedServer_handleWriteAccessForDataObject(IedServer self, DataObject* dataObject, FunctionalConstraint fc, WriteAccessHandler handler, void* parameter)
+{
+ if (dataObject == NULL) {
+ if (DEBUG_IED_SERVER)
+ printf("IED_SERVER: IedServer_handlerWriteAccessForDataObject - dataObject == NULL!\n");
+ }
+ else
+ {
+ ModelNode* childElement = dataObject->firstChild;
+
+ while (childElement)
+ {
+ if (childElement->modelType == DataAttributeModelType)
+ {
+ DataAttribute* dataAttribute = (DataAttribute*) childElement;
+
+ if (dataAttribute->fc == fc)
+ {
+ IedServer_handleWriteAccessForComplexAttribute(self, dataAttribute, handler, parameter);
+ }
+ }
+ else if (childElement->modelType == DataObjectModelType)
+ {
+ IedServer_handleWriteAccessForDataObject(self, (DataObject*) childElement, fc, handler, parameter);
+ }
+
+ childElement = childElement->sibling;
+ }
+ }
+}
+
void
IedServer_setReadAccessHandler(IedServer self, ReadAccessHandler handler, void* parameter)
{
@@ -1960,3 +2000,9 @@ IedServer_setControlBlockAccessHandler(IedServer self, IedServer_ControlBlockAcc
self->mmsMapping->controlBlockAccessHandler = handler;
self->mmsMapping->controlBlockAccessHandlerParameter = parameter;
}
+
+void
+IedServer_ignoreReadAccess(IedServer self, bool ignore)
+{
+ self->ignoreReadAccess = ignore;
+}
diff --git a/src/iec61850/server/mms_mapping/control.c b/src/iec61850/server/mms_mapping/control.c
index de2b6f89..07ef4324 100644
--- a/src/iec61850/server/mms_mapping/control.c
+++ b/src/iec61850/server/mms_mapping/control.c
@@ -74,7 +74,8 @@ ControlObject_unselect(ControlObject* self, MmsServerConnection connection, MmsM
static MmsValue*
getOperParameterCtlNum(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 7)
return MmsValue_getElement(operParameters, 3);
else if (MmsValue_getArraySize(operParameters) == 6)
@@ -87,7 +88,8 @@ getOperParameterCtlNum(MmsValue* operParameters)
static MmsValue*
getCancelParameterCtlNum(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 6)
return MmsValue_getElement(operParameters, 3);
else if (MmsValue_getArraySize(operParameters) == 5)
@@ -100,7 +102,8 @@ getCancelParameterCtlNum(MmsValue* operParameters)
static MmsValue*
getCancelParameterOrigin(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 6)
return MmsValue_getElement(operParameters, 2);
else if (MmsValue_getArraySize(operParameters) == 5)
@@ -166,6 +169,7 @@ getCancelParameterTest(MmsValue* operParameters)
return NULL;
}
+/* access the MmsValue of Oper.T or SBOw.T */
static MmsValue*
getOperParameterTime(MmsValue* operParameters)
{
@@ -179,7 +183,7 @@ getOperParameterTime(MmsValue* operParameters)
timeParameter = MmsValue_getElement(operParameters, 3);
}
- if (timeParameter != NULL)
+ if (timeParameter)
if ((MmsValue_getType(timeParameter) == MMS_UTC_TIME) || (MmsValue_getType(timeParameter) == MMS_BINARY_TIME))
return timeParameter;
@@ -211,11 +215,12 @@ getCancelParameterTime(MmsValue* operParameters)
static void
copyControlValuesToTrackingObject(MmsMapping* self, ControlObject* controlObject, IEC61850_ServiceType serviceType)
{
- if (controlObject->ctlVal) {
-
+ if (controlObject->ctlVal)
+ {
ControlTrkInstance trkInst = NULL;
- switch (controlObject->cdc) {
+ switch (controlObject->cdc)
+ {
case CST_SPCTRK:
trkInst = self->spcTrk;
break;
@@ -247,7 +252,8 @@ copyControlValuesToTrackingObject(MmsMapping* self, ControlObject* controlObject
break;
}
- if (trkInst) {
+ if (trkInst)
+ {
if (trkInst->ctlVal)
MmsValue_update(trkInst->ctlVal->mmsValue, controlObject->ctlVal);
@@ -265,16 +271,20 @@ copyControlValuesToTrackingObject(MmsMapping* self, ControlObject* controlObject
MmsValue* operVal = NULL;
- if (serviceType == IEC61850_SERVICE_TYPE_SELECT_WITH_VALUES) {
+ if (serviceType == IEC61850_SERVICE_TYPE_SELECT_WITH_VALUES)
+ {
if (controlObject->sbow)
operVal = controlObject->sbow;
}
- else if (serviceType == IEC61850_SERVICE_TYPE_OPERATE) {
+ else if (serviceType == IEC61850_SERVICE_TYPE_OPERATE)
+ {
if (controlObject->oper)
operVal = controlObject->oper;
}
- else if (serviceType == IEC61850_SERVICE_TYPE_CANCEL) {
- if (controlObject->cancel) {
+ else if (serviceType == IEC61850_SERVICE_TYPE_CANCEL)
+ {
+ if (controlObject->cancel)
+ {
operVal = controlObject->cancel;
if (trkInst->Test) {
MmsValue_update(trkInst->Test->mmsValue, getCancelParameterTest(operVal));
@@ -286,8 +296,8 @@ copyControlValuesToTrackingObject(MmsMapping* self, ControlObject* controlObject
}
}
- if (operVal) {
-
+ if (operVal)
+ {
if (trkInst->Test) {
MmsValue_update(trkInst->Test->mmsValue, getOperParameterTest(operVal));
}
@@ -300,7 +310,6 @@ copyControlValuesToTrackingObject(MmsMapping* self, ControlObject* controlObject
MmsValue_update(trkInst->T->mmsValue, getOperParameterTime(operVal));
}
}
-
}
}
}
@@ -310,8 +319,8 @@ convertCheckHandlerResultToServiceError(CheckHandlerResult controlHandlerResult)
{
IEC61850_ServiceError serviceError;
- switch (controlHandlerResult) {
-
+ switch (controlHandlerResult)
+ {
case CONTROL_HARDWARE_FAULT:
serviceError = IEC61850_SERVICE_ERROR_FAILED_DUE_TO_SERVER_CONSTRAINT;
break;
@@ -352,7 +361,8 @@ updateGenericTrackingObjectValues(MmsMapping* self, ControlObject* controlObject
ServiceTrkInstance trkInst = NULL;
- if (controlObject->ctlVal) {
+ if (controlObject->ctlVal)
+ {
switch(controlObject->cdc)
{
case CST_SPCTRK:
@@ -389,7 +399,8 @@ updateGenericTrackingObjectValues(MmsMapping* self, ControlObject* controlObject
}
}
- if (trkInst) {
+ if (trkInst)
+ {
if (trkInst->serviceType)
MmsValue_setInt32(trkInst->serviceType->mmsValue, (int) serviceType);
@@ -460,7 +471,8 @@ getState(ControlObject* self)
static void
setStSeld(ControlObject* self, bool value)
{
- if (self->stSeld) {
+ if (self->stSeld)
+ {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->pendingEventsLock);
#endif
@@ -479,7 +491,8 @@ setStSeld(ControlObject* self, bool value)
static void
updateSboTimeoutValue(ControlObject* self)
{
- if (self->sboTimeout != NULL) {
+ if (self->sboTimeout != NULL)
+ {
uint32_t sboTimeoutVal = MmsValue_toInt32(self->sboTimeout);
if (DEBUG_IED_SERVER)
@@ -506,7 +519,8 @@ selectObject(ControlObject* self, uint64_t selectTime, MmsServerConnection conne
updateNextControlTimeout(mmsMapping, selectTime);
- if (self->selectStateChangedHandler) {
+ if (self->selectStateChangedHandler)
+ {
self->selectStateChangedHandler((ControlAction) self,
self->selectStateChangedHandlerParameter,
true,
@@ -517,7 +531,8 @@ selectObject(ControlObject* self, uint64_t selectTime, MmsServerConnection conne
static void
unselectObject(ControlObject* self, SelectStateChangedReason reason, MmsMapping* mmsMapping)
{
- if (getState(self) != STATE_UNSELECTED) {
+ if (getState(self) != STATE_UNSELECTED)
+ {
setState(self, STATE_UNSELECTED);
setStSeld(self, false);
@@ -525,7 +540,8 @@ unselectObject(ControlObject* self, SelectStateChangedReason reason, MmsMapping*
/* trigger timeout check in next cycle to update the next timeout value */
mmsMapping->nextControlTimeout = 0;
- if (self->selectStateChangedHandler) {
+ if (self->selectStateChangedHandler)
+ {
self->selectStateChangedHandler((ControlAction) self,
self->selectStateChangedHandlerParameter,
false,
@@ -540,11 +556,14 @@ unselectObject(ControlObject* self, SelectStateChangedReason reason, MmsMapping*
static void
checkSelectTimeout(ControlObject* self, uint64_t currentTime, MmsMapping* mmsMapping)
{
- if ((self->ctlModel == 2) || (self->ctlModel == 4)) {
-
- if (getState(self) == STATE_READY) {
- if (self->selectTimeout > 0) {
- if (currentTime > (self->selectTime + self->selectTimeout)) {
+ if ((self->ctlModel == 2) || (self->ctlModel == 4))
+ {
+ if (getState(self) == STATE_READY)
+ {
+ if (self->selectTimeout > 0)
+ {
+ if (currentTime > (self->selectTime + self->selectTimeout))
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: select-timeout (timeout-val = %u) for control %s/%s.%s\n",
self->selectTimeout, MmsDomain_getName(self->mmsDomain), self->lnName, self->name);
@@ -562,7 +581,8 @@ checkSelectTimeout(ControlObject* self, uint64_t currentTime, MmsMapping* mmsMap
static void
setOpRcvd(ControlObject* self, bool value)
{
- if (self->opRcvd) {
+ if (self->opRcvd)
+ {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->pendingEventsLock);
#endif
@@ -581,13 +601,16 @@ setOpRcvd(ControlObject* self, bool value)
static void
setOpOk(ControlObject* self, bool value, uint64_t currentTimeInMs)
{
- if (self->opOk) {
+ if (self->opOk)
+ {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(self->pendingEventsLock);
#endif
- if (value) {
- if (self->tOpOk) {
+ if (value)
+ {
+ if (self->tOpOk)
+ {
MmsValue* timestamp = self->tOpOk->mmsValue;
MmsValue_setUtcTimeMsEx(timestamp, currentTimeInMs, self->iedServer->timeQuality);
@@ -607,7 +630,8 @@ setOpOk(ControlObject* self, bool value, uint64_t currentTimeInMs)
static bool
isSboClassOperateOnce(ControlObject* self)
{
- if (self->sboClass != NULL) {
+ if (self->sboClass != NULL)
+ {
if (MmsValue_toInt32(self->sboClass) == 1)
return false;
else
@@ -620,8 +644,8 @@ isSboClassOperateOnce(ControlObject* self)
static MmsValue*
getOperParameterOperTime(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
-
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 7)
return MmsValue_getElement(operParameters, 1);
}
@@ -659,12 +683,14 @@ exitControlTask(ControlObject* self)
static void
abortControlOperation(ControlObject* self, bool unconditional, SelectStateChangedReason reason, MmsMapping* mmsMapping)
{
- if ((self->ctlModel == 2) || (self->ctlModel == 4)) {
-
- if (unconditional) {
+ if ((self->ctlModel == 2) || (self->ctlModel == 4))
+ {
+ if (unconditional)
+ {
unselectObject(self, reason, mmsMapping);
}
- else {
+ else
+ {
if (isSboClassOperateOnce(self))
unselectObject(self, reason, mmsMapping);
else
@@ -694,7 +720,8 @@ operateControl(ControlObject* self, MmsValue* value, uint64_t currentTime, bool
static void
resetAddCause(ControlObject* self)
{
- if (self) {
+ if (self)
+ {
self->addCauseValue = ADD_CAUSE_UNKNOWN;
MmsValue_setInt32(self->addCause, self->addCauseValue);
@@ -710,8 +737,8 @@ executeStateMachine:
state = getState(controlObject);
- switch (state) {
-
+ switch (state)
+ {
case STATE_WAIT_FOR_SELECT:
{
controlObject->isSelect = 1;
@@ -724,12 +751,14 @@ executeStateMachine:
controlObject->isSelect = 0;
- if (checkHandlerResult != CONTROL_WAITING_FOR_SELECT) {
-
- if (controlObject->ctlModel == 2) {
+ if (checkHandlerResult != CONTROL_WAITING_FOR_SELECT)
+ {
+ if (controlObject->ctlModel == 2)
+ {
LinkedList values = LinkedList_create();
- if (checkHandlerResult == CONTROL_ACCEPTED) {
+ if (checkHandlerResult == CONTROL_ACCEPTED)
+ {
LinkedList_add(values, controlObject->sbo);
selectObject(controlObject, Hal_getTimeInMs(), controlObject->mmsConnection, self);
@@ -738,7 +767,8 @@ executeStateMachine:
updateGenericTrackingObjectValues(self, controlObject, IEC61850_SERVICE_TYPE_SELECT, IEC61850_SERVICE_ERROR_NO_ERROR);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
}
- else {
+ else
+ {
LinkedList_add(values, &emptyString);
setState(controlObject, STATE_UNSELECTED);
@@ -753,9 +783,10 @@ executeStateMachine:
LinkedList_destroyStatic(values);
}
- else if (controlObject->ctlModel == 4) {
- if (checkHandlerResult == CONTROL_ACCEPTED) {
-
+ else if (controlObject->ctlModel == 4)
+ {
+ if (checkHandlerResult == CONTROL_ACCEPTED)
+ {
selectObject(controlObject, Hal_getTimeInMs(), controlObject->mmsConnection, self);
if (controlObject->ctlNumSt)
@@ -773,8 +804,8 @@ executeStateMachine:
if (DEBUG_IED_SERVER)
printf("IED_SERVER: SBOw - selected successful\n");
}
- else {
-
+ else
+ {
setState(controlObject, STATE_UNSELECTED);
ControlObject_sendLastApplError(controlObject, controlObject->mmsConnection, "SBOw",
@@ -793,13 +824,15 @@ executeStateMachine:
printf("IED_SERVER: SBOw - select rejected by application!\n");
}
}
- else {
+ else
+ {
/* ERROR: invalid internal state! */
setState(controlObject, STATE_WAIT_FOR_SELECT);
}
}
- else {
+ else
+ {
updateNextControlTimeout(self, Hal_getTimeInMs() + 100);
}
@@ -818,19 +851,23 @@ executeStateMachine:
controlObject->errorValue = CONTROL_ERROR_NO_ERROR;
controlObject->addCauseValue = ADD_CAUSE_BLOCKED_BY_SYNCHROCHECK;
- if (controlObject->waitForExecutionHandler != NULL) {
+ if (controlObject->waitForExecutionHandler != NULL)
+ {
dynamicCheckResult = controlObject->waitForExecutionHandler((ControlAction) controlObject, controlObject->waitForExecutionHandlerParameter, controlObject->ctlVal,
controlObject->testMode, controlObject->synchroCheck);
}
- if (dynamicCheckResult == CONTROL_RESULT_FAILED) {
- if ((controlObject->errorValue != CONTROL_ERROR_NO_ERROR) || (controlObject->addCauseValue != ADD_CAUSE_UNKNOWN)) {
+ if (dynamicCheckResult == CONTROL_RESULT_FAILED)
+ {
+ if ((controlObject->errorValue != CONTROL_ERROR_NO_ERROR) || (controlObject->addCauseValue != ADD_CAUSE_UNKNOWN))
+ {
ControlObject_sendLastApplError(controlObject, controlObject->mmsConnection, "Oper",
controlObject->errorValue, controlObject->addCauseValue,
controlObject->ctlNum, controlObject->origin, false);
}
- if (!isTimeActivatedControl) {
+ if (!isTimeActivatedControl)
+ {
MmsServerConnection_sendWriteResponse(controlObject->mmsConnection, controlObject->operateInvokeId,
DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED, true);
@@ -838,7 +875,8 @@ executeStateMachine:
updateGenericTrackingObjectValues(self, controlObject, IEC61850_SERVICE_TYPE_OPERATE, IEC61850_SERVICE_ERROR_ACCESS_NOT_ALLOWED_IN_CURRENT_STATE);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
}
- else {
+ else
+ {
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
updateGenericTrackingObjectValues(self, controlObject, IEC61850_SERVICE_TYPE_TIME_ACTIVATED_OPERATE, IEC61850_SERVICE_ERROR_ACCESS_NOT_ALLOWED_IN_CURRENT_STATE);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
@@ -849,8 +887,10 @@ executeStateMachine:
abortControlOperation(controlObject, false, SELECT_STATE_REASON_OPERATE_FAILED, self);
exitControlTask(controlObject);
}
- else if (dynamicCheckResult == CONTROL_RESULT_OK) {
- if (isTimeActivatedControl) {
+ else if (dynamicCheckResult == CONTROL_RESULT_OK)
+ {
+ if (isTimeActivatedControl)
+ {
ControlObject_sendCommandTerminationPositive(controlObject);
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
@@ -862,7 +902,8 @@ executeStateMachine:
MmsValue_setUtcTime(operTm, 0);
MmsValue_setUtcTimeQuality(operTm, self->iedServer->timeQuality);
}
- else {
+ else
+ {
MmsServerConnection_sendWriteResponse(controlObject->mmsConnection, controlObject->operateInvokeId,
DATA_ACCESS_ERROR_SUCCESS, true);
@@ -877,7 +918,8 @@ executeStateMachine:
goto executeStateMachine;
}
- else {
+ else
+ {
updateNextControlTimeout(self, Hal_getTimeInMs() + 10);
}
}
@@ -889,11 +931,12 @@ executeStateMachine:
ControlHandlerResult result = operateControl(controlObject, controlObject->ctlVal, currentTime, controlObject->testMode);
- if (result != CONTROL_RESULT_WAITING) {
-
- if (result == CONTROL_RESULT_OK) {
-
- if ((controlObject->ctlModel == 4) || (controlObject->ctlModel == 3)) {
+ if (result != CONTROL_RESULT_WAITING)
+ {
+ if (result == CONTROL_RESULT_OK)
+ {
+ if ((controlObject->ctlModel == 4) || (controlObject->ctlModel == 3))
+ {
ControlObject_sendCommandTerminationPositive(controlObject);
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
@@ -903,9 +946,10 @@ executeStateMachine:
abortControlOperation(controlObject, false, SELECT_STATE_REASON_OPERATED, self);
}
- else {
-
- if ((controlObject->ctlModel == 4) || (controlObject->ctlModel == 3)) {
+ else
+ {
+ if ((controlObject->ctlModel == 4) || (controlObject->ctlModel == 3))
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: operate failed!\n");
@@ -925,7 +969,8 @@ executeStateMachine:
resetAddCause(controlObject);
}
- else {
+ else
+ {
updateNextControlTimeout(self, currentTimeInMs + 10);
}
}
@@ -949,7 +994,8 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char*
self->stateLock = Semaphore_create(1);
self->pendingEventsLock = Semaphore_create(1);
- if ((self->stateLock == NULL) || (self->pendingEventsLock == NULL)) {
+ if ((self->stateLock == NULL) || (self->pendingEventsLock == NULL))
+ {
ControlObject_destroy(self);
self = NULL;
goto exit_function;
@@ -958,7 +1004,8 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char*
self->name = StringUtils_copyString(name);
- if (self->name == NULL) {
+ if (self->name == NULL)
+ {
ControlObject_destroy(self);
self = NULL;
goto exit_function;
@@ -970,20 +1017,24 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char*
MmsVariableSpecification* ctlValSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "ctlVal", NULL);
- if (ctlValSpec) {
+ if (ctlValSpec)
+ {
self->ctlVal = MmsValue_newDefaultValue(ctlValSpec);
}
- else {
+ else
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: control object %s/%s.%s has no ctlVal element!\n", domain->domainName, lnName, name);
}
MmsVariableSpecification* originSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "origin", NULL);
- if (originSpec) {
+ if (originSpec)
+ {
self->origin = MmsValue_newDefaultValue(originSpec);
}
- else {
+ else
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: control object %s/%s.%s has no origin element!\n", domain->domainName, lnName, name);
}
@@ -1015,7 +1066,8 @@ ControlObject_initialize(ControlObject* self)
MmsValue* ctlModel = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, ctlModelName);
- if (ctlModel == NULL) {
+ if (ctlModel == NULL)
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: No control model found for variable %s\n", ctlModelName);
}
@@ -1028,7 +1080,8 @@ ControlObject_initialize(ControlObject* self)
self->ctlNumSt = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, ctlNumName);
- if (self->ctlNumSt == NULL) {
+ if (self->ctlNumSt == NULL)
+ {
/* for APC */
ctlNumName = StringUtils_createStringInBuffer(strBuf, 130, 4, self->lnName, "$MX$", self->name, "$ctlNum");
@@ -1039,7 +1092,8 @@ ControlObject_initialize(ControlObject* self)
self->originSt = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, originName);
- if (self->originSt == NULL) {
+ if (self->originSt == NULL)
+ {
/* for APC */
originName = StringUtils_createStringInBuffer(strBuf, 130, 4, self->lnName, "$MX$", self->name, "$origin");
@@ -1053,7 +1107,8 @@ ControlObject_initialize(ControlObject* self)
updateSboTimeoutValue(self);
- if (self->sbo) {
+ if (self->sbo)
+ {
char* controlObjectReference = StringUtils_createStringInBuffer(strBuf, 130, 5, self->mmsDomain->domainName,
"/", self->lnName, "$CO$", self->name);
@@ -1154,7 +1209,8 @@ ControlObject_initialize(ControlObject* self)
self->stSeld = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, stSeldName);
- if ((self->stSeld) && (self->stSeld->type != IEC61850_BOOLEAN)) {
+ if ((self->stSeld) && (self->stSeld->type != IEC61850_BOOLEAN))
+ {
self->stSeld = NULL;
if (DEBUG_IED_SERVER)
@@ -1165,7 +1221,8 @@ ControlObject_initialize(ControlObject* self)
self->opRcvd = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, opRcvdName);
- if ((self->opRcvd) && (self->opRcvd->type != IEC61850_BOOLEAN)) {
+ if ((self->opRcvd) && (self->opRcvd->type != IEC61850_BOOLEAN))
+ {
self->opRcvd = NULL;
if (DEBUG_IED_SERVER)
@@ -1176,7 +1233,8 @@ ControlObject_initialize(ControlObject* self)
self->opOk = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, opOkName);
- if ((self->opOk) && (self->opOk->type != IEC61850_BOOLEAN)) {
+ if ((self->opOk) && (self->opOk->type != IEC61850_BOOLEAN))
+ {
self->opOk = NULL;
if (DEBUG_IED_SERVER)
@@ -1187,7 +1245,8 @@ ControlObject_initialize(ControlObject* self)
self->tOpOk = (DataAttribute*) IedModel_getModelNodeByObjectReference(self->iedServer->model, tOpOkName);
- if ((self->tOpOk) && (self->tOpOk->type != IEC61850_TIMESTAMP)) {
+ if ((self->tOpOk) && (self->tOpOk->type != IEC61850_TIMESTAMP))
+ {
self->tOpOk = NULL;
if (DEBUG_IED_SERVER)
@@ -1197,7 +1256,8 @@ ControlObject_initialize(ControlObject* self)
self->error = MmsValue_newIntegerFromInt32(0);
self->addCause = MmsValue_newIntegerFromInt32(0);
- if (ctlModel != NULL) {
+ if (ctlModel != NULL)
+ {
int ctlModelVal = MmsValue_toInt32(ctlModel);
if (DEBUG_IED_SERVER)
@@ -1225,44 +1285,50 @@ ControlObject_handlePendingEvents(ControlObject* self)
Semaphore_wait(self->pendingEventsLock);
#endif
- if (self->pendingEvents > 0) {
-
- if (self->pendingEvents & PENDING_EVENT_SELECTED) {
+ if (self->pendingEvents > 0)
+ {
+ if (self->pendingEvents & PENDING_EVENT_SELECTED)
+ {
if (self->stSeld)
IedServer_updateBooleanAttributeValue(self->iedServer, self->stSeld, true);
self->pendingEvents &= ~(PENDING_EVENT_SELECTED);
}
- if (self->pendingEvents & PENDING_EVENT_UNSELECTED) {
+ if (self->pendingEvents & PENDING_EVENT_UNSELECTED)
+ {
if (self->stSeld)
IedServer_updateBooleanAttributeValue(self->iedServer, self->stSeld, false);
self->pendingEvents &= ~(PENDING_EVENT_UNSELECTED);
}
- if (self->pendingEvents & PENDING_EVENT_OP_RCVD_TRUE) {
+ if (self->pendingEvents & PENDING_EVENT_OP_RCVD_TRUE)
+ {
if (self->opRcvd)
IedServer_updateBooleanAttributeValue(self->iedServer, self->opRcvd, true);
self->pendingEvents &= ~(PENDING_EVENT_OP_RCVD_TRUE);
}
- if (self->pendingEvents & PENDING_EVENT_OP_RCVD_FALSE) {
+ if (self->pendingEvents & PENDING_EVENT_OP_RCVD_FALSE)
+ {
if (self->opRcvd)
IedServer_updateBooleanAttributeValue(self->iedServer, self->opRcvd, false);
self->pendingEvents &= ~(PENDING_EVENT_OP_RCVD_FALSE);
}
- if (self->pendingEvents & PENDING_EVENT_OP_OK_TRUE) {
+ if (self->pendingEvents & PENDING_EVENT_OP_OK_TRUE)
+ {
if (self->opOk)
IedServer_updateBooleanAttributeValue(self->iedServer, self->opOk, true);
self->pendingEvents &= ~(PENDING_EVENT_OP_OK_TRUE);
}
- if (self->pendingEvents & PENDING_EVENT_OP_OK_FALSE) {
+ if (self->pendingEvents & PENDING_EVENT_OP_OK_FALSE)
+ {
if (self->opOk)
IedServer_updateBooleanAttributeValue(self->iedServer, self->opOk, false);
@@ -1278,7 +1344,8 @@ ControlObject_handlePendingEvents(ControlObject* self)
void
ControlObject_destroy(ControlObject* self)
{
- if (self) {
+ if (self)
+ {
if (self->mmsValue)
MmsValue_delete(self->mmsValue);
@@ -1357,7 +1424,8 @@ ControlObject_getMmsValue(ControlObject* self)
bool
ControlObject_unselect(ControlObject* self, MmsServerConnection connection, MmsMapping* mmsMapping)
{
- if (self->mmsConnection == connection) {
+ if (self->mmsConnection == connection)
+ {
abortControlOperation(self, true, SELECT_STATE_REASON_DISCONNECTED, mmsMapping);
return true;
}
@@ -1415,29 +1483,32 @@ ControlObject_updateControlModel(ControlObject* self, ControlModel value, DataOb
void
Control_processControlActions(MmsMapping* self, uint64_t currentTimeInMs)
{
- if (currentTimeInMs >= self->nextControlTimeout) {
-
+ if (currentTimeInMs >= self->nextControlTimeout)
+ {
/* invalidate nextControlTimeout */
self->nextControlTimeout = (uint64_t) 0xFFFFFFFFFFFFFFFFLLU;
LinkedList element = LinkedList_getNext(self->controlObjects);
- while (element != NULL) {
+ while (element != NULL)
+ {
ControlObject* controlObject = (ControlObject*) element->data;
- if (controlObject->state != STATE_UNSELECTED) {
-
- if ((controlObject->ctlModel == 1) || (controlObject->ctlModel == 3)) {
- if (controlObject->state == STATE_READY) {
+ if (controlObject->state != STATE_UNSELECTED)
+ {
+ if ((controlObject->ctlModel == 1) || (controlObject->ctlModel == 3))
+ {
+ if (controlObject->state == STATE_READY)
+ {
element = LinkedList_getNext(element);
continue;
}
}
- if (controlObject->state == STATE_WAIT_FOR_ACTIVATION_TIME) {
-
- if (controlObject->operateTime <= currentTimeInMs) {
-
+ if (controlObject->state == STATE_WAIT_FOR_ACTIVATION_TIME)
+ {
+ if (controlObject->operateTime <= currentTimeInMs)
+ {
/* enter state Perform Test */
setOpRcvd(controlObject, true);
@@ -1448,7 +1519,9 @@ Control_processControlActions(MmsMapping* self, uint64_t currentTimeInMs)
CheckHandlerResult checkResult = CONTROL_ACCEPTED;
- if (controlObject->checkHandler != NULL) { /* perform operative tests */
+ if (controlObject->checkHandler != NULL)
+ {
+ /* perform operative tests */
controlObject->errorValue = CONTROL_ERROR_NO_ERROR;
controlObject->addCauseValue = ADD_CAUSE_BLOCKED_BY_INTERLOCKING;
@@ -1458,8 +1531,8 @@ Control_processControlActions(MmsMapping* self, uint64_t currentTimeInMs)
controlObject->interlockCheck);
}
- if (checkResult == CONTROL_ACCEPTED) {
-
+ if (checkResult == CONTROL_ACCEPTED)
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: time activated operate: command accepted\n");
@@ -1468,8 +1541,8 @@ Control_processControlActions(MmsMapping* self, uint64_t currentTimeInMs)
executeControlTask(self, controlObject, currentTimeInMs);
}
- else {
-
+ else
+ {
ControlObject_sendLastApplError(controlObject, controlObject->mmsConnection, "Oper",
controlObject->errorValue, controlObject->addCauseValue,
controlObject->ctlNum, controlObject->origin, false);
@@ -1512,12 +1585,16 @@ Control_lookupControlObject(MmsMapping* self, MmsDomain* domain, char* lnName, c
{
LinkedList element = LinkedList_getNext(self->controlObjects);
- while (element != NULL) {
+ while (element != NULL)
+ {
ControlObject* controlObject = (ControlObject*) element->data;
- if (ControlObject_getDomain(controlObject) == domain) {
- if (strcmp(ControlObject_getLNName(controlObject), lnName) == 0) {
- if (strcmp(ControlObject_getName(controlObject), objectName) == 0) {
+ if (ControlObject_getDomain(controlObject) == domain)
+ {
+ if (strcmp(ControlObject_getLNName(controlObject), lnName) == 0)
+ {
+ if (strcmp(ControlObject_getName(controlObject), objectName) == 0)
+ {
return controlObject;
}
}
@@ -1532,8 +1609,10 @@ Control_lookupControlObject(MmsMapping* self, MmsDomain* domain, char* lnName, c
static MmsValue*
getCtlVal(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
- if (MmsValue_getArraySize(operParameters) > 5) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
+ if (MmsValue_getArraySize(operParameters) > 5)
+ {
return MmsValue_getElement(operParameters, 0);
}
}
@@ -1678,7 +1757,8 @@ ControlObject_sendLastApplError(ControlObject* self, MmsServerConnection connect
StringUtils_createStringInBuffer(ctlObj, 130, 7, MmsDomain_getName(self->mmsDomain), "/",
self->lnName, "$CO$", self->name, "$", ctlVariable);
- if (DEBUG_IED_SERVER) {
+ if (DEBUG_IED_SERVER)
+ {
printf("IED_SERVER: sendLastApplError:\n");
printf("IED_SERVER: control object: %s\n", ctlObj);
printf("IED_SERVER: ctlNum: %u\n", MmsValue_toUint32(ctlNum));
@@ -1728,7 +1808,8 @@ doesElementEquals(char* element, char* name)
{
int i = 0;
- while (name[i] != 0) {
+ while (name[i] != 0)
+ {
if (element[i] == 0)
return false;
@@ -1766,9 +1847,6 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
char* lnName = variableId;
- if (lnName == NULL)
- return NULL;
-
char* objectName = MmsMapping_getNextNameElement(separator + 1);
if (objectName == NULL)
@@ -1776,13 +1854,14 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
char* varName = MmsMapping_getNextNameElement(objectName);
- if (varName != NULL) {
-
+ if (varName != NULL)
+ {
bool foundVar = false;
char* nextVarName = varName;
- do {
+ do
+ {
if (doesElementEquals(varName, "Oper") ||
doesElementEquals(varName, "SBO") ||
doesElementEquals(varName, "SBOw") ||
@@ -1795,10 +1874,10 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
nextVarName = MmsMapping_getNextNameElement(varName);
- if (nextVarName != NULL)
+ if (nextVarName)
varName = nextVarName;
- } while (nextVarName != NULL);
+ } while (nextVarName);
if (foundVar == false)
varName = NULL;
@@ -1809,24 +1888,28 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
ControlObject* controlObject = Control_lookupControlObject(self, domain, lnName, objectName);
- if (controlObject != NULL) {
-
- if (varName != NULL) {
+ if (controlObject != NULL)
+ {
+ if (varName != NULL)
+ {
if (strcmp(varName, "Oper") == 0)
value = controlObject->oper;
else if (strcmp(varName, "SBOw") == 0)
value = controlObject->sbow;
- else if (strcmp(varName, "SBO") == 0) {
- if (controlObject->ctlModel == 2) {
-
+ else if (strcmp(varName, "SBO") == 0)
+ {
+ if (controlObject->ctlModel == 2)
+ {
uint64_t currentTime = Hal_getTimeInMs();
value = &emptyString;
- if (isDirectAccess == true) {
+ if (isDirectAccess == true)
+ {
checkSelectTimeout(controlObject, currentTime, self);
- if (getState(controlObject) == STATE_UNSELECTED) {
+ if (getState(controlObject) == STATE_UNSELECTED)
+ {
CheckHandlerResult checkResult = CONTROL_ACCEPTED;
/* opRcvd must not be set here! */
@@ -1834,7 +1917,9 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
controlObject->addCauseValue = ADD_CAUSE_UNKNOWN;
controlObject->mmsConnection = connection;
- if (controlObject->checkHandler != NULL) { /* perform operative tests */
+ if (controlObject->checkHandler != NULL)
+ {
+ /* perform operative tests */
controlObject->isSelect = 1;
@@ -1844,7 +1929,8 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
controlObject->isSelect = 0;
}
- if (checkResult == CONTROL_ACCEPTED) {
+ if (checkResult == CONTROL_ACCEPTED)
+ {
selectObject(controlObject, currentTime, connection, self);
value = controlObject->sbo;
@@ -1852,13 +1938,15 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
updateGenericTrackingObjectValues(self, controlObject, IEC61850_SERVICE_TYPE_SELECT, IEC61850_SERVICE_ERROR_NO_ERROR);
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
}
- else if (checkResult == CONTROL_WAITING_FOR_SELECT) {
+ else if (checkResult == CONTROL_WAITING_FOR_SELECT)
+ {
controlObject->mmsConnection = connection;
controlObject->operateInvokeId = MmsServerConnection_getLastInvokeId(connection);
setState(controlObject, STATE_WAIT_FOR_SELECT);
value = &delayedResponse;
}
- else {
+ else
+ {
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
updateGenericTrackingObjectValues(self, controlObject, IEC61850_SERVICE_TYPE_SELECT,
convertCheckHandlerResultToServiceError(checkResult));
@@ -1866,9 +1954,9 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
}
}
}
-
}
- else {
+ else
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: select not applicable for control model %u\n", controlObject->ctlModel);
@@ -1878,7 +1966,8 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
else if (strcmp(varName, "Cancel") == 0)
value = controlObject->cancel;
- else {
+ else
+ {
value = MmsValue_getSubElement(ControlObject_getMmsValue(controlObject),
ControlObject_getTypeSpec(controlObject), varName);
}
@@ -1887,7 +1976,8 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
value = ControlObject_getMmsValue(controlObject);
}
}
- else {
+ else
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Control object not found %s/%s.%s\n", domain->domainName, lnName, objectName);
}
@@ -1926,7 +2016,7 @@ checkValidityOfOriginParameter(MmsValue* origin)
}
MmsDataAccessError
-Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection)
{
MmsDataAccessError indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
@@ -1961,13 +2051,14 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
char* varName = MmsMapping_getNextNameElement(objectName);
- if (varName != NULL) {
-
+ if (varName != NULL)
+ {
bool foundVar = false;
char* nextVarName = varName;
- do {
+ do
+ {
if (doesElementEquals(varName, "Oper") ||
doesElementEquals(varName, "SBO") ||
doesElementEquals(varName, "SBOw") ||
@@ -1992,31 +2083,36 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
if (DEBUG_IED_SERVER)
printf("IED_SERVER: write access control: objectName: (%s) varName: (%s)\n", objectName, varName);
- if (varName == NULL) {
+ if (varName == NULL)
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto free_and_return;
}
controlObject = Control_lookupControlObject(self, domain, lnName, objectName);
- if (controlObject == NULL) {
+ if (controlObject == NULL)
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto free_and_return;
}
- if (controlObject->ctlModel == CONTROL_MODEL_STATUS_ONLY) {
+ if (controlObject->ctlModel == CONTROL_MODEL_STATUS_ONLY)
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto free_and_return;
}
- if (strcmp(varName, "SBOw") == 0) { /* select with value */
-
+ if (strcmp(varName, "SBOw") == 0) /* select with value */
+ {
serviceType = IEC61850_SERVICE_TYPE_SELECT_WITH_VALUES;
- if (controlObject->ctlModel == 4) {
-
- if (controlObject->sbow) {
- if (MmsValue_update(controlObject->sbow, value) == false) {
+ if (controlObject->ctlModel == 4)
+ {
+ if (controlObject->sbow)
+ {
+ if (MmsValue_update(controlObject->sbow, value) == false)
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: SBOw - type mismatch\n");
}
@@ -2024,14 +2120,16 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
MmsValue* ctlVal = getCtlVal(value);
- if (ctlVal != NULL) {
-
+ if (ctlVal != NULL)
+ {
MmsValue* ctlNum = getOperParameterCtlNum(value);
MmsValue* origin = getOperParameterOrigin(value);
MmsValue* check = getOperParameterCheck(value);
MmsValue* test = getOperParameterTest(value);
+ MmsValue* t = getOperParameterTime(value);
- if (checkValidityOfOriginParameter(origin) == false) {
+ if (checkValidityOfOriginParameter(origin) == false)
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
ControlObject_sendLastApplError(controlObject, connection, "SBOw", CONTROL_ERROR_NO_ERROR,
@@ -2043,15 +2141,21 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
+ if (t)
+ {
+ Timestamp_fromMmsValue(&(controlObject->T), t);
+ }
+
int state = getState(controlObject);
uint64_t currentTime = Hal_getTimeInMs();
checkSelectTimeout(controlObject, currentTime, self);
- if (state != STATE_UNSELECTED) {
-
- if ((state == STATE_OPERATE) || (state == STATE_WAIT_FOR_EXECUTION)) {
+ if (state != STATE_UNSELECTED)
+ {
+ if ((state == STATE_OPERATE) || (state == STATE_WAIT_FOR_EXECUTION))
+ {
indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
ControlObject_sendLastApplError(controlObject, connection, "SBOw",
@@ -2063,7 +2167,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
- else {
+ else
+ {
indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
ControlObject_sendLastApplError(controlObject, connection, "SBOw", CONTROL_ERROR_NO_ERROR,
@@ -2075,8 +2180,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
}
- else {
-
+ else
+ {
CheckHandlerResult checkResult = CONTROL_ACCEPTED;
/* opRcvd must not be set here! */
@@ -2091,7 +2196,9 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
controlObject->testMode = testCondition;
- if (controlObject->checkHandler != NULL) { /* perform operative tests */
+ if (controlObject->checkHandler != NULL)
+ {
+ /* perform operative tests */
controlObject->isSelect = 1;
@@ -2103,7 +2210,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
controlObject->isSelect = 0;
}
- if (checkResult == CONTROL_ACCEPTED) {
+ if (checkResult == CONTROL_ACCEPTED)
+ {
selectObject(controlObject, currentTime, connection, self);
indication = DATA_ACCESS_ERROR_SUCCESS;
@@ -2111,7 +2219,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
if (DEBUG_IED_SERVER)
printf("IED_SERVER: SBOw - selected successful\n");
}
- else if (checkResult == CONTROL_WAITING_FOR_SELECT) {
+ else if (checkResult == CONTROL_WAITING_FOR_SELECT)
+ {
controlObject->mmsConnection = connection;
controlObject->operateInvokeId = MmsServerConnection_getLastInvokeId(connection);
@@ -2125,7 +2234,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
indication = DATA_ACCESS_ERROR_NO_RESPONSE;
}
- else {
+ else
+ {
indication = (MmsDataAccessError) checkResult;
ControlObject_sendLastApplError(controlObject, connection, "SBOw", controlObject->errorValue,
@@ -2138,17 +2248,19 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
}
}
}
- else {
+ else
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
- else {
+ else
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto free_and_return;
}
}
- else if (strcmp(varName, "Oper") == 0) {
-
+ else if (strcmp(varName, "Oper") == 0)
+ {
serviceType = IEC61850_SERVICE_TYPE_OPERATE;
MmsValue* ctlVal = getCtlVal(value);
@@ -2159,19 +2271,24 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
MmsValue* timeParameter = getOperParameterTime(value);
if ((ctlVal == NULL) || (test == NULL) || (ctlNum == NULL) || (origin == NULL) || (check == NULL)
- || (timeParameter == NULL)) {
+ || (timeParameter == NULL))
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto free_and_return;
}
- if (checkValidityOfOriginParameter(origin) == false) {
+ Timestamp_fromMmsValue(&(controlObject->T), timeParameter);
+
+ if (checkValidityOfOriginParameter(origin) == false)
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
ControlObject_sendLastApplError(controlObject, connection, "Oper",
CONTROL_ERROR_NO_ERROR, ADD_CAUSE_INCONSISTENT_PARAMETERS,
ctlNum, origin, true);
- if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4)) {
+ if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4))
+ {
unselectObject(controlObject, SELECT_STATE_REASON_OPERATE_FAILED, self);
}
@@ -2184,7 +2301,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
int state = getState(controlObject);
- if (state == STATE_WAIT_FOR_ACTIVATION_TIME) {
+ if (state == STATE_WAIT_FOR_ACTIVATION_TIME)
+ {
indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
ControlObject_sendLastApplError(controlObject, connection, "Oper",
@@ -2193,15 +2311,17 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
- else if (state == STATE_READY) {
-
+ else if (state == STATE_READY)
+ {
bool interlockCheck = MmsValue_getBitStringBit(check, 1);
bool synchroCheck = MmsValue_getBitStringBit(check, 0);
bool testCondition = MmsValue_getBoolean(test);
- if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4)) {
- if (controlObject->mmsConnection != connection) {
+ if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4))
+ {
+ if (controlObject->mmsConnection != connection)
+ {
indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Oper - operate from wrong client connection!\n");
@@ -2212,7 +2332,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
- if (controlObject->ctlModel == 4) { /* select-before-operate with enhanced security */
+ if (controlObject->ctlModel == 4) /* select-before-operate with enhanced security */
+ {
if ((MmsValue_equals(ctlVal, controlObject->ctlVal) &&
MmsValue_equals(origin, controlObject->origin) &&
MmsValue_equals(ctlNum, controlObject->ctlNum) &&
@@ -2240,24 +2361,29 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
MmsValue* operTm = getOperParameterOperTime(value);
- if (operTm != NULL) {
+ if (operTm != NULL)
+ {
controlObject->operateTime = MmsValue_getUtcTimeInMs(operTm);
- if (controlObject->operateTime > currentTime) {
+ if (controlObject->operateTime > currentTime)
+ {
controlObject->timeActivatedOperate = true;
controlObject->synchroCheck = synchroCheck;
controlObject->interlockCheck = interlockCheck;
controlObject->mmsConnection = connection;
CheckHandlerResult checkResult = CONTROL_ACCEPTED;
- if (controlObject->checkHandler != NULL) { /* perform operative tests */
+ if (controlObject->checkHandler != NULL)
+ {
+ /* perform operative tests */
checkResult = controlObject->checkHandler((ControlAction) controlObject,
controlObject->checkHandlerParameter, ctlVal, testCondition, interlockCheck);
}
- if (checkResult == CONTROL_ACCEPTED) {
+ if (checkResult == CONTROL_ACCEPTED)
+ {
initiateControlTask(controlObject);
setState(controlObject, STATE_WAIT_FOR_ACTIVATION_TIME);
@@ -2269,19 +2395,21 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
indication = DATA_ACCESS_ERROR_SUCCESS;
}
- else {
+ else
+ {
indication = (MmsDataAccessError) checkResult;
}
}
}
- else{
+ else
+ {
controlObject->operateTime = 0;
}
MmsValue_update(controlObject->oper, value);
- if (controlObject->timeActivatedOperate == false) {
-
+ if (controlObject->timeActivatedOperate == false)
+ {
CheckHandlerResult checkResult = CONTROL_ACCEPTED;
/* enter state Perform Test */
@@ -2291,13 +2419,16 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
controlObject->addCauseValue = ADD_CAUSE_UNKNOWN;
controlObject->mmsConnection = connection;
- if (controlObject->checkHandler != NULL) { /* perform operative tests */
+ if (controlObject->checkHandler != NULL)
+ {
+ /* perform operative tests */
checkResult = controlObject->checkHandler((ControlAction) controlObject,
controlObject->checkHandlerParameter, ctlVal, testCondition, interlockCheck);
}
- if (checkResult == CONTROL_ACCEPTED) {
+ if (checkResult == CONTROL_ACCEPTED)
+ {
indication = DATA_ACCESS_ERROR_NO_RESPONSE;
controlObject->mmsConnection = connection;
@@ -2313,7 +2444,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
updateNextControlTimeout(self, currentTime);
}
- else {
+ else
+ {
indication = (MmsDataAccessError) checkResult;
/* leave state Perform Test */
@@ -2321,7 +2453,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
abortControlOperation(controlObject, false, SELECT_STATE_REASON_OPERATE_FAILED, self);
- if ((controlObject->ctlModel == 3) || (controlObject->ctlModel == 4)) {
+ if ((controlObject->ctlModel == 3) || (controlObject->ctlModel == 4))
+ {
ControlObject_sendLastApplError(controlObject, connection, "Oper",
controlObject->errorValue, controlObject->addCauseValue,
ctlNum, origin, true);
@@ -2330,7 +2463,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
}
}
- else if (state == STATE_UNSELECTED) {
+ else if (state == STATE_UNSELECTED)
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Oper failed - control not selected!\n");
@@ -2343,7 +2477,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
- else if ((state == STATE_OPERATE) || (state == STATE_WAIT_FOR_EXECUTION)) {
+ else if ((state == STATE_OPERATE) || (state == STATE_WAIT_FOR_EXECUTION))
+ {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Oper failed - control already being executed!\n");
@@ -2356,8 +2491,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
}
- else if (strcmp(varName, "Cancel") == 0) {
-
+ else if (strcmp(varName, "Cancel") == 0)
+ {
serviceType = IEC61850_SERVICE_TYPE_CANCEL;
int state = getState(controlObject);
@@ -2368,14 +2503,16 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
MmsValue* ctlNum = getCancelParameterCtlNum(value);
MmsValue* origin = getCancelParameterOrigin(value);
- if ((ctlNum == NULL) || (origin == NULL)) {
+ if ((ctlNum == NULL) || (origin == NULL))
+ {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
if (DEBUG_IED_SERVER)
printf("IED_SERVER: Invalid cancel message!\n");
goto free_and_return;
}
- if ((state == STATE_OPERATE) || (state == STATE_WAIT_FOR_EXECUTION)) {
+ if ((state == STATE_OPERATE) || (state == STATE_WAIT_FOR_EXECUTION))
+ {
indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
ControlObject_sendLastApplError(controlObject, connection, "Cancel",
@@ -2385,26 +2522,32 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
- if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4)) {
- if (state != STATE_UNSELECTED) {
- if (controlObject->mmsConnection == connection) {
+ if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4))
+ {
+ if (state != STATE_UNSELECTED)
+ {
+ if (controlObject->mmsConnection == connection)
+ {
indication = DATA_ACCESS_ERROR_SUCCESS;
unselectObject(controlObject, SELECT_STATE_REASON_CANCELED, self);
goto free_and_return;
}
- else {
+ else
+ {
indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
ControlObject_sendLastApplError(controlObject, connection, "Cancel",
CONTROL_ERROR_NO_ERROR, ADD_CAUSE_LOCKED_BY_OTHER_CLIENT,
ctlNum, origin, true);
}
}
- else {
+ else
+ {
indication = DATA_ACCESS_ERROR_SUCCESS;
}
}
- if (controlObject->timeActivatedOperate) {
+ if (controlObject->timeActivatedOperate)
+ {
controlObject->timeActivatedOperate = false;
abortControlOperation(controlObject, false, SELECT_STATE_REASON_CANCELED, self);
@@ -2417,14 +2560,18 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
free_and_return:
#if (CONFIG_IEC61850_SERVICE_TRACKING == 1)
- if (controlObject) {
- if (serviceError == IEC61850_SERVICE_ERROR_NO_ERROR) {
- if (indication != DATA_ACCESS_ERROR_NO_RESPONSE) {
+ if (controlObject)
+ {
+ if (serviceError == IEC61850_SERVICE_ERROR_NO_ERROR)
+ {
+ if (indication != DATA_ACCESS_ERROR_NO_RESPONSE)
+ {
updateGenericTrackingObjectValues(self, controlObject, serviceType,
private_IedServer_convertMmsDataAccessErrorToServiceError(indication));
}
}
- else {
+ else
+ {
updateGenericTrackingObjectValues(self, controlObject, serviceType, serviceError);
}
}
@@ -2456,7 +2603,8 @@ ControlAction_getOrCat(ControlAction self)
{
ControlObject* controlObject = (ControlObject*) self;
- if (controlObject->origin) {
+ if (controlObject->origin)
+ {
MmsValue* orCat = MmsValue_getElement(controlObject->origin, 0);
if (orCat) {
@@ -2472,10 +2620,12 @@ ControlAction_getOrIdent(ControlAction self, int* orIdentSize)
{
ControlObject* controlObject = (ControlObject*) self;
- if (controlObject->origin) {
+ if (controlObject->origin)
+ {
MmsValue* orIdent = MmsValue_getElement(controlObject->origin, 1);
- if (orIdent) {
+ if (orIdent)
+ {
if (MmsValue_getType(orIdent) == MMS_OCTET_STRING) {
*orIdentSize = MmsValue_getOctetStringSize(orIdent);
return MmsValue_getOctetStringBuffer(orIdent);
@@ -2549,5 +2699,12 @@ ControlAction_getControlTime(ControlAction self)
return controlObject->operateTime;
}
-#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
+Timestamp*
+ControlAction_getT(ControlAction self)
+{
+ ControlObject* controlObject = (ControlObject*) self;
+ return &(controlObject->T);
+}
+
+#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c
index 7fcb78f1..59b0ba40 100644
--- a/src/iec61850/server/mms_mapping/logging.c
+++ b/src/iec61850/server/mms_mapping/logging.c
@@ -482,7 +482,7 @@ copyLCBValuesToTrackingObject(MmsMapping* self, LogControl* logControl)
#endif /* (CONFIG_IEC61850_SERVICE_TRACKING == 1) */
MmsDataAccessError
-LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection)
{
(void)connection;
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index 27471a58..1435df2d 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -1,7 +1,7 @@
/*
* mms_mapping.c
*
- * Copyright 2013-2023 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -1335,8 +1335,8 @@ checkForServiceTrackingVariables(MmsMapping* self, LogicalNode* logicalNode)
{
ModelNode* modelNode = logicalNode->firstChild;
- while (modelNode) {
-
+ while (modelNode)
+ {
if (!strcmp(modelNode->name, "SpcTrk") || !strcmp(modelNode->name, "DpcTrk") ||
!strcmp(modelNode->name, "IncTrk") || !strcmp(modelNode->name, "EncTrk1") ||
!strcmp(modelNode->name, "ApcFTrk") || !strcmp(modelNode->name, "ApcIntTrk") ||
@@ -2344,7 +2344,7 @@ lookupGCB(MmsMapping* self, MmsDomain* domain, char* lnName, char* objectName)
#endif
static MmsDataAccessError
-writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection)
{
char variableId[130];
@@ -2499,43 +2499,6 @@ writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variable
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
-#if 0
-static MmsValue*
-checkIfValueBelongsToModelNode(DataAttribute* dataAttribute, MmsValue* value, MmsValue* newValue)
-{
- if (dataAttribute->mmsValue == value)
- return newValue;
-
- DataAttribute* child = (DataAttribute*) dataAttribute->firstChild;
-
- while (child != NULL) {
- MmsValue* tmpValue = checkIfValueBelongsToModelNode(child, value, newValue);
-
- if (tmpValue != NULL)
- return tmpValue;
- else
- child = (DataAttribute*) child->sibling;
- }
-
- if (MmsValue_getType(value) == MMS_STRUCTURE) {
- int elementCount = MmsValue_getArraySize(value);
-
- int i;
- for (i = 0; i < elementCount; i++) {
- MmsValue* childValue = MmsValue_getElement(value, i);
- MmsValue* childNewValue = MmsValue_getElement(newValue, i);
-
- MmsValue* tmpValue = checkIfValueBelongsToModelNode(dataAttribute, childValue, childNewValue);
-
- if (tmpValue != NULL)
- return tmpValue;
- }
- }
-
- return NULL;
-}
-#endif
-
static FunctionalConstraint
getFunctionalConstraintForWritableNode(char* separator)
{
@@ -2605,16 +2568,28 @@ getAccessPolicyForFC(MmsMapping* self, FunctionalConstraint fc)
static MmsDataAccessError
mmsWriteHandler(void* parameter, MmsDomain* domain,
- char* variableId, MmsValue* value, MmsServerConnection connection)
+ const char* variableId, int arrayIdx, const char* componentId, MmsValue* value, MmsServerConnection connection)
{
MmsMapping* self = (MmsMapping*) parameter;
if (DEBUG_IED_SERVER)
- printf("IED_SERVER: Write requested %s\n", variableId);
+ {
+ if (arrayIdx != -1) {
+ if (componentId) {
+ printf("IED_SERVER: Write requested %s(%i).%s\n", variableId, arrayIdx, componentId);
+ }
+ else {
+ printf("IED_SERVER: Write requested %s(%i)\n", variableId, arrayIdx);
+ }
+ }
+ else {
+ printf("IED_SERVER: Write requested %s\n", variableId);
+ }
+ }
/* Access control based on functional constraint */
- char* separator = strchr(variableId, '$');
+ char* separator = (char*)strchr(variableId, '$');
if (separator == NULL)
return DATA_ACCESS_ERROR_INVALID_ADDRESS;
@@ -2691,7 +2666,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
if (rcNameLen == variableIdLen) {
if (strncmp(variableId, rc->name, variableIdLen) == 0) {
- char* elementName = variableId + rcNameLen + 1;
+ const char* elementName = variableId + rcNameLen + 1;
return Reporting_RCBWriteAccessHandler(self, rc, elementName, value, connection);
}
@@ -2713,6 +2688,10 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
if (nextSep != NULL) {
nextSep = strchr(nextSep + 1, '$');
+ if (nextSep == NULL) {
+ return DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
+ }
+
char* nameId = nextSep + 1;
/* check access permissions */
@@ -2942,13 +2921,19 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
#endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */
/* writable data model elements - SP, SV, CF, DC, BL */
- if (fc != IEC61850_FC_NONE) {
+ if (fc != IEC61850_FC_NONE)
+ {
MmsValue* cachedValue;
- cachedValue = MmsServer_getValueFromCache(self->mmsServer, domain, variableId);
-
- if (cachedValue) {
+ if (arrayIdx != -1) {
+ cachedValue = MmsServer_getValueFromCacheEx2(self->mmsServer, domain, variableId, arrayIdx, componentId);
+ }
+ else {
+ cachedValue = MmsServer_getValueFromCache(self->mmsServer, domain, variableId);
+ }
+ if (cachedValue)
+ {
if (!MmsValue_equalTypes(cachedValue, value)) {
return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
}
@@ -2961,7 +2946,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
printf("IED_SERVER: write to %s policy:%i\n", variableId, nodeAccessPolicy);
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
- if (isFunctionalConstraint("SE", separator)) {
+ if (isFunctionalConstraint("SE", separator))
+ {
SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
if (sg != NULL) {
@@ -2978,12 +2964,13 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
/* Call write access handlers */
LinkedList writeHandlerListElement = LinkedList_getNext(self->attributeAccessHandlers);
- while (writeHandlerListElement != NULL) {
+ while (writeHandlerListElement)
+ {
AttributeAccessHandler* accessHandler = (AttributeAccessHandler*) writeHandlerListElement->data;
DataAttribute* dataAttribute = accessHandler->attribute;
- if (dataAttribute->mmsValue == cachedValue) {
-
+ if (dataAttribute->mmsValue == cachedValue)
+ {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
@@ -2991,7 +2978,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
accessHandler->handler(dataAttribute, value, clientConnection,
accessHandler->parameter);
- if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)) {
+ if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE))
+ {
handlerFound = true;
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)
@@ -3007,14 +2995,14 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
}
/* DENY access if no handler is found and default policy is DENY */
- if (!handlerFound) {
-
+ if (!handlerFound)
+ {
if (nodeAccessPolicy == ACCESS_POLICY_DENY)
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
-
}
- if (updateValue) {
+ if (updateValue)
+ {
DataAttribute* da = IedModel_lookupDataAttributeByMmsValue(self->model, cachedValue);
if (da)
@@ -3161,7 +3149,6 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
}
#endif
-
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
/* GOOSE control blocks - GO */
if (isGooseControlBlock(separator)) {
@@ -3188,8 +3175,8 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */
- if (isReportControlBlock(separator)) {
-
+ if (isReportControlBlock(separator))
+ {
LinkedList reportControls = self->reportControls;
LinkedList nextElement = reportControls;
@@ -3210,11 +3197,12 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
else
variableIdLen = strlen(variableId);
- while ((nextElement = LinkedList_getNext(nextElement)) != NULL) {
+ while ((nextElement = LinkedList_getNext(nextElement)) != NULL)
+ {
ReportControl* rc = (ReportControl*) nextElement->data;
- if (rc->domain == domain) {
-
+ if (rc->domain == domain)
+ {
int parentLNNameStrLen = strlen(rc->parentLN->name);
if (parentLNNameStrLen != lnNameLength)
@@ -3223,7 +3211,8 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
if (memcmp(rc->parentLN->name, variableId, parentLNNameStrLen) != 0)
continue;
- if (strlen(rc->name) == variableIdLen) {
+ if (strlen(rc->name) == variableIdLen)
+ {
if (strncmp(variableId, rc->name, variableIdLen) == 0)
{
char* elementName = MmsMapping_getNextNameElement(reportName);
@@ -3640,15 +3629,26 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
if (DEBUG_IED_SERVER)
printf("IED_SERVER: mmsReadAccessHandler: Requested %s\n", variableId);
+ if (self->iedServer->ignoreReadAccess)
+ {
+ if (DEBUG_IED_SERVER)
+ printf("IED_SERVER: mmsReadAccessHandler - ignore request\n");
+
+ return DATA_ACCESS_ERROR_NO_RESPONSE;
+ }
+
char* separator = strchr(variableId, '$');
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
- if (separator) {
- if (isFunctionalConstraint("SE", separator)) {
+ if (separator)
+ {
+ if (isFunctionalConstraint("SE", separator))
+ {
SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
- if (sg != NULL) {
+ if (sg != NULL)
+ {
if (sg->sgcb->editSG == 0)
return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
}
@@ -3670,7 +3670,8 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
{
FunctionalConstraint fc = IEC61850_FC_NONE;
- if (separator != NULL) {
+ if (separator != NULL)
+ {
fc = FunctionalConstraint_fromString(separator + 1);
if (fc == IEC61850_FC_BR || fc == IEC61850_FC_US ||
@@ -3691,23 +3692,27 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
{
char* doStart = strchr(separator + 1, '$');
- if (doStart != NULL) {
-
+ if (doStart != NULL)
+ {
char* doEnd = strchr(doStart + 1, '$');
- if (doEnd == NULL) {
+ if (doEnd == NULL)
+ {
StringUtils_copyStringToBuffer(doStart + 1, str);
}
- else {
+ else
+ {
doEnd--;
StringUtils_createStringFromBufferInBuffer(str, (uint8_t*) (doStart + 1), doEnd - doStart);
}
- if (fc == IEC61850_FC_SP) {
+ if (fc == IEC61850_FC_SP)
+ {
if (!strcmp(str, "SGCB"))
{
- if (self->controlBlockAccessHandler) {
+ if (self->controlBlockAccessHandler)
+ {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
@@ -3722,10 +3727,10 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
ModelNode* dobj = ModelNode_getChild((ModelNode*) ln, str);
- if (dobj != NULL) {
-
- if (dobj->modelType == DataObjectModelType) {
-
+ if (dobj != NULL)
+ {
+ if (dobj->modelType == DataObjectModelType)
+ {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
@@ -3734,7 +3739,8 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
}
}
}
- else {
+ else
+ {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
@@ -3744,10 +3750,12 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
}
}
}
- else {
+ else
+ {
LogicalNode* ln = LogicalDevice_getLogicalNode(ld, variableId);
- if (ln != NULL) {
+ if (ln != NULL)
+ {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
return self->readAccessHandler(ld, ln, NULL, fc, clientConnection,
@@ -4219,10 +4227,12 @@ MmsMapping_triggerReportObservers(MmsMapping* self, MmsValue* value, int flag)
bool modelLocked = self->isModelLocked;
- while ((element = LinkedList_getNext(element)) != NULL) {
+ while ((element = LinkedList_getNext(element)) != NULL)
+ {
ReportControl* rc = (ReportControl*) element->data;
- if (rc->enabled || (rc->buffered && rc->dataSet != NULL)) {
+ if (rc->enabled || (rc->buffered && rc->dataSet != NULL))
+ {
int index;
switch (flag) {
diff --git a/src/iec61850/server/mms_mapping/mms_sv.c b/src/iec61850/server/mms_mapping/mms_sv.c
index ef2ad775..3fbd0d2b 100644
--- a/src/iec61850/server/mms_mapping/mms_sv.c
+++ b/src/iec61850/server/mms_mapping/mms_sv.c
@@ -131,7 +131,7 @@ MmsSampledValueControlBlock_isEnabled(MmsSampledValueControlBlock self)
}
MmsDataAccessError
-LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
+LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, const char* variableIdOrig,
MmsValue* value, MmsServerConnection connection)
{
char variableId[130];
diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c
index 493d5e48..0bb683f1 100644
--- a/src/iec61850/server/mms_mapping/reporting.c
+++ b/src/iec61850/server/mms_mapping/reporting.c
@@ -1,7 +1,7 @@
/*
* reporting.c
*
- * Copyright 2013-2023 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -185,7 +185,8 @@ purgeBuf(ReportControl* rc)
static void
deleteDataSetValuesShadowBuffer(ReportControl* self)
{
- if (self->bufferedDataSetValues != NULL) {
+ if (self->bufferedDataSetValues != NULL)
+ {
assert(self->dataSet != NULL);
int dataSetSize = DataSet_getSize(self->dataSet);
@@ -252,7 +253,7 @@ ReportControl_destroy(ReportControl* self)
}
MmsValue*
-ReportControl_getRCBValue(ReportControl* rc, char* elementName)
+ReportControl_getRCBValue(ReportControl* rc, const char* elementName)
{
if (rc->buffered) {
if (strcmp(elementName, "RptID") == 0)
@@ -460,7 +461,7 @@ copyRCBValuesToTrackingObject(MmsMapping* self, ReportControl* rc)
}
static void
-updateSingleTrackingValue(MmsMapping* self, ReportControl* rc, char* name, MmsValue* newValue)
+updateSingleTrackingValue(MmsMapping* self, ReportControl* rc, const char* name, MmsValue* newValue)
{
if (rc->buffered) {
if (self->brcbTrk) {
@@ -1906,7 +1907,7 @@ reserveRcb(ReportControl* rc, MmsServerConnection connection)
}
MmsDataAccessError
-Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* elementName, MmsValue* value,
+Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, const char* elementName, MmsValue* value,
MmsServerConnection connection)
{
MmsDataAccessError retVal = DATA_ACCESS_ERROR_SUCCESS;
@@ -2911,13 +2912,14 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
int dataBlockSize = 0;
- if (isIntegrity || isGI) {
-
+ if (isIntegrity || isGI)
+ {
DataSetEntry* dataSetEntry = reportControl->dataSet->fcdas;
int i;
- for (i = 0; i < inclusionBitStringSize; i++) {
+ for (i = 0; i < inclusionBitStringSize; i++)
+ {
/* don't need reason for inclusion in GI or integrity report */
int encodedSize;
@@ -2925,7 +2927,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
if (dataSetEntry->value) {
encodedSize = MmsValue_encodeMmsData(dataSetEntry->value, NULL, 0, false);
}
- else {
+ else
+ {
MmsValue _errVal;
_errVal.type = MMS_DATA_ACCESS_ERROR;
_errVal.value.dataAccessError = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
@@ -2940,17 +2943,19 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
bufferEntrySize += MemoryAllocator_getAlignedSize(sizeof(int) + dataBlockSize); /* add aligned_size(LEN + DATA) */
}
- else { /* other trigger reason */
+ else
+ {
+ /* other trigger reason */
bufferEntrySize += inclusionFieldSize;
int reasonForInclusionSize = 0;
int i;
- for (i = 0; i < inclusionBitStringSize; i++) {
-
- if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE) {
-
+ for (i = 0; i < inclusionBitStringSize; i++)
+ {
+ if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE)
+ {
reasonForInclusionSize++;
assert(reportControl->bufferedDataSetValues[i] != NULL);
@@ -2985,13 +2990,15 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
if (DEBUG_IED_SERVER)
printf("IED_SERVER: number of reports in report buffer: %i\n", buffer->reportsCount);
- if (buffer->lastEnqueuedReport == NULL) { /* buffer is empty - we start at the beginning of the memory block */
+ if (buffer->lastEnqueuedReport == NULL)
+ {
+ /* buffer is empty - we start at the beginning of the memory block */
entryBufPos = buffer->memoryBlock;
buffer->oldestReport = (ReportBufferEntry*) entryBufPos;
buffer->nextToTransmit = (ReportBufferEntry*) entryBufPos;
}
- else {
-
+ else
+ {
assert(buffer->lastEnqueuedReport != NULL);
assert(buffer->oldestReport != NULL);
@@ -3003,12 +3010,16 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
if (DEBUG_IED_SERVER) printf ("IED_SERVER: Last buffer offset: %i\n", (int) ((uint8_t*) buffer->lastEnqueuedReport - buffer->memoryBlock));
- if (buffer->lastEnqueuedReport == buffer->oldestReport) { /* --> buffer->reportsCount == 1 */
+ if (buffer->lastEnqueuedReport == buffer->oldestReport)
+ {
+ /* --> buffer->reportsCount == 1 */
assert(buffer->reportsCount == 1);
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
- if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
+ if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize))
+ {
+ /* buffer overflow */
entryBufPos = buffer->memoryBlock;
#if (DEBUG_IED_SERVER == 1)
@@ -3022,7 +3033,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
buffer->oldestReport->next = NULL;
buffer->nextToTransmit = NULL;
}
- else {
+ else
+ {
if (buffer->nextToTransmit == buffer->oldestReport)
buffer->nextToTransmit = buffer->lastEnqueuedReport;
@@ -3031,17 +3043,22 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
}
}
- else if (buffer->lastEnqueuedReport > buffer->oldestReport) {
+ else if (buffer->lastEnqueuedReport > buffer->oldestReport)
+ {
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
- if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
+ if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize))
+ {
+ /* buffer overflow */
entryBufPos = buffer->memoryBlock;
/* remove old reports until enough space for new entry is available */
- while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) {
+ while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport)
+ {
assert(buffer->oldestReport != NULL);
- if (buffer->nextToTransmit == buffer->oldestReport) {
+ if (buffer->nextToTransmit == buffer->oldestReport)
+ {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
overflow = true;
@@ -3056,7 +3073,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
buffer->reportsCount--;
- if (buffer->oldestReport == NULL) {
+ if (buffer->oldestReport == NULL)
+ {
buffer->oldestReport = (ReportBufferEntry*) entryBufPos;
buffer->oldestReport->next = NULL;
break;
@@ -3066,14 +3084,18 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
buffer->lastEnqueuedReport->next = (ReportBufferEntry*) entryBufPos;
}
- else if (buffer->lastEnqueuedReport < buffer->oldestReport) {
+ else if (buffer->lastEnqueuedReport < buffer->oldestReport)
+ {
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
- if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
+ if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize))
+ {
+ /* buffer overflow */
entryBufPos = buffer->memoryBlock;
/* remove older reports in upper buffer part */
- while ((uint8_t*) buffer->oldestReport > buffer->memoryBlock) {
+ while ((uint8_t*) buffer->oldestReport > buffer->memoryBlock)
+ {
assert(buffer->oldestReport != NULL);
if (buffer->nextToTransmit == buffer->oldestReport) {
@@ -3093,13 +3115,15 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
}
/* remove older reports in lower buffer part that will be overwritten by new report */
- while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) {
+ while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport)
+ {
if (buffer->oldestReport == NULL)
break;
assert(buffer->oldestReport != NULL);
- if (buffer->nextToTransmit == buffer->oldestReport) {
+ if (buffer->nextToTransmit == buffer->oldestReport)
+ {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
overflow = true;
@@ -3115,15 +3139,17 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
buffer->reportsCount--;
}
}
- else {
- while (((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) && ((uint8_t*) buffer->oldestReport != buffer->memoryBlock)) {
-
+ else
+ {
+ while (((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) && ((uint8_t*) buffer->oldestReport != buffer->memoryBlock))
+ {
if (buffer->oldestReport == NULL)
break;
assert(buffer->oldestReport != NULL);
- if (buffer->nextToTransmit == buffer->oldestReport) {
+ if (buffer->nextToTransmit == buffer->oldestReport)
+ {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
overflow = true;
@@ -3154,7 +3180,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
entry->timeOfEntry = timeOfEntry;
- if (isBuffered) {
+ if (isBuffered)
+ {
/* ENTRY_ID is set to system time in ms! */
uint64_t entryId = timeOfEntry;
@@ -3173,7 +3200,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
printf(" at pos %p\n", entryStartPos);
#endif
- if (reportControl->enabled == false) {
+ if (reportControl->enabled == false)
+ {
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore_wait(reportControl->rcbValuesLock);
#endif
@@ -3200,7 +3228,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
entryBufPos += MemoryAllocator_getAlignedSize(sizeof(ReportBufferEntry));
- if (isIntegrity || isGI) {
+ if (isIntegrity || isGI)
+ {
DataSetEntry* dataSetEntry = reportControl->dataSet->fcdas;
/* encode LEN */
@@ -3210,12 +3239,13 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
/* encode DATA */
int i;
- for (i = 0; i < inclusionBitStringSize; i++) {
-
+ for (i = 0; i < inclusionBitStringSize; i++)
+ {
if (dataSetEntry->value) {
entryBufPos += MmsValue_encodeMmsData(dataSetEntry->value, entryBufPos, 0, true);
}
- else {
+ else
+ {
MmsValue _errVal;
_errVal.type = MMS_DATA_ACCESS_ERROR;
_errVal.value.dataAccessError = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
@@ -3225,9 +3255,9 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
dataSetEntry = dataSetEntry->sibling;
}
-
}
- else {
+ else
+ {
/* encode inclusion bit string */
inclusionFieldStatic.value.bitString.buf = entryBufPos;
memset(entryBufPos, 0, inclusionFieldSize);
@@ -3240,10 +3270,10 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
/* encode DATA */
int i;
- for (i = 0; i < inclusionBitStringSize; i++) {
-
- if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE) {
-
+ for (i = 0; i < inclusionBitStringSize; i++)
+ {
+ if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE)
+ {
/* update inclusion bit string for report entry */
MmsValue_setBitStringBit(inclusionField, i, true);
@@ -3251,13 +3281,14 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
entryBufPos += MmsValue_encodeMmsData(reportControl->bufferedDataSetValues[i], entryBufPos, 0, true);
}
-
}
/* encode REASON */
- for (i = 0; i < inclusionBitStringSize; i++) {
+ for (i = 0; i < inclusionBitStringSize; i++)
+ {
- if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE) {
+ if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE)
+ {
*entryBufPos = (uint8_t) reportControl->inclusionFlags[i];
entryBufPos ++;
}
@@ -3286,10 +3317,12 @@ exit_function:
Semaphore_post(buffer->lock);
#endif
- if (reportControl->server) {
+ if (reportControl->server)
+ {
MmsMapping* mmsMapping = reportControl->server->mmsMapping;
- if (mmsMapping->rcbEventHandler) {
+ if (mmsMapping->rcbEventHandler)
+ {
if (overflow) {
mmsMapping->rcbEventHandler(mmsMapping->rcbEventHandlerParameter, reportControl->rcb, NULL, RCB_EVENT_OVERFLOW, NULL, DATA_ACCESS_ERROR_SUCCESS);
}
@@ -3980,11 +4013,12 @@ Reporting_activateBufferedReports(MmsMapping* self)
static void
processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
{
- if ((rc->enabled) || (rc->isBuffering)) {
-
- if (rc->triggerOps & TRG_OPT_GI) {
- if (rc->gi) {
-
+ if ((rc->enabled) || (rc->isBuffering))
+ {
+ if (rc->triggerOps & TRG_OPT_GI)
+ {
+ if (rc->gi)
+ {
/* send current events in event buffer before GI report */
if (rc->triggered) {
rc->triggered = false;
@@ -3999,12 +4033,12 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
}
}
- if (rc->triggerOps & TRG_OPT_INTEGRITY) {
-
- if (rc->intgPd > 0) {
-
- if (currentTimeInMs >= rc->nextIntgReportTime) {
-
+ if (rc->triggerOps & TRG_OPT_INTEGRITY)
+ {
+ if (rc->intgPd > 0)
+ {
+ if (currentTimeInMs >= rc->nextIntgReportTime)
+ {
/* send current events in event buffer before integrity report */
if (rc->triggered) {
enqueueReport(rc, false, false, currentTimeInMs);
@@ -4019,8 +4053,8 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
}
/* check for system time change effects */
- if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd)) {
-
+ if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd))
+ {
if (rc->server->syncIntegrityReportTimes) {
rc->nextIntgReportTime = getNextRoundedStartTime(currentTimeInMs, rc->intgPd);
}
@@ -4033,9 +4067,11 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
rc->triggered = false;
}
- else {
+ else
+ {
/* check for system time change effects */
- if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd)) {
+ if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd))
+ {
if (rc->server->syncIntegrityReportTimes) {
rc->nextIntgReportTime = getNextRoundedStartTime(currentTimeInMs, rc->intgPd);
}
@@ -4047,9 +4083,10 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
}
}
- if (rc->triggered) {
- if (currentTimeInMs >= rc->reportTime) {
-
+ if (rc->triggered)
+ {
+ if (currentTimeInMs >= rc->reportTime)
+ {
enqueueReport(rc, false, false, currentTimeInMs);
rc->triggered = false;
@@ -4065,11 +4102,12 @@ Reporting_processReportEvents(MmsMapping* self, uint64_t currentTimeInMs)
Semaphore_wait(self->isModelLockedMutex);
#endif
- if (self->isModelLocked == false) {
-
+ if (self->isModelLocked == false)
+ {
LinkedList element = self->reportControls;
- while ((element = LinkedList_getNext(element)) != NULL ) {
+ while ((element = LinkedList_getNext(element)) != NULL )
+ {
ReportControl* rc = (ReportControl*) element->data;
ReportControl_lockNotify(rc);
@@ -4093,11 +4131,12 @@ Reporting_sendReports(MmsMapping* self, MmsServerConnection connection)
{
LinkedList element = LinkedList_getNext(self->reportControls);
- while (element) {
+ while (element)
+ {
ReportControl* rc = (ReportControl*) LinkedList_getData(element);
- if (rc->clientConnection == connection) {
-
+ if (rc->clientConnection == connection)
+ {
ReportControl_lockNotify(rc);
if (rc->enabled) {
@@ -4124,8 +4163,10 @@ static void
copyValuesToReportBuffer(ReportControl* self)
{
int i;
- for (i = 0; i < self->dataSet->elementCount; i++) {
- if (self->inclusionFlags[i] & REPORT_CONTROL_NOT_UPDATED) {
+ for (i = 0; i < self->dataSet->elementCount; i++)
+ {
+ if (self->inclusionFlags[i] & REPORT_CONTROL_NOT_UPDATED)
+ {
copySingleValueToReportBuffer(self, i);
/* clear not-updated flag */
@@ -4142,13 +4183,14 @@ Reporting_processReportEventsAfterUnlock(MmsMapping* self)
uint64_t currentTime = Hal_getTimeInMs();
- while ((element = LinkedList_getNext(element)) != NULL ) {
+ while ((element = LinkedList_getNext(element)) != NULL )
+ {
ReportControl* rc = (ReportControl*) element->data;
ReportControl_lockNotify(rc);
- if ((rc->enabled) || (rc->isBuffering)) {
-
+ if ((rc->enabled) || (rc->isBuffering))
+ {
if (rc->triggered) {
copyValuesToReportBuffer(rc);
@@ -4166,10 +4208,13 @@ ReportControl_valueUpdated(ReportControl* self, int dataSetEntryIndex, int flag,
{
ReportControl_lockNotify(self);
- if (self->inclusionFlags[dataSetEntryIndex] & flag) { /* report for this data set entry is already pending (bypass BufTm) */
+ if (self->inclusionFlags[dataSetEntryIndex] & flag)
+ {
+ /* report for this data set entry is already pending (bypass BufTm and send report immediately) */
self->reportTime = Hal_getTimeInMs();
- if (modelLocked) {
+ if (modelLocked)
+ {
/* buffer all relevant values */
copyValuesToReportBuffer(self);
}
@@ -4177,19 +4222,21 @@ ReportControl_valueUpdated(ReportControl* self, int dataSetEntryIndex, int flag,
processEventsForReport(self, self->reportTime);
}
- if (modelLocked) {
+ if (modelLocked)
+ {
/* set flag to update values when report is to be sent or data model unlocked */
self->inclusionFlags[dataSetEntryIndex] = self->inclusionFlags[dataSetEntryIndex] | flag | REPORT_CONTROL_NOT_UPDATED;
-
}
- else {
+ else
+ {
self->inclusionFlags[dataSetEntryIndex] = flag;
/* buffer value for report */
copySingleValueToReportBuffer(self, dataSetEntryIndex);
}
- if (self->triggered == false) {
+ if (self->triggered == false)
+ {
uint64_t currentTime = Hal_getTimeInMs();
MmsValue_setBinaryTime(self->timeOfEntry, currentTime);
@@ -4218,7 +4265,8 @@ ReportControlBlock_getRptEna(ReportControlBlock* self)
char*
ReportControlBlock_getRptID(ReportControlBlock* self)
{
- if (self->trgOps & 64) {
+ if (self->trgOps & 64)
+ {
ReportControl* rc = (ReportControl*)(self->sibling);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
diff --git a/src/iec61850/server/model/config_file_parser.c b/src/iec61850/server/model/config_file_parser.c
index 8f2abeca..f9489375 100644
--- a/src/iec61850/server/model/config_file_parser.c
+++ b/src/iec61850/server/model/config_file_parser.c
@@ -1,7 +1,7 @@
/*
* config_file_parser.c
*
- * Copyright 2014-2022 Michael Zillgith
+ * Copyright 2014-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -28,9 +28,9 @@
#include "libiec61850_platform_includes.h"
#include "stack_config.h"
-#define READ_BUFFER_MAX_SIZE 1024
+#include
-static uint8_t lineBuffer[READ_BUFFER_MAX_SIZE];
+#define READ_BUFFER_MAX_SIZE 1024
static int
readLine(FileHandle fileHandle, uint8_t* buffer, int maxSize)
@@ -114,18 +114,132 @@ ConfigFileParser_createModelFromConfigFileEx(const char* filename)
return model;
}
+static bool
+setValue(char* lineBuffer, DataAttribute* dataAttribute)
+{
+ char* valueIndicator = strchr((char*) lineBuffer, '=');
+
+ if (valueIndicator != NULL) {
+ switch (dataAttribute->type) {
+ case IEC61850_UNICODE_STRING_255:
+ {
+ char* stringStart = valueIndicator + 2;
+ terminateString(stringStart, '"');
+ dataAttribute->mmsValue = MmsValue_newMmsString(stringStart);
+ }
+ break;
+
+ case IEC61850_VISIBLE_STRING_255:
+ case IEC61850_VISIBLE_STRING_129:
+ case IEC61850_VISIBLE_STRING_65:
+ case IEC61850_VISIBLE_STRING_64:
+ case IEC61850_VISIBLE_STRING_32:
+ case IEC61850_CURRENCY:
+ {
+ char* stringStart = valueIndicator + 2;
+ terminateString(stringStart, '"');
+ dataAttribute->mmsValue = MmsValue_newVisibleString(stringStart);
+ }
+ break;
+
+ case IEC61850_INT8:
+ case IEC61850_INT16:
+ case IEC61850_INT32:
+ case IEC61850_INT64:
+ case IEC61850_INT128:
+ case IEC61850_ENUMERATED:
+ {
+ int32_t intValue;
+ if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newIntegerFromInt32(intValue);
+ }
+ break;
+
+ case IEC61850_INT8U:
+ case IEC61850_INT16U:
+ case IEC61850_INT24U:
+ case IEC61850_INT32U:
+ {
+ uint32_t uintValue;
+ if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newUnsignedFromUint32(uintValue);
+ }
+ break;
+
+ case IEC61850_FLOAT32:
+ {
+ float floatValue;
+ if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newFloat(floatValue);
+ }
+ break;
+
+ case IEC61850_FLOAT64:
+ {
+ double doubleValue;
+ if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newDouble(doubleValue);
+ }
+ break;
+
+ case IEC61850_BOOLEAN:
+ {
+ int boolean;
+ if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newBoolean((bool) boolean);
+ }
+ break;
+
+ case IEC61850_OPTFLDS:
+ {
+ int value;
+ if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newBitString(-10);
+ MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
+ }
+ break;
+
+ case IEC61850_TRGOPS:
+ {
+ int value;
+ if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
+ dataAttribute->mmsValue = MmsValue_newBitString(-6);
+ MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ return true;
+
+exit_error:
+ return false;
+}
+
IedModel*
ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
{
+ uint8_t* lineBuffer = (uint8_t*)GLOBAL_MALLOC(READ_BUFFER_MAX_SIZE);
+
+ if (lineBuffer == NULL)
+ goto exit_error;
+
int bytesRead = 1;
bool stateInModel = false;
int indendation = 0;
+ bool inArray = false;
+ bool inArrayElement = false;
IedModel* model = NULL;
LogicalDevice* currentLD = NULL;
LogicalNode* currentLN = NULL;
ModelNode* currentModelNode = NULL;
+ ModelNode* currentArrayNode = NULL;
DataSet* currentDataSet = NULL;
GSEControlBlock* currentGoCB = NULL;
SVControlBlock* currentSMVCB = NULL;
@@ -136,16 +250,30 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
int currentLine = 0;
- while (bytesRead > 0) {
+ while (bytesRead > 0)
+ {
bytesRead = readLine(fileHandle, lineBuffer, READ_BUFFER_MAX_SIZE);
currentLine++;
- if (bytesRead > 0) {
+ if (bytesRead > 0)
+ {
lineBuffer[bytesRead] = 0;
- if (stateInModel) {
+ /* trim trailing spaces */
+ while (bytesRead > 1) {
+ bytesRead--;
+
+ if (isspace(lineBuffer[bytesRead])) {
+ lineBuffer[bytesRead] = 0;
+ }
+ else {
+ break;
+ }
+ }
+ if (stateInModel)
+ {
if (StringUtils_startsWith((char*) lineBuffer, "}")) {
if (indendation == 1) {
stateInModel = false;
@@ -161,13 +289,25 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
indendation = 3;
}
else if (indendation > 4) {
+
+ if (inArrayElement && currentModelNode->parent == currentArrayNode) {
+ inArrayElement = false;
+ }
+ else {
+ indendation--;
+ }
+
+ if (inArray && currentModelNode == currentArrayNode) {
+ inArray = false;
+ }
+
currentModelNode = currentModelNode->parent;
- indendation--;
}
}
-
- else if (indendation == 1) {
- if (StringUtils_startsWith((char*) lineBuffer, "LD")) {
+ else if (indendation == 1)
+ {
+ if (StringUtils_startsWith((char*) lineBuffer, "LD"))
+ {
indendation = 2;
char ldName[65];
@@ -178,7 +318,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
terminateString(nameString, ')');
- if (ldName[0] != 0) {
+ if (ldName[0] != 0)
+ {
terminateString(ldName, ')');
currentLD = LogicalDevice_createEx(nameString, model, ldName);
@@ -190,8 +331,10 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
else
goto exit_error;
}
- else if (indendation == 2) {
- if (StringUtils_startsWith((char*) lineBuffer, "LN")) {
+ else if (indendation == 2)
+ {
+ if (StringUtils_startsWith((char*) lineBuffer, "LN"))
+ {
indendation = 3;
if (sscanf((char*) lineBuffer, "LN(%129s)", nameString) < 1)
@@ -204,26 +347,35 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
else
goto exit_error;
}
- else if (indendation == 3) {
- if (StringUtils_startsWith((char*) lineBuffer, "DO")) {
+ else if (indendation == 3)
+ {
+ if (StringUtils_startsWith((char*) lineBuffer, "DO"))
+ {
indendation = 4;
int arrayElements = 0;
- sscanf((char*) lineBuffer, "DO(%129s %i)", nameString, &arrayElements);
+ if (sscanf((char*)lineBuffer, "DO(%129s %i)", nameString, &arrayElements) != 2) {
+ goto exit_error;
+ }
currentModelNode = (ModelNode*)
DataObject_create(nameString, (ModelNode*) currentLN, arrayElements);
}
- else if (StringUtils_startsWith((char*) lineBuffer, "DS")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "DS"))
+ {
indendation = 4;
- sscanf((char*) lineBuffer, "DS(%129s)", nameString);
+ if (sscanf((char*)lineBuffer, "DS(%129s)", nameString) != 1) {
+ goto exit_error;
+ }
+
terminateString(nameString, ')');
currentDataSet = DataSet_create(nameString, currentLN);
}
- else if (StringUtils_startsWith((char*) lineBuffer, "RC")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "RC"))
+ {
int isBuffered;
uint32_t confRef;
int trgOps;
@@ -250,7 +402,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
ReportControlBlock_create(nameString, currentLN, rptId,
(bool) isBuffered, dataSetName, confRef, trgOps, options, bufTm, intgPd);
}
- else if (StringUtils_startsWith((char*) lineBuffer, "LC")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "LC"))
+ {
uint32_t trgOps;
uint32_t intgPd;
int logEna;
@@ -271,7 +424,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
LogControlBlock_create(nameString, currentLN, dataSet, logRef, trgOps, intgPd, logEna, withReasonCode);
}
- else if (StringUtils_startsWith((char*) lineBuffer, "LOG")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "LOG"))
+ {
int matchedItems = sscanf((char*) lineBuffer, "LOG(%129s)", nameString);
if (matchedItems < 1) goto exit_error;
@@ -281,7 +435,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
Log_create(nameString, currentLN);
}
- else if (StringUtils_startsWith((char*) lineBuffer, "GC")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "GC"))
+ {
uint32_t confRef;
int fixedOffs;
int minTime = -1;
@@ -296,9 +451,9 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
nameString3, confRef, fixedOffs, minTime, maxTime);
indendation = 4;
-
}
- else if (StringUtils_startsWith((char*) lineBuffer, "SMVC")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "SMVC"))
+ {
uint32_t confRev;
int smpMod;
int smpRate;
@@ -313,10 +468,10 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
currentSMVCB = SVControlBlock_create(nameString, currentLN, nameString2, nameString3, confRev, smpMod, smpRate, optFlds, (bool) isUnicast);
indendation = 4;
-
}
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
- else if (StringUtils_startsWith((char*) lineBuffer, "SG")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "SG"))
+ {
if (strcmp(currentLN->name, "LLN0") != 0) {
if (DEBUG_IED_SERVER)
@@ -345,8 +500,10 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
}
- else if (indendation > 3) {
- if (StringUtils_startsWith((char*) lineBuffer, "DO")) {
+ else if (indendation > 3)
+ {
+ if (StringUtils_startsWith((char*) lineBuffer, "DO"))
+ {
indendation++;
int arrayElements = 0;
@@ -356,129 +513,116 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
if (matchedItems != 2) goto exit_error;
currentModelNode = (ModelNode*) DataObject_create(nameString, currentModelNode, arrayElements);
- }
- else if (StringUtils_startsWith((char*) lineBuffer, "DA")) {
- int arrayElements = 0;
+ if (arrayElements > 0)
+ {
+ inArray = true;
+ currentArrayNode = currentModelNode;
+ }
+ }
+ else if (StringUtils_startsWith((char*) lineBuffer, "["))
+ {
+ if (inArray == false) {
+ goto exit_error;
+ }
- int attributeType = 0;
- int functionalConstraint = 0;
- int triggerOptions = 0;
- uint32_t sAddr = 0;
+ int arrayIndex;
- sscanf((char*) lineBuffer, "DA(%129s %i %i %i %i %u)", nameString, &arrayElements, &attributeType, &functionalConstraint, &triggerOptions, &sAddr);
+ if (sscanf((char*)lineBuffer, "[%i]", &arrayIndex) != 1) {
+ goto exit_error;
+ }
- DataAttribute* dataAttribute = DataAttribute_create(nameString, currentModelNode,
- (DataAttributeType) attributeType, (FunctionalConstraint) functionalConstraint, triggerOptions, arrayElements, sAddr);
+ if (arrayIndex < 0) {
+ goto exit_error;
+ }
- char* valueIndicator = strchr((char*) lineBuffer, '=');
+ if (currentArrayNode->modelType == DataAttributeModelType)
+ {
+ if (StringUtils_endsWith((char*)lineBuffer, ";"))
+ {
+ /* array of basic data attribute */
+ ModelNode* arrayElementNode = ModelNode_getChildWithIdx(currentArrayNode, arrayIndex);
- if (valueIndicator != NULL) {
- switch (dataAttribute->type) {
- case IEC61850_UNICODE_STRING_255:
- {
- char* stringStart = valueIndicator + 2;
- terminateString(stringStart, '"');
- dataAttribute->mmsValue = MmsValue_newMmsString(stringStart);
- }
- break;
-
- case IEC61850_VISIBLE_STRING_255:
- case IEC61850_VISIBLE_STRING_129:
- case IEC61850_VISIBLE_STRING_65:
- case IEC61850_VISIBLE_STRING_64:
- case IEC61850_VISIBLE_STRING_32:
- case IEC61850_CURRENCY:
- {
- char* stringStart = valueIndicator + 2;
- terminateString(stringStart, '"');
- dataAttribute->mmsValue = MmsValue_newVisibleString(stringStart);
- }
- break;
-
- case IEC61850_INT8:
- case IEC61850_INT16:
- case IEC61850_INT32:
- case IEC61850_INT64:
- case IEC61850_INT128:
- case IEC61850_ENUMERATED:
- {
- int32_t intValue;
- if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newIntegerFromInt32(intValue);
+ if (arrayElementNode) {
+ setValue((char*)lineBuffer, (DataAttribute*)arrayElementNode);
}
- break;
-
- case IEC61850_INT8U:
- case IEC61850_INT16U:
- case IEC61850_INT24U:
- case IEC61850_INT32U:
- {
- uint32_t uintValue;
- if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newUnsignedFromUint32(uintValue);
+ else {
+ goto exit_error;
}
- break;
-
- case IEC61850_FLOAT32:
- {
- float floatValue;
- if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newFloat(floatValue);
- }
- break;
+ }
+ else if (StringUtils_endsWith((char*)lineBuffer, "{"))
+ {
+ /* array of constructed data attribtute */
+ currentModelNode = ModelNode_getChildWithIdx(currentArrayNode, arrayIndex);
- case IEC61850_FLOAT64:
- {
- double doubleValue;
- if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newDouble(doubleValue);
+ if (currentModelNode) {
+ inArrayElement = true;
}
- break;
-
- case IEC61850_BOOLEAN:
- {
- int boolean;
- if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newBoolean((bool) boolean);
+ else {
+ goto exit_error;
}
- break;
-
- case IEC61850_OPTFLDS:
- {
- int value;
- if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newBitString(-10);
- MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
+ }
+ }
+ else if (currentArrayNode->modelType == DataObjectModelType)
+ {
+ if (StringUtils_endsWith((char*)lineBuffer, "{"))
+ {
+ /* array of constructed data attribtute */
+ currentModelNode = ModelNode_getChildWithIdx(currentArrayNode, arrayIndex);
+
+ if (currentModelNode) {
+ inArrayElement = true;
}
- break;
-
- case IEC61850_TRGOPS:
- {
- int value;
- if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
- dataAttribute->mmsValue = MmsValue_newBitString(-6);
- MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
+ else {
+ goto exit_error;
}
- break;
+ }
+ else
+ {
+ if (DEBUG_IED_SERVER)
+ printf("Unexpected character at end of line: %s\n", lineBuffer);
+ goto exit_error;
+ }
+ }
+ }
+ else if (StringUtils_startsWith((char*) lineBuffer, "DA"))
+ {
+ int arrayElements = 0;
+
+ int attributeType = 0;
+ int functionalConstraint = 0;
+ int triggerOptions = 0;
+ uint32_t sAddr = 0;
- default:
- break;
+ if (sscanf((char*)lineBuffer, "DA(%129s %i %i %i %i %u)", nameString, &arrayElements, &attributeType, &functionalConstraint, &triggerOptions, &sAddr) != 6) {
+ goto exit_error;
+ }
- }
+ DataAttribute* dataAttribute = DataAttribute_create(nameString, currentModelNode,
+ (DataAttributeType) attributeType, (FunctionalConstraint) functionalConstraint, triggerOptions, arrayElements, sAddr);
+
+ if (arrayElements > 0)
+ {
+ inArray = true;
+ currentArrayNode = (ModelNode*)dataAttribute;
}
+ setValue((char*)lineBuffer, dataAttribute);
+
int lineLength = (int) strlen((char*) lineBuffer);
- if (lineBuffer[lineLength - 1] == '{') {
+ if (lineBuffer[lineLength - 1] == '{')
+ {
indendation++;
currentModelNode = (ModelNode*) dataAttribute;
}
}
- else if (StringUtils_startsWith((char*) lineBuffer, "DE")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "DE"))
+ {
char* start = strchr((char*) lineBuffer, '(');
- if (start) {
+ if (start)
+ {
start++;
StringUtils_copyStringMax(nameString, 130, start);
@@ -491,7 +635,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
/* check for index */
char* sep = strchr(nameString, ' ');
- if (sep) {
+ if (sep)
+ {
char* indexStr = sep + 1;
*sep = 0;
@@ -509,7 +654,8 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
DataSetEntry_create(currentDataSet, nameString, indexVal, componentVal);
}
}
- else if (StringUtils_startsWith((char*) lineBuffer, "PA")) {
+ else if (StringUtils_startsWith((char*) lineBuffer, "PA"))
+ {
uint32_t vlanPrio;
uint32_t vlanId;
uint32_t appId;
@@ -525,7 +671,6 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
if (StringUtils_createBufferFromHexString(nameString, (uint8_t*) nameString2) != 6)
goto exit_error;
-
PhyComAddress* dstAddress =
PhyComAddress_create((uint8_t) vlanPrio, (uint16_t) vlanId, (uint16_t) appId,
(uint8_t*) nameString2);
@@ -541,18 +686,20 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
else
goto exit_error;
}
-
-
}
- else {
- if (StringUtils_startsWith((char*) lineBuffer, "MODEL{")) {
-
+ else
+ {
+ if (StringUtils_startsWith((char*) lineBuffer, "MODEL{"))
+ {
model = IedModel_create("");
stateInModel = true;
indendation = 1;
}
- else if (StringUtils_startsWith((char*) lineBuffer, "MODEL(")) {
- sscanf((char*) lineBuffer, "MODEL(%129s)", nameString);
+ else if (StringUtils_startsWith((char*) lineBuffer, "MODEL("))
+ {
+ if (sscanf((char*)lineBuffer, "MODEL(%129s)", nameString) != 1)
+ goto exit_error;
+
terminateString(nameString, ')');
model = IedModel_create(nameString);
stateInModel = true;
@@ -564,14 +711,18 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
}
+ GLOBAL_FREEMEM(lineBuffer);
+
return model;
exit_error:
+
+ GLOBAL_FREEMEM(lineBuffer);
+
if (DEBUG_IED_SERVER)
printf("IED_SERVER: error parsing line %i (indentation level = %i)\n", currentLine, indendation);
IedModel_destroy(model);
+
return NULL;
}
-
-
diff --git a/src/iec61850/server/model/dynamic_model.c b/src/iec61850/server/model/dynamic_model.c
index 68710320..bfe266ed 100644
--- a/src/iec61850/server/model/dynamic_model.c
+++ b/src/iec61850/server/model/dynamic_model.c
@@ -1,7 +1,7 @@
/*
* dynamic_model.c
*
- * Copyright 2014-2022 Michael Zillgith
+ * Copyright 2014-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -75,10 +75,12 @@ IedModel_addDataSet(IedModel* self, DataSet* dataSet)
{
if (self->dataSets == NULL)
self->dataSets = dataSet;
- else {
+ else
+ {
DataSet* lastDataSet = self->dataSets;
- while (lastDataSet != NULL) {
+ while (lastDataSet != NULL)
+ {
if (lastDataSet->sibling == NULL) {
lastDataSet->sibling = dataSet;
break;
@@ -94,7 +96,8 @@ IedModel_addLogicalDevice(IedModel* self, LogicalDevice* lDevice)
{
if (self->firstChild == NULL)
self->firstChild = lDevice;
- else {
+ else
+ {
LogicalDevice* sibling = self->firstChild;
while (sibling->sibling != NULL)
@@ -109,7 +112,8 @@ IedModel_addLog(IedModel* self, Log* log)
{
if (self->logs == NULL)
self->logs = log;
- else {
+ else
+ {
Log* lastLog = self->logs;
while (lastLog->sibling != NULL)
@@ -124,7 +128,8 @@ IedModel_addLogControlBlock(IedModel* self, LogControlBlock* lcb)
{
if (self->lcbs == NULL)
self->lcbs = lcb;
- else {
+ else
+ {
LogControlBlock* lastLcb = self->lcbs;
while (lastLcb->sibling != NULL)
@@ -139,7 +144,8 @@ IedModel_addReportControlBlock(IedModel* self, ReportControlBlock* rcb)
{
if (self->rcbs == NULL)
self->rcbs = rcb;
- else {
+ else
+ {
ReportControlBlock* lastRcb = self->rcbs;
while (lastRcb->sibling != NULL)
@@ -155,7 +161,8 @@ IedModel_addSettingGroupControlBlock(IedModel* self, SettingGroupControlBlock* s
{
if (self->sgcbs == NULL)
self->sgcbs = sgcb;
- else {
+ else
+ {
SettingGroupControlBlock* lastSgcb = self->sgcbs;
while (lastSgcb->sibling != NULL)
@@ -171,7 +178,8 @@ IedModel_addGSEControlBlock(IedModel* self, GSEControlBlock* gcb)
{
if (self->gseCBs == NULL)
self->gseCBs = gcb;
- else {
+ else
+ {
GSEControlBlock* lastGcb = self->gseCBs;
while (lastGcb->sibling)
@@ -187,7 +195,8 @@ IedModel_addSMVControlBlock(IedModel* self, SVControlBlock* smvcb)
if (self->svCBs == NULL) {
self->svCBs = smvcb;
}
- else {
+ else
+ {
SVControlBlock* lastSvCB = self->svCBs;
while (lastSvCB->sibling)
@@ -202,7 +211,8 @@ LogicalDevice_createEx(const char* inst, IedModel* parent, const char* ldName)
{
LogicalDevice* self = (LogicalDevice*) GLOBAL_CALLOC(1, sizeof(LogicalDevice));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(inst);
self->modelType = LogicalDeviceModelType;
self->parent = (ModelNode*) parent;
@@ -257,7 +267,8 @@ LogicalNode_create(const char* name, LogicalDevice* parent)
{
LogicalNode* self = (LogicalNode*) GLOBAL_MALLOC(sizeof(LogicalNode));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->parent = (ModelNode*) parent;
self->modelType = LogicalNodeModelType;
@@ -311,7 +322,8 @@ Log_create(const char* name, LogicalNode* parent)
{
Log* self = (Log*) GLOBAL_MALLOC(sizeof(Log));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->parent = parent;
self->sibling = NULL;
@@ -336,7 +348,8 @@ LogControlBlock_create(const char* name, LogicalNode* parent, const char* dataSe
{
LogControlBlock* self = (LogControlBlock*) GLOBAL_MALLOC(sizeof(LogControlBlock));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->parent = parent;
self->sibling = NULL;
@@ -388,7 +401,8 @@ ReportControlBlock_create(const char* name, LogicalNode* parent, const char* rpt
{
ReportControlBlock* self = (ReportControlBlock*) GLOBAL_MALLOC(sizeof(ReportControlBlock));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->parent = parent;
@@ -469,7 +483,8 @@ SettingGroupControlBlock_create(LogicalNode* parent, uint8_t actSG, uint8_t numO
SettingGroupControlBlock* self = (SettingGroupControlBlock*) GLOBAL_MALLOC(sizeof(SettingGroupControlBlock));
- if (self) {
+ if (self)
+ {
self->parent = parent;
self->actSG = actSG;
self->numOfSGs = numOfSGs;
@@ -497,7 +512,8 @@ GSEControlBlock_create(const char* name, LogicalNode* parent, const char* appId,
{
GSEControlBlock* self = (GSEControlBlock*) GLOBAL_MALLOC(sizeof(GSEControlBlock));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->parent = parent;
@@ -541,7 +557,8 @@ SVControlBlock_create(const char* name, LogicalNode* parent, const char* svID, c
{
SVControlBlock* self = (SVControlBlock*) GLOBAL_MALLOC(sizeof(SVControlBlock));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->parent = parent;
@@ -587,7 +604,8 @@ PhyComAddress_create(uint8_t vlanPriority, uint16_t vlanId, uint16_t appId, uint
{
PhyComAddress* self = (PhyComAddress*) GLOBAL_MALLOC(sizeof(PhyComAddress));
- if (self) {
+ if (self)
+ {
self->vlanPriority = vlanPriority;
self->vlanId = vlanId;
self->appId = appId;
@@ -630,7 +648,8 @@ DataObject_create(const char* name, ModelNode* parent, int arrayElements)
{
DataObject* self = (DataObject*) GLOBAL_MALLOC(sizeof(DataObject));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->modelType = DataObjectModelType;
self->firstChild = NULL;
@@ -640,21 +659,23 @@ DataObject_create(const char* name, ModelNode* parent, int arrayElements)
self->elementCount = arrayElements;
self->arrayIndex = -1;
- if (arrayElements > 0) {
+ if (arrayElements > 0)
+ {
int i;
- for (i = 0; i < arrayElements; i++) {
+ for (i = 0; i < arrayElements; i++)
+ {
DataObject* arrayElement = (DataObject*) GLOBAL_MALLOC(sizeof(DataObject));
- if (self) {
- self->name = NULL;
- self->modelType = DataObjectModelType;
- self->firstChild = NULL;
- self->parent = parent;
- self->sibling = NULL;
+ if (arrayElement) {
+ arrayElement->name = NULL;
+ arrayElement->modelType = DataObjectModelType;
+ arrayElement->firstChild = NULL;
+ arrayElement->parent = (ModelNode*) self;
+ arrayElement->sibling = NULL;
- self->elementCount = 0;
- self->arrayIndex = i;
+ arrayElement->elementCount = 0;
+ arrayElement->arrayIndex = i;
DataObject_addChild(self, (ModelNode*) arrayElement);
}
@@ -703,7 +724,8 @@ DataAttribute_create(const char* name, ModelNode* parent, DataAttributeType type
{
DataAttribute* self = (DataAttribute*) GLOBAL_MALLOC(sizeof(DataAttribute));
- if (self) {
+ if (self)
+ {
self->name = StringUtils_copyString(name);
self->elementCount = arrayElements;
self->arrayIndex = -1;
@@ -717,13 +739,16 @@ DataAttribute_create(const char* name, ModelNode* parent, DataAttributeType type
self->triggerOptions = triggerOptions;
self->sAddr = sAddr;
- if (arrayElements > 0) {
+ if (arrayElements > 0)
+ {
int i;
- for (i = 0; i < arrayElements; i++) {
+ for (i = 0; i < arrayElements; i++)
+ {
DataAttribute* arrayElement = (DataAttribute*) GLOBAL_MALLOC(sizeof(DataAttribute));
- if (arrayElement) {
+ if (arrayElement)
+ {
arrayElement->name = NULL;
arrayElement->elementCount = 0;
arrayElement->arrayIndex = i;
@@ -785,7 +810,8 @@ DataSet_create(const char* name, LogicalNode* parent)
{
DataSet* self = (DataSet*) GLOBAL_MALLOC(sizeof(DataSet));
- if (self) {
+ if (self)
+ {
LogicalDevice* ld = (LogicalDevice*) parent->parent;
self->name = StringUtils_createString(3, parent->name, "$", name);
@@ -831,11 +857,12 @@ DataSet_addEntry(DataSet* self, DataSetEntry* newEntry)
if (self->fcdas == NULL)
self->fcdas = newEntry;
- else {
+ else
+ {
DataSetEntry* lastEntry = self->fcdas;
- while (lastEntry != NULL) {
-
+ while (lastEntry != NULL)
+ {
if (lastEntry->sibling == NULL) {
lastEntry->sibling = newEntry;
break;
@@ -851,21 +878,24 @@ DataSetEntry_create(DataSet* dataSet, const char* variable, int index, const cha
{
DataSetEntry* self = (DataSetEntry*) GLOBAL_MALLOC(sizeof(DataSetEntry));
- if (self) {
+ if (self)
+ {
char variableName[130];
StringUtils_copyStringMax(variableName, 130, variable);
char* separator = strchr(variableName, '/');
- if (separator != NULL) {
+ if (separator != NULL)
+ {
*separator = 0;
self->variableName = StringUtils_copyString(separator + 1);
self->logicalDeviceName = StringUtils_copyString(variableName);
self->isLDNameDynamicallyAllocated = true;
}
- else {
+ else
+ {
self->variableName = StringUtils_copyString(variable);
self->logicalDeviceName = dataSet->logicalDeviceName;
self->isLDNameDynamicallyAllocated = false;
@@ -891,14 +921,15 @@ DataSetEntry_create(DataSet* dataSet, const char* variable, int index, const cha
static void
ModelNode_destroy(ModelNode* modelNode)
{
- if (modelNode) {
-
+ if (modelNode)
+ {
if (modelNode->name)
GLOBAL_FREEMEM(modelNode->name);
ModelNode* currentChild = modelNode->firstChild;
- while (currentChild != NULL) {
+ while (currentChild != NULL)
+ {
ModelNode* nextChild = currentChild->sibling;
ModelNode_destroy(currentChild);
@@ -906,7 +937,8 @@ ModelNode_destroy(ModelNode* modelNode)
currentChild = nextChild;
}
- if (modelNode->modelType == DataAttributeModelType) {
+ if (modelNode->modelType == DataAttributeModelType)
+ {
DataAttribute* dataAttribute = (DataAttribute*) modelNode;
if (dataAttribute->mmsValue != NULL) {
@@ -929,8 +961,8 @@ IedModel_destroy(IedModel* model)
LogicalDevice* ld = model->firstChild;
- while (ld != NULL) {
-
+ while (ld != NULL)
+ {
if (ld->name)
GLOBAL_FREEMEM(ld->name);
@@ -939,7 +971,8 @@ IedModel_destroy(IedModel* model)
LogicalNode* ln = (LogicalNode*) ld->firstChild;
- while (ln != NULL) {
+ while (ln != NULL)
+ {
GLOBAL_FREEMEM(ln->name);
/* delete all data objects */
@@ -960,7 +993,6 @@ IedModel_destroy(IedModel* model)
GLOBAL_FREEMEM(currentLn);
}
-
LogicalDevice* currentLd = ld;
ld = (LogicalDevice*) ld->sibling;
@@ -1092,4 +1124,3 @@ IedModel_destroy(IedModel* model)
GLOBAL_FREEMEM(model);
}
}
-
diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c
index 375d62f9..55b6409e 100644
--- a/src/iec61850/server/model/model.c
+++ b/src/iec61850/server/model/model.c
@@ -538,19 +538,34 @@ static int
createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool withoutIedName)
{
int bufPos;
+ int arrayIndex = -1;
- if (node->modelType != LogicalNodeModelType) {
+ if (node->modelType != LogicalNodeModelType)
+ {
bufPos = createObjectReference(node->parent, objectReference, bufSize, withoutIedName);
+ if (node->modelType == DataAttributeModelType)
+ {
+ arrayIndex = ((DataAttribute*)(node))->arrayIndex;
+ }
+ else if (node->modelType == DataObjectModelType)
+ {
+ arrayIndex = ((DataObject*)(node))->arrayIndex;
+ }
+
if (bufPos == -1)
return -1;
- if (bufPos < bufSize)
- objectReference[bufPos++] = '.';
- else
- return -1;
+ if (arrayIndex < 0)
+ {
+ if (bufPos < bufSize)
+ objectReference[bufPos++] = '.';
+ else
+ return -1;
+ }
}
- else {
+ else
+ {
LogicalNode* lNode = (LogicalNode*) node;
LogicalDevice* lDevice = (LogicalDevice*) lNode->parent;
@@ -559,12 +574,13 @@ createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool
bufPos = 0;
- if (withoutIedName) {
+ if (withoutIedName)
+ {
objectReference[0] = 0;
StringUtils_appendString(objectReference, bufSize, lDevice->name);
}
- else {
-
+ else
+ {
if (lDevice->ldName) {
StringUtils_copyStringMax(objectReference, bufSize, lDevice->ldName);
}
@@ -581,20 +597,49 @@ createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool
return -1;
}
- /* append own name */
- int nameLength = strlen(node->name);
+ if (node->name)
+ {
+ /* append own name */
+ int nameLength = strlen(node->name);
+
+ if (bufPos + nameLength < bufSize)
+ {
+ int i;
+ for (i = 0; i < nameLength; i++) {
+ objectReference[bufPos++] = node->name[i];
+ }
- if (bufPos + nameLength < bufSize) {
- int i;
- for (i = 0; i < nameLength; i++) {
- objectReference[bufPos++] = node->name[i];
+ return bufPos;
+ }
+ else {
+ return -1;
}
-
- return bufPos;
}
- else {
- return -1;
+
+ if (arrayIndex > -1)
+ {
+ char arrayIndexStr[11];
+
+ snprintf(arrayIndexStr, 11, "%d", arrayIndex);
+
+ int arrayIndexStrLength = strlen(arrayIndexStr);
+
+ if (bufPos + arrayIndexStrLength + 2 < bufSize)
+ {
+ int i;
+
+ objectReference[bufPos++] = '(';
+
+ for (i = 0; i < arrayIndexStrLength; i++) {
+ objectReference[bufPos++] = arrayIndexStr[i];
+ }
+ objectReference[bufPos++] = ')';
+ }
+ else
+ return -1;
}
+
+ return bufPos;
}
char*
@@ -608,15 +653,18 @@ ModelNode_getObjectReferenceEx(ModelNode* node, char* objectReference, bool with
{
bool allocated = false;
- if (objectReference == NULL) {
+ if (objectReference == NULL)
+ {
objectReference = (char*) GLOBAL_MALLOC(130);
allocated = true;
}
- if (objectReference) {
+ if (objectReference)
+ {
int bufPos = createObjectReference(node, objectReference, 130, withoutIedName);
- if (bufPos == -1) {
+ if (bufPos == -1)
+ {
if (allocated)
GLOBAL_FREEMEM(objectReference);
@@ -729,16 +777,16 @@ ModelNode_getChild(ModelNode* self, const char* name)
ModelNode* matchingNode = NULL;
- while (nextNode) {
-
+ while (nextNode)
+ {
if (nextNode->name == NULL) {
break; /* is an array element */
}
int nodeNameLen = strlen(nextNode->name);
- if (nodeNameLen == nameElementLength) {
-
+ if (nodeNameLen == nameElementLength)
+ {
if (memcmp(nextNode->name, name, nodeNameLen) == 0) {
matchingNode = nextNode;
break;
@@ -760,12 +808,14 @@ ModelNode_getChildWithIdx(ModelNode* self, int idx)
{
ModelNode* foundElement = NULL;
- if (self->modelType == DataObjectModelType || self->modelType == DataAttributeModelType) {
+ if (self->modelType == DataObjectModelType || self->modelType == DataAttributeModelType)
+ {
ModelNode* nextNode = self->firstChild;
int currentIdx = 0;
- while (nextNode) {
+ while (nextNode)
+ {
if (currentIdx == idx) {
foundElement = nextNode;
break;
@@ -797,14 +847,17 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
ModelNode* matchingNode = NULL;
- while (nextNode != NULL) {
+ while (nextNode != NULL)
+ {
int nodeNameLen = strlen(nextNode->name);
- if (nodeNameLen == nameElementLength) {
- if (memcmp(nextNode->name, name, nodeNameLen) == 0) {
-
+ if (nodeNameLen == nameElementLength)
+ {
+ if (memcmp(nextNode->name, name, nodeNameLen) == 0)
+ {
if (separator == NULL) {
- if (nextNode->modelType == DataAttributeModelType) {
+ if (nextNode->modelType == DataAttributeModelType)
+ {
DataAttribute* da = (DataAttribute*) nextNode;
if (da->fc == fc) {
@@ -813,9 +866,10 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
}
}
}
- else {
-
- if (nextNode->modelType == DataAttributeModelType) {
+ else
+ {
+ if (nextNode->modelType == DataAttributeModelType)
+ {
DataAttribute* da = (DataAttribute*) nextNode;
if (da->fc == fc) {
diff --git a/src/mms/inc/mms_client_connection.h b/src/mms/inc/mms_client_connection.h
index 86f12c9b..7447b33b 100644
--- a/src/mms/inc/mms_client_connection.h
+++ b/src/mms/inc/mms_client_connection.h
@@ -160,6 +160,16 @@ MmsConnection_setFilestoreBasepath(MmsConnection self, const char* basepath);
LIB61850_API void
MmsConnection_setRequestTimeout(MmsConnection self, uint32_t timeoutInMs);
+/**
+ * \brief Set the maximum number outstanding calls allowed for this connection
+ *
+ * \param self MmsConnection instance to operate on
+ * \param calling the maximum outstanding calls allowed by the caller (client)
+ * \param called the maximum outstanding calls allowed by the called endpoint (server)
+ */
+LIB61850_API void
+MmsConnnection_setMaxOutstandingCalls(MmsConnection self, int calling, int called);
+
/**
* \brief Get the request timeout in ms for this connection
*
diff --git a/src/mms/inc_private/mms_client_internal.h b/src/mms/inc_private/mms_client_internal.h
index aa0e60f3..5a7b2242 100644
--- a/src/mms/inc_private/mms_client_internal.h
+++ b/src/mms/inc_private/mms_client_internal.h
@@ -95,6 +95,8 @@ struct sMmsConnection {
Semaphore outstandingCallsLock;
MmsOutstandingCall outstandingCalls;
+ int maxOutstandingCalled;
+ int maxOutstandingCalling;
uint32_t requestTimeout;
uint32_t connectTimeout;
diff --git a/src/mms/inc_private/mms_common_internal.h b/src/mms/inc_private/mms_common_internal.h
index f096e7bc..61faea58 100644
--- a/src/mms/inc_private/mms_common_internal.h
+++ b/src/mms/inc_private/mms_common_internal.h
@@ -1,7 +1,7 @@
/*
* mms_common_internal.h
*
- * Copyright 2013-2019 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -30,10 +30,10 @@
#include "byte_buffer.h"
#include "mms_server.h"
-#define DEFAULT_MAX_SERV_OUTSTANDING_CALLING 5
-#define DEFAULT_MAX_SERV_OUTSTANDING_CALLED 5
#define DEFAULT_DATA_STRUCTURE_NESTING_LEVEL 10
+typedef struct sMmsOutstandingCall* MmsOutstandingCall;
+
#if (MMS_FILE_SERVICE == 1)
#ifndef CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION
@@ -42,8 +42,6 @@
#include "hal_filesystem.h"
-typedef struct sMmsOutstandingCall* MmsOutstandingCall;
-
typedef struct {
int32_t frsmId;
uint32_t readPosition;
diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h
index 08d0988a..3fae4f26 100644
--- a/src/mms/inc_private/mms_server_internal.h
+++ b/src/mms/inc_private/mms_server_internal.h
@@ -399,7 +399,7 @@ mmsServer_isAccessToArrayComponent(AlternateAccess_t* alternateAccess);
LIB61850_INTERNAL MmsValue*
mmsServer_getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable,
- MmsValue* structuredValue);
+ MmsValue* structuredValue, char* componentId);
LIB61850_INTERNAL int
mmsServer_getLowIndex(AlternateAccess_t* alternateAccess);
@@ -417,6 +417,10 @@ LIB61850_INTERNAL MmsDataAccessError
mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value,
MmsServerConnection connection);
+LIB61850_INTERNAL MmsDataAccessError
+mmsServer_setValueEx(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value,
+ MmsServerConnection connection, int arrayIdx, const char* componentId);
+
/**
* \brief Get the current value of a variable in the server data model
*
diff --git a/src/mms/inc_private/mms_server_libinternal.h b/src/mms/inc_private/mms_server_libinternal.h
index bdaf4b68..f7daa70c 100644
--- a/src/mms/inc_private/mms_server_libinternal.h
+++ b/src/mms/inc_private/mms_server_libinternal.h
@@ -34,7 +34,7 @@ typedef MmsDataAccessError (*MmsReadAccessHandler) (void* parameter, MmsDomain*
char* variableId, MmsServerConnection connection, bool isDirectAccess);
typedef MmsDataAccessError (*MmsWriteVariableHandler)(void* parameter,
- MmsDomain* domain, char* variableId, MmsValue* value,
+ MmsDomain* domain, const char* variableId, int arrayIdx, const char* componentId, MmsValue* value,
MmsServerConnection connection);
typedef bool (*MmsListAccessHandler) (void* parameter, MmsGetNameListType listType, MmsDomain* domain,
diff --git a/src/mms/iso_acse/acse.c b/src/mms/iso_acse/acse.c
index f46b024d..9f5b4186 100644
--- a/src/mms/iso_acse/acse.c
+++ b/src/mms/iso_acse/acse.c
@@ -1,7 +1,7 @@
/*
* acse.c
*
- * Copyright 2013 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -43,9 +43,10 @@ checkAuthMechanismName(uint8_t* authMechanism, int authMechLen)
{
AcseAuthenticationMechanism authenticationMechanism = ACSE_AUTH_NONE;
- if (authMechanism != NULL) {
-
- if (authMechLen == 3) {
+ if (authMechanism != NULL)
+ {
+ if (authMechLen == 3)
+ {
if (memcmp(auth_mech_password_oid, authMechanism, 3) == 0) {
authenticationMechanism = ACSE_AUTH_PASSWORD;
}
@@ -64,11 +65,13 @@ authenticateClient(AcseConnection* self, AcseAuthenticationMechanism mechanism,
authParameter->mechanism = mechanism;
- if (mechanism == ACSE_AUTH_PASSWORD) {
+ if (mechanism == ACSE_AUTH_PASSWORD)
+ {
authParameter->value.password.octetString = authValue;
authParameter->value.password.passwordLength = authValueLen;
}
- else if (mechanism == ACSE_AUTH_TLS) {
+ else if (mechanism == ACSE_AUTH_TLS)
+ {
authParameter->value.certificate.buf = authValue;
authParameter->value.certificate.length = authValueLen;
}
@@ -81,15 +84,15 @@ checkAuthentication(AcseConnection* self, uint8_t* authMechanism, int authMechLe
{
self->securityToken = NULL;
- if (self->authenticator != NULL) {
-
+ if (self->authenticator != NULL)
+ {
AcseAuthenticationMechanism mechanism = checkAuthMechanismName(authMechanism, authMechLen);
- if (mechanism == ACSE_AUTH_NONE) {
-
+ if (mechanism == ACSE_AUTH_NONE)
+ {
#if (CONFIG_MMS_SUPPORT_TLS == 1)
- if (self->tlsSocket) {
-
+ if (self->tlsSocket)
+ {
int certLen;
uint8_t* certBuf = TLSSocket_getPeerCertificate(self->tlsSocket, &certLen);
@@ -120,13 +123,18 @@ parseUserInformation(AcseConnection* self, uint8_t* buffer, int bufPos, int maxB
bool hasindirectReference = false;
bool isDataValid = false;
- while (bufPos < maxBufPos) {
+ while (bufPos < maxBufPos)
+ {
uint8_t tag = buffer[bufPos++];
int len;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
- if (bufPos < 0) {
+ if (len == 0)
+ continue;
+
+ if ((bufPos < 0) || (bufPos + len > maxBufPos))
+ {
*userInfoValid = false;
return -1;
}
@@ -155,7 +163,8 @@ parseUserInformation(AcseConnection* self, uint8_t* buffer, int bufPos, int maxB
}
}
- if (DEBUG_ACSE) {
+ if (DEBUG_ACSE)
+ {
if (!hasindirectReference)
printf("ACSE: User data has no indirect reference!\n");
@@ -181,13 +190,22 @@ parseAarePdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
uint32_t result = 99;
- while (bufPos < maxBufPos) {
+ while (bufPos < maxBufPos)
+ {
uint8_t tag = buffer[bufPos++];
int len;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
- if (bufPos < 0)
+
+ if (len == 0)
+ continue;
+
+ if ((bufPos < 0) || (bufPos + len > maxBufPos))
+ {
+ if (DEBUG_ACSE)
+ printf("ACSE: Invalid PDU!\n");
return ACSE_ERROR;
+ }
switch (tag)
{
@@ -212,12 +230,14 @@ parseAarePdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
break;
case 0xbe: /* user information */
- if (buffer[bufPos] != 0x28) {
+ if (buffer[bufPos] != 0x28)
+ {
if (DEBUG_ACSE)
printf("ACSE: invalid user info\n");
bufPos += len;
}
- else {
+ else
+ {
bufPos++;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
@@ -263,13 +283,18 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
int authMechLen = 0;
bool userInfoValid = false;
- while (bufPos < maxBufPos) {
+ while (bufPos < maxBufPos)
+ {
uint8_t tag = buffer[bufPos++];
int len;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
- if (bufPos < 0) {
+ if (len == 0)
+ continue;
+
+ if ((bufPos < 0) || (bufPos + len > maxBufPos))
+ {
if (DEBUG_ACSE)
printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
@@ -290,7 +315,9 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
case 0xa6: /* calling AP title */
{
- if (buffer[bufPos] == 0x06) { /* ap-title-form2 */
+ if (buffer[bufPos] == 0x06)
+ {
+ /* ap-title-form2 */
int innerLength = buffer[bufPos + 1];
@@ -303,7 +330,9 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
case 0xa7: /* calling AE qualifier */
{
- if (buffer[bufPos] == 0x02) { /* ae-qualifier-form2 */
+ if (buffer[bufPos] == 0x02)
+ {
+ /* ae-qualifier-form2 */
int innerLength = buffer[bufPos + 1];
@@ -328,7 +357,8 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
bufPos++;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
- if (bufPos < 0) {
+ if (bufPos < 0)
+ {
if (DEBUG_ACSE)
printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
@@ -340,17 +370,20 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
break;
case 0xbe: /* user information */
- if (buffer[bufPos] != 0x28) {
+ if (buffer[bufPos] != 0x28)
+ {
if (DEBUG_ACSE)
printf("ACSE: invalid user info\n");
bufPos += len;
}
- else {
+ else
+ {
bufPos++;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
- if (bufPos < 0) {
+ if (bufPos < 0)
+ {
if (DEBUG_ACSE)
printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
@@ -358,7 +391,8 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
bufPos = parseUserInformation(self, buffer, bufPos, bufPos + len, &userInfoValid);
- if (bufPos < 0) {
+ if (bufPos < 0)
+ {
if (DEBUG_ACSE)
printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
@@ -378,14 +412,16 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
}
}
- if (checkAuthentication(self, authMechanism, authMechLen, authValue, authValueLen) == false) {
+ if (checkAuthentication(self, authMechanism, authMechLen, authValue, authValueLen) == false)
+ {
if (DEBUG_ACSE)
printf("ACSE: parseAarqPdu: check authentication failed!\n");
return ACSE_ASSOCIATE_FAILED;
}
- if (userInfoValid == false) {
+ if (userInfoValid == false)
+ {
if (DEBUG_ACSE)
printf("ACSE: parseAarqPdu: user info invalid!\n");
@@ -420,6 +456,14 @@ AcseConnection_parseMessage(AcseConnection* self, ByteBuffer* message)
{
AcseIndication indication = ACSE_ERROR;
+ if (message == NULL || message->size < 1)
+ {
+ if (DEBUG_ACSE)
+ printf("ACSE: invalid message - no payload\n");
+
+ return ACSE_ERROR;
+ }
+
uint8_t* buffer = message->buffer;
int messageSize = message->size;
@@ -826,4 +870,3 @@ AcseConnection_createReleaseResponseMessage(AcseConnection* self, BufferChain wr
writeBuffer->length = 2;
writeBuffer->nextPart = NULL;
}
-
diff --git a/src/mms/iso_client/iso_client_connection.c b/src/mms/iso_client/iso_client_connection.c
index 4f37176b..ee2202a3 100644
--- a/src/mms/iso_client/iso_client_connection.c
+++ b/src/mms/iso_client/iso_client_connection.c
@@ -3,7 +3,7 @@
*
* Client side representation of the ISO stack (COTP, session, presentation, ACSE)
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -146,7 +146,8 @@ IsoClientConnection_create(IsoConnectionParameters parameters, IsoIndicationCall
{
IsoClientConnection self = (IsoClientConnection) GLOBAL_CALLOC(1, sizeof(struct sIsoClientConnection));
- if (self) {
+ if (self)
+ {
self->parameters = parameters;
self->callback = callback;
self->callbackParameter = callbackParameter;
@@ -196,7 +197,8 @@ sendConnectionRequestMessage(IsoClientConnection self)
int socketExtensionBufferSize = CONFIG_MMS_MAXIMUM_PDU_SIZE + 1000;
uint8_t* socketExtensionBuffer = NULL;
- if (self->cotpConnection) {
+ if (self->cotpConnection)
+ {
/* Destroy existing handle set when connection is reused */
if (self->cotpConnection->handleSet)
Handleset_destroy(self->cotpConnection->handleSet);
@@ -205,19 +207,20 @@ sendConnectionRequestMessage(IsoClientConnection self)
socketExtensionBuffer = self->cotpConnection->socketExtensionBuffer;
}
- if (socketExtensionBuffer == NULL) {
+ if (socketExtensionBuffer == NULL)
+ {
socketExtensionBuffer = (uint8_t*)GLOBAL_MALLOC(socketExtensionBufferSize);
}
- if (socketExtensionBuffer) {
-
+ if (socketExtensionBuffer)
+ {
/* COTP (ISO transport) handshake */
CotpConnection_init(self->cotpConnection, self->socket, self->receiveBuffer, self->cotpReadBuffer, self->cotpWriteBuffer,
socketExtensionBuffer, socketExtensionBufferSize);
#if (CONFIG_MMS_SUPPORT_TLS == 1)
- if (self->parameters->tlsConfiguration) {
-
+ if (self->parameters->tlsConfiguration)
+ {
TLSConfiguration_setClientMode(self->parameters->tlsConfiguration);
/* create TLSSocket and start TLS authentication */
@@ -225,8 +228,8 @@ sendConnectionRequestMessage(IsoClientConnection self)
if (tlsSocket)
self->cotpConnection->tlsSocket = tlsSocket;
- else {
-
+ else
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: TLS handshake failed!\n");
@@ -244,7 +247,8 @@ sendConnectionRequestMessage(IsoClientConnection self)
else
return true;
}
- else {
+ else
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Failed to allocate socket extension buffer\n");
@@ -298,14 +302,14 @@ sendAcseInitiateRequest(IsoClientConnection self)
Semaphore_post(self->transmitBufferMutex);
}
-
static void
releaseSocket(IsoClientConnection self)
{
- if (self->socket) {
-
+ if (self->socket)
+ {
#if (CONFIG_MMS_SUPPORT_TLS == 1)
- if (self->cotpConnection->tlsSocket) {
+ if (self->cotpConnection->tlsSocket)
+ {
TLSSocket_close(self->cotpConnection->tlsSocket);
self->cotpConnection->tlsSocket = NULL;
}
@@ -345,29 +349,34 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
{
SocketState socketState = Socket_checkAsyncConnectState(self->socket);
- if (socketState == SOCKET_STATE_CONNECTED) {
- if (sendConnectionRequestMessage(self)) {
+ if (socketState == SOCKET_STATE_CONNECTED)
+ {
+ if (sendConnectionRequestMessage(self))
+ {
self->nextReadTimeout = Hal_getTimeInMs() + self->readTimeoutInMs;
nextState = INT_STATE_WAIT_FOR_COTP_CONNECT_RESP;
}
- else {
+ else
+ {
IsoClientConnection_releaseTransmitBuffer(self);
self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
nextState = INT_STATE_CLOSE_ON_ERROR;
}
}
- else if (socketState == SOCKET_STATE_FAILED) {
+ else if (socketState == SOCKET_STATE_FAILED)
+ {
IsoClientConnection_releaseTransmitBuffer(self);
self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
-
+ else
+ {
/* check connect timeout */
uint64_t currentTime = Hal_getTimeInMs();
- if (currentTime > self->nextReadTimeout) {
+ if (currentTime > self->nextReadTimeout)
+ {
IsoClientConnection_releaseTransmitBuffer(self);
self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
nextState = INT_STATE_CLOSE_ON_ERROR;
@@ -385,8 +394,8 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
{
uint64_t currentTime = Hal_getTimeInMs();
- if (currentTime > self->nextReadTimeout) {
-
+ if (currentTime > self->nextReadTimeout)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Timeout waiting for COTP CR\n");
@@ -396,15 +405,16 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
-
+ else
+ {
TpktState packetState = CotpConnection_readToTpktBuffer(self->cotpConnection);
- if (packetState == TPKT_PACKET_COMPLETE) {
-
+ if (packetState == TPKT_PACKET_COMPLETE)
+ {
CotpIndication cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection);
- if (cotpIndication != COTP_CONNECT_INDICATION) {
+ if (cotpIndication != COTP_CONNECT_INDICATION)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Unexpected COTP state (%i)\n", cotpIndication);
@@ -414,7 +424,8 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
+ else
+ {
sendAcseInitiateRequest(self);
self->nextReadTimeout = Hal_getTimeInMs() + self->readTimeoutInMs;
@@ -422,7 +433,8 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
nextState = INT_STATE_WAIT_FOR_ACSE_RESP;
}
}
- else if (packetState == TPKT_ERROR) {
+ else if (packetState == TPKT_ERROR)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Error receiving COTP message\n");
@@ -435,7 +447,6 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
else {
waits = true;
}
-
}
}
break;
@@ -444,8 +455,8 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
{
uint64_t currentTime = Hal_getTimeInMs();
- if (currentTime > self->nextReadTimeout) {
-
+ if (currentTime > self->nextReadTimeout)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Timeout waiting for ACSE initiate response\n");
@@ -453,15 +464,16 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
-
+ else
+ {
TpktState packetState = CotpConnection_readToTpktBuffer(self->cotpConnection);
- if (packetState == TPKT_PACKET_COMPLETE) {
-
+ if (packetState == TPKT_PACKET_COMPLETE)
+ {
CotpIndication cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection);
- if (cotpIndication != COTP_DATA_INDICATION) {
+ if (cotpIndication != COTP_DATA_INDICATION)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Unexpected COTP state (%i)\n", cotpIndication);
@@ -469,67 +481,71 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
-
+ else
+ {
/* parse ACSE response */
- IsoSessionIndication sessionIndication;
-
- sessionIndication =
- IsoSession_parseMessage(self->session, CotpConnection_getPayload(self->cotpConnection));
+ IsoSessionIndication sessionIndication;
- if (sessionIndication != SESSION_CONNECT) {
- if (DEBUG_ISO_CLIENT)
- printf("ISO_CLIENT: IsoClientConnection_associate: no session connect indication\n");
+ sessionIndication =
+ IsoSession_parseMessage(self->session, CotpConnection_getPayload(self->cotpConnection));
- self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
-
- nextState = INT_STATE_CLOSE_ON_ERROR;
- }
- else {
-
- if (IsoPresentation_parseAcceptMessage(self->presentation, IsoSession_getUserData(self->session)) == false) {
-
- if (DEBUG_ISO_CLIENT)
- printf("ISO_CLIENT: IsoClientConnection_associate: no presentation ok indication\n");
-
- self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
-
- nextState = INT_STATE_CLOSE_ON_ERROR;
- }
- else {
-
- AcseIndication acseIndication = AcseConnection_parseMessage(&(self->acseConnection), &self->presentation->nextPayload);
-
- if (acseIndication != ACSE_ASSOCIATE) {
- if (DEBUG_ISO_CLIENT)
- printf("ISO_CLIENT: IsoClientConnection_associate: no ACSE_ASSOCIATE indication\n");
-
- self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
-
- nextState = INT_STATE_CLOSE_ON_ERROR;
- }
- else {
-
- ByteBuffer_wrap(self->receivePayloadBuffer, self->acseConnection.userDataBuffer,
- self->acseConnection.userDataBufferSize, self->acseConnection.userDataBufferSize);
+ if (sessionIndication != SESSION_CONNECT)
+ {
+ if (DEBUG_ISO_CLIENT)
+ printf("ISO_CLIENT: IsoClientConnection_associate: no session connect indication\n");
- setState(self, STATE_CONNECTED);
- nextState = INT_STATE_WAIT_FOR_DATA_MSG;
+ self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
- if (self->callback(ISO_IND_ASSOCIATION_SUCCESS, self->callbackParameter, self->receivePayloadBuffer) == false) {
- nextState = INT_STATE_CLOSE_ON_ERROR;
- }
+ nextState = INT_STATE_CLOSE_ON_ERROR;
+ }
+ else
+ {
+ if (IsoPresentation_parseAcceptMessage(self->presentation, IsoSession_getUserData(self->session)) == false)
+ {
+ if (DEBUG_ISO_CLIENT)
+ printf("ISO_CLIENT: no presentation accept indication\n");
- }
+ self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
- }
+ nextState = INT_STATE_CLOSE_ON_ERROR;
+ }
+ else
+ {
+ AcseIndication acseIndication = AcseConnection_parseMessage(&(self->acseConnection), &self->presentation->nextPayload);
+
+ if (acseIndication != ACSE_ASSOCIATE)
+ {
+ if (DEBUG_ISO_CLIENT)
+ printf("ISO_CLIENT: no ACSE_ASSOCIATE indication\n");
+
+ self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL);
+
+ nextState = INT_STATE_CLOSE_ON_ERROR;
+ }
+ else
+ {
+ if (DEBUG_ISO_CLIENT)
+ printf("ISO_CLIENT: ACSE AARE - association accepted\n");
+
+ ByteBuffer_wrap(self->receivePayloadBuffer, self->acseConnection.userDataBuffer,
+ self->acseConnection.userDataBufferSize, self->acseConnection.userDataBufferSize);
+
+ setState(self, STATE_CONNECTED);
+ nextState = INT_STATE_WAIT_FOR_DATA_MSG;
+
+ if (self->callback(ISO_IND_ASSOCIATION_SUCCESS, self->callbackParameter, self->receivePayloadBuffer) == false) {
+ nextState = INT_STATE_CLOSE_ON_ERROR;
+ }
+ }
+ }
- CotpConnection_resetPayload(self->cotpConnection);
- }
+ CotpConnection_resetPayload(self->cotpConnection);
+ }
}
}
- else if (packetState == TPKT_ERROR) {
+ else if (packetState == TPKT_ERROR)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Error receiving COTP message\n");
@@ -540,7 +556,6 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
else {
waits = true;
}
-
}
}
break;
@@ -552,8 +567,8 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
if (packetState == TPKT_ERROR) {
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else if (packetState == TPKT_PACKET_COMPLETE) {
-
+ else if (packetState == TPKT_PACKET_COMPLETE)
+ {
CotpIndication cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection);
switch (cotpIndication) {
@@ -576,23 +591,24 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
IsoSession_parseMessage(self->session,
CotpConnection_getPayload(self->cotpConnection));
- if (sessionIndication != SESSION_DATA) {
+ if (sessionIndication != SESSION_DATA)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT_CONNECTION: Invalid session message\n");
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
-
- if (!IsoPresentation_parseUserData(self->presentation, IsoSession_getUserData(self->session))) {
-
+ else
+ {
+ if (!IsoPresentation_parseUserData(self->presentation, IsoSession_getUserData(self->session)))
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT_CONNECTION: Invalid presentation message\n");
nextState = INT_STATE_CLOSE_ON_ERROR;
}
- else {
-
+ else
+ {
self->callback(ISO_IND_DATA, self->callbackParameter,
&(self->presentation->nextPayload));
@@ -659,7 +675,6 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
return waits;
}
-
bool
IsoClientConnection_associateAsync(IsoClientConnection self, uint32_t connectTimeoutInMs, uint32_t readTimeoutInMs)
{
@@ -669,7 +684,8 @@ IsoClientConnection_associateAsync(IsoClientConnection self, uint32_t connectTim
self->socket = TcpSocket_create();
- if (self->socket == NULL) {
+ if (self->socket == NULL)
+ {
Semaphore_post(self->tickMutex);
return false;
}
@@ -697,8 +713,8 @@ IsoClientConnection_associateAsync(IsoClientConnection self, uint32_t connectTim
Socket_bind(self->socket, self->parameters->localIpAddress, self->parameters->localTcpPort);
}
- if (Socket_connectAsync(self->socket, self->parameters->hostname, self->parameters->tcpPort) == false) {
-
+ if (Socket_connectAsync(self->socket, self->parameters->hostname, self->parameters->tcpPort) == false)
+ {
Socket_destroy(self->socket);
self->socket = NULL;
@@ -718,7 +734,8 @@ IsoClientConnection_associateAsync(IsoClientConnection self, uint32_t connectTim
void
IsoClientConnection_sendMessage(IsoClientConnection self, ByteBuffer* payloadBuffer)
{
- if (getState(self) == STATE_CONNECTED) {
+ if (getState(self) == STATE_CONNECTED)
+ {
struct sBufferChain payloadBCMemory;
BufferChain payload = &payloadBCMemory;
@@ -743,7 +760,8 @@ IsoClientConnection_sendMessage(IsoClientConnection self, ByteBuffer* payloadBuf
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: IsoClientConnection_sendMessage: send message failed!\n");
}
- else {
+ else
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: Not connected --> cannot send message\n");
}
@@ -762,7 +780,8 @@ IsoClientConnection_close(IsoClientConnection self)
eIsoClientInternalState intState = getIntState(self);
- if ((intState != INT_STATE_IDLE) && (intState != INT_STATE_ERROR) && (intState != INT_STATE_CLOSE_ON_ERROR)) {
+ if ((intState != INT_STATE_IDLE) && (intState != INT_STATE_ERROR) && (intState != INT_STATE_CLOSE_ON_ERROR))
+ {
setIntState(self, INT_STATE_CLOSING_CONNECTION);
Semaphore_post(self->tickMutex);
@@ -783,8 +802,8 @@ IsoClientConnection_destroy(IsoClientConnection self)
int state = getState(self);
- if (state == STATE_CONNECTED) {
-
+ if (state == STATE_CONNECTED)
+ {
if (DEBUG_ISO_CLIENT)
printf("ISO_CLIENT: call IsoClientConnection_close\n");
@@ -798,7 +817,8 @@ IsoClientConnection_destroy(IsoClientConnection self)
if (self->receiveBuffer != NULL)
GLOBAL_FREEMEM(self->receiveBuffer);
- if (self->cotpConnection != NULL) {
+ if (self->cotpConnection != NULL)
+ {
if (self->cotpConnection->handleSet != NULL)
Handleset_destroy(self->cotpConnection->handleSet);
@@ -910,7 +930,6 @@ IsoClientConnection_release(IsoClientConnection self)
Semaphore_post(self->transmitBufferMutex);
}
-
ByteBuffer*
IsoClientConnection_allocateTransmitBuffer(IsoClientConnection self)
{
diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c
index 6f743b0b..e92f8046 100644
--- a/src/mms/iso_mms/client/mms_client_connection.c
+++ b/src/mms/iso_mms/client/mms_client_connection.c
@@ -1,7 +1,7 @@
/*
* mms_client_connection.c
*
- * Copyright 2013-2022 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -37,7 +37,6 @@
#define CONFIG_MMS_CONNECTION_DEFAULT_TIMEOUT 5000
#define CONFIG_MMS_CONNECTION_DEFAULT_CONNECT_TIMEOUT 10000
-#define OUTSTANDING_CALLS 10
static void
setConnectionState(MmsConnection self, MmsConnectionState newState)
@@ -65,7 +64,8 @@ getConnectionState(MmsConnection self)
static void
handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
{
- if (self->reportHandler != NULL) {
+ if (self->reportHandler)
+ {
MmsPdu_t* mmsPdu = NULL; /* allow asn1c to allocate structure */
if (DEBUG_MMS_CLIENT)
@@ -74,12 +74,13 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu,
(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));
- if (rval.code == RC_OK) {
+ if (rval.code == RC_OK)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received report (size:%i)\n", (int) rval.consumed);
- if (mmsPdu->present == MmsPdu_PR_unconfirmedPDU) {
-
+ if (mmsPdu->present == MmsPdu_PR_unconfirmedPDU)
+ {
if (mmsPdu->choice.unconfirmedPDU.unconfirmedService.present ==
UnconfirmedService_PR_informationReport)
{
@@ -121,7 +122,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
int listSize = report->listOfAccessResult.list.count;
int variableSpecSize = report->variableAccessSpecification.choice.listOfVariable.list.count;
- if (listSize != variableSpecSize) {
+ if (listSize != variableSpecSize)
+ {
if (DEBUG_MMS_CLIENT)
printf("report contains wrong number of access results\n");
return;
@@ -131,7 +133,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
report->listOfAccessResult.list.array, listSize, false);
int i;
- for (i = 0; i < variableSpecSize; i++) {
+ for (i = 0; i < variableSpecSize; i++)
+ {
if (report->variableAccessSpecification.choice.listOfVariable.list.array[i]->variableSpecification.present
== VariableSpecification_PR_name)
{
@@ -146,7 +149,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
report->variableAccessSpecification.choice.listOfVariable.list.array[i]
->variableSpecification.choice.name.choice.vmdspecific.buf;
- if (nameSize < 129) {
+ if (nameSize < 129)
+ {
char variableListName[129];
memcpy(variableListName, buffer, nameSize);
variableListName[nameSize] = 0;
@@ -167,8 +171,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
}
}
else if (report->variableAccessSpecification.choice.listOfVariable.list.array[i]
- ->variableSpecification.choice.name.present == ObjectName_PR_domainspecific) {
-
+ ->variableSpecification.choice.name.present == ObjectName_PR_domainspecific)
+ {
int domainNameSize =
report->variableAccessSpecification.choice.listOfVariable.list.array[i]
->variableSpecification.choice.name.choice.domainspecific.domainId.size;
@@ -177,7 +181,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
report->variableAccessSpecification.choice.listOfVariable.list.array[i]
->variableSpecification.choice.name.choice.domainspecific.itemId.size;
- if ((domainNameSize < 65) && (itemNameSize < 65)) {
+ if ((domainNameSize < 65) && (itemNameSize < 65))
+ {
char domainNameStr[65];
char itemNameStr[65];
@@ -216,7 +221,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
if (values != NULL)
MmsValue_delete(values);
}
- else {
+ else
+ {
/* Ignore */
if (DEBUG_MMS_CLIENT)
printf("unrecognized information report\n");
@@ -226,7 +232,8 @@ handleUnconfirmedMmsPdu(MmsConnection self, ByteBuffer* message)
}
}
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("handleUnconfirmedMmsPdu: error parsing PDU at %u\n", (uint32_t) rval.consumed);
}
@@ -242,6 +249,10 @@ getNextInvokeId(MmsConnection self)
Semaphore_wait(self->nextInvokeIdLock);
self->nextInvokeId++;
+
+ if (self->nextInvokeId == 0)
+ self->nextInvokeId = 1;
+
nextInvokeId = self->nextInvokeId;
Semaphore_post(self->nextInvokeIdLock);
@@ -255,9 +266,12 @@ checkForOutstandingCall(MmsConnection self, uint32_t invokeId)
Semaphore_wait(self->outstandingCallsLock);
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
- if (self->outstandingCalls[i].isUsed) {
- if (self->outstandingCalls[i].invokeId == invokeId) {
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
+ if (self->outstandingCalls[i].isUsed)
+ {
+ if (self->outstandingCalls[i].invokeId == invokeId)
+ {
Semaphore_post(self->outstandingCallsLock);
return &(self->outstandingCalls[i]);
}
@@ -276,8 +290,10 @@ addToOutstandingCalls(MmsConnection self, uint32_t invokeId, eMmsOutstandingCall
Semaphore_wait(self->outstandingCallsLock);
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
- if (self->outstandingCalls[i].isUsed == false) {
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
+ if (self->outstandingCalls[i].isUsed == false)
+ {
self->outstandingCalls[i].isUsed = true;
self->outstandingCalls[i].invokeId = invokeId;
self->outstandingCalls[i].timeout = Hal_getTimeInMs() + self->requestTimeout;
@@ -302,9 +318,12 @@ removeFromOutstandingCalls(MmsConnection self, uint32_t invokeId)
Semaphore_wait(self->outstandingCallsLock);
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
- if (self->outstandingCalls[i].isUsed) {
- if (self->outstandingCalls[i].invokeId == invokeId) {
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
+ if (self->outstandingCalls[i].isUsed)
+ {
+ if (self->outstandingCalls[i].invokeId == invokeId)
+ {
self->outstandingCalls[i].isUsed = false;
break;
}
@@ -321,16 +340,18 @@ mmsClient_getMatchingObtainFileRequest(MmsConnection self, const char* filename)
Semaphore_wait(self->outstandingCallsLock);
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
- if (self->outstandingCalls[i].isUsed) {
-
- if (self->outstandingCalls[i].type == MMS_CALL_TYPE_OBTAIN_FILE) {
-
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
+ if (self->outstandingCalls[i].isUsed)
+ {
+ if (self->outstandingCalls[i].type == MMS_CALL_TYPE_OBTAIN_FILE)
+ {
char* storedFilename = (char*) self->outstandingCalls[i].internalParameter.ptr;
- if (storedFilename) {
-
- if (!strcmp(filename, storedFilename)) {
+ if (storedFilename)
+ {
+ if (!strcmp(filename, storedFilename))
+ {
Semaphore_post(self->outstandingCallsLock);
return &(self->outstandingCalls[i]);
}
@@ -348,7 +369,8 @@ static void
sendMessage(MmsConnection self, ByteBuffer* message)
{
#if (CONFIG_MMS_RAW_MESSAGE_LOGGING == 1)
- if (self->rawMmsMessageHandler != NULL) {
+ if (self->rawMmsMessageHandler != NULL)
+ {
MmsRawMessageHandler handler = (MmsRawMessageHandler) self->rawMmsMessageHandler;
handler(self->rawMmsMessageHandlerParameter, message->buffer, message->size, false);
}
@@ -361,8 +383,8 @@ static MmsError
sendAsyncRequest(MmsConnection self, uint32_t invokeId, ByteBuffer* message, eMmsOutstandingCallType type,
void* userCallback, void* userParameter, MmsClientInternalParameter internalParameter)
{
- if (addToOutstandingCalls(self, invokeId, type, userCallback, userParameter, internalParameter) == false) {
-
+ if (addToOutstandingCalls(self, invokeId, type, userCallback, userParameter, internalParameter) == false)
+ {
/* message cannot be sent - release resources */
IsoClientConnection_releaseTransmitBuffer(self->isoClient);
@@ -527,7 +549,8 @@ parseServiceError(uint8_t* buffer, int bufPos, int maxLength, MmsServiceError* e
int endPos = bufPos + maxLength;
int length;
- while (bufPos < endPos) {
+ while (bufPos < endPos)
+ {
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, endPos);
@@ -588,7 +611,8 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32
int endPos = bufPos + length;
- while (bufPos < endPos) {
+ while (bufPos < endPos)
+ {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
@@ -649,7 +673,8 @@ mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invo
int endPos = bufPos + length;
- while (bufPos < endPos) {
+ while (bufPos < endPos)
+ {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
@@ -657,13 +682,16 @@ mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invo
if (bufPos < 0)
goto exit_error;
- if (tag == 0x80) { /* invoke id */
+ if (tag == 0x80)
+ {
+ /* invoke id */
if (hasInvokeId)
*hasInvokeId = true;
if (invokeId != NULL)
*invokeId = BerDecoder_decodeUint32(buffer, length, bufPos);
}
- else if (tag > 0x80 && tag < 0x8c) {
+ else if (tag > 0x80 && tag < 0x8c)
+ {
*rejectType = tag - 0x80;
*rejectReason = BerDecoder_decodeInt32(buffer, length, bufPos);
}
@@ -686,15 +714,19 @@ exit_error:
static void
handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, MmsOutstandingCall outstandingCall, MmsError err)
{
- if (outstandingCall->type == MMS_CALL_TYPE_READ_VARIABLE) {
-
+ if (outstandingCall->type == MMS_CALL_TYPE_READ_VARIABLE)
+ {
MmsConnection_ReadVariableHandler handler =
(MmsConnection_ReadVariableHandler) outstandingCall->userCallback;
if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL);
- else {
- if (response) {
+ }
+ else
+ {
+ if (response)
+ {
MmsValue* value = mmsClient_parseReadResponse(response, NULL, false);
if (value == NULL)
@@ -705,15 +737,19 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_READ_MULTIPLE_VARIABLES) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_READ_MULTIPLE_VARIABLES)
+ {
MmsConnection_ReadVariableHandler handler =
(MmsConnection_ReadVariableHandler) outstandingCall->userCallback;
if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL);
- else {
- if (response) {
+ }
+ else
+ {
+ if (response)
+ {
MmsValue* value = mmsClient_parseReadResponse(response, NULL, true);
if (value == NULL)
@@ -721,19 +757,21 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, value);
}
-
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_WRITE_VARIABLE) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_WRITE_VARIABLE)
+ {
MmsConnection_WriteVariableHandler handler =
(MmsConnection_WriteVariableHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, DATA_ACCESS_ERROR_NO_RESPONSE);
}
- else {
- if (response) {
+ else
+ {
+ if (response)
+ {
MmsDataAccessError daError = mmsClient_parseWriteResponse(response, bufPos, &err);
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, daError);
@@ -741,16 +779,19 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_WRITE_MULTIPLE_VARIABLES) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_WRITE_MULTIPLE_VARIABLES)
+ {
MmsConnection_WriteMultipleVariablesHandler handler =
(MmsConnection_WriteMultipleVariablesHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL);
}
- else {
- if (response) {
+ else
+ {
+ if (response)
+ {
LinkedList accessResults = NULL;
mmsClient_parseWriteMultipleItemsResponse(response, bufPos, &err, -1, &accessResults);
@@ -759,15 +800,19 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_READ_NVL_DIRECTORY) {
+ else if (outstandingCall->type == MMS_CALL_TYPE_READ_NVL_DIRECTORY)
+ {
MmsConnection_ReadNVLDirectoryHandler handler =
(MmsConnection_ReadNVLDirectoryHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL, false);
}
- else {
- if (response) {
+ else
+ {
+ if (response)
+ {
bool deletable = false;
LinkedList accessSpec = mmsClient_parseGetNamedVariableListAttributesResponse(response, &deletable);
@@ -779,15 +824,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_DEFINE_NVL) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_DEFINE_NVL)
+ {
MmsConnection_GenericServiceHandler handler =
(MmsConnection_GenericServiceHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, false);
}
- else {
+ else
+ {
bool success = false;
if (!mmsClient_parseDefineNamedVariableResponse(response, NULL))
@@ -798,15 +845,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, success);
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_DELETE_NVL) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_DELETE_NVL)
+ {
MmsConnection_GenericServiceHandler handler =
(MmsConnection_GenericServiceHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, false);
}
- else {
+ else
+ {
bool success = false;
long numberMatched = 0;
@@ -816,8 +865,11 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
success = true;
if (numberMatched == 0)
+ {
err = MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT;
- else {
+ }
+ else
+ {
if (numberDeleted == 0)
err = MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED;
}
@@ -825,14 +877,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, success);
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_GET_VAR_ACCESS_ATTR) {
+ else if (outstandingCall->type == MMS_CALL_TYPE_GET_VAR_ACCESS_ATTR)
+ {
MmsConnection_GetVariableAccessAttributesHandler handler =
(MmsConnection_GetVariableAccessAttributesHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL);
}
- else {
+ else
+ {
MmsVariableSpecification* typeSpec = mmsClient_parseGetVariableAccessAttributesResponse(response, NULL);
if (typeSpec == NULL)
@@ -841,14 +896,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, typeSpec);
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_GET_SERVER_STATUS) {
+ else if (outstandingCall->type == MMS_CALL_TYPE_GET_SERVER_STATUS)
+ {
MmsConnection_GetServerStatusHandler handler =
(MmsConnection_GetServerStatusHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, 0, 0);
}
- else {
+ else
+ {
int vmdLogicalStatus;
int vmdPhysicalStatus;
@@ -858,15 +916,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, vmdLogicalStatus, vmdPhysicalStatus);
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_IDENTIFY) {
+ else if (outstandingCall->type == MMS_CALL_TYPE_IDENTIFY)
+ {
MmsConnection_IdentifyHandler handler =
(MmsConnection_IdentifyHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL, NULL, NULL);
}
- else {
-
+ else
+ {
if (mmsClient_parseIdentifyResponse(self, response, bufPos, outstandingCall->invokeId, handler,
outstandingCall->userParameter) == false)
{
@@ -876,15 +936,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_READ_JOURNAL) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_READ_JOURNAL)
+ {
MmsConnection_ReadJournalHandler handler =
(MmsConnection_ReadJournalHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL, false);
}
- else {
+ else
+ {
bool moreFollows = false;
LinkedList entries = NULL;
@@ -896,15 +958,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_GET_NAME_LIST) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_GET_NAME_LIST)
+ {
MmsConnection_GetNameListHandler handler =
(MmsConnection_GetNameListHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL, false);
}
- else {
+ else
+ {
LinkedList nameList = (LinkedList) outstandingCall->internalParameter.ptr;
bool moreFollows = mmsClient_parseGetNameListResponse(&nameList, response);
@@ -917,15 +981,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
}
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_FILE_OPEN) {
-
+ else if (outstandingCall->type == MMS_CALL_TYPE_FILE_OPEN)
+ {
MmsConnection_FileOpenHandler handler =
(MmsConnection_FileOpenHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, 0, 0, 0);
}
- else {
+ else
+ {
int32_t frsmId;
uint32_t fileSize;
uint64_t lastModified;
@@ -935,21 +1001,25 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
{
handler(outstandingCall->invokeId, outstandingCall->userParameter, MMS_ERROR_PARSING_RESPONSE, 0, 0, 0);
}
- else {
+ else
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, frsmId, fileSize, lastModified);
}
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_FILE_READ) {
+ else if (outstandingCall->type == MMS_CALL_TYPE_FILE_READ)
+ {
MmsConnection_FileReadHandler handler =
(MmsConnection_FileReadHandler) outstandingCall->userCallback;
int32_t frsmId = outstandingCall->internalParameter.i32;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, frsmId, NULL, 0, false);
}
- else {
+ else
+ {
bool moreFollows;
if (mmsMsg_parseFileReadResponse(ByteBuffer_getBuffer(response), bufPos, ByteBuffer_getSize(response), outstandingCall->invokeId, frsmId, &moreFollows,
@@ -967,7 +1037,8 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
MmsConnection_GenericServiceHandler handler =
(MmsConnection_GenericServiceHandler) outstandingCall->userCallback;
- if (outstandingCall->type == MMS_CALL_TYPE_OBTAIN_FILE) {
+ if (outstandingCall->type == MMS_CALL_TYPE_OBTAIN_FILE)
+ {
if (outstandingCall->internalParameter.ptr)
GLOBAL_FREEMEM(outstandingCall->internalParameter.ptr);
}
@@ -979,14 +1050,17 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, true);
}
}
- else if (outstandingCall->type == MMS_CALL_TYPE_GET_FILE_DIR) {
+ else if (outstandingCall->type == MMS_CALL_TYPE_GET_FILE_DIR)
+ {
MmsConnection_FileDirectoryHandler handler =
(MmsConnection_FileDirectoryHandler) outstandingCall->userCallback;
- if (err != MMS_ERROR_NONE) {
+ if (err != MMS_ERROR_NONE)
+ {
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL, 0, 0, false);
}
- else {
+ else
+ {
if (mmsClient_parseFileDirectoryResponse(response, bufPos, outstandingCall->invokeId, handler, outstandingCall->userParameter) == false)
handler(outstandingCall->invokeId, outstandingCall->userParameter, MMS_ERROR_PARSING_RESPONSE, NULL, 0, 0, false);
}
@@ -1005,24 +1079,24 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (indication != ISO_IND_TICK)
printf("MMS_CLIENT: mmsIsoCallback called with indication %i\n", indication);
- if (indication == ISO_IND_TICK) {
-
+ if (indication == ISO_IND_TICK)
+ {
/* check timeouts */
uint64_t currentTime = Hal_getTimeInMs();
int i = 0;
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
-
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
Semaphore_wait(self->outstandingCallsLock);
- if (self->outstandingCalls[i].isUsed) {
-
+ if (self->outstandingCalls[i].isUsed)
+ {
Semaphore_post(self->outstandingCallsLock);
- if (currentTime > self->outstandingCalls[i].timeout) {
-
+ if (currentTime > self->outstandingCalls[i].timeout)
+ {
if (self->outstandingCalls[i].type != MMS_CALL_TYPE_NONE)
handleAsyncResponse(self, NULL, 0, &(self->outstandingCalls[i]), MMS_ERROR_SERVICE_TIMEOUT);
@@ -1038,8 +1112,10 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
}
}
- if (self->concludeHandler) {
- if (currentTime > self->concludeTimeout) {
+ if (self->concludeHandler)
+ {
+ if (currentTime > self->concludeTimeout)
+ {
self->concludeHandler(self->concludeHandlerParameter, MMS_ERROR_SERVICE_TIMEOUT, false);
self->concludeHandler = NULL;
}
@@ -1048,7 +1124,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
return true;
}
- if (indication == ISO_IND_CLOSED) {
+ if (indication == ISO_IND_CLOSED)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: mmsIsoCallback: Connection lost or closed by client!\n");
@@ -1062,12 +1139,12 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
{
int i;
- for (i = 0; i < OUTSTANDING_CALLS; i++) {
-
+ for (i = 0; i < self->maxOutstandingCalled; i++)
+ {
Semaphore_wait(self->outstandingCallsLock);
- if (self->outstandingCalls[i].isUsed) {
-
+ if (self->outstandingCalls[i].isUsed)
+ {
Semaphore_post(self->outstandingCallsLock);
if (self->outstandingCalls[i].type != MMS_CALL_TYPE_NONE)
@@ -1085,7 +1162,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
return true;
}
- if (indication == ISO_IND_ASSOCIATION_FAILED) {
+ if (indication == ISO_IND_ASSOCIATION_FAILED)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: mmsIsoCallback: association failed!\n");
@@ -1093,7 +1171,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
return false;
}
- if (payload != NULL) {
+ if (payload != NULL)
+ {
if (ByteBuffer_getSize(payload) < 1) {
return false;
}
@@ -1102,7 +1181,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
uint8_t* buf = ByteBuffer_getBuffer(payload);
#if (CONFIG_MMS_RAW_MESSAGE_LOGGING == 1)
- if (self->rawMmsMessageHandler != NULL) {
+ if (self->rawMmsMessageHandler != NULL)
+ {
MmsRawMessageHandler handler = (MmsRawMessageHandler) self->rawMmsMessageHandler;
handler(self->rawMmsMessageHandlerParameter, buf, payload->size, true);
}
@@ -1113,20 +1193,25 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: MMS-PDU: %02x\n", tag);
- if (tag == 0xa9) { /* initiate response PDU */
-
- if (indication == ISO_IND_ASSOCIATION_SUCCESS) {
+ if (tag == 0xa9)
+ {
+ /* initiate response PDU */
- if (mmsClient_parseInitiateResponse(self, payload)) {
+ if (indication == ISO_IND_ASSOCIATION_SUCCESS)
+ {
+ if (mmsClient_parseInitiateResponse(self, payload))
+ {
setConnectionState(self, MMS_CONNECTION_STATE_CONNECTED);
}
- else {
+ else
+ {
setConnectionState(self, MMS_CONNECTION_STATE_CLOSING);
goto exit_with_error;
}
}
- else {
+ else
+ {
setConnectionState(self, MMS_CONNECTION_STATE_CLOSING);
if (DEBUG_MMS_CLIENT)
@@ -1135,7 +1220,9 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
return false;
}
}
- else if (tag == 0xaa) { /* initiate error PDU */
+ else if (tag == 0xaa)
+ {
+ /* initiate error PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received initiate error PDU\n");
@@ -1144,36 +1231,48 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
return false;
}
- else if (tag == 0xa3) { /* unconfirmed PDU */
+ else if (tag == 0xa3)
+ {
+ /* unconfirmed PDU */
handleUnconfirmedMmsPdu(self, payload);
}
- else if (tag == 0x8b) { /* conclude request PDU */
+ else if (tag == 0x8b)
+ {
+ /* conclude request PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received conclude.request\n");
/* TODO block all new user requests? */
}
- else if (tag == 0x8c) { /* conclude response PDU */
+ else if (tag == 0x8c)
+ {
+ /* conclude response PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received conclude.response+\n");
- if (self->concludeHandler) {
+ if (self->concludeHandler)
+ {
self->concludeHandler(self->concludeHandlerParameter, MMS_ERROR_NONE, true);
self->concludeHandler = NULL;
}
IsoClientConnection_release(self->isoClient);
}
- else if (tag == 0x8d) { /* conclude error PDU */
+ else if (tag == 0x8d)
+ {
+ /* conclude error PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received conclude.reponse-\n");
- if (self->concludeHandler) {
+ if (self->concludeHandler)
+ {
self->concludeHandler(self->concludeHandlerParameter, MMS_ERROR_CONCLUDE_REJECTED, false);
self->concludeHandler = NULL;
}
}
- else if (tag == 0xa2) { /* confirmed error PDU */
+ else if (tag == 0xa2)
+ {
+ /* confirmed error PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: Confirmed error PDU!\n");
@@ -1183,37 +1282,43 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
MmsServiceError serviceError = { 0, 0 };
- if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &hasInvokeId, &serviceError) < 0) {
+ if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &hasInvokeId, &serviceError) < 0)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n");
goto exit_with_error;
}
- else {
-
- if (hasInvokeId) {
+ else
+ {
+ if (hasInvokeId)
+ {
MmsOutstandingCall call = checkForOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
MmsError err = convertServiceErrorToMmsError(serviceError);
- if (call->type != MMS_CALL_TYPE_NONE) {
+ if (call->type != MMS_CALL_TYPE_NONE)
+ {
handleAsyncResponse(self, NULL, 0, call, err);
}
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: internal problem (unexpected call type - error PDU)\n");
}
}
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: server sent unexpected confirmed error PDU!\n");
return false;
}
}
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: server sent confirmed error PDU without invoke ID!\n");
@@ -1222,7 +1327,9 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
}
}
- else if (tag == 0xa4) { /* reject PDU */
+ else if (tag == 0xa4)
+ {
+ /* reject PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: reject PDU!\n");
@@ -1232,23 +1339,25 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
int rejectType;
int rejectReason;
- if (mmsMsg_parseRejectPDU(payload->buffer, 0, payload->size, &invokeId, &hasInvokeId, &rejectType, &rejectReason) >= 0) {
-
+ if (mmsMsg_parseRejectPDU(payload->buffer, 0, payload->size, &invokeId, &hasInvokeId, &rejectType, &rejectReason) >= 0)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: reject PDU invokeID: %u type: %i reason: %i\n", invokeId, rejectType, rejectReason);
- if (hasInvokeId) {
+ if (hasInvokeId)
+ {
MmsOutstandingCall call = checkForOutstandingCall(self, invokeId);
- if (call) {
-
+ if (call)
+ {
MmsError err = convertRejectCodesToMmsError(rejectType, rejectReason);
- if (call->type != MMS_CALL_TYPE_NONE) {
+ if (call->type != MMS_CALL_TYPE_NONE)
+ {
handleAsyncResponse(self, NULL, 0, call, err);
}
- else {
-
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: internal problem (unexpected call type - reject PDU)\n");
}
@@ -1260,12 +1369,13 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
else {
return false;
}
-
}
else
goto exit_with_error;
}
- else if (tag == 0xa1) { /* confirmed response PDU */
+ else if (tag == 0xa1)
+ {
+ /* confirmed response PDU */
int length;
int bufPos = 1;
@@ -1274,7 +1384,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (bufPos < 0)
goto exit_with_error;
- if (buf[bufPos++] == 0x02) {
+ if (buf[bufPos++] == 0x02)
+ {
int invokeIdLength;
bufPos = BerDecoder_decodeLength(buf, &invokeIdLength, bufPos, payload->size);
@@ -1292,17 +1403,20 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
MmsOutstandingCall call = checkForOutstandingCall(self, invokeId);
- if (call) {
-
- if (call->type != MMS_CALL_TYPE_NONE) {
+ if (call)
+ {
+ if (call->type != MMS_CALL_TYPE_NONE)
+ {
handleAsyncResponse(self, payload, bufPos, call, MMS_ERROR_NONE);
}
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: internal problem (unexpected call type - confirmed response PDU)\n");
}
}
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: unexpected message from server!\n");
@@ -1313,8 +1427,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
goto exit_with_error;
}
#if (MMS_OBTAIN_FILE_SERVICE == 1)
- else if (tag == 0xa0) {
-
+ else if (tag == 0xa0)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received confirmed request PDU (size=%i)\n", payload->size);
@@ -1330,13 +1444,14 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
bool hasInvokeId = false;
uint32_t invokeId = 0;
- while (bufPos < payload->size) {
-
+ while (bufPos < payload->size)
+ {
uint8_t nestedTag = buf[bufPos++];
bool extendedTag = false;
- if ((nestedTag & 0x1f) == 0x1f) {
+ if ((nestedTag & 0x1f) == 0x1f)
+ {
extendedTag = true;
nestedTag = buf[bufPos++];
}
@@ -1345,9 +1460,10 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (bufPos < 0)
goto exit_with_error;
- if (extendedTag) {
-
- if (hasInvokeId == false) {
+ if (extendedTag)
+ {
+ if (hasInvokeId == false)
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: invalid message received - missing invoke ID!\n");
@@ -1434,7 +1550,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
}
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
- else {
+ else
+ {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: unknown message type\n");
@@ -1460,7 +1577,8 @@ connectionHandlingThread(void* parameter)
{
MmsConnection self = (MmsConnection) parameter;
- while (self->connectionThreadRunning) {
+ while (self->connectionThreadRunning)
+ {
if (MmsConnection_tick(self))
Thread_sleep(10);
}
@@ -1479,8 +1597,8 @@ MmsConnection_createInternal(TLSConfiguration tlsConfig, bool createThread)
MmsConnection self = (MmsConnection) GLOBAL_CALLOC(1, sizeof(struct sMmsConnection));
- if (self) {
-
+ if (self)
+ {
self->parameters.dataStructureNestingLevel = -1;
self->parameters.maxServOutstandingCalled = -1;
self->parameters.maxServOutstandingCalling = -1;
@@ -1498,7 +1616,9 @@ MmsConnection_createInternal(TLSConfiguration tlsConfig, bool createThread)
self->concludeHandlerParameter = NULL;
self->concludeTimeout = 0;
- self->outstandingCalls = (MmsOutstandingCall) GLOBAL_CALLOC(OUTSTANDING_CALLS, sizeof(struct sMmsOutstandingCall));
+ self->maxOutstandingCalling = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ self->maxOutstandingCalled = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ self->outstandingCalls = (MmsOutstandingCall) GLOBAL_CALLOC(CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED, sizeof(struct sMmsOutstandingCall));
self->isoParameters = IsoConnectionParameters_create();
@@ -1555,43 +1675,49 @@ MmsConnection_createNonThreaded(TLSConfiguration tlsConfig)
void
MmsConnection_destroy(MmsConnection self)
{
+ if (self)
+ {
#if (CONFIG_MMS_THREADLESS_STACK == 0)
- if (self->createThread) {
- if (self->connectionHandlingThread) {
- if (self->connectionThreadRunning) {
- self->connectionThreadRunning = false;
- Thread_destroy(self->connectionHandlingThread);
- self->connectionHandlingThread = NULL;
+ if (self->createThread)
+ {
+ if (self->connectionHandlingThread)
+ {
+ if (self->connectionThreadRunning)
+ {
+ self->connectionThreadRunning = false;
+ Thread_destroy(self->connectionHandlingThread);
+ self->connectionHandlingThread = NULL;
+ }
}
}
- }
#endif
- if (self->isoClient != NULL)
- IsoClientConnection_destroy(self->isoClient);
+ if (self->isoClient != NULL)
+ IsoClientConnection_destroy(self->isoClient);
- if (self->isoParameters != NULL)
- IsoConnectionParameters_destroy(self->isoParameters);
+ if (self->isoParameters != NULL)
+ IsoConnectionParameters_destroy(self->isoParameters);
- Semaphore_destroy(self->nextInvokeIdLock);
+ Semaphore_destroy(self->nextInvokeIdLock);
- Semaphore_destroy(self->outstandingCallsLock);
+ Semaphore_destroy(self->outstandingCallsLock);
- Semaphore_destroy(self->associationStateLock);
+ Semaphore_destroy(self->associationStateLock);
- GLOBAL_FREEMEM(self->outstandingCalls);
+ GLOBAL_FREEMEM(self->outstandingCalls);
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
- if (self->filestoreBasepath != NULL)
- GLOBAL_FREEMEM(self->filestoreBasepath);
+ if (self->filestoreBasepath != NULL)
+ GLOBAL_FREEMEM(self->filestoreBasepath);
#endif
- /* Close outstanding open files */
- mmsClient_closeOutstandingOpenFiles(self);
+ /* Close outstanding open files */
+ mmsClient_closeOutstandingOpenFiles(self);
#endif
- GLOBAL_FREEMEM(self);
+ GLOBAL_FREEMEM(self);
+ }
}
void
@@ -1599,7 +1725,8 @@ MmsConnection_setFilestoreBasepath(MmsConnection self, const char* basepath)
{
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
- if (self->filestoreBasepath != NULL) {
+ if (self->filestoreBasepath != NULL)
+ {
GLOBAL_FREEMEM(self->filestoreBasepath);
self->filestoreBasepath = NULL;
}
@@ -1657,6 +1784,25 @@ MmsConnection_setRequestTimeout(MmsConnection self, uint32_t timeoutInMs)
self->requestTimeout = timeoutInMs;
}
+void
+MmsConnnection_setMaxOutstandingCalls(MmsConnection self, int calling, int called)
+{
+ if (calling < 1)
+ calling = 1;
+
+ if (called < 1)
+ called = 1;
+
+ if (self->outstandingCalls)
+ {
+ GLOBAL_FREEMEM(self->outstandingCalls);
+ }
+
+ self->maxOutstandingCalling = calling;
+ self->maxOutstandingCalled = called;
+ self->outstandingCalls = (MmsOutstandingCall)GLOBAL_CALLOC(called, sizeof(struct sMmsOutstandingCall));
+}
+
uint32_t
MmsConnection_getRequestTimeout(MmsConnection self)
{
@@ -1740,22 +1886,25 @@ MmsConnection_connect(MmsConnection self, MmsError* mmsError, const char* server
MmsConnection_connectAsync(self, &err, serverName, serverPort);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(conParams.sem);
- if (conParams.state == MMS_CONNECTION_STATE_CONNECTED) {
+ if (conParams.state == MMS_CONNECTION_STATE_CONNECTED)
+ {
*mmsError = MMS_ERROR_NONE;
success = true;
}
- else {
+ else
+ {
*mmsError = MMS_ERROR_CONNECTION_REJECTED;
}
if (conParams.originalHandler)
conParams.originalHandler(self, conParams.originalParameter, conParams.state);
-
}
- else {
+ else
+ {
*mmsError = err;
}
@@ -1770,7 +1919,8 @@ MmsConnection_connect(MmsConnection self, MmsError* mmsError, const char* server
void
MmsConnection_connectAsync(MmsConnection self, MmsError* mmsError, const char* serverName, int serverPort)
{
- if (serverPort == -1) {
+ if (serverPort == -1)
+ {
#if (CONFIG_MMS_SUPPORT_TLS == 1)
if (self->isoParameters->tlsConfiguration)
serverPort = 3782;
@@ -1782,9 +1932,10 @@ MmsConnection_connectAsync(MmsConnection self, MmsError* mmsError, const char* s
}
#if (CONFIG_MMS_THREADLESS_STACK == 0)
- if (self->createThread) {
- if (self->connectionHandlingThread == NULL) {
-
+ if (self->createThread)
+ {
+ if (self->connectionHandlingThread == NULL)
+ {
self->connectionHandlingThread = Thread_create(connectionHandlingThread, self, false);
self->connectionThreadRunning = true;
Thread_start(self->connectionHandlingThread);
@@ -1802,13 +1953,15 @@ MmsConnection_connectAsync(MmsConnection self, MmsError* mmsError, const char* s
mmsClient_createInitiateRequest(self, payload);
#if (CONFIG_MMS_RAW_MESSAGE_LOGGING == 1)
- if (self->rawMmsMessageHandler != NULL) {
+ if (self->rawMmsMessageHandler != NULL)
+ {
MmsRawMessageHandler handler = (MmsRawMessageHandler) self->rawMmsMessageHandler;
handler(self->rawMmsMessageHandlerParameter, payload->buffer, payload->size, false);
}
#endif /* (CONFIG_MMS_RAW_MESSAGE_LOGGING == 1) */
- if (IsoClientConnection_associateAsync(self->isoClient, self->connectTimeout, self->requestTimeout)) {
+ if (IsoClientConnection_associateAsync(self->isoClient, self->connectTimeout, self->requestTimeout))
+ {
setConnectionState(self, MMS_CONNECTION_STATE_CONNECTING);
*mmsError = MMS_ERROR_NONE;
}
@@ -1837,7 +1990,8 @@ MmsConnection_abortAsync(MmsConnection self, MmsError* mmsError)
{
self->connectionLostHandler = NULL;
- if (getConnectionState(self) == MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) == MMS_CONNECTION_STATE_CONNECTED)
+ {
IsoClientConnection_abortAsync(self->isoClient);
*mmsError = MMS_ERROR_NONE;
}
@@ -1855,14 +2009,16 @@ MmsConnection_abort(MmsConnection self, MmsError* mmsError)
bool success = false;
- if (getConnectionState(self) == MMS_CONNECTION_STATE_CONNECTED) {
-
+ if (getConnectionState(self) == MMS_CONNECTION_STATE_CONNECTED)
+ {
IsoClientConnection_abortAsync(self->isoClient);
uint64_t timeout = Hal_getTimeInMs() + self->requestTimeout;
- while (Hal_getTimeInMs() < timeout) {
- if (getConnectionState(self) == MMS_CONNECTION_STATE_CLOSED) {
+ while (Hal_getTimeInMs() < timeout)
+ {
+ if (getConnectionState(self) == MMS_CONNECTION_STATE_CLOSED)
+ {
success = true;
break;
}
@@ -1870,10 +2026,10 @@ MmsConnection_abort(MmsConnection self, MmsError* mmsError)
Thread_sleep(10);
}
}
-
}
- if (success == false) {
+ if (success == false)
+ {
IsoClientConnection_close(self->isoClient);
*mmsError = MMS_ERROR_SERVICE_TIMEOUT;
}
@@ -1915,7 +2071,8 @@ MmsConnection_conclude(MmsConnection self, MmsError* mmsError)
MmsConnection_concludeAsync(self, &err, concludeHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
err = parameter.err;
}
@@ -1929,7 +2086,8 @@ MmsConnection_conclude(MmsConnection self, MmsError* mmsError)
void
MmsConnection_concludeAsync(MmsConnection self, MmsError* mmsError, MmsConnection_ConcludeAbortHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
}
@@ -1971,7 +2129,8 @@ mmsClient_getNameListSingleRequestAsync(
void* parameter,
LinkedList nameList)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -1987,8 +2146,8 @@ mmsClient_getNameListSingleRequestAsync(
if (associationSpecific)
mmsClient_createMmsGetNameListRequestAssociationSpecific(invokeId,
payload, continueAfter);
- else {
-
+ else
+ {
if (objectClass == MMS_OBJECT_CLASS_DOMAIN)
mmsClient_createMmsGetNameListRequestVMDspecific(invokeId,
payload, continueAfter);
@@ -2032,7 +2191,6 @@ getNameListHandler(uint32_t invokeId, void* parameter, MmsError mmsError, Linked
Semaphore_post(parameters->sem);
}
-
static LinkedList /* */
mmsClient_getNameList(MmsConnection self, MmsError *mmsError,
const char* domainId,
@@ -2055,7 +2213,8 @@ mmsClient_getNameList(MmsConnection self, MmsError *mmsError,
mmsClient_getNameListSingleRequestAsync(self, NULL, &err, domainId, objectClass, associationSpecific, NULL,
getNameListHandler, ¶meter, NULL);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
err = parameter.err;
list = parameter.nameList;
@@ -2064,7 +2223,8 @@ mmsClient_getNameList(MmsConnection self, MmsError *mmsError,
Semaphore_destroy(parameter.sem);
- while (moreFollows) {
+ while (moreFollows)
+ {
parameter.sem = Semaphore_create(1);
char* continueAfter = NULL;
@@ -2077,12 +2237,18 @@ mmsClient_getNameList(MmsConnection self, MmsError *mmsError,
mmsClient_getNameListSingleRequestAsync(self, NULL, &err, domainId, objectClass, associationSpecific, continueAfter,
getNameListHandler, ¶meter, list);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
err = parameter.err;
list = parameter.nameList;
moreFollows = parameter.moreFollows;
}
+ else
+ {
+ /* exit loop when message cannot be sent */
+ moreFollows = false;
+ }
Semaphore_destroy(parameter.sem);
}
@@ -2090,8 +2256,10 @@ mmsClient_getNameList(MmsConnection self, MmsError *mmsError,
if (mmsError)
*mmsError = err;
- if (err != MMS_ERROR_NONE) {
- if (list) {
+ if (err != MMS_ERROR_NONE)
+ {
+ if (list)
+ {
LinkedList_destroy(list);
list = NULL;
}
@@ -2184,7 +2352,6 @@ MmsConnection_getVariableListNamesAssociationSpecificAsync(MmsConnection self, u
continueAfter, handler, parameter, NULL);
}
-
struct readNVParameters
{
Semaphore sem;
@@ -2210,7 +2377,8 @@ void
MmsConnection_readVariableAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError, const char* domainId, const char* itemId,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
@@ -2255,7 +2423,8 @@ MmsConnection_readVariable(MmsConnection self, MmsError* mmsError,
MmsConnection_readVariableAsync(self, NULL, &err, domainId, itemId, readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2275,7 +2444,8 @@ MmsConnection_readVariableComponentAsync(MmsConnection self, uint32_t* usedInvok
const char* domainId, const char* itemId, const char* componentId,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
@@ -2320,7 +2490,8 @@ MmsConnection_readVariableComponent(MmsConnection self, MmsError* mmsError,
MmsConnection_readVariableComponentAsync(self, NULL, &err, domainId, itemId, componentId, readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2354,7 +2525,8 @@ MmsConnection_readArrayElements(MmsConnection self, MmsError* mmsError,
MmsConnection_readArrayElementsAsync(self, NULL, &err, domainId, itemId, startIndex, numberOfElements,
readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2374,7 +2546,8 @@ MmsConnection_readArrayElementsAsync(MmsConnection self, uint32_t* usedInvokeId,
uint32_t startIndex, uint32_t numberOfElements,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2420,7 +2593,8 @@ MmsConnection_readSingleArrayElementWithComponent(MmsConnection self, MmsError*
MmsConnection_readSingleArrayElementWithComponentAsync(self, NULL, &err, domainId, itemId, index, componentId,
readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2442,7 +2616,8 @@ MmsConnection_readSingleArrayElementWithComponentAsync(MmsConnection self, uint3
uint32_t index, const char* componentId,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2488,7 +2663,8 @@ MmsConnection_readMultipleVariables(MmsConnection self, MmsError* mmsError,
MmsConnection_readMultipleVariablesAsync(self, NULL, &err, domainId, items,
readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2508,7 +2684,8 @@ MmsConnection_readMultipleVariablesAsync(MmsConnection self, uint32_t* usedInvok
const char* domainId, LinkedList /**/items,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2521,7 +2698,8 @@ MmsConnection_readMultipleVariablesAsync(MmsConnection self, uint32_t* usedInvok
if (usedInvokeId)
*usedInvokeId = invokeId;
- if (mmsClient_createReadRequestMultipleValues(invokeId, domainId, items, payload) > 0) {
+ if (mmsClient_createReadRequestMultipleValues(invokeId, domainId, items, payload) > 0)
+ {
MmsClientInternalParameter intParam;
intParam.ptr = NULL;
@@ -2530,7 +2708,8 @@ MmsConnection_readMultipleVariablesAsync(MmsConnection self, uint32_t* usedInvok
if (mmsError)
*mmsError = err;
}
- else {
+ else
+ {
if (mmsError)
*mmsError = MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE;
}
@@ -2558,7 +2737,8 @@ MmsConnection_readNamedVariableListValues(MmsConnection self, MmsError* mmsError
MmsConnection_readNamedVariableListValuesAsync(self, NULL, &err, domainId, listName, specWithResult,
readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2578,7 +2758,8 @@ MmsConnection_readNamedVariableListValuesAsync(MmsConnection self, uint32_t* use
const char* domainId, const char* listName, bool specWithResult,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2626,7 +2807,8 @@ MmsConnection_readNamedVariableListValuesAssociationSpecific(
MmsConnection_readNamedVariableListValuesAssociationSpecificAsync(self, NULL, &err, listName, specWithResult,
readVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
value = parameter.value;
@@ -2646,7 +2828,8 @@ MmsConnection_readNamedVariableListValuesAssociationSpecificAsync(MmsConnection
const char* listName, bool specWithResult,
MmsConnection_ReadVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2716,7 +2899,8 @@ MmsConnection_readNamedVariableListDirectory(MmsConnection self, MmsError* mmsEr
MmsConnection_readNamedVariableListDirectoryAsync(self, NULL, &err, domainId, listName,
readNVLDirectoryHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(waitForResponse);
err = parameter.err;
specs = parameter.specs;
@@ -2738,7 +2922,8 @@ MmsConnection_readNamedVariableListDirectoryAsync(MmsConnection self, uint32_t*
const char* domainId, const char* listName,
MmsConnection_ReadNVLDirectoryHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2785,7 +2970,8 @@ MmsConnection_readNamedVariableListDirectoryAssociationSpecific(MmsConnection se
MmsConnection_readNamedVariableListDirectoryAssociationSpecificAsync(self, NULL, &err, listName,
readNVLDirectoryHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(waitForResponse);
err = parameter.err;
specs = parameter.specs;
@@ -2807,7 +2993,8 @@ MmsConnection_readNamedVariableListDirectoryAssociationSpecificAsync(MmsConnecti
const char* listName,
MmsConnection_ReadNVLDirectoryHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2872,7 +3059,8 @@ MmsConnection_defineNamedVariableList(MmsConnection self, MmsError* mmsError,
MmsConnection_defineNamedVariableListAsync(self, NULL, &err, domainId, listName, variableSpecs,
defineNVLHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
}
@@ -2888,7 +3076,8 @@ MmsConnection_defineNamedVariableListAsync(MmsConnection self, uint32_t* usedInv
const char* listName, LinkedList variableSpecs,
MmsConnection_GenericServiceHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2931,7 +3120,8 @@ MmsConnection_defineNamedVariableListAssociationSpecific(MmsConnection self,
MmsConnection_defineNamedVariableListAssociationSpecificAsync(self, NULL, &err, listName, variableSpecs,
defineNVLHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
}
@@ -2947,7 +3137,8 @@ MmsConnection_defineNamedVariableListAssociationSpecificAsync(MmsConnection self
const char* listName, LinkedList variableSpecs,
MmsConnection_GenericServiceHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -2991,7 +3182,8 @@ MmsConnection_deleteNamedVariableList(MmsConnection self, MmsError* mmsError,
MmsConnection_deleteNamedVariableListAsync(self, NULL, &err, domainId, listName, defineNVLHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
isDeleted = parameter.success;
@@ -3009,7 +3201,8 @@ void
MmsConnection_deleteNamedVariableListAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError, const char* domainId, const char* listName,
MmsConnection_GenericServiceHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3052,7 +3245,8 @@ MmsConnection_deleteAssociationSpecificNamedVariableList(MmsConnection self,
MmsConnection_deleteAssociationSpecificNamedVariableListAsync(self, NULL, &err, listName, defineNVLHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
isDeleted = parameter.success;
@@ -3070,7 +3264,8 @@ void
MmsConnection_deleteAssociationSpecificNamedVariableListAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError, const char* listName,
MmsConnection_GenericServiceHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3135,7 +3330,8 @@ MmsConnection_getVariableAccessAttributes(MmsConnection self, MmsError* mmsError
MmsConnection_getVariableAccessAttributesAsync(self, NULL, &err, domainId, itemId, getAccessAttrHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
typeSpec = parameter.typeSpec;
@@ -3154,7 +3350,8 @@ MmsConnection_getVariableAccessAttributesAsync(MmsConnection self, uint32_t* use
const char* domainId, const char* itemId,
MmsConnection_GetVariableAccessAttributesHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3224,7 +3421,8 @@ MmsConnection_identify(MmsConnection self, MmsError* mmsError)
MmsConnection_identifyAsync(self, NULL, &err, identifyHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
identity = parameter.identify;
@@ -3242,7 +3440,8 @@ void
MmsConnection_identifyAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError,
MmsConnection_IdentifyHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3310,7 +3509,8 @@ MmsConnection_getServerStatus(MmsConnection self, MmsError* mmsError, int* vmdLo
MmsConnection_getServerStatusAsync(self, NULL, &err, extendedDerivation, getServerStatusHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3331,7 +3531,8 @@ void
MmsConnection_getServerStatusAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError, bool extendedDerivation,
MmsConnection_GetServerStatusHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3361,7 +3562,8 @@ exit_function:
static void
MmsJournalVariable_destroy(MmsJournalVariable self)
{
- if (self != NULL) {
+ if (self)
+ {
GLOBAL_FREEMEM(self->tag);
MmsValue_delete(self->value);
GLOBAL_FREEMEM(self);
@@ -3371,7 +3573,8 @@ MmsJournalVariable_destroy(MmsJournalVariable self)
void
MmsJournalEntry_destroy(MmsJournalEntry self)
{
- if (self != NULL) {
+ if (self)
+ {
MmsValue_delete(self->entryID);
MmsValue_delete(self->occurenceTime);
LinkedList_destroyDeep(self->journalVariables,
@@ -3451,7 +3654,8 @@ MmsConnection_readJournalTimeRange(MmsConnection self, MmsError* mmsError, const
MmsConnection_readJournalTimeRangeAsync(self, NULL, &err, domainId, itemId, startTime, endTime, readJournalHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3472,15 +3676,16 @@ void
MmsConnection_readJournalTimeRangeAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError, const char* domainId, const char* itemId,
MmsValue* startTime, MmsValue* endTime, MmsConnection_ReadJournalHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
}
if ((MmsValue_getType(startTime) != MMS_BINARY_TIME) ||
- (MmsValue_getType(endTime) != MMS_BINARY_TIME)) {
-
+ (MmsValue_getType(endTime) != MMS_BINARY_TIME))
+ {
if (mmsError)
*mmsError = MMS_ERROR_INVALID_ARGUMENTS;
goto exit_function;
@@ -3524,7 +3729,8 @@ MmsConnection_readJournalStartAfter(MmsConnection self, MmsError* mmsError, cons
MmsConnection_readJournalStartAfterAsync(self, NULL, &err, domainId, itemId, timeSpecification, entrySpecification, readJournalHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3545,15 +3751,16 @@ void
MmsConnection_readJournalStartAfterAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError* mmsError, const char* domainId, const char* itemId,
MmsValue* timeSpecification, MmsValue* entrySpecification, MmsConnection_ReadJournalHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
}
if ((MmsValue_getType(timeSpecification) != MMS_BINARY_TIME) ||
- (MmsValue_getType(entrySpecification) != MMS_OCTET_STRING)) {
-
+ (MmsValue_getType(entrySpecification) != MMS_OCTET_STRING))
+ {
if (mmsError)
*mmsError = MMS_ERROR_INVALID_ARGUMENTS;
goto exit_function;
@@ -3626,7 +3833,8 @@ MmsConnection_fileOpen(MmsConnection self, MmsError* mmsError, const char* filen
MmsConnection_fileOpenAsync(self, NULL, &err, filename, initialPosition, fileOpenHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3659,7 +3867,8 @@ MmsConnection_fileOpenAsync(MmsConnection self, uint32_t* usedInvokeId, MmsError
{
#if (MMS_FILE_SERVICE == 1)
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3731,7 +3940,8 @@ MmsConnection_fileClose(MmsConnection self, MmsError* mmsError, int32_t frsmId)
MmsConnection_fileCloseAsync(self, NULL, &err, frsmId, fileOperationHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3755,7 +3965,8 @@ MmsConnection_fileCloseAsync(MmsConnection self, uint32_t* usedInvokeId, MmsErro
{
#if (MMS_FILE_SERVICE == 1)
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3806,7 +4017,8 @@ MmsConnection_fileDelete(MmsConnection self, MmsError* mmsError, const char* fil
MmsConnection_fileDeleteAsync(self, NULL, &err, fileName, fileOperationHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3831,7 +4043,8 @@ MmsConnection_fileDeleteAsync(MmsConnection self, uint32_t* usedInvokeId, MmsErr
{
#if (MMS_FILE_SERVICE == 1)
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -3913,7 +4126,8 @@ MmsConnection_fileRead(MmsConnection self, MmsError* mmsError, int32_t frsmId, M
MmsConnection_fileReadAsync(self, NULL, &err, frsmId, fileReadHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -3993,7 +4207,8 @@ getFileDirHandler(uint32_t invokeId, void* parameter, MmsError mmsError, char* f
parameters->err = mmsError;
- if ((mmsError != MMS_ERROR_NONE) || (filename == NULL)) {
+ if ((mmsError != MMS_ERROR_NONE) || (filename == NULL))
+ {
parameters->moreFollows = moreFollows;
/* last call --> unblock user thread */
@@ -4024,7 +4239,8 @@ MmsConnection_getFileDirectory(MmsConnection self, MmsError* mmsError, const cha
MmsConnection_getFileDirectoryAsync(self, NULL, &err, fileSpecification, continueAfter, getFileDirHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
moreFollows = parameter.moreFollows;
@@ -4051,7 +4267,8 @@ MmsConnection_getFileDirectoryAsync(MmsConnection self, uint32_t* usedInvokeId,
{
#if (MMS_FILE_SERVICE == 1)
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4102,7 +4319,8 @@ MmsConnection_fileRename(MmsConnection self, MmsError* mmsError, const char* cur
MmsConnection_fileRenameAsync(self, NULL, &err, currentFileName, newFileName, fileOperationHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -4126,7 +4344,8 @@ MmsConnection_fileRenameAsync(MmsConnection self, uint32_t* usedInvokeId, MmsErr
{
#if (MMS_FILE_SERVICE == 1)
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4177,7 +4396,8 @@ MmsConnection_obtainFile(MmsConnection self, MmsError* mmsError, const char* sou
MmsConnection_obtainFileAsync(self, NULL, &err, sourceFile, destinationFile, fileOperationHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -4209,7 +4429,8 @@ MmsConnection_obtainFileAsync(MmsConnection self, uint32_t* usedInvokeId, MmsErr
{
#if (MMS_FILE_SERVICE == 1)
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4278,7 +4499,8 @@ MmsConnection_writeVariable(MmsConnection self, MmsError* mmsError,
MmsConnection_writeVariableAsync(self, NULL, &err, domainId, itemId, value, writeVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -4297,7 +4519,8 @@ MmsConnection_writeVariableAsync(MmsConnection self, uint32_t* usedInvokeId, Mms
const char* domainId, const char* itemId, MmsValue* value,
MmsConnection_WriteVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4341,7 +4564,8 @@ MmsConnection_writeSingleArrayElementWithComponent(MmsConnection self, MmsError*
MmsConnection_writeSingleArrayElementWithComponentAsync(self, NULL, &err, domainId, itemId, arrayIndex, componentId, value, writeVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -4361,7 +4585,8 @@ MmsConnection_writeSingleArrayElementWithComponentAsync(MmsConnection self, uint
uint32_t arrayIndex, const char* componentId, MmsValue* value,
MmsConnection_WriteVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4406,7 +4631,8 @@ MmsConnection_writeVariableComponent(MmsConnection self, MmsError* mmsError,
MmsConnection_writeVariableComponentAsync(self, NULL, &err, domainId, itemId, componentId, value, writeVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -4425,7 +4651,8 @@ MmsConnection_writeVariableComponentAsync(MmsConnection self, uint32_t* usedInvo
const char* domainId, const char* itemId, const char* componentId, MmsValue* value,
MmsConnection_WriteVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4491,8 +4718,8 @@ MmsConnection_writeMultipleVariables(MmsConnection self, MmsError* mmsError, con
MmsConnection_writeMultipleVariablesAsync(self, NULL, &err, domainId, items, values, writeMultipleVariablesHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
-
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
err = parameter.err;
@@ -4518,7 +4745,8 @@ MmsConnection_writeMultipleVariablesAsync(MmsConnection self, uint32_t* usedInvo
LinkedList /**/ items, LinkedList /* */ values,
MmsConnection_WriteMultipleVariablesHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4531,7 +4759,8 @@ MmsConnection_writeMultipleVariablesAsync(MmsConnection self, uint32_t* usedInvo
if (usedInvokeId)
*usedInvokeId = invokeId;
- if (mmsClient_createWriteMultipleItemsRequest(invokeId, domainId, items, values, payload) != -1) {
+ if (mmsClient_createWriteMultipleItemsRequest(invokeId, domainId, items, values, payload) != -1)
+ {
MmsClientInternalParameter intParam;
intParam.ptr = NULL;
@@ -4540,7 +4769,8 @@ MmsConnection_writeMultipleVariablesAsync(MmsConnection self, uint32_t* usedInvo
if (mmsError)
*mmsError = err;
}
- else {
+ else
+ {
*mmsError = MMS_ERROR_RESOURCE_OTHER;
}
@@ -4566,7 +4796,8 @@ MmsConnection_writeArrayElements(MmsConnection self, MmsError* mmsError,
MmsConnection_writeArrayElementsAsync(self, NULL, &err, domainId, itemId, index, numberOfElements, value, writeVariableHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.waitForResponse);
err = parameter.err;
@@ -4586,7 +4817,8 @@ MmsConnection_writeArrayElementsAsync(MmsConnection self, uint32_t* usedInvokeId
MmsValue* value,
MmsConnection_WriteVariableHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4630,8 +4862,8 @@ MmsConnection_writeNamedVariableList(MmsConnection self, MmsError* mmsError, boo
MmsConnection_writeNamedVariableListAsync(self, NULL, &err, isAssociationSpecific, domainId, itemId, values, writeMultipleVariablesHandler, ¶meter);
- if (err == MMS_ERROR_NONE) {
-
+ if (err == MMS_ERROR_NONE)
+ {
Semaphore_wait(parameter.sem);
err = parameter.err;
@@ -4641,7 +4873,8 @@ MmsConnection_writeNamedVariableList(MmsConnection self, MmsError* mmsError, boo
else
LinkedList_destroyDeep(parameter.result, (LinkedListValueDeleteFunction) MmsValue_delete);
}
- else {
+ else
+ {
if (accessResults)
*accessResults = NULL;
}
@@ -4657,7 +4890,8 @@ MmsConnection_writeNamedVariableListAsync(MmsConnection self, uint32_t* usedInvo
const char* domainId, const char* itemId, LinkedList /* */values,
MmsConnection_WriteMultipleVariablesHandler handler, void* parameter)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4687,7 +4921,8 @@ exit_function:
void
MmsConnection_sendRawData(MmsConnection self, MmsError* mmsError, uint8_t* buffer, int bufSize)
{
- if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) {
+ if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED)
+ {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
@@ -4709,16 +4944,19 @@ exit_function:
void
MmsServerIdentity_destroy(MmsServerIdentity* self)
{
- if (self->modelName != NULL)
- GLOBAL_FREEMEM(self->modelName);
+ if (self)
+ {
+ if (self->modelName != NULL)
+ GLOBAL_FREEMEM(self->modelName);
- if (self->vendorName != NULL)
- GLOBAL_FREEMEM(self->vendorName);
+ if (self->vendorName != NULL)
+ GLOBAL_FREEMEM(self->vendorName);
- if (self->revision != NULL)
- GLOBAL_FREEMEM(self->revision);
+ if (self->revision != NULL)
+ GLOBAL_FREEMEM(self->revision);
- GLOBAL_FREEMEM(self);
+ GLOBAL_FREEMEM(self);
+ }
}
MmsVariableAccessSpecification*
@@ -4727,10 +4965,13 @@ MmsVariableAccessSpecification_create(char* domainId, char* itemId)
MmsVariableAccessSpecification* self = (MmsVariableAccessSpecification*)
GLOBAL_MALLOC(sizeof(MmsVariableAccessSpecification));
- self->domainId = domainId;
- self->itemId = itemId;
- self->arrayIndex = -1;
- self->componentName = NULL;
+ if (self)
+ {
+ self->domainId = domainId;
+ self->itemId = itemId;
+ self->arrayIndex = -1;
+ self->componentName = NULL;
+ }
return self;
}
@@ -4742,10 +4983,13 @@ MmsVariableAccessSpecification_createAlternateAccess(char* domainId, char* itemI
MmsVariableAccessSpecification* self = (MmsVariableAccessSpecification*)
GLOBAL_MALLOC(sizeof(MmsVariableAccessSpecification));
- self->domainId = domainId;
- self->itemId = itemId;
- self->arrayIndex = index;
- self->componentName = componentName;
+ if (self)
+ {
+ self->domainId = domainId;
+ self->itemId = itemId;
+ self->arrayIndex = index;
+ self->componentName = componentName;
+ }
return self;
}
@@ -4753,14 +4997,17 @@ MmsVariableAccessSpecification_createAlternateAccess(char* domainId, char* itemI
void
MmsVariableAccessSpecification_destroy(MmsVariableAccessSpecification* self)
{
- if (self->domainId != NULL)
- GLOBAL_FREEMEM((void*) self->domainId);
+ if (self)
+ {
+ if (self->domainId != NULL)
+ GLOBAL_FREEMEM((void*) self->domainId);
- if (self->itemId != NULL)
- GLOBAL_FREEMEM((void*) self->itemId);
+ if (self->itemId != NULL)
+ GLOBAL_FREEMEM((void*) self->itemId);
- if (self->componentName != NULL)
- GLOBAL_FREEMEM((void*) self->componentName);
+ if (self->componentName != NULL)
+ GLOBAL_FREEMEM((void*) self->componentName);
- GLOBAL_FREEMEM(self);
+ GLOBAL_FREEMEM(self);
+ }
}
diff --git a/src/mms/iso_mms/client/mms_client_files.c b/src/mms/iso_mms/client/mms_client_files.c
index 4fca418e..5ea8fb01 100644
--- a/src/mms/iso_mms/client/mms_client_files.c
+++ b/src/mms/iso_mms/client/mms_client_files.c
@@ -180,7 +180,6 @@ exit_reject_invalid_pdu:
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
}
-
void
mmsClient_handleFileReadRequest(
MmsConnection connection,
@@ -191,7 +190,7 @@ mmsClient_handleFileReadRequest(
int32_t frsmId = BerDecoder_decodeInt32(buffer, maxBufPos - bufPos, bufPos);
if (DEBUG_MMS_CLIENT)
- printf("MMS_CLIENT: mmsClient_handleFileReadRequest read request for frsmId: %i\n", frsmId);
+ printf("MMS_CLIENT: mmsClient_handleFileReadRequest read request for frsmId: %i\n", (int)frsmId);
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
@@ -401,7 +400,6 @@ mmsClient_createFileDirectoryRequest(uint32_t invokeId, ByteBuffer* request, con
request->size = bufPos;
}
-
void
mmsClient_createFileRenameRequest(uint32_t invokeId, ByteBuffer* request, const char* currentFileName, const char* newFileName)
{
@@ -466,7 +464,6 @@ mmsClient_createObtainFileRequest(uint32_t invokeId, ByteBuffer* request, const
request->size = bufPos;
}
-
static bool
parseFileAttributes(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* fileSize, uint64_t* lastModified)
{
@@ -610,7 +607,6 @@ parseListOfDirectoryEntries(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t
return true;
}
-
bool
mmsClient_parseFileDirectoryResponse(ByteBuffer* response, int bufPos, uint32_t invokeId, MmsConnection_FileDirectoryHandler handler, void* parameter)
{
@@ -731,16 +727,14 @@ mmsMsg_parseFileOpenResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t
}
bool
-mmsMsg_parseFileReadResponse(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t invokeId, int frsmId, bool* moreFollows, MmsConnection_FileReadHandler handler, void* handlerParameter)
+mmsMsg_parseFileReadResponse(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t invokeId, int32_t frsmId, bool* moreFollows, MmsConnection_FileReadHandler handler, void* handlerParameter)
{
int length;
uint8_t* data = NULL;
int dataLen = 0;
-
uint8_t tag = buffer[bufPos++];
-
if (tag != 0xbf) {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT/SERVER: mmsClient_parseFileReadResponse: unknown tag %02x\n", tag);
diff --git a/src/mms/iso_mms/client/mms_client_initiate.c b/src/mms/iso_mms/client/mms_client_initiate.c
index fdd9b94e..8eb930de 100644
--- a/src/mms/iso_mms/client/mms_client_initiate.c
+++ b/src/mms/iso_mms/client/mms_client_initiate.c
@@ -39,18 +39,16 @@ static uint8_t servicesSupported[] = { 0xee, 0x1c, 0x00, 0x00, 0x04, 0x08, 0x00,
void
mmsClient_createInitiateRequest(MmsConnection self, ByteBuffer* message)
{
- int maxServerOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
- int maxServerOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
int dataStructureNestingLevel = DEFAULT_DATA_STRUCTURE_NESTING_LEVEL;
uint32_t localDetailSize =
BerEncoder_UInt32determineEncodedSize(self->parameters.maxPduSize);
uint32_t proposedMaxServerOutstandingCallingSize =
- BerEncoder_UInt32determineEncodedSize(maxServerOutstandingCalling);
+ BerEncoder_UInt32determineEncodedSize(self->maxOutstandingCalling);
uint32_t proposedMaxServerOutstandingCalledSize =
- BerEncoder_UInt32determineEncodedSize(maxServerOutstandingCalled);
+ BerEncoder_UInt32determineEncodedSize(self->maxOutstandingCalled);
uint32_t dataStructureNestingLevelSize =
BerEncoder_UInt32determineEncodedSize(dataStructureNestingLevel);
@@ -76,11 +74,11 @@ mmsClient_createInitiateRequest(MmsConnection self, ByteBuffer* message)
/* proposedMaxServerOutstandingCalling */
bufPos = BerEncoder_encodeTL(0x81, proposedMaxServerOutstandingCallingSize, buffer, bufPos);
- bufPos = BerEncoder_encodeUInt32(maxServerOutstandingCalling, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(self->maxOutstandingCalling, buffer, bufPos);
/* proposedMaxServerOutstandingCalled */
bufPos = BerEncoder_encodeTL(0x82, proposedMaxServerOutstandingCalledSize, buffer, bufPos);
- bufPos = BerEncoder_encodeUInt32(maxServerOutstandingCalled, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(self->maxOutstandingCalled, buffer, bufPos);
/* proposedDataStructureNestingLevel */
bufPos = BerEncoder_encodeTL(0x83, dataStructureNestingLevelSize, buffer, bufPos);
@@ -169,8 +167,8 @@ mmsClient_parseInitiateResponse(MmsConnection self, ByteBuffer* response)
{
self->parameters.maxPduSize = CONFIG_MMS_MAXIMUM_PDU_SIZE;
self->parameters.dataStructureNestingLevel = DEFAULT_DATA_STRUCTURE_NESTING_LEVEL;
- self->parameters.maxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
- self->parameters.maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ self->parameters.maxServOutstandingCalled = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ self->parameters.maxServOutstandingCalling = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
int bufPos = 1; /* ignore tag - already checked */
@@ -203,16 +201,16 @@ mmsClient_parseInitiateResponse(MmsConnection self, ByteBuffer* response)
case 0x81: /* proposed-max-serv-outstanding-calling */
self->parameters.maxServOutstandingCalling = BerDecoder_decodeUint32(buffer, length, bufPos);
- if (self->parameters.maxServOutstandingCalling > DEFAULT_MAX_SERV_OUTSTANDING_CALLING)
- self->parameters.maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ if (self->parameters.maxServOutstandingCalling > CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING)
+ self->parameters.maxServOutstandingCalling = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
break;
case 0x82: /* proposed-max-serv-outstanding-called */
self->parameters.maxServOutstandingCalled = BerDecoder_decodeUint32(buffer, length, bufPos);
- if (self->parameters.maxServOutstandingCalled > DEFAULT_MAX_SERV_OUTSTANDING_CALLED)
- self->parameters.maxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ if (self->parameters.maxServOutstandingCalled > CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED)
+ self->parameters.maxServOutstandingCalled = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
break;
case 0x83: /* proposed-data-structure-nesting-level */
diff --git a/src/mms/iso_mms/common/mms_type_spec.c b/src/mms/iso_mms/common/mms_type_spec.c
index f83b804e..c1db5d89 100644
--- a/src/mms/iso_mms/common/mms_type_spec.c
+++ b/src/mms/iso_mms/common/mms_type_spec.c
@@ -1,7 +1,7 @@
/*
* mms_type_spec.c
*
- * Copyright 2013 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -108,36 +108,40 @@ MmsVariableSpecification_getType(MmsVariableSpecification* self)
bool
MmsVariableSpecification_isValueOfType(MmsVariableSpecification* self, const MmsValue* value)
{
- if ((self->type) == (value->type)) {
-
- if ((self->type == MMS_STRUCTURE) || (self->type == MMS_ARRAY)) {
-
+ if ((self->type) == (value->type))
+ {
+ if ((self->type == MMS_STRUCTURE) || (self->type == MMS_ARRAY))
+ {
int componentCount = self->typeSpec.structure.elementCount;
if (componentCount != (int) MmsValue_getArraySize(value))
return false;
- if (self->type == MMS_STRUCTURE) {
-
+ if (self->type == MMS_STRUCTURE)
+ {
int i;
- for (i = 0; i < componentCount; i++) {
-
+ for (i = 0; i < componentCount; i++)
+ {
if (MmsVariableSpecification_isValueOfType(self->typeSpec.structure.elements[i], MmsValue_getElement(value, i)) == false)
return false;
}
return true;
}
- else {
+ else
+ {
int i;
- for (i = 0; i < componentCount; i++) {
-
+ for (i = 0; i < componentCount; i++)
+ {
if (MmsVariableSpecification_isValueOfType(self->typeSpec.array.elementTypeSpec, MmsValue_getElement(value, i)) == false)
return false;
}
+
+ return true;
}
}
- else if (self->type == MMS_BIT_STRING) {
+ else if (self->type == MMS_BIT_STRING)
+ {
if (self->typeSpec.bitString == value->value.bitString.size)
return true;
diff --git a/src/mms/iso_mms/common/mms_value.c b/src/mms/iso_mms/common/mms_value.c
index 549619a8..f88e232b 100644
--- a/src/mms/iso_mms/common/mms_value.c
+++ b/src/mms/iso_mms/common/mms_value.c
@@ -1463,13 +1463,15 @@ MmsValue_newOctetString(int size, int maxSize)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- if (self) {
+ if (self)
+ {
self->type = MMS_OCTET_STRING;
self->value.octetString.size = size;
self->value.octetString.maxSize = maxSize;
self->value.octetString.buf = (uint8_t*) GLOBAL_CALLOC(1, abs(maxSize));
- if (self->value.octetString.buf == NULL) {
+ if ((maxSize != 0) && (self->value.octetString.buf == NULL))
+ {
GLOBAL_FREEMEM(self);
self = NULL;
}
@@ -1677,14 +1679,16 @@ exit_function:
}
static void
-setVisibleStringValue(MmsValue* self, const char* string)
+setVisibleStringValue(MmsValue* self, const char* value)
{
- if (self->value.visibleString.buf != NULL) {
- if (string != NULL) {
-
- int newStringSize = strlen(string);
+ if (self->value.visibleString.buf != NULL)
+ {
+ if (value != NULL)
+ {
+ int newStringSize = strlen(value);
- if (newStringSize > self->value.visibleString.size) {
+ if (newStringSize > self->value.visibleString.size)
+ {
GLOBAL_FREEMEM(self->value.visibleString.buf);
self->value.visibleString.buf = (char*) GLOBAL_MALLOC(newStringSize + 1);
@@ -1694,7 +1698,7 @@ setVisibleStringValue(MmsValue* self, const char* string)
self->value.visibleString.size = newStringSize;
}
- StringUtils_copyStringMax(self->value.visibleString.buf, self->value.visibleString.size + 1, string);
+ StringUtils_copyStringMax(self->value.visibleString.buf, self->value.visibleString.size + 1, value);
}
else
self->value.visibleString.buf[0] = 0;
@@ -1906,7 +1910,8 @@ MmsValue_newStringFromByteArray(const uint8_t* byteArray, int size, MmsType type
self->value.visibleString.buf = StringUtils_createStringFromBuffer(byteArray, size);
- if (self->value.visibleString.buf == NULL) {
+ if (self->value.visibleString.buf == NULL)
+ {
GLOBAL_FREEMEM(self);
self = NULL;
}
@@ -2008,17 +2013,20 @@ MmsValue_createArray(const MmsVariableSpecification* elementType, int size)
self->value.structure.size = size;
self->value.structure.components = (MmsValue**) GLOBAL_CALLOC(size, sizeof(MmsValue*));
- if (self->value.structure.components == NULL) {
+ if (self->value.structure.components == NULL)
+ {
GLOBAL_FREEMEM(self);
self = NULL;
goto exit_function;
}
int i;
- for (i = 0; i < size; i++) {
+ for (i = 0; i < size; i++)
+ {
self->value.structure.components[i] = MmsValue_newDefaultValue(elementType);
- if (self->value.structure.components[i] == NULL) {
+ if (self->value.structure.components[i] == NULL)
+ {
MmsValue_delete(self);
self = NULL;
goto exit_function;
@@ -2102,9 +2110,10 @@ MmsValue_setDeletable(MmsValue* self)
void
MmsValue_setDeletableRecursive(MmsValue* self)
{
- if (self != NULL) {
-
- if ((MmsValue_getType(self) == MMS_ARRAY) || (MmsValue_getType(self) == MMS_STRUCTURE)) {
+ if (self)
+ {
+ if ((MmsValue_getType(self) == MMS_ARRAY) || (MmsValue_getType(self) == MMS_STRUCTURE))
+ {
int i;
int elementCount = MmsValue_getArraySize(self);
@@ -2179,7 +2188,8 @@ MmsValue_getTypeString(MmsValue* self)
const char*
MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
{
- if (self == NULL) {
+ if (self == NULL)
+ {
StringUtils_copyStringMax(buffer, bufferSize, "(null)");
return buffer;
@@ -2240,7 +2250,8 @@ MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
int size = MmsValue_getBitStringSize(self);
/* fill buffer with zeros */
- if (size + 1 > bufferSize) {
+ if (size + 1 > bufferSize)
+ {
memset(buffer, 0, bufferSize);
size = bufferSize - 1;
@@ -2250,7 +2261,8 @@ MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
}
int i;
- for (i = 0; i < size; i++) {
+ for (i = 0; i < size; i++)
+ {
if (MmsValue_getBitStringBit(self, i))
buffer[bufPos++] = '1';
else
@@ -2290,7 +2302,8 @@ MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
int size = MmsValue_getOctetStringSize(self);
int bufPos = 0;
int i;
- for (i = 0; i < size; i++) {
+ for (i = 0; i < size; i++)
+ {
snprintf(buffer + bufPos, bufferSize - bufPos, "%02x", self->value.octetString.buf[i]);
bufPos += 2;
diff --git a/src/mms/iso_mms/server/mms_access_result.c b/src/mms/iso_mms/server/mms_access_result.c
index b17461f0..95dcef8a 100644
--- a/src/mms/iso_mms/server/mms_access_result.c
+++ b/src/mms/iso_mms/server/mms_access_result.c
@@ -171,9 +171,12 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength, int* endBu
if (bufPos < 0)
goto exit_with_error;
- /* if not indefinite length end tag, data length must be > 0 */
- if ((tag != 0) && (dataLength == 0))
- goto exit_with_error;
+ /* if not indefinite length end tag, visible-string, mms-string, or octet-string, data length must be > 0 */
+ if (tag != 0)
+ {
+ if (tag != 0x8a && tag != 0x90 && tag != 0x89 && dataLength == 0)
+ goto exit_with_error;
+ }
switch (tag) {
@@ -192,8 +195,8 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength, int* endBu
int i;
- for (i = 0; i < elementCount; i++) {
-
+ for (i = 0; i < elementCount; i++)
+ {
int elementLength;
int newBufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos + 1, dataEndBufPos);
@@ -304,7 +307,8 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength, int* endBu
break;
case 0x91: /* MMS_UTC_TIME */
- if (dataLength == 8) {
+ if (dataLength == 8)
+ {
value = MmsValue_newUtcTime(0);
MmsValue_setUtcTimeByBuffer(value, buffer + bufPos);
bufPos += dataLength;
diff --git a/src/mms/iso_mms/server/mms_association_service.c b/src/mms/iso_mms/server/mms_association_service.c
index 83a32f3e..667f365d 100644
--- a/src/mms/iso_mms/server/mms_association_service.c
+++ b/src/mms/iso_mms/server/mms_association_service.c
@@ -330,9 +330,9 @@ parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, i
self->dataStructureNestingLevel =
DEFAULT_DATA_STRUCTURE_NESTING_LEVEL;
- self->maxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ self->maxServOutstandingCalled = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
- self->maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ self->maxServOutstandingCalling = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
self->negotiatedParameterCBC[0] = 0;
self->negotiatedParameterCBC[1] = 0;
@@ -367,16 +367,16 @@ parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, i
case 0x81: /* proposed-max-serv-outstanding-calling */
self->maxServOutstandingCalling = BerDecoder_decodeUint32(buffer, length, bufPos);
- if (self->maxServOutstandingCalling > DEFAULT_MAX_SERV_OUTSTANDING_CALLING)
- self->maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ if (self->maxServOutstandingCalling > CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING)
+ self->maxServOutstandingCalling = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
break;
case 0x82: /* proposed-max-serv-outstanding-called */
self->maxServOutstandingCalled = BerDecoder_decodeUint32(buffer, length, bufPos);
- if (self->maxServOutstandingCalled > DEFAULT_MAX_SERV_OUTSTANDING_CALLED)
- self->maxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ if (self->maxServOutstandingCalled > CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED)
+ self->maxServOutstandingCalled = CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
break;
case 0x83: /* proposed-data-structure-nesting-level */
diff --git a/src/mms/iso_mms/server/mms_get_var_access_service.c b/src/mms/iso_mms/server/mms_get_var_access_service.c
index c27ff76b..4adb6f4c 100644
--- a/src/mms/iso_mms/server/mms_get_var_access_service.c
+++ b/src/mms/iso_mms/server/mms_get_var_access_service.c
@@ -1,7 +1,7 @@
/*
* mms_get_var_access_service.c
*
- * Copyright 2013-2023 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -310,9 +310,12 @@ mmsServer_handleGetVariableAccessAttributesRequest(
rval = ber_decode(NULL, &asn_DEF_GetVariableAccessAttributesRequest,
(void**) &request, buffer + bufPos, maxBufPos - bufPos);
- if (rval.code == RC_OK) {
- if (request->present == GetVariableAccessAttributesRequest_PR_name) {
- if (request->choice.name.present == ObjectName_PR_domainspecific) {
+ if (rval.code == RC_OK)
+ {
+ if (request->present == GetVariableAccessAttributesRequest_PR_name)
+ {
+ if (request->choice.name.present == ObjectName_PR_domainspecific)
+ {
Identifier_t domainId = request->choice.name.choice.domainspecific.domainId;
Identifier_t nameId = request->choice.name.choice.domainspecific.itemId;
@@ -328,7 +331,8 @@ mmsServer_handleGetVariableAccessAttributesRequest(
GLOBAL_FREEMEM(nameIdStr);
}
#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
- else if (request->choice.name.present == ObjectName_PR_vmdspecific) {
+ else if (request->choice.name.present == ObjectName_PR_vmdspecific)
+ {
Identifier_t nameId = request->choice.name.choice.vmdspecific;
char* nameIdStr = StringUtils_createStringFromBuffer(nameId.buf, nameId.size);
@@ -357,6 +361,12 @@ mmsServer_handleGetVariableAccessAttributesRequest(
asn_DEF_GetVariableAccessAttributesRequest.free_struct(&asn_DEF_GetVariableAccessAttributesRequest, request, 0);
+ if (ByteBuffer_getSize(response) > connection->maxPduSize)
+ {
+ ByteBuffer_setSize(response, 0);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
+ }
+
return retVal;
}
diff --git a/src/mms/iso_mms/server/mms_named_variable_list_service.c b/src/mms/iso_mms/server/mms_named_variable_list_service.c
index 85f1b960..a38cfd7f 100644
--- a/src/mms/iso_mms/server/mms_named_variable_list_service.c
+++ b/src/mms/iso_mms/server/mms_named_variable_list_service.c
@@ -130,16 +130,22 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
goto exit_function;
}
- if ((mmsPdu->present == MmsPdu_PR_confirmedRequestPdu) &&
- (mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.present
- == ConfirmedServiceRequest_PR_deleteNamedVariableList))
- {
- request = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.deleteNamedVariableList);
- }
- else {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- goto exit_function;
- }
+ if ((mmsPdu->present == MmsPdu_PR_confirmedRequestPdu) &&
+ (mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.present
+ == ConfirmedServiceRequest_PR_deleteNamedVariableList))
+ {
+ request = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.deleteNamedVariableList);
+ }
+ else {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ goto exit_function;
+ }
+
+ if (request->listOfVariableListName == NULL)
+ {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ goto exit_function;
+ }
long scopeOfDelete = DeleteNamedVariableListRequest__scopeOfDelete_specific;
@@ -675,7 +681,8 @@ createGetNamedVariableListAttributesResponse(int invokeId, ByteBuffer* response,
LinkedList variable = LinkedList_getNext(variables);
int i;
- for (i = 0; i < variableCount; i++) {
+ for (i = 0; i < variableCount; i++)
+ {
MmsNamedVariableListEntry variableEntry = (MmsNamedVariableListEntry) variable->data;
varListResponse->listOfVariable.list.array[i] = (struct GetNamedVariableListAttributesResponse__listOfVariable__Member*)
@@ -740,8 +747,8 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
goto exit_function;
}
- if (request->present == ObjectName_PR_domainspecific) {
-
+ if (request->present == ObjectName_PR_domainspecific)
+ {
char domainName[65];
char itemName[65];
@@ -761,11 +768,12 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
MmsDomain* domain = MmsDevice_getDomain(mmsDevice, domainName);
- if (domain != NULL) {
+ if (domain != NULL)
+ {
MmsNamedVariableList varList = MmsDomain_getNamedVariableList(domain, itemName);
- if (varList) {
-
+ if (varList)
+ {
MmsError accessError = mmsServer_callVariableListChangedHandler(MMS_VARLIST_GET_DIRECTORY, MMS_DOMAIN_SPECIFIC, domain, varList->name, connection);
if (accessError == MMS_ERROR_NONE) {
@@ -792,8 +800,8 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
}
#if (MMS_DYNAMIC_DATA_SETS == 1)
- else if (request->present == ObjectName_PR_aaspecific) {
-
+ else if (request->present == ObjectName_PR_aaspecific)
+ {
char listName[65];
if (request->choice.aaspecific.size > 64) {
@@ -806,11 +814,12 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
MmsNamedVariableList varList = MmsServerConnection_getNamedVariableList(connection, listName);
- if (varList) {
-
+ if (varList)
+ {
MmsError accessError = mmsServer_callVariableListChangedHandler(MMS_VARLIST_GET_DIRECTORY, MMS_ASSOCIATION_SPECIFIC, NULL, varList->name, connection);
- if (accessError == MMS_ERROR_NONE) {
+ if (accessError == MMS_ERROR_NONE)
+ {
if (createGetNamedVariableListAttributesResponse(invokeId, response, varList) == false) {
/* encoding failed - probably because buffer size is too small for message */
@@ -829,7 +838,8 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
}
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
- else if (request->present == ObjectName_PR_vmdspecific) {
+ else if (request->present == ObjectName_PR_vmdspecific)
+ {
char listName[65];
if (request->choice.vmdspecific.size > 64) {
@@ -844,11 +854,12 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
MmsNamedVariableList varList = mmsServer_getNamedVariableListWithName(mmsDevice->namedVariableLists, listName);
- if (varList) {
-
+ if (varList)
+ {
MmsError accessError = mmsServer_callVariableListChangedHandler(MMS_VARLIST_GET_DIRECTORY, MMS_VMD_SPECIFIC, NULL, varList->name, connection);
- if (accessError == MMS_ERROR_NONE) {
+ if (accessError == MMS_ERROR_NONE)
+ {
if (createGetNamedVariableListAttributesResponse(invokeId, response, varList) == false) {
/* encoding failed - probably because buffer size is too small for message */
@@ -870,6 +881,12 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
}
+ if (ByteBuffer_getSize(response) > connection->maxPduSize)
+ {
+ ByteBuffer_setSize(response, 0);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
+ }
+
exit_function:
asn_DEF_GetVariableAccessAttributesRequest.free_struct(&asn_DEF_GetNamedVariableListAttributesRequest,
diff --git a/src/mms/iso_mms/server/mms_read_service.c b/src/mms/iso_mms/server/mms_read_service.c
index 2b33dc41..043e03ce 100644
--- a/src/mms/iso_mms/server/mms_read_service.c
+++ b/src/mms/iso_mms/server/mms_read_service.c
@@ -1,7 +1,7 @@
/*
* mms_read_service.c
*
- * Copyright 2013-2023 Michael Zillgith
+ * Copyright 2013-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -202,30 +202,35 @@ alternateArrayAccess(MmsServerConnection connection,
MmsValue* arrayValue = mmsServer_getValue(connection->server, domain, itemId, connection, false);
- if (arrayValue != NULL) {
-
+ if (arrayValue != NULL)
+ {
MmsValue* value = NULL;
if (numberOfElements == 0)
- if (mmsServer_isAccessToArrayComponent(alternateAccess)) {
+ {
+ if (mmsServer_isAccessToArrayComponent(alternateAccess))
+ {
if (namedVariable->typeSpec.array.elementTypeSpec->type == MMS_STRUCTURE) {
MmsValue* structValue = MmsValue_getElement(arrayValue, index);
if (structValue != NULL)
value = mmsServer_getComponentOfArrayElement(alternateAccess,
- namedVariable, structValue);
+ namedVariable, structValue, NULL);
}
}
else {
value = MmsValue_getElement(arrayValue, index);
}
- else {
+ }
+ else
+ {
value = MmsValue_createEmptyArray(numberOfElements);
MmsValue_setDeletable(value);
int resultIndex = 0;
- while (index < lowIndex + numberOfElements) {
+ while (index < lowIndex + numberOfElements)
+ {
MmsValue* elementValue = NULL;
elementValue = MmsValue_getElement(arrayValue, index);
@@ -352,7 +357,8 @@ encodeVariableAccessSpecification(VarAccessSpec* accessSpec, uint8_t* buffer, in
varAccessSpecSize += itemIdLen + BerEncoder_determineLengthSize(itemIdLen) + 1;
- if (accessSpec->domainId != NULL) {
+ if (accessSpec->domainId != NULL)
+ {
uint32_t domainIdLen = strlen(accessSpec->domainId);
varAccessSpecSize += domainIdLen + BerEncoder_determineLengthSize(domainIdLen) + 1;
@@ -370,7 +376,8 @@ encodeVariableAccessSpecification(VarAccessSpec* accessSpec, uint8_t* buffer, in
varAccessSpecSize += 1 + BerEncoder_determineLengthSize(varAccessSpecLength);
- if (encode == false) {
+ if (encode == false)
+ {
bufPos = varAccessSpecSize;
goto exit_function;
}
@@ -378,8 +385,8 @@ encodeVariableAccessSpecification(VarAccessSpec* accessSpec, uint8_t* buffer, in
/* encode to buffer */
bufPos = BerEncoder_encodeTL(0xa0, varAccessSpecLength, buffer, bufPos);
- if (accessSpec->isNamedVariableList == true) {
-
+ if (accessSpec->isNamedVariableList == true)
+ {
bufPos = BerEncoder_encodeTL(0xa1, variableListNameLength, buffer, bufPos);
if (accessSpec->specific == 0) { /* vmd-specific */
@@ -425,8 +432,8 @@ encodeReadResponse(MmsServerConnection connection,
/* iterate values list to determine encoded size */
LinkedList value = LinkedList_getNext(values);
- for (i = 0; i < variableCount; i++) {
-
+ for (i = 0; i < variableCount; i++)
+ {
MmsValue* data = (MmsValue*) value->data;
accessResultSize += MmsValue_encodeMmsData(data, NULL, 0, false);
@@ -452,12 +459,13 @@ encodeReadResponse(MmsServerConnection connection,
confirmedResponseContentSize;
/* Check if message would fit in the MMS PDU */
- if (mmsPduSize > connection->maxPduSize) {
+ if (mmsPduSize > connection->maxPduSize)
+ {
if (DEBUG_MMS_SERVER)
printf("MMS read: message to large! send error PDU!\n");
mmsMsg_createServiceErrorPdu(invokeId, response,
- MMS_ERROR_SERVICE_OTHER);
+ MMS_ERROR_RESOURCE_OTHER);
goto exit_function;
}
@@ -487,7 +495,8 @@ encodeReadResponse(MmsServerConnection connection,
/* encode access results */
value = LinkedList_getNext(values);
- for (i = 0; i < variableCount; i++) {
+ for (i = 0; i < variableCount; i++)
+ {
MmsValue* data = (MmsValue*) value->data;
bufPos = MmsValue_encodeMmsData(data, buffer, bufPos, true);
@@ -529,16 +538,18 @@ handleReadListOfVariablesRequest(
int i;
- for (i = 0; i < variableCount; i++) {
+ for (i = 0; i < variableCount; i++)
+ {
VariableSpecification_t varSpec =
read->variableAccessSpecification.choice.listOfVariable.list.array[i]->variableSpecification;
AlternateAccess_t* alternateAccess =
read->variableAccessSpecification.choice.listOfVariable.list.array[i]->alternateAccess;
- if (varSpec.present == VariableSpecification_PR_name) {
-
- if (varSpec.choice.name.present == ObjectName_PR_domainspecific) {
+ if (varSpec.present == VariableSpecification_PR_name)
+ {
+ if (varSpec.choice.name.present == ObjectName_PR_domainspecific)
+ {
char domainIdStr[65];
char nameIdStr[65];
@@ -571,7 +582,8 @@ handleReadListOfVariablesRequest(
}
#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
- else if (varSpec.choice.name.present == ObjectName_PR_vmdspecific) {
+ else if (varSpec.choice.name.present == ObjectName_PR_vmdspecific)
+ {
char nameIdStr[65];
mmsMsg_copyAsn1IdentifierToStringBuffer(varSpec.choice.name.choice.vmdspecific, nameIdStr, 65);
@@ -607,11 +619,12 @@ handleReadListOfVariablesRequest(
LinkedList valueElement = LinkedList_getNext(values);
- while (valueElement) {
-
+ while (valueElement)
+ {
MmsValue* value = (MmsValue*) LinkedList_getData(valueElement);
- if (value) {
+ if (value)
+ {
if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) {
if (MmsValue_getDataAccessError(value) == DATA_ACCESS_ERROR_NO_RESPONSE) {
sendResponse = false;
@@ -637,21 +650,24 @@ static void
addNamedVariableToNamedVariableListResultList(MmsVariableSpecification* namedVariable, MmsDomain* domain, char* nameIdStr,
LinkedList /**/ values, MmsServerConnection connection, MmsNamedVariableListEntry listEntry)
{
- if (namedVariable != NULL) {
-
+ if (namedVariable != NULL)
+ {
if (DEBUG_MMS_SERVER)
printf("MMS read: found named variable %s with search string %s\n",
namedVariable->name, nameIdStr);
MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection, false);
- if (value) {
- if (listEntry->arrayIndex != -1) {
- if (MmsValue_getType(value) == MMS_ARRAY) {
-
+ if (value)
+ {
+ if (listEntry->arrayIndex != -1)
+ {
+ if (MmsValue_getType(value) == MMS_ARRAY)
+ {
MmsValue* elementValue = MmsValue_getElement(value, listEntry->arrayIndex);
- if (listEntry->componentName) {
+ if (listEntry->componentName)
+ {
MmsVariableSpecification* elementType = namedVariable->typeSpec.array.elementTypeSpec;
MmsValue* subElementValue = MmsVariableSpecification_getChildValue(elementType, elementValue, listEntry->componentName);
@@ -669,7 +685,8 @@ addNamedVariableToNamedVariableListResultList(MmsVariableSpecification* namedVar
}
}
- else {
+ else
+ {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: data set entry of unexpected type!\n");
@@ -697,8 +714,8 @@ createNamedVariableListResponse(MmsServerConnection connection, MmsNamedVariable
LinkedList variable = LinkedList_getNext(variables);
- while (variable) {
-
+ while (variable)
+ {
MmsNamedVariableListEntry variableListEntry = (MmsNamedVariableListEntry) variable->data;
MmsDomain* variableDomain = MmsNamedVariableListEntry_getDomain(variableListEntry);
@@ -757,11 +774,13 @@ handleReadNamedVariableListRequest(
MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainIdStr);
- if (domain == NULL) {
+ if (domain == NULL)
+ {
if (DEBUG_MMS_SERVER) printf("MMS read: domain %s not found!\n", domainIdStr);
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
}
- else {
+ else
+ {
MmsNamedVariableList namedList = MmsDomain_getNamedVariableList(domain, nameIdStr);
if (namedList)
@@ -796,12 +815,15 @@ handleReadNamedVariableListRequest(
MmsNamedVariableList namedList = mmsServer_getNamedVariableListWithName(connection->server->device->namedVariableLists, listName);
if (namedList == NULL)
+ {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
- else {
-
+ }
+ else
+ {
MmsError accessError = mmsServer_callVariableListChangedHandler(MMS_VARLIST_READ, MMS_VMD_SPECIFIC, NULL, namedList->name, connection);
- if (accessError == MMS_ERROR_NONE) {
+ if (accessError == MMS_ERROR_NONE)
+ {
VarAccessSpec accessSpec;
accessSpec.isNamedVariableList = true;
@@ -816,7 +838,6 @@ handleReadNamedVariableListRequest(
mmsMsg_createServiceErrorPdu(invokeId, response, accessError);
}
-
}
}
#if (MMS_DYNAMIC_DATA_SETS == 1)
@@ -831,13 +852,15 @@ handleReadNamedVariableListRequest(
MmsNamedVariableList namedList = MmsServerConnection_getNamedVariableList(connection, listName);
if (namedList == NULL)
+ {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
- else {
-
+ }
+ else
+ {
MmsError accessError = mmsServer_callVariableListChangedHandler(MMS_VARLIST_READ, MMS_ASSOCIATION_SPECIFIC, NULL, namedList->name, connection);
- if (accessError == MMS_ERROR_NONE) {
-
+ if (accessError == MMS_ERROR_NONE)
+ {
VarAccessSpec accessSpec;
accessSpec.isNamedVariableList = true;
@@ -891,7 +914,8 @@ mmsServer_handleReadRequest(
goto exit_function;
}
- if (request->variableAccessSpecification.present == VariableAccessSpecification_PR_listOfVariable) {
+ if (request->variableAccessSpecification.present == VariableAccessSpecification_PR_listOfVariable)
+ {
MmsServer_lockModel(connection->server);
handleReadListOfVariablesRequest(connection, request, invokeId, response);
@@ -899,7 +923,8 @@ mmsServer_handleReadRequest(
MmsServer_unlockModel(connection->server);
}
#if (MMS_DATA_SET_SERVICE == 1)
- else if (request->variableAccessSpecification.present == VariableAccessSpecification_PR_variableListName) {
+ else if (request->variableAccessSpecification.present == VariableAccessSpecification_PR_variableListName)
+ {
MmsServer_lockModel(connection->server);
handleReadNamedVariableListRequest(connection, request, invokeId, response);
@@ -911,6 +936,12 @@ mmsServer_handleReadRequest(
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
}
+ if (ByteBuffer_getSize(response) > connection->maxPduSize)
+ {
+ ByteBuffer_setSize(response, 0);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
+ }
+
exit_function:
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
}
diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c
index 18b95464..2f6f2b27 100644
--- a/src/mms/iso_mms/server/mms_server.c
+++ b/src/mms/iso_mms/server/mms_server.c
@@ -536,9 +536,10 @@ mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* va
{
MmsDataAccessError indication;
- if (self->writeHandler != NULL) {
+ if (self->writeHandler)
+ {
indication = self->writeHandler(self->writeHandlerParameter, domain,
- itemId, value, connection);
+ itemId, -1, NULL, value, connection);
}
else {
MmsValue* cachedValue;
@@ -548,7 +549,36 @@ mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* va
cachedValue = MmsServer_getValueFromCache(self, domain, itemId);
- if (cachedValue != NULL) {
+ if (cachedValue) {
+ MmsValue_update(cachedValue, value);
+ indication = DATA_ACCESS_ERROR_SUCCESS;
+ } else
+ indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
+ }
+
+ return indication;
+}
+
+MmsDataAccessError
+mmsServer_setValueEx(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value,
+ MmsServerConnection connection, int arrayIdx, const char* componentId)
+{
+ MmsDataAccessError indication;
+
+ if (self->writeHandler)
+ {
+ indication = self->writeHandler(self->writeHandlerParameter, domain,
+ itemId, arrayIdx, componentId, value, connection);
+ }
+ else {
+ MmsValue* cachedValue = NULL;
+
+ if (domain == NULL)
+ domain = (MmsDomain*) self->device;
+
+ cachedValue = MmsServer_getValueFromCacheEx2(self, domain, itemId, arrayIdx, componentId);
+
+ if (cachedValue) {
MmsValue_update(cachedValue, value);
indication = DATA_ACCESS_ERROR_SUCCESS;
} else
@@ -591,8 +621,6 @@ mmsServer_checkReadAccess(MmsServer self, MmsDomain* domain, char* itemId, MmsSe
{
MmsDataAccessError accessError = DATA_ACCESS_ERROR_SUCCESS;
- printf("mmsServer_checkReadAccess(%s/%s)\n", domain->domainName, itemId);
-
if (self->readAccessHandler) {
accessError =
self->readAccessHandler(self->readAccessHandlerParameter, (domain == (MmsDomain*) self->device) ? NULL : domain,
diff --git a/src/mms/iso_mms/server/mms_server_common.c b/src/mms/iso_mms/server/mms_server_common.c
index 455a26ec..545702be 100644
--- a/src/mms/iso_mms/server/mms_server_common.c
+++ b/src/mms/iso_mms/server/mms_server_common.c
@@ -287,7 +287,7 @@ mmsServer_isAccessToArrayComponent(AlternateAccess_t* alternateAccess)
MmsValue*
mmsServer_getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable,
- MmsValue* structuredValue)
+ MmsValue* structuredValue, char* componentId)
{
MmsValue* retValue = NULL;
@@ -309,24 +309,43 @@ mmsServer_getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVari
goto exit_function;
int i;
- for (i = 0; i < structSpec->typeSpec.structure.elementCount; i++) {
-
+ for (i = 0; i < structSpec->typeSpec.structure.elementCount; i++)
+ {
if ((int) strlen(structSpec->typeSpec.structure.elements[i]->name)
- == component.size) {
+ == component.size)
+ {
if (strncmp(structSpec->typeSpec.structure.elements[i]->name,
- (char*) component.buf, component.size) == 0) {
+ (char*) component.buf, component.size) == 0)
+ {
MmsValue* value = MmsValue_getElement(structuredValue, i);
- if (mmsServer_isAccessToArrayComponent(
- alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess)) {
- retValue =
- mmsServer_getComponentOfArrayElement(
- alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess,
- structSpec->typeSpec.structure.elements[i],
- value);
+ if (value)
+ {
+ if (mmsServer_isAccessToArrayComponent(
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess))
+ {
+ if (componentId)
+ {
+ strcat(componentId, structSpec->typeSpec.structure.elements[i]->name);
+ strcat(componentId, "$");
+ }
+
+ retValue =
+ mmsServer_getComponentOfArrayElement(
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess,
+ structSpec->typeSpec.structure.elements[i],
+ value, componentId);
+ }
+ else
+ {
+ if (componentId)
+ {
+ strcat(componentId, structSpec->typeSpec.structure.elements[i]->name);
+ }
+
+ retValue = value;
+ }
}
- else
- retValue = value;
goto exit_function;
}
diff --git a/src/mms/iso_mms/server/mms_write_service.c b/src/mms/iso_mms/server/mms_write_service.c
index 096bc30f..f46ddef6 100644
--- a/src/mms/iso_mms/server/mms_write_service.c
+++ b/src/mms/iso_mms/server/mms_write_service.c
@@ -517,33 +517,36 @@ getComponent(MmsServerConnection connection, MmsDomain* domain, AlternateAccess_
{
MmsVariableSpecification* retValue = NULL;
- if (mmsServer_isComponentAccess(alternateAccess)) {
+ if (mmsServer_isComponentAccess(alternateAccess))
+ {
Identifier_t component =
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component;
if (component.size > 129)
goto exit_function;
- if (namedVariable->type == MMS_STRUCTURE) {
-
+ if (namedVariable->type == MMS_STRUCTURE)
+ {
int i;
- for (i = 0; i < namedVariable->typeSpec.structure.elementCount; i++) {
-
+ for (i = 0; i < namedVariable->typeSpec.structure.elementCount; i++)
+ {
if ((int) strlen(namedVariable->typeSpec.structure.elements[i]->name)
- == component.size) {
+ == component.size)
+ {
if (!strncmp(namedVariable->typeSpec.structure.elements[i]->name,
(char*) component.buf, component.size))
{
- if (strlen(variableName) + component.size < 199) {
-
+ if (strlen(variableName) + component.size < 199)
+ {
StringUtils_appendString(variableName, 200, "$");
/* here we need strncat because component.buf is not null terminated! */
strncat(variableName, (const char*)component.buf, (size_t)component.size);
if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess
- != NULL) {
+ != NULL)
+ {
retValue =
getComponent(connection, domain,
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess,
@@ -598,12 +601,13 @@ mmsServer_handleWriteRequest(
MmsServer_lockModel(connection->server);
- if (writeRequest->variableAccessSpecification.present == VariableAccessSpecification_PR_variableListName) {
+ if (writeRequest->variableAccessSpecification.present == VariableAccessSpecification_PR_variableListName)
+ {
handleWriteNamedVariableListRequest(connection, writeRequest, invokeId, response);
goto exit_function;
}
- else if (writeRequest->variableAccessSpecification.present == VariableAccessSpecification_PR_listOfVariable) {
-
+ else if (writeRequest->variableAccessSpecification.present == VariableAccessSpecification_PR_listOfVariable)
+ {
int numberOfWriteItems = writeRequest->variableAccessSpecification.choice.listOfVariable.list.count;
if (numberOfWriteItems < 1) {
@@ -627,7 +631,8 @@ mmsServer_handleWriteRequest(
int i;
- for (i = 0; i < numberOfWriteItems; i++) {
+ for (i = 0; i < numberOfWriteItems; i++)
+ {
ListOfVariableSeq_t* varSpec =
writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[i];
@@ -644,7 +649,8 @@ mmsServer_handleWriteRequest(
char nameIdStr[65];
- if (varSpec->variableSpecification.choice.name.present == ObjectName_PR_domainspecific) {
+ if (varSpec->variableSpecification.choice.name.present == ObjectName_PR_domainspecific)
+ {
Identifier_t domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId;
char domainIdStr[65];
@@ -687,8 +693,8 @@ mmsServer_handleWriteRequest(
AlternateAccess_t* alternateAccess = varSpec->alternateAccess;
- if (alternateAccess != NULL) {
-
+ if (alternateAccess)
+ {
if ((variable->type == MMS_STRUCTURE) && (mmsServer_isComponentAccess(alternateAccess) == false)) {
accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
continue;
@@ -714,12 +720,13 @@ mmsServer_handleWriteRequest(
continue;
}
- if (alternateAccess != NULL) {
-
+ if (alternateAccess)
+ {
if (domain == NULL)
domain = (MmsDomain*) device;
- if (mmsServer_isIndexAccess(alternateAccess)) {
+ if (mmsServer_isIndexAccess(alternateAccess))
+ {
MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr);
if (cachedArray == NULL) {
@@ -730,8 +737,8 @@ mmsServer_handleWriteRequest(
int index = mmsServer_getLowIndex(alternateAccess);
int numberOfElements = mmsServer_getNumberOfElements(alternateAccess);
- if (numberOfElements == 0) { /* select single array element with index */
-
+ if (numberOfElements == 0) /* select single array element with index */
+ {
MmsValue* elementValue = MmsValue_getElement(cachedArray, index);
if (elementValue == NULL) {
@@ -739,34 +746,45 @@ mmsServer_handleWriteRequest(
goto end_of_main_loop;
}
- if (mmsServer_isAccessToArrayComponent(alternateAccess)) {
+ if (mmsServer_isAccessToArrayComponent(alternateAccess))
+ {
MmsVariableSpecification* namedVariable = MmsDomain_getNamedVariable(domain, nameIdStr);
+ char componentId[65];
+ componentId[0] = 0;
+
if (namedVariable) {
- elementValue = mmsServer_getComponentOfArrayElement(alternateAccess, namedVariable, elementValue);
+ elementValue = mmsServer_getComponentOfArrayElement(alternateAccess, namedVariable, elementValue, componentId);
}
if ((namedVariable == NULL) || (elementValue == NULL)) {
accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
- goto end_of_main_loop;
}
- }
+ else
+ {
+ accessResults[i] = mmsServer_setValueEx(connection->server, domain, nameIdStr, value, connection, index, componentId);
+ }
- if (MmsValue_update(elementValue, value) == false) {
- accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+ else
+ {
+ accessResults[i] = mmsServer_setValueEx(connection->server, domain, nameIdStr, value, connection, index, NULL);
goto end_of_main_loop;
}
}
- else { /* select sub-array with start-index and number-of-elements */
-
- if (MmsValue_getType(value) != MMS_ARRAY) {
+ else /* select sub-array with start-index and number-of-elements */
+ {
+ if (MmsValue_getType(value) != MMS_ARRAY)
+ {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
int elementNo;
- for (elementNo = 0; elementNo < numberOfElements; elementNo++) {
+ for (elementNo = 0; elementNo < numberOfElements; elementNo++)
+ {
MmsValue* newElement = MmsValue_getElement(value, elementNo);
MmsValue* elementValue = MmsValue_getElement(cachedArray, index++);
@@ -785,36 +803,37 @@ mmsServer_handleWriteRequest(
accessResults[i] = DATA_ACCESS_ERROR_SUCCESS;
goto end_of_main_loop;
}
- else if (mmsServer_isComponentAccess(alternateAccess)) {
+ else if (mmsServer_isComponentAccess(alternateAccess))
+ {
variable = getComponent(connection, domain, alternateAccess, variable, nameIdStr);
- if (variable == NULL) {
+ if (variable == NULL)
+ {
accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
goto end_of_main_loop;
}
}
- else {
+ else
+ {
accessResults[i] = DATA_ACCESS_ERROR_SUCCESS;
goto end_of_main_loop;
}
}
/* Check for correct type */
- if (MmsVariableSpecification_isValueOfType(variable, value) == false) {
+ if (MmsVariableSpecification_isValueOfType(variable, value) == false)
+ {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
- MmsDataAccessError valueIndication =
- mmsServer_setValue(connection->server, domain, nameIdStr, value, connection);
-
- if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE)
- sendResponse = false;
-
- accessResults[i] = valueIndication;
+ accessResults[i] = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection);
end_of_main_loop:
+ if (accessResults[i] == DATA_ACCESS_ERROR_NO_RESPONSE)
+ sendResponse = false;
+
MmsValue_delete(value);
}
diff --git a/tools/model_generator/build2.sh b/tools/model_generator/build2.sh
index 8bf31dfb..52bd6f80 100755
--- a/tools/model_generator/build2.sh
+++ b/tools/model_generator/build2.sh
@@ -4,7 +4,7 @@ mkdir build
find src/ -name "*.java" > listFile.tmp
-javac -target 1.6 -source 1.6 -d build @listFile.tmp
+javac -target 1.8 -source 1.8 -d build @listFile.tmp
jar cfm genconfig.jar manifest-dynamic.mf -C build/ com/
diff --git a/tools/model_generator/genconfig.jar b/tools/model_generator/genconfig.jar
index 0ef0c1d3..51e83774 100644
Binary files a/tools/model_generator/genconfig.jar and b/tools/model_generator/genconfig.jar differ
diff --git a/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java b/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java
index 2bd18a3d..ccf4d8f0 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java
@@ -188,19 +188,35 @@ public class DataModelValue {
case TIMESTAMP:
case ENTRY_TIME:
- try {
+ {
String modValueString = value.replace(',', '.');
- SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-d'T'HH:mm:ss.SSS");
- parser.setTimeZone(TimeZone.getTimeZone("UTC"));
+ try {
+ SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-d'T'HH:mm:ss.SSS");
+ parser.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ Date date = parser.parse(modValueString);
- Date date = parser.parse(modValueString);
+ this.value = new Long(date.toInstant().toEpochMilli());
+
+ break;
+ }
+ catch (java.text.ParseException e) {};
+
+ try {
+ SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-d'T'HH:mm:ss");
+ parser.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ Date date = parser.parse(modValueString);
- this.value = new Long(date.toInstant().toEpochMilli());
- }
- catch (java.text.ParseException e) {
+ this.value = new Long(date.toInstant().toEpochMilli());
+
+ break;
+ }
+ catch (java.text.ParseException e) {};
+
this.value = null;
- System.out.println("Warning: Val element does not contain a valid time stamp: " + e.getMessage());
+ System.out.println("Warning: Val element does not contain a valid time stamp: " + value);
}
break;
diff --git a/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java
index 2d5bf36e..fffd94ef 100644
--- a/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java
+++ b/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java
@@ -3,7 +3,7 @@ package com.libiec61850.tools;
/*
* DynamicModelGenerator.java
*
- * Copyright 2014-2020 Michael Zillgith
+ * Copyright 2014-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -447,11 +447,7 @@ public class DynamicModelGenerator {
output.println("}");
}
- private void exportDataObject(PrintStream output, DataObject dataObject, boolean isTransient) {
-
- if (dataObject.isTransient())
- isTransient = true;
-
+ private void exportDataObjectChild(PrintStream output, DataObject dataObject, boolean isTransient) {
for (DataObject subDataObject : dataObject.getSubDataObjects()) {
output.print("DO(" + subDataObject.getName() + " " + subDataObject.getCount() + "){\n");
@@ -465,6 +461,105 @@ public class DynamicModelGenerator {
}
}
+ private void exportDataObject(PrintStream output, DataObject dataObject, boolean isTransient) {
+
+ if (dataObject.isTransient())
+ isTransient = true;
+
+ if (dataObject.getCount() > 0) {
+ /* data object is an array */
+ for (int i = 0; i < dataObject.getCount(); i++) {
+ output.print("[" + i + "]{\n");
+
+ exportDataObjectChild(output, dataObject, isTransient);
+
+ output.print("}\n");
+ }
+ }
+ else {
+ exportDataObjectChild(output, dataObject, isTransient);
+ }
+
+ }
+
+ private void printDataAttributeValue(PrintStream output, DataAttribute dataAttribute, boolean isTransient)
+ {
+ if (dataAttribute.isBasicAttribute()) {
+ DataModelValue value = dataAttribute.getValue();
+
+ /* if no value is given use default value for type if present */
+ if (value == null) {
+ value = dataAttribute.getDefinition().getValue();
+
+ if (value != null)
+ if (value.getValue() == null)
+ value.updateEnumOrdValue(ied.getTypeDeclarations());
+ }
+
+ if (value != null) {
+
+ switch (dataAttribute.getType()) {
+ case ENUMERATED:
+ case INT8:
+ case INT16:
+ case INT32:
+ case INT64:
+ output.print("=" + value.getIntValue());
+ break;
+ case INT8U:
+ case INT16U:
+ case INT24U:
+ case INT32U:
+ output.print("=" + value.getLongValue());
+ break;
+ case BOOLEAN:
+ {
+ Boolean boolVal = (Boolean) value.getValue();
+
+ if (boolVal.booleanValue())
+ output.print("=1");
+ }
+ break;
+ case UNICODE_STRING_255:
+ output.print("=\"" + value.getValue()+ "\"");
+ break;
+ case CURRENCY:
+ case VISIBLE_STRING_32:
+ case VISIBLE_STRING_64:
+ case VISIBLE_STRING_129:
+ case VISIBLE_STRING_255:
+ case VISIBLE_STRING_65:
+ output.print("=\"" + value.getValue()+ "\"");
+ break;
+ case FLOAT32:
+ case FLOAT64:
+ output.print("=" + value.getValue());
+ break;
+ case TIMESTAMP:
+ case ENTRY_TIME:
+ output.print("=" + value.getLongValue());
+ break;
+
+ default:
+ System.out.println("Unknown default value for " + dataAttribute.getName() + " type: " + dataAttribute.getType());
+ break;
+ }
+
+ }
+
+ output.println(";");
+ }
+ else {
+ output.println("{");
+
+ for (DataAttribute subDataAttribute : dataAttribute.getSubDataAttributes()) {
+ exportDataAttribute(output, subDataAttribute, isTransient);
+ }
+
+ output.println("}");
+ }
+ }
+
private void exportDataAttribute(PrintStream output, DataAttribute dataAttribute, boolean isTransient) {
output.print("DA(" + dataAttribute.getName() + " ");
@@ -493,78 +588,22 @@ public class DynamicModelGenerator {
else
output.print("0");
- output.print(")");
-
- if (dataAttribute.isBasicAttribute()) {
- DataModelValue value = dataAttribute.getValue();
-
- /* if no value is given use default value for type if present */
- if (value == null) {
- value = dataAttribute.getDefinition().getValue();
-
- if (value != null)
- if (value.getValue() == null)
- value.updateEnumOrdValue(ied.getTypeDeclarations());
- }
-
- if (value != null) {
-
- switch (dataAttribute.getType()) {
- case ENUMERATED:
- case INT8:
- case INT16:
- case INT32:
- case INT64:
- output.print("=" + value.getIntValue());
- break;
- case INT8U:
- case INT16U:
- case INT24U:
- case INT32U:
- output.print("=" + value.getLongValue());
- break;
- case BOOLEAN:
- {
- Boolean boolVal = (Boolean) value.getValue();
-
- if (boolVal.booleanValue())
- output.print("=1");
- }
- break;
- case UNICODE_STRING_255:
- output.print("=\"" + value.getValue()+ "\"");
- break;
- case CURRENCY:
- case VISIBLE_STRING_32:
- case VISIBLE_STRING_64:
- case VISIBLE_STRING_129:
- case VISIBLE_STRING_255:
- case VISIBLE_STRING_65:
- output.print("=\"" + value.getValue()+ "\"");
- break;
- case FLOAT32:
- case FLOAT64:
- output.print("=" + value.getValue());
- break;
- default:
- System.out.println("Unknown default value for " + dataAttribute.getName() + " type: " + dataAttribute.getType());
- break;
- }
-
- }
-
- output.println(";");
- }
- else {
- output.println("{");
+ output.print(")");
- for (DataAttribute subDataAttribute : dataAttribute.getSubDataAttributes()) {
- exportDataAttribute(output, subDataAttribute, isTransient);
+ if (dataAttribute.getCount() > 0) {
+ output.print("{\n");
+
+ for (int i = 0; i < dataAttribute.getCount(); i++) {
+ output.print("[" + i + "]");
+
+ printDataAttributeValue(output, dataAttribute, isTransient);
}
- output.println("}");
+ output.print("}\n");
+ }
+ else {
+ printDataAttributeValue(output, dataAttribute, isTransient);
}
-
}
public static void main(String[] args) throws FileNotFoundException {