LinkedList /*<FileDirectoryEntry>*/ IedConnection_getFileDirectory(IedConnection self, IedClientError* error, char* directoryName) { *error = IED_ERROR_OK; MmsError mmsError = MMS_ERROR_NONE; LinkedList fileNames = LinkedList_create(); char* continueAfter = NULL; bool moreFollows = false; do { moreFollows = MmsConnection_getFileDirectory(self->connection, &mmsError, directoryName, continueAfter, mmsFileDirectoryHandler, fileNames); if (mmsError != MMS_ERROR_NONE) { *error = iedConnection_mapMmsErrorToIedError(mmsError); LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy); return NULL; } } while (moreFollows == true); return fileNames; }
void IedConnection_destroy(IedConnection self) { IedConnection_close(self); if (self->logicalDevices != NULL) LinkedList_destroyDeep(self->logicalDevices, (LinkedListValueDeleteFunction) ICLogicalDevice_destroy); if (self->enabledReports != NULL) LinkedList_destroyDeep(self->enabledReports, (LinkedListValueDeleteFunction) ClientReport_destroy); LinkedList_destroyStatic(self->clientControls); Semaphore_destroy(self->stateMutex); free(self); }
void IedConnection_getDeviceModelFromServer(IedConnection self, IedClientError* error) { MmsError mmsError = MMS_ERROR_NONE; *error = IED_ERROR_OK; LinkedList logicalDeviceNames = MmsConnection_getDomainNames(self->connection, &mmsError); if (logicalDeviceNames != NULL) { if (self->logicalDevices != NULL) { LinkedList_destroyDeep(self->logicalDevices, (LinkedListValueDeleteFunction) ICLogicalDevice_destroy); self->logicalDevices = NULL; } LinkedList logicalDevice = LinkedList_getNext(logicalDeviceNames); LinkedList logicalDevices = LinkedList_create(); while (logicalDevice != NULL) { char* name = (char*) logicalDevice->data; ICLogicalDevice* icLogicalDevice = ICLogicalDevice_create(name); LinkedList variables = MmsConnection_getDomainVariableNames(self->connection, &mmsError, name); if (variables != NULL) ICLogicalDevice_setVariableList(icLogicalDevice, variables); else { *error = iedConnection_mapMmsErrorToIedError(mmsError); break; } LinkedList dataSets = MmsConnection_getDomainVariableListNames(self->connection, &mmsError, name); if (dataSets != NULL) ICLogicalDevice_setDataSetList(icLogicalDevice, dataSets); else { *error = iedConnection_mapMmsErrorToIedError(mmsError); break; } LinkedList_add(logicalDevices, icLogicalDevice); logicalDevice = LinkedList_getNext(logicalDevice); } self->logicalDevices = logicalDevices; LinkedList_destroy(logicalDeviceNames); } else { *error = iedConnection_mapMmsErrorToIedError(mmsError); } }
void GooseReceiver_destroy(GooseReceiver self) { LinkedList_destroyDeep(self->subscriberList, (LinkedListValueDeleteFunction) GooseSubscriber_destroy); GLOBAL_FREEMEM(self->buffer); GLOBAL_FREEMEM(self); }
void IedServer_destroy(IedServer self) { MmsServer_destroy(self->mmsServer); IsoServer_destroy(self->isoServer); MmsMapping_destroy(self->mmsMapping); LinkedList_destroyDeep(self->clientConnections, (LinkedListValueDeleteFunction) private_ClientConnection_destroy); free(self); }
void IedConnection_createDataSet(IedConnection self, IedClientError* error, char* dataSetReference, LinkedList /* <char*> */dataSetElements) { char domainIdBuffer[65]; char itemIdBuffer[129]; char* domainId; char* itemId; bool isAssociationSpecific = false; if (dataSetReference[0] != '@') { domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer); StringUtils_replace(itemId, '.', '$'); } else { itemId = dataSetReference; isAssociationSpecific = true; } MmsError mmsError; LinkedList dataSetEntries = LinkedList_create(); LinkedList dataSetElement = LinkedList_getNext(dataSetElements); while (dataSetElement != NULL) { MmsVariableAccessSpecification* dataSetEntry = MmsMapping_ObjectReferenceToVariableAccessSpec((char*) dataSetElement->data); LinkedList_add(dataSetEntries, (void*) dataSetEntry); dataSetElement = LinkedList_getNext(dataSetElement); } if (isAssociationSpecific) MmsConnection_defineNamedVariableListAssociationSpecific(self->connection, &mmsError, itemId, dataSetEntries); else MmsConnection_defineNamedVariableList(self->connection, &mmsError, domainId, itemId, dataSetEntries); /* delete list and all elements */ LinkedList_destroyDeep(dataSetEntries, (LinkedListValueDeleteFunction) MmsVariableAccessSpecification_destroy); *error = iedConnection_mapMmsErrorToIedError(mmsError); }
void MmsDomain_destroy(MmsDomain* self) { free(self->domainName); if (self->namedVariables != NULL) { freeNamedVariables(self->namedVariables, self->namedVariablesCount); free(self->namedVariables); } LinkedList_destroyDeep(self->namedVariableLists, MmsNamedVariableList_destroy); free(self); }
void MmsServerConnection_destroy(MmsServerConnection* self) { LinkedList_destroyDeep(self->namedVariableLists, MmsNamedVariableList_destroy); free(self); }
void LinkedList_destroy(LinkedList list) { LinkedList_destroyDeep(list, free); }
LinkedList /* <char*> */ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, char* dataSetReference, bool* isDeletable) { bool deletable = false; LinkedList dataSetMembers = NULL; char domainIdBuffer[65]; char itemIdBuffer[129]; char* domainId = NULL; char* itemId = NULL; bool isAssociationSpecific = false; if (dataSetReference[0] != '@') { domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer); StringUtils_replace(itemId, '.', '$'); } else { itemId = dataSetReference; isAssociationSpecific = true; } MmsError mmsError; LinkedList entries; if (isAssociationSpecific) entries = MmsConnection_readNamedVariableListDirectoryAssociationSpecific(self->connection, &mmsError, itemId, &deletable); else entries = MmsConnection_readNamedVariableListDirectory(self->connection, &mmsError, domainId, itemId, &deletable); if (mmsError == MMS_ERROR_NONE) { LinkedList entry = LinkedList_getNext(entries); dataSetMembers = LinkedList_create(); while (entry != NULL) { MmsVariableAccessSpecification* varAccessSpec = (MmsVariableAccessSpecification*) entry->data; char* objectReference = MmsMapping_varAccessSpecToObjectReference(varAccessSpec); LinkedList_add(dataSetMembers, objectReference); entry = LinkedList_getNext(entry); } if (isDeletable != NULL) *isDeletable = deletable; LinkedList_destroyDeep(entries, (LinkedListValueDeleteFunction) MmsVariableAccessSpecification_destroy); } *error = iedConnection_mapMmsErrorToIedError(mmsError); return dataSetMembers; }
static void sendReport(ReportControl* self, bool isIntegrity, bool isGI) { LinkedList reportElements = LinkedList_create(); LinkedList deletableElements = LinkedList_create(); MmsValue* rptId = ReportControl_getRCBValue(self, "RptID"); MmsValue* optFlds = ReportControl_getRCBValue(self, "OptFlds"); MmsValue* datSet = ReportControl_getRCBValue(self, "DatSet"); LinkedList_add(reportElements, rptId); LinkedList_add(reportElements, optFlds); /* delete option fields for unsupported options */ MmsValue_setBitStringBit(optFlds, 5, false); /* data-reference */ MmsValue_setBitStringBit(optFlds, 7, false); /* entryID */ MmsValue_setBitStringBit(optFlds, 9, false); /* segmentation */ MmsValue* sqNum = ReportControl_getRCBValue(self, "SqNum"); if (MmsValue_getBitStringBit(optFlds, 1)) /* sequence number */ LinkedList_add(reportElements, sqNum); if (MmsValue_getBitStringBit(optFlds, 2)) { /* report time stamp */ LinkedList_add(reportElements, self->timeOfEntry); } if (MmsValue_getBitStringBit(optFlds, 4)) /* data set reference */ LinkedList_add(reportElements, datSet); if (MmsValue_getBitStringBit(optFlds, 6)) { /* bufOvfl */ MmsValue* bufOvfl = MmsValue_newBoolean(false); LinkedList_add(reportElements, bufOvfl); LinkedList_add(deletableElements, bufOvfl); } if (MmsValue_getBitStringBit(optFlds, 8)) LinkedList_add(reportElements, self->confRev); if (isGI || isIntegrity) MmsValue_setAllBitStringBits(self->inclusionField); else MmsValue_deleteAllBitStringBits(self->inclusionField); LinkedList_add(reportElements, self->inclusionField); /* add data set value elements */ int i = 0; for (i = 0; i < self->dataSet->elementCount; i++) { if (isGI || isIntegrity) LinkedList_add(reportElements, self->dataSet->fcda[i]->value); else { if (self->inclusionFlags[i] != REPORT_CONTROL_NONE) { LinkedList_add(reportElements, self->dataSet->fcda[i]->value); MmsValue_setBitStringBit(self->inclusionField, i, true); } } } /* add reason code to report if requested */ if (MmsValue_getBitStringBit(optFlds, 3)) { for (i = 0; i < self->dataSet->elementCount; i++) { if (isGI || isIntegrity) { MmsValue* reason = MmsValue_newBitString(6); if (isGI) MmsValue_setBitStringBit(reason, 5, true); if (isIntegrity) MmsValue_setBitStringBit(reason, 4, true); LinkedList_add(reportElements, reason); LinkedList_add(deletableElements, reason); } else if (self->inclusionFlags[i] != REPORT_CONTROL_NONE) { MmsValue* reason = MmsValue_newBitString(6); switch(self->inclusionFlags[i]) { case REPORT_CONTROL_QUALITY_CHANGED: MmsValue_setBitStringBit(reason, 2, true); break; case REPORT_CONTROL_VALUE_CHANGED: MmsValue_setBitStringBit(reason, 1, true); break; case REPORT_CONTROL_VALUE_UPDATE: MmsValue_setBitStringBit(reason, 3, true); break; } LinkedList_add(reportElements, reason); LinkedList_add(deletableElements, reason); } } } /* clear inclusion flags */ for (i = 0; i < self->dataSet->elementCount; i++) { self->inclusionFlags[i] = REPORT_CONTROL_NONE; } MmsServerConnection_sendInformationReportVMDSpecific(self->clientConnection, "RPT", reportElements); /* Increase sequence number */ self->sqNum++; MmsValue_setUint16(sqNum, self->sqNum); LinkedList_destroyDeep(deletableElements, (LinkedListValueDeleteFunction) MmsValue_delete); LinkedList_destroyStatic(reportElements); /* clear GI flag */ if (isGI) { MmsValue* gi = ReportControl_getRCBValue(self, "GI"); self->gi = false; MmsValue_setBoolean(gi, false); } }
void MmsServerConnection_destroy(MmsServerConnection* self) { LinkedList_destroyDeep(self->namedVariableLists, (LinkedListValueDeleteFunction) MmsNamedVariableList_destroy); free(self); }
void IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientReportControlBlock rcb, uint32_t parametersMask, bool singleRequest) { *error = IED_ERROR_OK; MmsError mmsError = MMS_ERROR_NONE; bool isBuffered = ClientReportControlBlock_isBuffered(rcb); char domainId[65]; char itemId[129]; char* rcbReference = ClientReportControlBlock_getObjectReference(rcb); MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId); strcpy(itemId, rcbReference + strlen(domainId) + 1); StringUtils_replace(itemId, '.', '$'); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: setRCBValues for %s\n", rcbReference); int itemIdLen = strlen(itemId); /* create the list of requested itemIds references */ LinkedList itemIds = LinkedList_create(); LinkedList values = LinkedList_create(); /* add resv/resvTms as first element and rptEna as last element */ if (parametersMask & RCB_ELEMENT_RESV) { if (isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$Resv"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->resv); } if (parametersMask & RCB_ELEMENT_RESV_TMS) { if (!isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$ResvTms"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->resvTms); } if (parametersMask & RCB_ELEMENT_RPT_ID) { strcpy(itemId + itemIdLen, "$RptID"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->rptId); } if (parametersMask & RCB_ELEMENT_DATSET) { strcpy(itemId + itemIdLen, "$DatSet"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->datSet); } if (parametersMask & RCB_ELEMENT_ENTRY_ID) { strcpy(itemId + itemIdLen, "$EntryID"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->entryId); } if (parametersMask & RCB_ELEMENT_OPT_FLDS) { strcpy(itemId + itemIdLen, "$OptFlds"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->optFlds); } if (parametersMask & RCB_ELEMENT_BUF_TM) { strcpy(itemId + itemIdLen, "$BufTm"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->bufTm); } if (parametersMask & RCB_ELEMENT_TRG_OPS) { strcpy(itemId + itemIdLen, "$TrgOps"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->trgOps); } if (parametersMask & RCB_ELEMENT_INTG_PD) { strcpy(itemId + itemIdLen, "$IntgPd"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->intgPd); } if (parametersMask & RCB_ELEMENT_GI) { strcpy(itemId + itemIdLen, "$GI"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->gi); } if (parametersMask & RCB_ELEMENT_PURGE_BUF) { if (!isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$PurgeBuf"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->purgeBuf); } if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY) { if (!isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$TimeOfEntry"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->timeOfEntry); } if (parametersMask & RCB_ELEMENT_RPT_ENA) { strcpy(itemId + itemIdLen, "$RptEna"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->rptEna); } if (singleRequest) { LinkedList accessResults = NULL; MmsConnection_writeMultipleVariables(self->connection, &mmsError, domainId, itemIds, values, &accessResults); if (accessResults != NULL) LinkedList_destroyDeep(accessResults, (LinkedListValueDeleteFunction) MmsValue_delete); *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } else { LinkedList itemIdElement = LinkedList_getNext(itemIds); LinkedList valueElement = LinkedList_getNext(values); while (itemIdElement != NULL) { char* rcbItemId = (char*) itemIdElement->data; MmsValue* value = (MmsValue*) valueElement->data; MmsConnection_writeVariable(self->connection, &mmsError, domainId, rcbItemId, value); if (mmsError != MMS_ERROR_NONE) break; itemIdElement = LinkedList_getNext(itemIdElement); valueElement = LinkedList_getNext(valueElement); } *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } error_invalid_parameter: *error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT; exit_function: LinkedList_destroy(itemIds); LinkedList_destroyStatic(values); }
void IedConnection_setGoCBValues(IedConnection self, IedClientError* error, ClientGooseControlBlock goCB, uint32_t parametersMask, bool singleRequest) { *error = IED_ERROR_OK; MmsError mmsError = MMS_ERROR_NONE; char domainId[65]; char itemId[129]; MmsMapping_getMmsDomainFromObjectReference(goCB->objectReference, domainId); char* itemIdStart = goCB->objectReference + strlen(domainId) + 1; char* separator = strchr(itemIdStart, '.'); if (separator == NULL) { *error = IED_ERROR_OBJECT_REFERENCE_INVALID; return; } int separatorOffset = separator - itemIdStart; memcpy(itemId, itemIdStart, separatorOffset); itemId[separatorOffset] = '$'; itemId[separatorOffset + 1] = 'G'; itemId[separatorOffset + 2] = 'O'; itemId[separatorOffset + 3] = '$'; strcpy(itemId + separatorOffset + 4, separator + 1); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: setGoCBValues for %s\n", goCB->objectReference); int itemIdLen = strlen(itemId); /* create the list of requested itemIds references */ LinkedList itemIds = LinkedList_create(); LinkedList values = LinkedList_create(); /* add rGoEna as last element */ if (parametersMask & GOCB_ELEMENT_GO_ID) { strcpy(itemId + itemIdLen, "$GoID"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->goID); } if (parametersMask & GOCB_ELEMENT_DATSET) { strcpy(itemId + itemIdLen, "$DatSet"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->datSet); } if (parametersMask & GOCB_ELEMENT_CONF_REV) { strcpy(itemId + itemIdLen, "$ConfRev"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->confRev); } if (parametersMask & GOCB_ELEMENT_NDS_COMM) { strcpy(itemId + itemIdLen, "$NdsCom"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->ndsCom); } if (parametersMask & GOCB_ELEMENT_DST_ADDRESS) { strcpy(itemId + itemIdLen, "$DstAddress"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->dstAddress); } if (parametersMask & GOCB_ELEMENT_MIN_TIME) { strcpy(itemId + itemIdLen, "$MinTime"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->minTime); } if (parametersMask & GOCB_ELEMENT_MAX_TIME) { strcpy(itemId + itemIdLen, "$MaxTime"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->maxTime); } if (parametersMask & GOCB_ELEMENT_FIXED_OFFS) { strcpy(itemId + itemIdLen, "$FixedOffs"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->fixedOffs); } if (parametersMask & GOCB_ELEMENT_GO_ENA) { strcpy(itemId + itemIdLen, "$GoEna"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->goEna); } if (singleRequest) { LinkedList accessResults = NULL; MmsConnection_writeMultipleVariables(self->connection, &mmsError, domainId, itemIds, values, &accessResults); if (accessResults != NULL) { LinkedList element = LinkedList_getNext(accessResults); while (element != NULL) { MmsValue* accessResult = (MmsValue*) element->data; if (MmsValue_getDataAccessError(accessResult) != DATA_ACCESS_ERROR_SUCCESS) { mmsError = MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT; break; } element = LinkedList_getNext(element); } LinkedList_destroyDeep(accessResults, (LinkedListValueDeleteFunction) MmsValue_delete); } *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } else { LinkedList itemIdElement = LinkedList_getNext(itemIds); LinkedList valueElement = LinkedList_getNext(values); while (itemIdElement != NULL) { char* rcbItemId = (char*) itemIdElement->data; MmsValue* value = (MmsValue*) valueElement->data; MmsConnection_writeVariable(self->connection, &mmsError, domainId, rcbItemId, value); if (mmsError != MMS_ERROR_NONE) break; itemIdElement = LinkedList_getNext(itemIdElement); valueElement = LinkedList_getNext(valueElement); } *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } exit_function: LinkedList_destroy(itemIds); LinkedList_destroyStatic(values); }
void mmsClient_parseWriteMultipleItemsResponse(ByteBuffer* message, int32_t bufPos, MmsError* mmsError, int itemCount, LinkedList* accessResults) { uint8_t* buf = message->buffer; int size = message->size; int length; *mmsError = MMS_ERROR_NONE; uint8_t tag = buf[bufPos++]; if (tag == 0xa5) { bufPos = BerDecoder_decodeLength(buf, &length, bufPos, size); if (bufPos == -1) { *mmsError = MMS_ERROR_PARSING_RESPONSE; return; } *accessResults = LinkedList_create(); int endPos = bufPos + length; int numberOfAccessResults = 0; while (bufPos < endPos) { tag = buf[bufPos++]; bufPos = BerDecoder_decodeLength(buf, &length, bufPos, size); if (bufPos == -1) goto exit_with_error; if (tag == 0x81) { MmsValue* value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_SUCCESS); LinkedList_add(*accessResults, (void*) value); } if (tag == 0x80) { uint32_t dataAccessErrorCode = BerDecoder_decodeUint32(buf, length, bufPos); MmsValue* value = MmsValue_newDataAccessError((MmsDataAccessError) dataAccessErrorCode); LinkedList_add(*accessResults, (void*) value); } bufPos += length; numberOfAccessResults++; } if (itemCount != numberOfAccessResults) goto exit_with_error; } else *mmsError = MMS_ERROR_PARSING_RESPONSE; return; exit_with_error: *mmsError = MMS_ERROR_PARSING_RESPONSE; LinkedList_destroyDeep(*accessResults, (LinkedListValueDeleteFunction) MmsValue_delete); }