diff --git a/dotnet/IEC61850forCSharp/Control.cs b/dotnet/IEC61850forCSharp/Control.cs
index bb4f876c..d8bcc86d 100644
--- a/dotnet/IEC61850forCSharp/Control.cs
+++ b/dotnet/IEC61850forCSharp/Control.cs
@@ -36,14 +36,20 @@ namespace IEC61850
///
/// Control model
- ///
- public enum ControlModel {
- CONTROL_MODEL_STATUS_ONLY = 0,
- CONTROL_MODEL_DIRECT_NORMAL = 1,
- CONTROL_MODEL_SBO_NORMAL = 2,
- CONTROL_MODEL_DIRECT_ENHANCED = 3,
- CONTROL_MODEL_SBO_ENHANCED = 4
- }
+ ///
+ public enum ControlModel
+ {
+ /** status only */
+ STATUS_ONLY = 0,
+ /** direct with normal security */
+ DIRECT_NORMAL= 1,
+ /** select before operate (SBO) with normal security */
+ SBO_NORMAL = 2,
+ /** direct with enhanced security */
+ DIRECT_ENHANCED = 3,
+ /** select before operate (SBO) with enhanced security */
+ SBO_ENHANCED = 4
+ }
///
/// Originator category
@@ -144,8 +150,9 @@ namespace IEC61850
private static extern void ControlObjectClient_setCommandTerminationHandler(IntPtr self,
InternalCommandTerminationHandler handler, IntPtr handlerParameter);
- public delegate void CommandTerminationHandler (Object parameter, ControlObject controlObject);
-
+ public delegate void CommandTerminationHandler (Object parameter, ControlObject controlObject);
+
+ private IedConnection iedConnection;
private IntPtr controlObject;
private CommandTerminationHandler commandTerminationHandler = null;
@@ -158,8 +165,10 @@ namespace IEC61850
}
- internal ControlObject (string objectReference, IntPtr connection)
- {
+ internal ControlObject (string objectReference, IntPtr connection, IedConnection iedConnection)
+ {
+ this.iedConnection = iedConnection;
+
this.controlObject = ControlObjectClient_create(objectReference, connection);
if (this.controlObject == System.IntPtr.Zero)
diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index 992623da..b6c993ae 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -250,7 +250,7 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public ControlObject CreateControlObject (string objectReference)
{
- ControlObject controlObject = new ControlObject (objectReference, connection);
+ ControlObject controlObject = new ControlObject (objectReference, connection, this);
return controlObject;
}
diff --git a/dotnet/IEC61850forCSharp/ReportControlBlock.cs b/dotnet/IEC61850forCSharp/ReportControlBlock.cs
index c1ddedb8..86a9ed6c 100644
--- a/dotnet/IEC61850forCSharp/ReportControlBlock.cs
+++ b/dotnet/IEC61850forCSharp/ReportControlBlock.cs
@@ -473,6 +473,26 @@ namespace IEC61850
flagRptEna = true;
}
+ ///
+ /// Get the purgeBuf flag of the report control block
+ ///
+ /// the prugeBuf value
+ public bool GetPurgeBuf ()
+ {
+ return ClientReportControlBlock_getPurgeBuf(self);
+ }
+
+ ///
+ /// Set the purgeBuf flag of the report control block
+ ///
+ /// This is only for buffered RCBs. If set to true the report buffer of a buffered RCB will be cleaned.
+ /// set to true to flush report buffer
+ public void SetPurgeBuf (bool purgeBuf)
+ {
+ ClientReportControlBlock_setPurgeBuf(self, purgeBuf);
+ flagPurgeBuf = true;
+ }
+
///
/// Gets the buffer time.
///
diff --git a/dotnet/IEC61850forCSharp/Reporting.cs b/dotnet/IEC61850forCSharp/Reporting.cs
index 68e7e7aa..583627f9 100644
--- a/dotnet/IEC61850forCSharp/Reporting.cs
+++ b/dotnet/IEC61850forCSharp/Reporting.cs
@@ -116,6 +116,8 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getRptId(IntPtr self);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr ClientReport_getDataReference(IntPtr self, int elementIndex);
private IntPtr self;
@@ -246,6 +248,25 @@ namespace IEC61850
return Marshal.PtrToStringAnsi (rcbRef);
}
+ ///
+ /// Gets the data reference for the specified data set element
+ ///
+ ///
+ /// The data reference or null if the data reference is not available
+ ///
+ ///
+ /// index of the data set element starting with 0
+ ///
+ public string GetDataReference (int index)
+ {
+ IntPtr dataRef = ClientReport_getDataReference(self, index);
+
+ if (dataRef != IntPtr.Zero)
+ return Marshal.PtrToStringAnsi(dataRef);
+ else
+ return null;
+ }
+
public string GetRptId ()
{
IntPtr rptId = ClientReport_getRptId(self);
diff --git a/examples/goose_subscriber/goose_subscriber_example.c b/examples/goose_subscriber/goose_subscriber_example.c
index 00fd888c..4295f474 100644
--- a/examples/goose_subscriber/goose_subscriber_example.c
+++ b/examples/goose_subscriber/goose_subscriber_example.c
@@ -42,7 +42,7 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
int
main(int argc, char** argv)
{
- MmsValue* dataSetValues = MmsValue_createEmtpyArray(4);
+ MmsValue* dataSetValues = MmsValue_createEmptyArray(4);
int i;
for (i = 0; i < 4; i++) {
diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c
index 0b5e39d6..8554a7af 100644
--- a/src/goose/goose_receiver.c
+++ b/src/goose/goose_receiver.c
@@ -321,7 +321,7 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
if (isStructure)
dataSetValues = MmsValue_createEmptyStructure(elementIndex);
else
- dataSetValues = MmsValue_createEmtpyArray(elementIndex);
+ dataSetValues = MmsValue_createEmptyArray(elementIndex);
elementIndex = 0;
bufPos = 0;
diff --git a/src/iec61850/client/client_control.c b/src/iec61850/client/client_control.c
index 80576830..9a24e2f1 100644
--- a/src/iec61850/client/client_control.c
+++ b/src/iec61850/client/client_control.c
@@ -28,6 +28,7 @@
#include "iec61850_client.h"
#include "mms_client_connection.h"
#include "ied_connection_private.h"
+#include "mms_mapping.h"
#include
@@ -39,9 +40,6 @@
#define DEBUG_IED_CLIENT 0
#endif
-char*
-MmsMapping_getMmsDomainFromObjectReference(const char* objectReference, char* buffer);
-
struct sControlObjectClient
{
ControlModel ctlModel;
@@ -110,11 +108,16 @@ resetLastApplError(ControlObjectClient self)
ControlObjectClient
ControlObjectClient_create(char* objectReference, IedConnection connection)
{
+ ControlObjectClient self = NULL;
+
/* request control model from server */
char domainId[65];
- char itemId[129];
+ char itemId[65];
- MmsMapping_getMmsDomainFromObjectReference(objectReference, domainId);
+ char* domainName = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainId);
+
+ if (domainName == NULL)
+ goto exit_function;
convertToMmsAndInsertFC(itemId, objectReference + strlen(domainId) + 1, "CF");
@@ -128,7 +131,8 @@ ControlObjectClient_create(char* objectReference, IedConnection connection)
if (ctlModel == NULL) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: ControlObjectClient_create: failed to get ctlModel from server\n");
- return NULL;
+
+ goto exit_function;
}
int ctlModelVal = MmsValue_toUint32(ctlModel);
@@ -143,7 +147,8 @@ ControlObjectClient_create(char* objectReference, IedConnection connection)
if (dataDirectory == NULL) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: ControlObjectClient_create: failed to get data directory of control object\n");
- return NULL;
+
+ goto exit_function;
}
/* check what control elements are available */
@@ -165,7 +170,8 @@ ControlObjectClient_create(char* objectReference, IedConnection connection)
if (hasOper == false) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: control is missing required element \"Oper\"\n");
- return NULL;
+
+ goto exit_function;
}
/* check for time activated control */
@@ -175,6 +181,9 @@ ControlObjectClient_create(char* objectReference, IedConnection connection)
strcat(itemId, ".Oper");
dataDirectory = IedConnection_getDataDirectory(connection, &error, itemId);
+ if (dataDirectory == NULL)
+ goto exit_function;
+
element = LinkedList_getNext(dataDirectory);
while (element != NULL) {
@@ -196,11 +205,15 @@ ControlObjectClient_create(char* objectReference, IedConnection connection)
if (oper == NULL) {
if (DEBUG_IED_CLIENT)
- printf("reading Oper failed!\n");
- return NULL;
+ printf("IED_CLIENT: reading \"Oper\" failed!\n");
+
+ goto exit_function;
}
- ControlObjectClient self = (ControlObjectClient) GLOBAL_CALLOC(1, sizeof(struct sControlObjectClient));
+ self = (ControlObjectClient) GLOBAL_CALLOC(1, sizeof(struct sControlObjectClient));
+
+ if (self == NULL)
+ goto exit_function;
self->objectReference = copyString(objectReference);
self->connection = connection;
@@ -229,23 +242,27 @@ ControlObjectClient_create(char* objectReference, IedConnection connection)
private_IedConnection_addControlClient(connection, self);
+exit_function:
return self;
}
void
ControlObjectClient_destroy(ControlObjectClient self)
{
- GLOBAL_FREEMEM(self->objectReference);
+ if (self != NULL)
+ {
+ GLOBAL_FREEMEM(self->objectReference);
- private_IedConnection_removeControlClient(self->connection, self);
+ private_IedConnection_removeControlClient(self->connection, self);
- if (self->ctlVal != NULL)
- MmsValue_delete(self->ctlVal);
+ if (self->ctlVal != NULL)
+ MmsValue_delete(self->ctlVal);
- if (self->orIdent != NULL)
- GLOBAL_FREEMEM(self->orIdent);
+ if (self->orIdent != NULL)
+ GLOBAL_FREEMEM(self->orIdent);
- GLOBAL_FREEMEM(self);
+ GLOBAL_FREEMEM(self);
+ }
}
void
@@ -282,7 +299,15 @@ static MmsValue*
createOriginValue(ControlObjectClient self)
{
MmsValue* origin = MmsValue_createEmptyStructure(2);
+
+ if (origin == NULL)
+ goto exit_function;
+
MmsValue* orCat = MmsValue_newIntegerFromInt16(self->orCat);
+
+ if (orCat == NULL)
+ goto cleanup_on_error;
+
MmsValue_setElement(origin, 0, orCat);
MmsValue* orIdent;
@@ -290,19 +315,42 @@ createOriginValue(ControlObjectClient self)
if (self->orIdent != NULL) {
int octetStringLen = strlen(self->orIdent);
orIdent = MmsValue_newOctetString(0, octetStringLen);
+
+ if (orIdent == NULL)
+ goto cleanup_on_error;
+
MmsValue_setOctetString(orIdent, (uint8_t*) self->orIdent, octetStringLen);
}
else
orIdent = MmsValue_newOctetString(0, 0);
+ if (orIdent == NULL)
+ goto cleanup_on_error;
+
MmsValue_setElement(origin, 1, orIdent);
+ goto exit_function;
+
+cleanup_on_error:
+ MmsValue_delete(origin);
+ origin = NULL;
+
+exit_function:
return origin;
}
bool
ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t operTime)
{
+ bool success = false;
+
+ if (ctlVal == NULL) {
+ if (DEBUG_IED_CLIENT)
+ printf("IED_CLIENT: operate - (ctlVal == NULL)!\n");
+
+ goto exit_function;
+ }
+
resetLastApplError(self);
MmsValue* operParameters;
@@ -337,6 +385,7 @@ ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t
ctlTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(ctlTime, timestamp);
}
+
MmsValue_setElement(operParameters, index++, ctlTime);
MmsValue* ctlTest = MmsValue_newBoolean(self->test);
@@ -348,7 +397,7 @@ ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t
MmsValue_setElement(operParameters, index++, check);
char domainId[65];
- char itemId[130];
+ char itemId[65];
MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId);
@@ -370,10 +419,14 @@ ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t
if (mmsError != MMS_ERROR_NONE) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: operate failed!\n");
- return false;
+
+ goto exit_function;
}
- return true;
+ success = true;
+
+exit_function:
+ return success;
}
bool
@@ -382,13 +435,13 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal)
resetLastApplError(self);
char domainId[65];
- char itemId[130];
+ char itemId[65];
MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId);
convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO");
- strncat(itemId, "$SBOw", 129);
+ strncat(itemId, "$SBOw", 64);
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select with value: %s/%s\n", domainId, itemId);
@@ -459,13 +512,13 @@ ControlObjectClient_select(ControlObjectClient self)
resetLastApplError(self);
char domainId[65];
- char itemId[130];
+ char itemId[65];
MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId);
convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO");
- strncat(itemId, "$SBO", 129);
+ strncat(itemId, "$SBO", 64);
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select: %s/%s\n", domainId, itemId);
@@ -480,7 +533,7 @@ ControlObjectClient_select(ControlObjectClient self)
if (value == NULL) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: select: read SBO failed!\n");
- return false;
+ goto exit_function;
}
char sboReference[130];
@@ -509,6 +562,7 @@ ControlObjectClient_select(ControlObjectClient self)
MmsValue_delete(value);
+exit_function:
return selected;
}
@@ -555,13 +609,13 @@ ControlObjectClient_cancel(ControlObjectClient self)
MmsValue_setElement(cancelParameters, index++, ctlTest);
char domainId[65];
- char itemId[130];
+ char itemId[65];
MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId);
convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO");
- strncat(itemId, "$Cancel", 129);
+ strncat(itemId, "$Cancel", 64);
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: cancel: %s/%s\n", domainId, itemId);
@@ -611,5 +665,5 @@ void
private_ControlObjectClient_invokeCommandTerminationHandler(ControlObjectClient self)
{
if (self->commandTerminationHandler != NULL)
- self->commandTerminationHandler(self->commandTerminaionHandlerParameter, self);
+ self->commandTerminationHandler(self->commandTerminaionHandlerParameter, self);
}
diff --git a/src/iec61850/client/client_report.c b/src/iec61850/client/client_report.c
index c02aa3c3..1087be7d 100644
--- a/src/iec61850/client/client_report.c
+++ b/src/iec61850/client/client_report.c
@@ -197,7 +197,23 @@ ClientReport_hasDataReference(ClientReport self)
return self->hasDataReference;
}
+const char*
+ClientReport_getDataReference(ClientReport self, int elementIndex)
+{
+ char* dataReference = NULL;
+
+ if (self->dataReferences != NULL) {
+ MmsValue* dataRefValue = MmsValue_getElement(self->dataReferences, elementIndex);
+ if (dataRefValue != NULL) {
+ if (MmsValue_getType(dataRefValue) == MMS_VISIBLE_STRING) {
+ return MmsValue_toString(dataRefValue);
+ }
+ }
+ }
+
+ return dataReference;
+}
MmsValue*
ClientReport_getDataSetValues(ClientReport self)
@@ -324,7 +340,7 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
}
if (matchingReport == NULL)
- return;
+ goto exit_function;
matchingReport->hasSequenceNumber = false;
matchingReport->hasTimestamp = false;
@@ -427,19 +443,38 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
dataSetSize);
int valueIndex = inclusionIndex + 1;
- /* skip data-reference fields */
+
+ /* parse data-references if required */
if (MmsValue_getBitStringBit(optFlds, 5) == true) {
-// if (matchingReport->dataReferences == NULL)
-// matchingReport->dataReferences = MmsValue_createEmptyArray(dataSetSize);
+
+ if (matchingReport->dataReferences == NULL)
+ matchingReport->dataReferences = MmsValue_createEmptyArray(dataSetSize);
+
matchingReport->hasDataReference = true;
- valueIndex += includedElements;
+ int elementIndex;
+
+ for (elementIndex = 0; elementIndex < dataSetSize; elementIndex++) {
+ if (MmsValue_getBitStringBit(inclusion, elementIndex) == true) {
+ MmsValue* dataSetElement = MmsValue_getElement(matchingReport->dataReferences, elementIndex);
+
+ if (dataSetElement == NULL) {
+ dataSetElement = MmsValue_clone(MmsValue_getElement(value, valueIndex));
+
+ MmsValue_setElement(matchingReport->dataReferences, elementIndex, dataSetElement);
+ }
+
+ valueIndex += 1;
+ }
+ }
+
+ // valueIndex += includedElements;
}
int i;
if (matchingReport->dataSetValues == NULL) {
- matchingReport->dataSetValues = MmsValue_createEmtpyArray(dataSetSize);
+ matchingReport->dataSetValues = MmsValue_createEmptyArray(dataSetSize);
matchingReport->reasonForInclusion = (ReasonForInclusion*)
GLOBAL_MALLOC(sizeof(ReasonForInclusion) * dataSetSize);
@@ -498,8 +533,11 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
matchingReport->reasonForInclusion[i] = REASON_NOT_INCLUDED;
}
}
- if (matchingReport->callback != NULL) {
+
+ if (matchingReport->callback != NULL)
matchingReport->callback(matchingReport->callbackParameter, matchingReport);
- }
+
+exit_function:
+ return;
}
diff --git a/src/iec61850/client/client_report_control.c b/src/iec61850/client/client_report_control.c
index daac8336..2e7407f0 100644
--- a/src/iec61850/client/client_report_control.c
+++ b/src/iec61850/client/client_report_control.c
@@ -431,9 +431,12 @@ IedConnection_getRCBValues(IedConnection self, IedClientError* error, char* rcbR
ClientReportControlBlock returnRcb = updateRcb;
char domainId[65];
- char itemId[129];
+ char itemId[65];
- MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId);
+ char* domainName = MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId);
+
+ if (domainName == NULL)
+ return NULL;
strcpy(itemId, rcbReference + strlen(domainId) + 1);
diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h
index 37d2b8fd..1f93a812 100644
--- a/src/iec61850/inc/iec61850_client.h
+++ b/src/iec61850/inc/iec61850_client.h
@@ -727,9 +727,32 @@ ClientReport_getConfRev(ClientReport self);
bool
ClientReport_hasBufOvfl(ClientReport self);
+/**
+ * \brief Indicates if the report contains data references for the reported data set members
+ *
+ * \param self the ClientReport instance
+ *
+ * \returns true if the report contains data-references, false otherwise
+ */
bool
ClientReport_hasDataReference(ClientReport self);
+/**
+ * \brief get the data-reference of the element of the report data set
+ *
+ * This function will only return a non-NULL value if the received report contains data-references.
+ * This can be determined by the ClientReport_hasDataReference function.
+ * NOTE: The returned string is allocated and hold by the ClientReport instance and is only valid until
+ * the ClientReport instance exists!
+ *
+ * \param self the ClientReport instance
+ * \param elementIndex index of the data set element (starting with 0)
+ *
+ * \param the data reference as string as provided by the report or NULL if the data reference is not available
+ */
+const char*
+ClientReport_getDataReference(ClientReport self, int elementIndex);
+
/**
* \brief get the timestamp of the report
@@ -1215,9 +1238,19 @@ typedef enum {
} ControlModel;
-
+/**
+ * \brief Create a new client control object
+ *
+ * A client control object is used to handle all client side aspects of a controllable
+ * data object.
+ *
+ * \param objectReference the reference of the controllable data object
+ * \param connection the connection instance where the control object has to be reached
+ *
+ * \return the newly created instance or NULL if the creation failed
+ */
ControlObjectClient
-ControlObjectClient_create(char* dataAttributeReference, IedConnection connection);
+ControlObjectClient_create(char* objectReference, IedConnection connection);
void
ControlObjectClient_destroy(ControlObjectClient self);
diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c
index 17f21b4b..f31f00d9 100644
--- a/src/iec61850/server/impl/ied_server.c
+++ b/src/iec61850/server/impl/ied_server.c
@@ -35,11 +35,13 @@
#endif
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
-static void
+static bool
createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariableSpecification* typeSpec, char* namePrefix)
{
MmsMapping* mapping = self->mmsMapping;
+ bool success = false;
+
if (typeSpec->type == MMS_STRUCTURE) {
int coCount = typeSpec->typeSpec.structure.elementCount;
int i;
@@ -98,10 +100,19 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
if (DEBUG_IED_SERVER)
printf("IED_SERVER: create control object LN:%s DO:%s\n", lnName, objectName);
+
ControlObject* controlObject = ControlObject_create(self, domain, lnName, objectName);
+ if (controlObject == NULL)
+ goto exit_function;
+
MmsValue* structure = MmsValue_newDefaultValue(coSpec);
+ if (structure == NULL) {
+ ControlObject_destroy(controlObject);
+ goto exit_function;
+ }
+
ControlObject_setMmsValue(controlObject, structure);
ControlObject_setTypeSpec(controlObject, coSpec);
@@ -123,19 +134,28 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
}
else {
strcat(objectName, coSpec->name);
- createControlObjects(self, domain, lnName, coSpec, objectName);
+
+ if (createControlObjects(self, domain, lnName, coSpec, objectName) == false)
+ goto exit_function;
}
}
}
}
+
+ success = true;
+
+exit_function:
+ return success;
}
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
-static void
+static bool
createMmsServerCache(IedServer self)
{
assert(self != NULL);
+ bool success = false;
+
int domain = 0;
for (domain = 0; domain < self->mmsDevice->domainCount; domain++) {
@@ -149,7 +169,7 @@ createMmsServerCache(IedServer self)
char* lnName = logicalDevice->namedVariables[i]->name;
if (DEBUG_IED_SERVER)
- printf("ied_server.c: Insert into cache %s - %s\n", logicalDevice->domainName, lnName);
+ printf("IED_SERVER: Insert into cache %s - %s\n", logicalDevice->domainName, lnName);
int fcCount = logicalDevice->namedVariables[i]->typeSpec.structure.elementCount;
int j;
@@ -168,12 +188,18 @@ createMmsServerCache(IedServer self)
if ((strcmp(fcName, "BR") != 0) && (strcmp(fcName, "RP") != 0)
&& (strcmp(fcName, "GO") != 0))
- {
-
+ {
char* variableName = createString(3, lnName, "$", fcName);
+ if (variableName == NULL) goto exit_function;
+
MmsValue* defaultValue = MmsValue_newDefaultValue(fcSpec);
+ if (defaultValue == NULL) {
+ GLOBAL_FREEMEM(variableName);
+ goto exit_function;
+ }
+
if (DEBUG_IED_SERVER)
printf("ied_server.c: Insert into cache %s - %s\n", logicalDevice->domainName, variableName);
@@ -184,6 +210,11 @@ createMmsServerCache(IedServer self)
}
}
}
+
+ success = true;
+
+exit_function:
+ return success;
}
static void
diff --git a/src/iec61850/server/mms_mapping/control.c b/src/iec61850/server/mms_mapping/control.c
index 529085fc..84c43875 100644
--- a/src/iec61850/server/mms_mapping/control.c
+++ b/src/iec61850/server/mms_mapping/control.c
@@ -430,18 +430,35 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char*
{
ControlObject* self = (ControlObject*) GLOBAL_CALLOC(1, sizeof(ControlObject));
+ if (self == NULL)
+ goto exit_function;
+
if (DEBUG_IED_SERVER)
printf("create control object for LD: %s, LN: %s, name: %s\n", domain->domainName, lnName, name);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
self->stateLock = Semaphore_create(1);
+
+ if (self->stateLock == NULL) {
+ ControlObject_destroy(self);
+ self = NULL;
+ goto exit_function;
+ }
#endif
self->name = copyString(name);
+
+ if (self->name == NULL) {
+ ControlObject_destroy(self);
+ self = NULL;
+ goto exit_function;
+ }
+
self->lnName = lnName;
self->mmsDomain = domain;
self->iedServer = iedServer;
+exit_function:
return self;
}
@@ -475,10 +492,12 @@ ControlObject_destroy(ControlObject* self)
if (self->origin != NULL)
MmsValue_delete(self->origin);
- free(self->name);
+ if (self->name != NULL)
+ free(self->name);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
- Semaphore_destroy(self->stateLock);
+ if (self->stateLock != NULL)
+ Semaphore_destroy(self->stateLock);
#endif
free(self);
@@ -762,7 +781,8 @@ getCancelParameterOrigin(MmsValue* operParameters)
static MmsValue*
getOperParameterTest(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 7)
return MmsValue_getElement(operParameters, 5);
else if (MmsValue_getArraySize(operParameters) == 6)
@@ -775,7 +795,8 @@ getOperParameterTest(MmsValue* operParameters)
static MmsValue*
getOperParameterCheck(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 7)
return MmsValue_getElement(operParameters, 6);
else if (MmsValue_getArraySize(operParameters) == 6)
@@ -788,7 +809,8 @@ getOperParameterCheck(MmsValue* operParameters)
static MmsValue*
getOperParameterOrigin(MmsValue* operParameters)
{
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 7)
return MmsValue_getElement(operParameters, 2);
else if (MmsValue_getArraySize(operParameters) == 6)
@@ -803,7 +825,8 @@ getOperParameterTime(MmsValue* operParameters)
{
MmsValue* timeParameter = NULL;
- if (MmsValue_getType(operParameters) == MMS_STRUCTURE) {
+ if (MmsValue_getType(operParameters) == MMS_STRUCTURE)
+ {
if (MmsValue_getArraySize(operParameters) == 7)
timeParameter = MmsValue_getElement(operParameters, 4);
else if (MmsValue_getArraySize(operParameters) == 6)
@@ -820,7 +843,7 @@ getOperParameterTime(MmsValue* operParameters)
void
ControlObject_sendCommandTerminationPositive(ControlObject* self)
{
- char itemId[130];
+ char itemId[68]; /* 64 characters + space for FC + separator + string terminator */
createStringInBuffer(itemId, 4, self->lnName, "$CO$", self->name, "$Oper");
@@ -837,13 +860,16 @@ ControlObject_sendCommandTerminationPositive(ControlObject* self)
LinkedList varSpecList = LinkedList_create();
LinkedList values = LinkedList_create();
- LinkedList_add(varSpecList, &varSpec);
- LinkedList_add(values, self->oper);
+ if ((varSpecList != NULL) && (values != NULL))
+ {
+ LinkedList_add(varSpecList, &varSpec);
+ LinkedList_add(values, self->oper);
- MmsServerConnection_sendInformationReportListOfVariables(self->mmsConnection, varSpecList, values, false);
+ MmsServerConnection_sendInformationReportListOfVariables(self->mmsConnection, varSpecList, values, false);
- LinkedList_destroyStatic(varSpecList);
- LinkedList_destroyStatic(values);
+ LinkedList_destroyStatic(varSpecList);
+ LinkedList_destroyStatic(values);
+ }
}
void
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index c36974ff..a00e8530 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -2236,10 +2236,11 @@ char*
MmsMapping_getMmsDomainFromObjectReference(const char* objectReference, char* buffer)
{
int objRefLength = strlen(objectReference);
+ char* domainName = NULL;
/* check for object reference size limit VISIBLESTRING129 */
if (objRefLength > 129)
- return NULL;
+ goto exit_function;
/* check if LD name is present */
int i;
@@ -2251,12 +2252,10 @@ MmsMapping_getMmsDomainFromObjectReference(const char* objectReference, char* bu
/* check for LD name limit (=64 characters) */
if (i > 64)
- return NULL;
+ goto exit_function;
if (i == objRefLength)
- return NULL;
-
- char* domainName;
+ goto exit_function;
if (buffer == NULL)
domainName = (char*) GLOBAL_MALLOC(i + 1);
@@ -2270,6 +2269,7 @@ MmsMapping_getMmsDomainFromObjectReference(const char* objectReference, char* bu
domainName[j] = 0;
+exit_function:
return domainName;
}
@@ -2549,6 +2549,9 @@ MmsMapping_ObjectReferenceToVariableAccessSpec(char* objectReference)
int domainIdLen = domainIdEnd - objectReference;
+ if (domainIdLen > 64)
+ return NULL;
+
char* fcStart = strchr(objectReference, '[');
if (fcStart == NULL) /* no FC present */
diff --git a/src/mms/inc/mms_value.h b/src/mms/inc/mms_value.h
index cfe35633..42ac4753 100644
--- a/src/mms/inc/mms_value.h
+++ b/src/mms/inc/mms_value.h
@@ -111,8 +111,18 @@ MmsValue_getElement(MmsValue* array, int index);
* \return a newly created empty array instance
*/
MmsValue*
-MmsValue_createEmtpyArray(int size);
+MmsValue_createEmptyArray(int size);
+/**
+ * \brief Set an element of a complex type
+ *
+ * NOTE: If the element already exists it will simply be replaced by the provided new value.
+ * The caller is responsible to free the replaced value.
+ *
+ * \param complexValue MmsValue instance to operate on. Has to be of a type MMS_STRUCTURE or MMS_ARRAY
+ * \param the index of the element to set/replace
+ * \param elementValue the (new) value of the element
+ */
void
MmsValue_setElement(MmsValue* complexValue, int index, MmsValue* elementValue);
diff --git a/src/mms/iso_mms/client/mms_client_read.c b/src/mms/iso_mms/client/mms_client_read.c
index 5c39235e..fdeab19e 100644
--- a/src/mms/iso_mms/client/mms_client_read.c
+++ b/src/mms/iso_mms/client/mms_client_read.c
@@ -43,7 +43,7 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
int elementCount = listSize;
if ((elementCount > 1) || createArray)
- valueList = MmsValue_createEmtpyArray(elementCount);
+ valueList = MmsValue_createEmptyArray(elementCount);
int i = 0;
diff --git a/src/mms/iso_mms/common/mms_value.c b/src/mms/iso_mms/common/mms_value.c
index 8f632dee..38400e64 100644
--- a/src/mms/iso_mms/common/mms_value.c
+++ b/src/mms/iso_mms/common/mms_value.c
@@ -71,8 +71,11 @@ MmsValue*
MmsValue_newIntegerFromBerInteger(Asn1PrimitiveValue* berInteger)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- self->type = MMS_INTEGER;
+ if (self == NULL)
+ return NULL;
+
+ self->type = MMS_INTEGER;
self->value.integer = berInteger;
return self;
@@ -82,8 +85,11 @@ MmsValue*
MmsValue_newUnsignedFromBerInteger(Asn1PrimitiveValue* berInteger)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- self->type = MMS_UNSIGNED;
+ if (self == NULL)
+ return NULL;
+
+ self->type = MMS_UNSIGNED;
self->value.integer = berInteger;
return self;
@@ -283,6 +289,9 @@ MmsValue_newDataAccessError(MmsDataAccessError accessError)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ if (self == NULL)
+ return NULL;
+
self->type = MMS_DATA_ACCESS_ERROR;
self->value.dataAccessError = accessError;
@@ -294,6 +303,9 @@ MmsValue_newBitString(int bitSize)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
+ if (self == NULL)
+ return NULL;
+
self->type = MMS_BIT_STRING;
self->value.bitString.size = bitSize;
self->value.bitString.buf = (uint8_t*) GLOBAL_CALLOC(bitStringByteSize(self), 1);
@@ -480,16 +492,19 @@ MmsValue_setBitStringFromIntegerBigEndian(MmsValue* self, uint32_t intValue)
MmsValue*
MmsValue_newFloat(float variable)
{
- MmsValue* value = (MmsValue*) GLOBAL_MALLOC(sizeof(MmsValue));;
+ MmsValue* self = (MmsValue*) GLOBAL_MALLOC(sizeof(MmsValue));;
- value->type = MMS_FLOAT;
- value->value.floatingPoint.formatWidth = 32;
- value->value.floatingPoint.exponentWidth = 8;
- value->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(4);
+ if (self == NULL)
+ return NULL;
- *((float*) value->value.floatingPoint.buf) = variable;
+ self->type = MMS_FLOAT;
+ self->value.floatingPoint.formatWidth = 32;
+ self->value.floatingPoint.exponentWidth = 8;
+ self->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(4);
- return value;
+ *((float*) self->value.floatingPoint.buf) = variable;
+
+ return self;
}
void
@@ -521,108 +536,111 @@ MmsValue_setDouble(MmsValue* value, double newFloatValue)
MmsValue*
MmsValue_newDouble(double variable)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
- value->type = MMS_FLOAT;
- value->value.floatingPoint.formatWidth = 64;
- value->value.floatingPoint.exponentWidth = 11;
- value->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(8);
+ self->type = MMS_FLOAT;
+ self->value.floatingPoint.formatWidth = 64;
+ self->value.floatingPoint.exponentWidth = 11;
+ self->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(8);
- *((double*) value->value.floatingPoint.buf) = variable;
+ *((double*) self->value.floatingPoint.buf) = variable;
- return value;
+ return self;
}
MmsValue*
MmsValue_newIntegerFromInt8(int8_t integer)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
- value->type = MMS_INTEGER;
- value->value.integer = BerInteger_createFromInt32((int32_t) integer);
+ self->type = MMS_INTEGER;
+ self->value.integer = BerInteger_createFromInt32((int32_t) integer);
- return value;
+ return self;
}
MmsValue*
MmsValue_newIntegerFromInt16(int16_t integer)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
- value->type = MMS_INTEGER;
- value->value.integer = BerInteger_createFromInt32((int32_t) integer);
+ self->type = MMS_INTEGER;
+ self->value.integer = BerInteger_createFromInt32((int32_t) integer);
- return value;
+ return self;
}
void
-MmsValue_setInt8(MmsValue* value, int8_t integer)
+MmsValue_setInt8(MmsValue* self, int8_t integer)
{
- if (value->type == MMS_INTEGER) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 1) {
- BerInteger_setInt32(value->value.integer, (int32_t) integer);
+ if (self->type == MMS_INTEGER) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 1) {
+ BerInteger_setInt32(self->value.integer, (int32_t) integer);
}
}
}
void
-MmsValue_setInt16(MmsValue* value, int16_t integer)
+MmsValue_setInt16(MmsValue* self, int16_t integer)
{
- if (value->type == MMS_INTEGER) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 1) {
- BerInteger_setInt32(value->value.integer, (int32_t) integer);
+ if (self->type == MMS_INTEGER) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 1) {
+ BerInteger_setInt32(self->value.integer, (int32_t) integer);
}
}
}
void
-MmsValue_setInt32(MmsValue* value, int32_t integer)
+MmsValue_setInt32(MmsValue* self, int32_t integer)
{
- if (value->type == MMS_INTEGER) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 4) {
- BerInteger_setInt32(value->value.integer, integer);
+ if (self->type == MMS_INTEGER) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 4) {
+ BerInteger_setInt32(self->value.integer, integer);
}
}
}
void
-MmsValue_setInt64(MmsValue* value, int64_t integer)
+MmsValue_setInt64(MmsValue* self, int64_t integer)
{
- if (value->type == MMS_INTEGER) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 8) {
- BerInteger_setInt64(value->value.integer, integer);
+ if (self->type == MMS_INTEGER) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 8) {
+ BerInteger_setInt64(self->value.integer, integer);
}
}
}
void
-MmsValue_setUint32(MmsValue* value, uint32_t integer)
+MmsValue_setUint32(MmsValue* self, uint32_t integer)
{
- if (value->type == MMS_UNSIGNED) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 4) {
- BerInteger_setUint32(value->value.integer, integer);
+ if (self->type == MMS_UNSIGNED) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 4) {
+ BerInteger_setUint32(self->value.integer, integer);
}
}
}
void
-MmsValue_setUint16(MmsValue* value, uint16_t integer)
+MmsValue_setUint16(MmsValue* self, uint16_t integer)
{
- if (value->type == MMS_UNSIGNED) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 2) {
- BerInteger_setUint16(value->value.integer, integer);
+ if (self->type == MMS_UNSIGNED) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 2) {
+ BerInteger_setUint16(self->value.integer, integer);
}
}
}
void
-MmsValue_setUint8(MmsValue* value, uint8_t integer)
+MmsValue_setUint8(MmsValue* self, uint8_t integer)
{
- if (value->type == MMS_UNSIGNED) {
- if (Asn1PrimitiveValue_getMaxSize(value->value.integer) >= 1) {
- BerInteger_setUint8(value->value.integer, integer);
+ if (self->type == MMS_UNSIGNED) {
+ if (Asn1PrimitiveValue_getMaxSize(self->value.integer) >= 1) {
+ BerInteger_setUint8(self->value.integer, integer);
}
}
@@ -630,23 +648,23 @@ MmsValue_setUint8(MmsValue* value, uint8_t integer)
void
-MmsValue_setBoolean(MmsValue* value, bool boolValue)
+MmsValue_setBoolean(MmsValue* self, bool boolValue)
{
- value->value.boolean = boolValue;
+ self->value.boolean = boolValue;
}
bool
-MmsValue_getBoolean(MmsValue* value)
+MmsValue_getBoolean(MmsValue* self)
{
- return value->value.boolean;
+ return self->value.boolean;
}
MmsValue*
-MmsValue_setUtcTime(MmsValue* value, uint32_t timeval)
+MmsValue_setUtcTime(MmsValue* self, uint32_t timeval)
{
uint8_t* timeArray = (uint8_t*) &timeval;
- uint8_t* valueArray = value->value.utcTime;
+ uint8_t* valueArray = self->value.utcTime;
#if (ORDER_LITTLE_ENDIAN == 1)
memcpyReverseByteOrder(valueArray, timeArray, 4);
@@ -654,7 +672,7 @@ MmsValue_setUtcTime(MmsValue* value, uint32_t timeval)
memcpy(valueArray, timeArray, 4);
#endif
- return value;
+ return self;
}
@@ -739,57 +757,66 @@ MmsValue_getUtcTimeInMs(MmsValue* self)
MmsValue*
MmsValue_newIntegerFromInt32(int32_t integer)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
- value->type = MMS_INTEGER;
- value->value.integer = BerInteger_createFromInt32(integer);
+ self->type = MMS_INTEGER;
+ self->value.integer = BerInteger_createFromInt32(integer);
- return value;
+ return self;
}
MmsValue*
MmsValue_newUnsignedFromUint32(uint32_t integer)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
- value->type = MMS_UNSIGNED;
- value->value.integer = BerInteger_createFromUint32(integer);
+ if (self == NULL)
+ return NULL;
- return value;
+ self->type = MMS_UNSIGNED;
+ self->value.integer = BerInteger_createFromUint32(integer);
+
+ return self;
}
MmsValue*
MmsValue_newIntegerFromInt64(int64_t integer)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));;
+
+ if (self == NULL)
+ return NULL;
- value->type = MMS_INTEGER;
- value->value.integer = BerInteger_createFromInt64(integer);
+ self->type = MMS_INTEGER;
+ self->value.integer = BerInteger_createFromInt64(integer);
- return value;
+ return self;
}
/**
* Convert signed integer to int32_t
*/
int32_t
-MmsValue_toInt32(MmsValue* value)
+MmsValue_toInt32(MmsValue* self)
{
int32_t integerValue = 0;
- if ((value->type == MMS_INTEGER) || (value->type == MMS_UNSIGNED))
- BerInteger_toInt32(value->value.integer, &integerValue);
+ if ((self->type == MMS_INTEGER) || (self->type == MMS_UNSIGNED))
+ BerInteger_toInt32(self->value.integer, &integerValue);
return integerValue;
}
uint32_t
-MmsValue_toUint32(MmsValue* value)
+MmsValue_toUint32(MmsValue* self)
{
uint32_t integerValue = 0;
- if ((value->type == MMS_INTEGER) || (value->type == MMS_UNSIGNED))
- BerInteger_toUint32(value->value.integer, &integerValue);
+ if ((self->type == MMS_INTEGER) || (self->type == MMS_UNSIGNED))
+ BerInteger_toUint32(self->value.integer, &integerValue);
return integerValue;
}
@@ -798,29 +825,29 @@ MmsValue_toUint32(MmsValue* value)
* Convert signed integer to int64_t and do sign extension if required
*/
int64_t
-MmsValue_toInt64(MmsValue* value)
+MmsValue_toInt64(MmsValue* self)
{
int64_t integerValue = 0;
- if ((value->type == MMS_INTEGER) || (value->type == MMS_UNSIGNED))
- BerInteger_toInt64(value->value.integer, &integerValue);
+ if ((self->type == MMS_INTEGER) || (self->type == MMS_UNSIGNED))
+ BerInteger_toInt64(self->value.integer, &integerValue);
return integerValue;
}
float
-MmsValue_toFloat(MmsValue* value)
+MmsValue_toFloat(MmsValue* self)
{
- if (value->type == MMS_FLOAT) {
- if (value->value.floatingPoint.formatWidth == 32) {
+ if (self->type == MMS_FLOAT) {
+ if (self->value.floatingPoint.formatWidth == 32) {
float val;
- val = *((float*) (value->value.floatingPoint.buf));
+ val = *((float*) (self->value.floatingPoint.buf));
return val;
}
- else if (value->value.floatingPoint.formatWidth == 64) {
+ else if (self->value.floatingPoint.formatWidth == 64) {
float val;
- val = *((double*) (value->value.floatingPoint.buf));
+ val = *((double*) (self->value.floatingPoint.buf));
return val;
}
}
@@ -831,16 +858,16 @@ MmsValue_toFloat(MmsValue* value)
}
double
-MmsValue_toDouble(MmsValue* value)
+MmsValue_toDouble(MmsValue* self)
{
- if (value->type == MMS_FLOAT) {
+ if (self->type == MMS_FLOAT) {
double val;
- if (value->value.floatingPoint.formatWidth == 32) {
- val = (double) *((float*) (value->value.floatingPoint.buf));
+ if (self->value.floatingPoint.formatWidth == 32) {
+ val = (double) *((float*) (self->value.floatingPoint.buf));
return val;
}
- if (value->value.floatingPoint.formatWidth == 64) {
- val = *((double*) (value->value.floatingPoint.buf));
+ if (self->value.floatingPoint.formatWidth == 64) {
+ val = *((double*) (self->value.floatingPoint.buf));
return val;
}
}
@@ -851,21 +878,21 @@ MmsValue_toDouble(MmsValue* value)
uint32_t
-MmsValue_toUnixTimestamp(MmsValue* value)
+MmsValue_toUnixTimestamp(MmsValue* self)
{
uint32_t timestamp;
uint8_t* timeArray = (uint8_t*) ×tamp;
#if (ORDER_LITTLE_ENDIAN == 1)
- timeArray[0] = value->value.utcTime[3];
- timeArray[1] = value->value.utcTime[2];
- timeArray[2] = value->value.utcTime[1];
- timeArray[3] = value->value.utcTime[0];
+ timeArray[0] = self->value.utcTime[3];
+ timeArray[1] = self->value.utcTime[2];
+ timeArray[2] = self->value.utcTime[1];
+ timeArray[3] = self->value.utcTime[0];
#else
- timeArray[0] = value->value.utcTime[0];
- timeArray[1] = value->value.utcTime[1];
- timeArray[2] = value->value.utcTime[2];
- timeArray[3] = value->value.utcTime[3];
+ timeArray[0] = self->self.utcTime[0];
+ timeArray[1] = self->self.utcTime[1];
+ timeArray[2] = self->self.utcTime[2];
+ timeArray[3] = self->self.utcTime[3];
#endif
return timestamp;
@@ -887,25 +914,31 @@ MmsValue_getSizeInMemory(MmsValue* self)
memorySize += MmsValue_getSizeInMemory(self->value.structure.components[i]);
}
break;
+
case MMS_BIT_STRING:
memorySize += bitStringByteSize(self);
break;
+
case MMS_INTEGER:
case MMS_UNSIGNED:
memorySize += sizeof(Asn1PrimitiveValue);
memorySize += self->value.integer->maxSize;
break;
+
case MMS_FLOAT:
memorySize += (self->value.floatingPoint.formatWidth / 8);
break;
+
case MMS_OCTET_STRING:
memorySize += self->value.octetString.maxSize;
break;
+
case MMS_STRING:
case MMS_VISIBLE_STRING:
memorySize += strlen(self->value.visibleString.buf);
memorySize += 1; /* add space for 0 character */
break;
+
default:
break;
}
@@ -941,6 +974,7 @@ MmsValue_cloneToBuffer(MmsValue* self, uint8_t* destinationAddress)
newValue->value.bitString.buf = destinationAddress;
destinationAddress += bitStringByteSize(self);
break;
+
case MMS_INTEGER:
case MMS_UNSIGNED:
{
@@ -952,6 +986,7 @@ MmsValue_cloneToBuffer(MmsValue* self, uint8_t* destinationAddress)
destinationAddress += self->value.integer->maxSize;
}
break;
+
case MMS_FLOAT:
{
int floatSizeInBytes = (self->value.floatingPoint.formatWidth / 8);
@@ -961,11 +996,13 @@ MmsValue_cloneToBuffer(MmsValue* self, uint8_t* destinationAddress)
destinationAddress += floatSizeInBytes;
}
break;
+
case MMS_OCTET_STRING:
newValue->value.octetString.buf = destinationAddress;
memcpy(destinationAddress, self->value.octetString.buf, self->value.octetString.maxSize);
destinationAddress += self->value.octetString.maxSize;
break;
+
case MMS_STRING:
case MMS_VISIBLE_STRING:
newValue->value.visibleString.buf = (char*) destinationAddress;
@@ -973,6 +1010,7 @@ MmsValue_cloneToBuffer(MmsValue* self, uint8_t* destinationAddress)
strcpy((char*) destinationAddress, self->value.visibleString.buf);
destinationAddress += (strlen(self->value.visibleString.buf) + 1);
break;
+
default:
break;
}
@@ -982,214 +1020,241 @@ MmsValue_cloneToBuffer(MmsValue* self, uint8_t* destinationAddress)
// create a deep clone
MmsValue*
-MmsValue_clone(MmsValue* value)
+MmsValue_clone(MmsValue* self)
{
MmsValue* newValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- newValue->deleteValue = value->deleteValue;
- newValue->type = value->type;
+
+ if (newValue == NULL)
+ goto exit_function;
+
+ newValue->deleteValue = self->deleteValue;
+ newValue->type = self->type;
int size;
- switch(value->type) {
+ switch(self->type) {
case MMS_ARRAY:
case MMS_STRUCTURE:
{
- int componentCount = value->value.structure.size;
+ int componentCount = self->value.structure.size;
newValue->value.structure.size = componentCount;
newValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));
int i;
for (i = 0; i < componentCount; i++) {
newValue->value.structure.components[i] =
- MmsValue_clone(value->value.structure.components[i]);
+ MmsValue_clone(self->value.structure.components[i]);
}
}
break;
case MMS_INTEGER:
case MMS_UNSIGNED:
- newValue->value.integer = Asn1PrimitiveValue_clone(value->value.integer);
+ newValue->value.integer = Asn1PrimitiveValue_clone(self->value.integer);
break;
+
case MMS_FLOAT:
- newValue->value.floatingPoint.formatWidth = value->value.floatingPoint.formatWidth;
- newValue->value.floatingPoint.exponentWidth = value->value.floatingPoint.exponentWidth;
- size = value->value.floatingPoint.formatWidth / 8;
+ newValue->value.floatingPoint.formatWidth = self->value.floatingPoint.formatWidth;
+ newValue->value.floatingPoint.exponentWidth = self->value.floatingPoint.exponentWidth;
+ size = self->value.floatingPoint.formatWidth / 8;
newValue->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(size);
- memcpy(newValue->value.floatingPoint.buf, value->value.floatingPoint.buf, size);
+ memcpy(newValue->value.floatingPoint.buf, self->value.floatingPoint.buf, size);
break;
+
case MMS_BIT_STRING:
- newValue->value.bitString.size = value->value.bitString.size;
- size = bitStringByteSize(value);
+ newValue->value.bitString.size = self->value.bitString.size;
+ size = bitStringByteSize(self);
newValue->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size);
- memcpy(newValue->value.bitString.buf, value->value.bitString.buf, size);
+ memcpy(newValue->value.bitString.buf, self->value.bitString.buf, size);
break;
+
case MMS_BOOLEAN:
- newValue->value.boolean = value->value.boolean;
+ newValue->value.boolean = self->value.boolean;
break;
+
case MMS_OCTET_STRING:
- size = value->value.octetString.size;
+ size = self->value.octetString.size;
newValue->value.octetString.size = size;
- newValue->value.octetString.maxSize = value->value.octetString.maxSize;
- newValue->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(value->value.octetString.maxSize);
- memcpy(newValue->value.octetString.buf, value->value.octetString.buf, size);
+ newValue->value.octetString.maxSize = self->value.octetString.maxSize;
+ newValue->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(self->value.octetString.maxSize);
+ memcpy(newValue->value.octetString.buf, self->value.octetString.buf, size);
break;
+
case MMS_UTC_TIME:
- memcpy(newValue->value.utcTime, value->value.utcTime, 8);
+ memcpy(newValue->value.utcTime, self->value.utcTime, 8);
break;
+
case MMS_BINARY_TIME:
- newValue->value.binaryTime.size = value->value.binaryTime.size;
- memcpy(newValue->value.binaryTime.buf, value->value.binaryTime.buf, 6);
+ newValue->value.binaryTime.size = self->value.binaryTime.size;
+ memcpy(newValue->value.binaryTime.buf, self->value.binaryTime.buf, 6);
break;
+
case MMS_VISIBLE_STRING:
case MMS_STRING:
- size = value->value.visibleString.size;
+ size = self->value.visibleString.size;
newValue->value.visibleString.buf = (char*) GLOBAL_MALLOC(size + 1);
newValue->value.visibleString.size = size;
- strcpy(newValue->value.visibleString.buf, value->value.visibleString.buf);
+ strcpy(newValue->value.visibleString.buf, self->value.visibleString.buf);
break;
+
case MMS_DATA_ACCESS_ERROR:
- newValue->value.dataAccessError = value->value.dataAccessError;
+ newValue->value.dataAccessError = self->value.dataAccessError;
break;
+
default:
break;
}
+exit_function:
return newValue;
}
uint32_t
-MmsValue_getArraySize(MmsValue* value)
+MmsValue_getArraySize(MmsValue* self)
{
- return value->value.structure.size;
+ return self->value.structure.size;
}
void
-MmsValue_deleteIfNotNull(MmsValue* value)
+MmsValue_deleteIfNotNull(MmsValue* self)
{
- if (value != NULL)
- MmsValue_delete(value);
+ if (self != NULL)
+ MmsValue_delete(self);
}
void
-MmsValue_delete(MmsValue* value)
+MmsValue_delete(MmsValue* self)
{
- switch (value->type) {
+ switch (self->type) {
case MMS_INTEGER:
case MMS_UNSIGNED:
- Asn1PrimitiveValue_destroy(value->value.integer);
+ Asn1PrimitiveValue_destroy(self->value.integer);
break;
case MMS_FLOAT:
- GLOBAL_FREEMEM(value->value.floatingPoint.buf);
+ GLOBAL_FREEMEM(self->value.floatingPoint.buf);
break;
case MMS_BIT_STRING:
- GLOBAL_FREEMEM(value->value.bitString.buf);
+ GLOBAL_FREEMEM(self->value.bitString.buf);
break;
case MMS_OCTET_STRING:
- GLOBAL_FREEMEM(value->value.octetString.buf);
+ GLOBAL_FREEMEM(self->value.octetString.buf);
break;
case MMS_VISIBLE_STRING:
case MMS_STRING:
- if (value->value.visibleString.buf != NULL)
- GLOBAL_FREEMEM(value->value.visibleString.buf);
+ if (self->value.visibleString.buf != NULL)
+ GLOBAL_FREEMEM(self->value.visibleString.buf);
break;
case MMS_ARRAY:
case MMS_STRUCTURE:
{
- int componentCount = value->value.structure.size;
+ int componentCount = self->value.structure.size;
int i;
for (i = 0; i < componentCount; i++) {
- if (value->value.structure.components[i] != NULL)
- MmsValue_delete(value->value.structure.components[i]);
+ if (self->value.structure.components[i] != NULL)
+ MmsValue_delete(self->value.structure.components[i]);
}
}
- GLOBAL_FREEMEM(value->value.structure.components);
+ GLOBAL_FREEMEM(self->value.structure.components);
break;
default:
break;
}
- GLOBAL_FREEMEM(value);
+ GLOBAL_FREEMEM(self);
}
/* delete only when deleteValue field set */
void
-MmsValue_deleteConditional(MmsValue* value)
+MmsValue_deleteConditional(MmsValue* self)
{
- if (value->deleteValue == 1) {
+ if (self->deleteValue == 1) {
- switch (value->type) {
+ switch (self->type) {
case MMS_INTEGER:
case MMS_UNSIGNED:
- Asn1PrimitiveValue_destroy(value->value.integer);
+ Asn1PrimitiveValue_destroy(self->value.integer);
break;
case MMS_FLOAT:
- GLOBAL_FREEMEM(value->value.floatingPoint.buf);
+ GLOBAL_FREEMEM(self->value.floatingPoint.buf);
break;
case MMS_BIT_STRING:
- GLOBAL_FREEMEM(value->value.bitString.buf);
+ GLOBAL_FREEMEM(self->value.bitString.buf);
break;
case MMS_OCTET_STRING:
- GLOBAL_FREEMEM(value->value.octetString.buf);
+ GLOBAL_FREEMEM(self->value.octetString.buf);
break;
case MMS_VISIBLE_STRING:
case MMS_STRING:
- if (value->value.visibleString.buf != NULL)
- GLOBAL_FREEMEM(value->value.visibleString.buf);
+ if (self->value.visibleString.buf != NULL)
+ GLOBAL_FREEMEM(self->value.visibleString.buf);
break;
case MMS_ARRAY:
case MMS_STRUCTURE:
{
- int componentCount = value->value.structure.size;
+ int componentCount = self->value.structure.size;
int i;
for (i = 0; i < componentCount; i++) {
- if (value->value.structure.components[i] != NULL)
- MmsValue_deleteConditional(value->value.structure.components[i]);
+ if (self->value.structure.components[i] != NULL)
+ MmsValue_deleteConditional(self->value.structure.components[i]);
}
}
- GLOBAL_FREEMEM(value->value.structure.components);
+ GLOBAL_FREEMEM(self->value.structure.components);
break;
default:
break;
}
- GLOBAL_FREEMEM(value);
+ GLOBAL_FREEMEM(self);
}
}
MmsValue*
MmsValue_newInteger(int size /*integer size in bits*/)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_INTEGER;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
+
+ self->type = MMS_INTEGER;
if (size <= 32)
- value->value.integer = BerInteger_createInt32();
+ self->value.integer = BerInteger_createInt32();
else
- value->value.integer = BerInteger_createInt64();
+ self->value.integer = BerInteger_createInt64();
- return value;
+ return self;
}
MmsValue*
MmsValue_newUnsigned(int size /*integer size in bits*/)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_UNSIGNED;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
+
+ self->type = MMS_UNSIGNED;
if (size <= 32)
- value->value.integer = BerInteger_createInt32();
+ self->value.integer = BerInteger_createInt32();
else
- value->value.integer = BerInteger_createInt64();
+ self->value.integer = BerInteger_createInt64();
- return value;
+ return self;
}
MmsValue*
MmsValue_newBoolean(bool boolean)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
+
self->type = MMS_BOOLEAN;
+
if (boolean == true)
self->value.boolean = 1;
else
@@ -1202,6 +1267,10 @@ MmsValue*
MmsValue_newOctetString(int size, int maxSize)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
+
self->type = MMS_OCTET_STRING;
self->value.octetString.size = size;
self->value.octetString.maxSize = maxSize;
@@ -1242,6 +1311,9 @@ MmsValue_newStructure(MmsVariableSpecification* typeSpec)
{
MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ if (self == NULL)
+ return NULL;
+
self->type = MMS_STRUCTURE;
int componentCount = typeSpec->typeSpec.structure.elementCount;
self->value.structure.size = componentCount;
@@ -1259,123 +1331,169 @@ MmsValue_newStructure(MmsVariableSpecification* typeSpec)
MmsValue*
MmsValue_newDefaultValue(MmsVariableSpecification* typeSpec)
{
- MmsValue* value = NULL;
+ MmsValue* self = NULL;
switch (typeSpec->type) {
case MMS_INTEGER:
- value = MmsValue_newInteger(typeSpec->typeSpec.integer);
+ self = MmsValue_newInteger(typeSpec->typeSpec.integer);
break;
+
case MMS_UNSIGNED:
- value = MmsValue_newUnsigned(typeSpec->typeSpec.unsignedInteger);
+ self = MmsValue_newUnsigned(typeSpec->typeSpec.unsignedInteger);
break;
+
case MMS_FLOAT:
- value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_FLOAT;
- value->value.floatingPoint.exponentWidth = typeSpec->typeSpec.floatingpoint.exponentWidth;
- value->value.floatingPoint.formatWidth = typeSpec->typeSpec.floatingpoint.formatWidth;
- value->value.floatingPoint.buf = (uint8_t*) GLOBAL_CALLOC(1, typeSpec->typeSpec.floatingpoint.formatWidth / 8);
+ self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = MMS_FLOAT;
+ self->value.floatingPoint.exponentWidth = typeSpec->typeSpec.floatingpoint.exponentWidth;
+ self->value.floatingPoint.formatWidth = typeSpec->typeSpec.floatingpoint.formatWidth;
+ self->value.floatingPoint.buf = (uint8_t*) GLOBAL_CALLOC(1, typeSpec->typeSpec.floatingpoint.formatWidth / 8);
break;
+
case MMS_BIT_STRING:
- value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_BIT_STRING;
+ self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = MMS_BIT_STRING;
{
int bitSize = abs(typeSpec->typeSpec.bitString);
- value->value.bitString.size = bitSize;
+ self->value.bitString.size = bitSize;
int size = (bitSize / 8) + ((bitSize % 8) > 0);
- value->value.bitString.buf = (uint8_t*) GLOBAL_CALLOC(1, size);
+ self->value.bitString.buf = (uint8_t*) GLOBAL_CALLOC(1, size);
}
break;
+
case MMS_OCTET_STRING:
- value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_OCTET_STRING;
+ self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = MMS_OCTET_STRING;
if (typeSpec->typeSpec.octetString < 0)
- value->value.octetString.size = 0;
+ self->value.octetString.size = 0;
else
- value->value.octetString.size = typeSpec->typeSpec.octetString;
+ self->value.octetString.size = typeSpec->typeSpec.octetString;
- value->value.octetString.maxSize = abs(typeSpec->typeSpec.octetString);
- value->value.octetString.buf = (uint8_t*) GLOBAL_CALLOC(1, abs(typeSpec->typeSpec.octetString));
+ self->value.octetString.maxSize = abs(typeSpec->typeSpec.octetString);
+ self->value.octetString.buf = (uint8_t*) GLOBAL_CALLOC(1, abs(typeSpec->typeSpec.octetString));
break;
+
case MMS_VISIBLE_STRING:
- value = MmsValue_newVisibleStringWithSize(abs(typeSpec->typeSpec.visibleString));
+ self = MmsValue_newVisibleStringWithSize(abs(typeSpec->typeSpec.visibleString));
break;
+
case MMS_BOOLEAN:
- value = MmsValue_newBoolean(false);
+ self = MmsValue_newBoolean(false);
break;
+
case MMS_UTC_TIME:
- value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_UTC_TIME;
+ self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = MMS_UTC_TIME;
break;
+
case MMS_ARRAY:
- value = MmsValue_createArray(typeSpec->typeSpec.array.elementTypeSpec,
+ self = MmsValue_createArray(typeSpec->typeSpec.array.elementTypeSpec,
typeSpec->typeSpec.array.elementCount);
break;
+
case MMS_STRUCTURE:
- value = MmsValue_newStructure(typeSpec);
+ self = MmsValue_newStructure(typeSpec);
break;
+
case MMS_STRING:
- value = MmsValue_newMmsStringWithSize(abs(typeSpec->typeSpec.visibleString));
+ self = MmsValue_newMmsStringWithSize(abs(typeSpec->typeSpec.visibleString));
break;
+
case MMS_BINARY_TIME:
if (typeSpec->typeSpec.binaryTime == 4)
- value = MmsValue_newBinaryTime(true);
+ self = MmsValue_newBinaryTime(true);
else
- value = MmsValue_newBinaryTime(false);
+ self = MmsValue_newBinaryTime(false);
break;
+
default:
break;
}
- if (value != NULL)
- value->deleteValue = 0;
+ if (self != NULL)
+ self->deleteValue = 0;
- return value;
+exit_function:
+ return self;
}
static inline void
-setVisibleStringValue(MmsValue* value, char* string)
+setVisibleStringValue(MmsValue* self, char* string)
{
- if (value->value.visibleString.buf != NULL) {
+ if (self->value.visibleString.buf != NULL) {
if (string != NULL) {
int newStringSize = strlen(string);
- if (newStringSize > value->value.visibleString.size) {
- GLOBAL_FREEMEM(value->value.visibleString.buf);
- value->value.visibleString.buf = (char*) GLOBAL_MALLOC(newStringSize + 1);
- value->value.visibleString.size = newStringSize;
+ if (newStringSize > self->value.visibleString.size) {
+ GLOBAL_FREEMEM(self->value.visibleString.buf);
+ self->value.visibleString.buf = (char*) GLOBAL_MALLOC(newStringSize + 1);
+
+ if (self->value.visibleString.buf == NULL)
+ goto exit_function;
+
+ self->value.visibleString.size = newStringSize;
}
- strncpy(value->value.visibleString.buf, string, value->value.visibleString.size + 1);
- value->value.visibleString.buf[value->value.visibleString.size] = 0;
+ strncpy(self->value.visibleString.buf, string, self->value.visibleString.size + 1);
+ self->value.visibleString.buf[self->value.visibleString.size] = 0;
}
else
- value->value.visibleString.buf[0] = 0;
+ self->value.visibleString.buf[0] = 0;
}
+
+exit_function:
+ return;
}
static MmsValue*
MmsValue_newString(char* string, MmsType type)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = type;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = type;
if (string == NULL) {
- value->value.visibleString.size = 0;
- value->value.visibleString.buf = NULL;
+ self->value.visibleString.size = 0;
+ self->value.visibleString.buf = NULL;
}
else {
int stringSize = strlen(string);
- value->value.visibleString.size = stringSize;
- value->value.visibleString.buf = (char*) GLOBAL_MALLOC(stringSize + 1);
+ self->value.visibleString.size = stringSize;
+ self->value.visibleString.buf = (char*) GLOBAL_MALLOC(stringSize + 1);
- setVisibleStringValue(value, string);
- }
+ if (self->value.visibleString.buf == NULL) {
+ GLOBAL_FREEMEM(self);
+ self = NULL;
+ goto exit_function;
+ }
+ setVisibleStringValue(self, string);
+ }
- return value;
+exit_function:
+ return self;
}
MmsValue*
@@ -1387,14 +1505,26 @@ MmsValue_newVisibleString(char* string)
static MmsValue*
MmsValue_newStringWithSize(int size, MmsType type)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = type;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->value.visibleString.size = size;
- value->value.visibleString.buf = (char*) GLOBAL_MALLOC(size + 1);
- value->value.visibleString.buf[0] = 0;
+ if (self == NULL)
+ goto exit_function;
- return value;
+ self->type = type;
+
+ self->value.visibleString.size = size;
+ self->value.visibleString.buf = (char*) GLOBAL_MALLOC(size + 1);
+
+ if (self->value.visibleString.buf == NULL) {
+ GLOBAL_FREEMEM(self);
+ self = NULL;
+ goto exit_function;
+ }
+
+ self->value.visibleString.buf[0] = 0;
+
+exit_function:
+ return self;
}
MmsValue*
@@ -1419,25 +1549,29 @@ MmsValue_newMmsStringWithSize(int size)
MmsValue*
MmsValue_newBinaryTime(bool timeOfDay)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_BINARY_TIME;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ return NULL;
+
+ self->type = MMS_BINARY_TIME;
if (timeOfDay == true)
- value->value.binaryTime.size = 4;
+ self->value.binaryTime.size = 4;
else
- value->value.binaryTime.size = 6;
+ self->value.binaryTime.size = 6;
- return value;
+ return self;
}
void
-MmsValue_setBinaryTime(MmsValue* value, uint64_t timestamp)
+MmsValue_setBinaryTime(MmsValue* self, uint64_t timestamp)
{
uint64_t mmsTime = timestamp - (441763200000LL);
- uint8_t* binaryTimeBuf = value->value.binaryTime.buf;
+ uint8_t* binaryTimeBuf = self->value.binaryTime.buf;
- if (value->value.binaryTime.size == 6) {
+ if (self->value.binaryTime.size == 6) {
uint16_t daysDiff = mmsTime / (86400000LL);
uint8_t* daysDiffBuf = (uint8_t*) &daysDiff;
@@ -1468,13 +1602,13 @@ MmsValue_setBinaryTime(MmsValue* value, uint64_t timestamp)
}
uint64_t
-MmsValue_getBinaryTimeAsUtcMs(MmsValue* value)
+MmsValue_getBinaryTimeAsUtcMs(MmsValue* self)
{
uint64_t timestamp = 0;
- uint8_t* binaryTimeBuf = value->value.binaryTime.buf;
+ uint8_t* binaryTimeBuf = self->value.binaryTime.buf;
- if (value->value.binaryTime.size == 6) {
+ if (self->value.binaryTime.size == 6) {
uint16_t daysDiff;
@@ -1508,25 +1642,36 @@ MmsValue_getDataAccessError(MmsValue* self)
}
void
-MmsValue_setMmsString(MmsValue* value, char* string)
+MmsValue_setMmsString(MmsValue* self, char* string)
{
- if (value->type == MMS_STRING) {
- assert(value->value.visibleString.buf != NULL);
+ if (self->type == MMS_STRING) {
+ assert(self->value.visibleString.buf != NULL);
- setVisibleStringValue(value, string);
+ setVisibleStringValue(self, string);
}
}
static MmsValue*
MmsValue_newStringFromByteArray(uint8_t* byteArray, int size, MmsType type)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = type;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->value.visibleString.buf = createStringFromBuffer(byteArray, size);
- value->value.visibleString.size = size;
+ if (self == NULL)
+ goto exit_function;
- return value;
+ self->type = type;
+
+ self->value.visibleString.size = size;
+
+ self->value.visibleString.buf = createStringFromBuffer(byteArray, size);
+
+ if (self->value.visibleString.buf == NULL) {
+ GLOBAL_FREEMEM(self);
+ self = NULL;
+ }
+
+exit_function:
+ return self;
}
MmsValue*
@@ -1542,20 +1687,20 @@ MmsValue_newMmsStringFromByteArray(uint8_t* byteArray, int size)
}
void
-MmsValue_setVisibleString(MmsValue* value, char* string)
+MmsValue_setVisibleString(MmsValue* self, char* string)
{
- if (value->type == MMS_VISIBLE_STRING) {
- assert(value->value.visibleString.buf != NULL);
+ if (self->type == MMS_VISIBLE_STRING) {
+ assert(self->value.visibleString.buf != NULL);
- setVisibleStringValue(value, string);
+ setVisibleStringValue(self, string);
}
}
char*
-MmsValue_toString(MmsValue* value)
+MmsValue_toString(MmsValue* self)
{
- if ((value->type == MMS_VISIBLE_STRING) || (value->type == MMS_STRING))
- return value->value.visibleString.buf;
+ if ((self->type == MMS_VISIBLE_STRING) || (self->type == MMS_STRING))
+ return self->value.visibleString.buf;
return NULL;
}
@@ -1563,11 +1708,15 @@ MmsValue_toString(MmsValue* value)
MmsValue*
MmsValue_newUtcTime(uint32_t timeval)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_UTC_TIME;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = MMS_UTC_TIME;
uint8_t* timeArray = (uint8_t*) &timeval;
- uint8_t* valueArray = value->value.utcTime;
+ uint8_t* valueArray = self->value.utcTime;
#if (ORDER_LITTLE_ENDIAN == 1)
valueArray[0] = timeArray[3];
@@ -1581,63 +1730,96 @@ MmsValue_newUtcTime(uint32_t timeval)
valueArray[3] = timeArray[3];
#endif
- return value;
+exit_function:
+ return self;
}
MmsValue*
MmsValue_newUtcTimeByMsTime(uint64_t timeval)
{
- MmsValue* value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- value->type = MMS_UTC_TIME;
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- MmsValue_setUtcTimeMs(value, timeval);
+ if (self == NULL)
+ return NULL;
- return value;
+ self->type = MMS_UTC_TIME;
+ MmsValue_setUtcTimeMs(self, timeval);
+
+ return self;
}
MmsValue*
MmsValue_createArray(MmsVariableSpecification* elementType, int size)
{
- MmsValue* array = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
- array->type = MMS_ARRAY;
- array->value.structure.size = size;
- array->value.structure.components = (MmsValue**) GLOBAL_CALLOC(size, sizeof(MmsValue*));
+ if (self == NULL)
+ goto exit_function;
+
+ self->type = MMS_ARRAY;
+ self->value.structure.size = size;
+ self->value.structure.components = (MmsValue**) GLOBAL_CALLOC(size, sizeof(MmsValue*));
+
+ if (self->value.structure.components == NULL) {
+ GLOBAL_FREEMEM(self);
+ self = NULL;
+ goto exit_function;
+ }
int i;
for (i = 0; i < size; i++) {
- array->value.structure.components[i] = MmsValue_newDefaultValue(elementType);
+ self->value.structure.components[i] = MmsValue_newDefaultValue(elementType);
+
+ if (self->value.structure.components[i] == NULL) {
+ MmsValue_delete(self);
+ self = NULL;
+ goto exit_function;
+ }
}
- return array;
+exit_function:
+ return self;
}
MmsValue*
-MmsValue_createEmtpyArray(int size)
+MmsValue_createEmptyArray(int size)
{
- MmsValue* array = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ MmsValue* self = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+
+ if (self == NULL)
+ goto exit_function;
- array->type = MMS_ARRAY;
- array->value.structure.size = size;
- array->value.structure.components = (MmsValue**) GLOBAL_CALLOC(size, sizeof(MmsValue*));
+ self->type = MMS_ARRAY;
+ self->value.structure.size = size;
+ self->value.structure.components = (MmsValue**) GLOBAL_CALLOC(size, sizeof(MmsValue*));
+
+ if (self->value.structure.components == NULL) {
+ GLOBAL_FREEMEM(self);
+ self = NULL;
+ goto exit_function;
+ }
int i;
for (i = 0; i < size; i++) {
- array->value.structure.components[i] = NULL;
+ self->value.structure.components[i] = NULL;
}
- return array;
+exit_function:
+ return self;
}
MmsValue*
MmsValue_createEmptyStructure(int size)
{
- MmsValue* structure = MmsValue_createEmtpyArray(size);
+ MmsValue* self = MmsValue_createEmptyArray(size);
+
+ if (self == NULL)
+ return NULL;
- structure->type = MMS_STRUCTURE;
+ self->type = MMS_STRUCTURE;
- return structure;
+ return self;
}
void
@@ -1665,35 +1847,38 @@ MmsValue_getElement(MmsValue* complexValue, int index)
}
void
-MmsValue_setDeletable(MmsValue* value)
+MmsValue_setDeletable(MmsValue* self)
{
- value->deleteValue = 1;
+ self->deleteValue = 1;
}
void
-MmsValue_setDeletableRecursive(MmsValue* value)
+MmsValue_setDeletableRecursive(MmsValue* self)
{
- if ((MmsValue_getType(value) == MMS_ARRAY) || (MmsValue_getType(value) == MMS_STRUCTURE)) {
- int i;
- int elementCount = MmsValue_getArraySize(value);
+ if (self != NULL) {
- for (i = 0; i < elementCount; i++)
- MmsValue_setDeletableRecursive(MmsValue_getElement(value, i));
- }
+ if ((MmsValue_getType(self) == MMS_ARRAY) || (MmsValue_getType(self) == MMS_STRUCTURE)) {
+ int i;
+ int elementCount = MmsValue_getArraySize(self);
- MmsValue_setDeletable(value);
+ for (i = 0; i < elementCount; i++)
+ MmsValue_setDeletableRecursive(MmsValue_getElement(self, i));
+ }
+
+ MmsValue_setDeletable(self);
+ }
}
int
-MmsValue_isDeletable(MmsValue* value)
+MmsValue_isDeletable(MmsValue* self)
{
- return value->deleteValue;
+ return self->deleteValue;
}
MmsType
-MmsValue_getType(MmsValue* value)
+MmsValue_getType(MmsValue* self)
{
- return value->type;
+ return self->type;
}
MmsValue*
@@ -1813,7 +1998,6 @@ MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize)
break;
case MMS_OCTET_STRING:
{
-
int size = MmsValue_getOctetStringSize(self);
int bufPos = 0;
int i;
diff --git a/src/mms/iso_mms/server/mms_read_service.c b/src/mms/iso_mms/server/mms_read_service.c
index 135ffb08..56c50b23 100644
--- a/src/mms/iso_mms/server/mms_read_service.c
+++ b/src/mms/iso_mms/server/mms_read_service.c
@@ -215,7 +215,7 @@ alternateArrayAccess(MmsServerConnection* connection,
else
value = MmsValue_getElement(arrayValue, index);
else {
- value = MmsValue_createEmtpyArray(numberOfElements);
+ value = MmsValue_createEmptyArray(numberOfElements);
MmsValue_setDeletable(value);
diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def
index 2ba1daf6..ddfae6bc 100644
--- a/src/vs/libiec61850-wo-goose.def
+++ b/src/vs/libiec61850-wo-goose.def
@@ -303,7 +303,7 @@ EXPORTS
MmsValue_cloneToBuffer @697
MmsValue_createArray @698
MmsValue_createEmptyStructure @699
- MmsValue_createEmtpyArray @700
+ MmsValue_createEmptyArray @700
MmsValue_delete @701
MmsValue_deleteAllBitStringBits @702
MmsValue_deleteConditional @703
@@ -472,3 +472,13 @@ EXPORTS
ClientReport_hasBufOvfl
ClientReport_hasDataReference
LibIEC61850_getVersionString
+ ClientReport_getDataReference
+ IedServer_getBooleanAttributeValue
+ IedServer_getInt32AttributeValue
+ IedServer_getInt64AttributeValue
+ IedServer_getUInt32AttributeValue
+ IedServer_getFloatAttributeValue
+ IedServer_getUTCTimeAttributeValue
+ IedServer_getBitStringAttributeValue
+ IedServer_getStringAttributeValue
+
diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def
index 3f30dcee..18a6306b 100644
--- a/src/vs/libiec61850.def
+++ b/src/vs/libiec61850.def
@@ -327,7 +327,7 @@ EXPORTS
MmsValue_cloneToBuffer @697
MmsValue_createArray @698
MmsValue_createEmptyStructure @699
- MmsValue_createEmtpyArray @700
+ MmsValue_createEmptyArray @700
MmsValue_delete @701
MmsValue_deleteAllBitStringBits @702
MmsValue_deleteConditional @703
@@ -496,4 +496,13 @@ EXPORTS
ClientReport_hasBufOvfl
ClientReport_hasDataReference
LibIEC61850_getVersionString
+ ClientReport_getDataReference
+ IedServer_getBooleanAttributeValue
+ IedServer_getInt32AttributeValue
+ IedServer_getInt64AttributeValue
+ IedServer_getUInt32AttributeValue
+ IedServer_getFloatAttributeValue
+ IedServer_getUTCTimeAttributeValue
+ IedServer_getBitStringAttributeValue
+ IedServer_getStringAttributeValue