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