void ReportControl_destroy(ReportControl* self) { if (self->rcbValues != NULL ) MmsValue_delete(self->rcbValues); if (self->inclusionFlags != NULL) free(self->inclusionFlags); if (self->inclusionField != NULL) MmsValue_delete(self->inclusionField); if (self->bufferd == false) MmsValue_delete(self->timeOfEntry); if (self->isDynamicDataSet) { if (self->dataSet != NULL) MmsMapping_freeDynamicallyCreatedDataSet(self->dataSet); } free(self->name); free(self); }
ClientReportControlBlock IedConnection_getRCBValues(IedConnection self, IedClientError* error, char* rcbReference, ClientReportControlBlock updateRcb) { MmsError mmsError = MMS_ERROR_NONE; ClientReportControlBlock returnRcb = updateRcb; char domainId[65]; char itemId[129]; MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId); strcpy(itemId, rcbReference + strlen(domainId) + 1); StringUtils_replace(itemId, '.', '$'); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: readRCBValues for %s\n", rcbReference); MmsValue* rcb = MmsConnection_readVariable(self->connection, &mmsError, domainId, itemId); if (mmsError != MMS_ERROR_NONE) { *error = iedConnection_mapMmsErrorToIedError(mmsError); return NULL; } if (rcb == NULL) { *error = IED_ERROR_OBJECT_DOES_NOT_EXIST; return NULL; } if (MmsValue_getType(rcb) != MMS_STRUCTURE) { if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: getRCBValues returned wrong type!\n"); MmsValue_delete(rcb); *error = IED_ERROR_UNKNOWN; return NULL; } if (returnRcb == NULL) returnRcb = ClientReportControlBlock_create(rcbReference); private_ClientReportControlBlock_updateValues(returnRcb, rcb); MmsValue_delete(rcb); *error = IED_ERROR_OK; return returnRcb; }
Timestamp* IedConnection_readTimestampValue(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc, Timestamp* timeStamp) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); Timestamp* retVal = timeStamp; if (retVal == NULL) retVal = (Timestamp*) malloc(sizeof(Timestamp)); if (value != NULL) { if (MmsValue_getType(value) == MMS_UTC_TIME) { memcpy(retVal->val, value->value.utcTime, 8); } else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); } return retVal; }
void controlHandler(void* parameter, MmsValue* value, bool test) { printf("received control command %i %i: ", value->type, value->value.boolean); if (value->value.boolean) printf("on\n"); else printf("off\n"); MmsValue* timeStamp = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs()); if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO1) { IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_stVal, value); IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_t, timeStamp); } if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO2) { IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2_stVal, value); IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2_t, timeStamp); } if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO3) { IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3_stVal, value); IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3_t, timeStamp); } if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO4) { IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_stVal, value); IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO4_t, timeStamp); } MmsValue_delete(timeStamp); }
static void updateControlParameters(ControlObject* controlObject, MmsValue* ctlVal, MmsValue* ctlNum, MmsValue* origin) { if (controlObject->ctlVal != NULL) MmsValue_delete(controlObject->ctlVal); if (controlObject->ctlNum != NULL) MmsValue_delete(controlObject->ctlNum); if (controlObject->origin != NULL) MmsValue_delete(controlObject->origin); controlObject->ctlVal = MmsValue_clone(ctlVal); controlObject->ctlNum = MmsValue_clone(ctlNum); controlObject->origin = MmsValue_clone(origin); }
void ControlObject_destroy(ControlObject* self) { if (self->mmsValue != NULL) MmsValue_delete(self->mmsValue); free(self); }
static void cacheEntryDelete(MmsValueCacheEntry* entry) { if (entry != NULL) { MmsValue_delete(entry->value); free(entry); } }
static void cacheEntryDelete(MmsValueCacheEntry* entry) { if (entry != NULL) { MmsValue_delete(entry->value); GLOBAL_FREEMEM(entry); } }
void ClientDataSet_destroy(ClientDataSet self) { if (self->dataSetValues != NULL) MmsValue_delete(self->dataSetValues); free(self->dataSetReference); free(self); }
static void deleteValueList(LinkedList values) { LinkedList value = values; MmsValue* typedValue; while ((value = LinkedList_getNext(value)) != NULL ) { typedValue = (MmsValue*) (value->data); if (typedValue->deleteValue == 1) { MmsValue_delete(typedValue); } } LinkedList_destroyStatic(values); }
static MmsValue* addNamedVariableValue(MmsVariableSpecification* namedVariable, MmsServerConnection connection, MmsDomain* domain, char* itemId) { MmsValue* value = NULL; if (namedVariable->type == MMS_STRUCTURE) { value = mmsServer_getValue(connection->server, domain, itemId, connection); if (value != NULL) goto exit_function; else { int componentCount = namedVariable->typeSpec.structure.elementCount; value = MmsValue_createEmptyStructure(componentCount); value->deleteValue = 1; int i; for (i = 0; i < componentCount; i++) { char newNameIdStr[65]; StringUtils_createStringInBuffer(newNameIdStr, 3, itemId, "$", namedVariable->typeSpec.structure.elements[i]->name); MmsValue* element = addNamedVariableValue(namedVariable->typeSpec.structure.elements[i], connection, domain, newNameIdStr); if (element == NULL) { MmsValue_delete(value); value = NULL; break; } MmsValue_setElement(value, i, element); } } } else { value = mmsServer_getValue(connection->server, domain, itemId, connection); } exit_function: return value; }
int main(int argc, char** argv) { char* hostname; char* variable; int tcpPort = 102; // char varname; //variable for searching with just the name variable = argv[1]; if (argc > 2) hostname = argv[2]; else hostname = "localhost"; if (argc > 3) tcpPort = atoi(argv[3]); // if (argc > 4) // varname = atoi(argv[4]); // varname is the 4th command given when client is run MmsConnection con = MmsConnection_create(); MmsError error; if (!MmsConnection_connect(con, &error, hostname, tcpPort)) { printf("MMS connect failed!\n"); goto exit; } else printf("MMS connected.\n\n"); //MmsValue* value = MmsConnection_readVariable(con, &error, "simpleIOGenericIO", variable); MmsValue* value = IedConnection_readObject(con, &error, "SampleIEDDevice1/MMXN1.Vol.mag.f"); if (value == NULL) printf("reading value failed!\n"); else { float fval = MmsValue_toFloat(value); printf("read float value: %f\n", fval); MmsValue_delete(value); } exit: MmsConnection_destroy(con); }
void ControlObjectClient_destroy(ControlObjectClient self) { if (self != NULL) { GLOBAL_FREEMEM(self->objectReference); private_IedConnection_removeControlClient(self->connection, self); if (self->ctlVal != NULL) MmsValue_delete(self->ctlVal); if (self->orIdent != NULL) GLOBAL_FREEMEM(self->orIdent); GLOBAL_FREEMEM(self); } }
static void informationReportHandler(void* parameter, char* domainName, char* variableListName, MmsValue* value, bool isVariableListName) { IedConnection self = (IedConnection) parameter; if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: received information report for %s\n", variableListName); if (domainName == NULL) { if (isVariableListName) { private_IedConnection_handleReport(self, value); } else { if (strcmp(variableListName, "LastApplError") == 0) handleLastApplErrorMessage(self, value); else { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: Received unknown variable list report for list: %s\n", variableListName); } } } else { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: RCVD CommandTermination for %s/%s\n", domainName, variableListName); LinkedList control = LinkedList_getNext(self->clientControls); while (control != NULL) { ControlObjectClient object = (ControlObjectClient) control->data; char* objectRef = ControlObjectClient_getObjectReference(object); if (doesReportMatchControlObject(domainName, variableListName, objectRef)) private_ControlObjectClient_invokeCommandTerminationHandler(object); control = LinkedList_getNext(control); } } MmsValue_delete(value); }
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; 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; }
void ControlObject_destroy(ControlObject* self) { if (self->mmsValue != NULL) MmsValue_delete(self->mmsValue); if (self->sbo != NULL) MmsValue_delete(self->sbo); if (self->emptyString != NULL) MmsValue_delete(self->emptyString); if (self->ctlObjectName != NULL) GLOBAL_FREEMEM(self->ctlObjectName); if (self->error != NULL) MmsValue_delete(self->error); if (self->addCause != NULL) MmsValue_delete(self->addCause); if (self->ctlVal != NULL) MmsValue_delete(self->ctlVal); if (self->ctlNum != NULL) MmsValue_delete(self->ctlNum); if (self->origin != NULL) MmsValue_delete(self->origin); if (self->name != NULL) GLOBAL_FREEMEM(self->name); #if (CONFIG_MMS_THREADLESS_STACK != 1) if (self->stateLock != NULL) Semaphore_destroy(self->stateLock); #endif GLOBAL_FREEMEM(self); }
static void installDefaultValuesForDataAttribute(IedServer self, DataAttribute* dataAttribute, char* objectReference, int position) { sprintf(objectReference + position, ".%s", dataAttribute->name); char mmsVariableName[65]; /* maximum size is 64 according to 61850-8-1 */ MmsValue* value = dataAttribute->mmsValue; MmsMapping_createMmsVariableNameFromObjectReference(objectReference, dataAttribute->fc, mmsVariableName); char domainName[65]; MmsMapping_getMmsDomainFromObjectReference(objectReference, domainName); MmsDomain* domain = MmsDevice_getDomain(self->mmsDevice, domainName); if (domain == NULL) { if (DEBUG_IED_SERVER) printf("Error domain (%s) not found!\n", domainName); return; } MmsValue* cacheValue = MmsServer_getValueFromCache(self->mmsServer, domain, mmsVariableName); dataAttribute->mmsValue = cacheValue; if (value != NULL) { MmsValue_update(cacheValue, value); MmsValue_delete(value); } int childPosition = strlen(objectReference); DataAttribute* subDataAttribute = (DataAttribute*) dataAttribute->firstChild; while (subDataAttribute != NULL) { installDefaultValuesForDataAttribute(self, subDataAttribute, objectReference, childPosition); subDataAttribute = (DataAttribute*) subDataAttribute->sibling; } }
Quality IedConnection_readQualityValue(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); Quality quality = QUALITY_VALIDITY_GOOD; if ((MmsValue_getType(value) == MMS_BIT_STRING) && (MmsValue_getBitStringSize(value) == 13)) { quality = Quality_fromMmsValue(value); } else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); return quality; }
char* IedConnection_readStringValue(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); char* retVal = NULL; if (value != NULL) { if ((MmsValue_getType(value) == MMS_VISIBLE_STRING) || (MmsValue_getType(value) == MMS_STRING)) retVal = copyString(MmsValue_toString(value)); else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); } return retVal; }
float IedConnection_readFloatValue(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); float retVal = 0.f; if (value != NULL) { if (MmsValue_getType(value) == MMS_FLOAT) retVal = MmsValue_toFloat(value); else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); } return retVal; }
bool IedConnection_readBooleanValue(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); bool retVal = false; if (value != NULL) { if (MmsValue_getType(value) == MMS_BOOLEAN) retVal = MmsValue_getBoolean(value); else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); } return retVal; }
uint32_t IedConnection_readUnsigned32Value(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); uint32_t retVal = 0.f; if (value != NULL) { if ((MmsValue_getType(value) == MMS_INTEGER) || (MmsValue_getType(value) == MMS_UNSIGNED)) retVal = MmsValue_toUint32(value); else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); } return retVal; }
static void alternateArrayAccess(MmsServerConnection* connection, AlternateAccess_t* alternateAccess, MmsDomain* domain, char* itemId, LinkedList values, MmsTypeSpecification* namedVariable) { if (mmsServer_isIndexAccess(alternateAccess)) { int lowIndex = mmsServer_getLowIndex(alternateAccess); int numberOfElements = mmsServer_getNumberOfElements(alternateAccess); if (DEBUG) printf("Alternate access index: %i elements %i\n", lowIndex, numberOfElements); int index = lowIndex; MmsValue* value = NULL; MmsValue* arrayValue = mmsServer_getValue(connection->server, domain, itemId); if (arrayValue != NULL) { if (numberOfElements == 0) if (isAccessToArrayComponent(alternateAccess)) { if (namedVariable->typeSpec.array.elementTypeSpec->type == MMS_STRUCTURE) { MmsValue* structValue = MmsValue_getElement(arrayValue, index); if (structValue != NULL) value = getComponentOfArrayElement(alternateAccess, namedVariable, structValue); } } else value = MmsValue_getElement(arrayValue, index); else { value = MmsValue_createEmtpyArray(numberOfElements); MmsValue_setDeletable(value); int resultIndex = 0; while (index < lowIndex + numberOfElements) { MmsValue* elementValue = NULL; elementValue = MmsValue_getElement(arrayValue, index); if (!MmsValue_isDeletable(elementValue)) elementValue = MmsValue_clone(elementValue); MmsValue_setElement(value, resultIndex, elementValue); index++; resultIndex++; } } appendValueToResultList(value, values); if (MmsValue_isDeletable(arrayValue)) MmsValue_delete(arrayValue); } else /* access error */ appendErrorToResultList(values, 10 /* object-non-existant*/); } else { // invalid access if (DEBUG) printf("Invalid alternate access\n"); appendErrorToResultList(values, 10 /* object-non-existant*/); } }
bool ControlObjectClient_cancel(ControlObjectClient self) { resetLastApplError(self); MmsValue* cancelParameters; if (self->hasTimeActivatedMode) cancelParameters = MmsValue_createEmptyStructure(6); else cancelParameters = MmsValue_createEmptyStructure(5); MmsValue_setElement(cancelParameters, 0, self->ctlVal); int index = 1; if (self->hasTimeActivatedMode) { MmsValue* operTm = MmsValue_newUtcTimeByMsTime(self->opertime); MmsValue_setElement(cancelParameters, index++, operTm); } MmsValue* origin = createOriginValue(self); MmsValue_setElement(cancelParameters, index++, origin); MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum); MmsValue_setElement(cancelParameters, index++, ctlNum); uint64_t timestamp = Hal_getTimeInMs(); MmsValue* ctlTime; if (self->edition == 2) ctlTime = MmsValue_newUtcTimeByMsTime(timestamp); else { ctlTime = MmsValue_newBinaryTime(false); MmsValue_setBinaryTime(ctlTime, timestamp); } MmsValue_setElement(cancelParameters, index++, ctlTime); MmsValue* ctlTest = MmsValue_newBoolean(self->test); MmsValue_setElement(cancelParameters, index++, ctlTest); char domainId[65]; char itemId[65]; MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); strncat(itemId, "$Cancel", 64); if (DEBUG_IED_CLIENT) printf("IED_CLIENT: cancel: %s/%s\n", domainId, itemId); MmsError mmsError; MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId, cancelParameters); MmsValue_setElement(cancelParameters, 0, NULL); MmsValue_delete(cancelParameters); if (mmsError != MMS_ERROR_NONE) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: cancel failed!\n"); return false; } return true; }
void mmsServer_handleWriteRequest( MmsServerConnection* connection, uint8_t* buffer, int bufPos, int maxBufPos, uint32_t invokeId, ByteBuffer* response) { WriteRequest_t* writeRequest = 0; MmsPdu_t* mmsPdu = 0; asn_dec_rval_t rval; /* Decoder return value */ rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, CONFIG_MMS_MAXIMUM_PDU_SIZE); if (rval.code != RC_OK) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; } writeRequest = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write); int numberOfWriteItems = writeRequest->variableAccessSpecification.choice.listOfVariable.list.count; if (numberOfWriteItems < 1) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); return; } if (numberOfWriteItems > CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_OTHER, response); return; } if (writeRequest->listOfData.list.count != numberOfWriteItems) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); return; } MmsDataAccessError accessResults[CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS * sizeof(MmsDataAccessError)]; bool sendResponse = true; int i; for (i = 0; i < numberOfWriteItems; i++) { ListOfVariableSeq_t* varSpec = writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[i]; if (varSpec->variableSpecification.present != VariableSpecification_PR_name) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } if (varSpec->variableSpecification.choice.name.present != ObjectName_PR_domainspecific) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } Identifier_t domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId; char* domainIdStr = createStringFromBuffer(domainId.buf, domainId.size); MmsDevice* device = MmsServer_getDevice(connection->server); MmsDomain* domain = MmsDevice_getDomain(device, domainIdStr); free(domainIdStr); if (domain == NULL) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; continue; } Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId; char* nameIdStr = createStringFromBuffer(nameId.buf, nameId.size); MmsVariableSpecification* variable = MmsDomain_getNamedVariable(domain, nameIdStr); if (variable == NULL) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; continue; } AlternateAccess_t* alternateAccess = varSpec->alternateAccess; if (alternateAccess != NULL) { if (variable->type != MMS_ARRAY) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (!mmsServer_isIndexAccess(alternateAccess)) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } } Data_t* dataElement = writeRequest->listOfData.list.array[i]; MmsValue* value = mmsMsg_parseDataElement(dataElement); if (value == NULL) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (alternateAccess != NULL) { MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr); if (cachedArray == NULL) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } int index = mmsServer_getLowIndex(alternateAccess); MmsValue* elementValue = MmsValue_getElement(cachedArray, index); if (elementValue == NULL) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (MmsValue_update(elementValue, value) == false) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT; continue; } free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_SUCCESS; continue; } MmsDataAccessError valueIndication = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection); if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE) sendResponse = false; accessResults[i] = valueIndication; MmsValue_delete(value); free(nameIdStr); } if (sendResponse) { mmsServer_createMmsWriteResponse(connection, invokeId, response, numberOfWriteItems, accessResults); } asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); }
bool ControlObjectClient_select(ControlObjectClient self) { resetLastApplError(self); char domainId[65]; char itemId[65]; MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); strncat(itemId, "$SBO", 64); if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select: %s/%s\n", domainId, itemId); MmsError mmsError; MmsValue* value = MmsConnection_readVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId); bool selected = false; self->ctlNum++; if (value == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select: read SBO failed!\n"); goto exit_function; } char sboReference[130]; snprintf(sboReference, 129, "%s/%s", domainId, itemId); if (MmsValue_getType(value) == MMS_VISIBLE_STRING) { if (strcmp(MmsValue_toString(value), "") == 0) { if (DEBUG_IED_CLIENT) printf("select-response-\n"); } else if (strcmp(MmsValue_toString(value), sboReference)) { if (DEBUG_IED_CLIENT) printf("select-response+: (%s)\n", MmsValue_toString(value)); selected = true; } else { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select-response: (%s)\n", MmsValue_toString(value)); } } else { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select: unexpected response from server!\n"); } MmsValue_delete(value); exit_function: return selected; }
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; if (self->hasTimeActivatedMode) operParameters = MmsValue_createEmptyStructure(7); else operParameters = MmsValue_createEmptyStructure(6); MmsValue_setElement(operParameters, 0, ctlVal); int index = 1; if (self->hasTimeActivatedMode) { MmsValue* operTm = MmsValue_newUtcTimeByMsTime(operTime); MmsValue_setElement(operParameters, index++, operTm); } MmsValue* origin = createOriginValue(self); MmsValue_setElement(operParameters, index++, origin); if (!((self->ctlModel == CONTROL_MODEL_SBO_NORMAL) || (self->ctlModel == CONTROL_MODEL_SBO_ENHANCED))) { self->ctlNum++; } MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum); MmsValue_setElement(operParameters, index++, ctlNum); uint64_t timestamp = Hal_getTimeInMs(); MmsValue* ctlTime; if (self->edition == 2) ctlTime = MmsValue_newUtcTimeByMsTime(timestamp); else { ctlTime = MmsValue_newBinaryTime(false); MmsValue_setBinaryTime(ctlTime, timestamp); } MmsValue_setElement(operParameters, index++, ctlTime); MmsValue* ctlTest = MmsValue_newBoolean(self->test); MmsValue_setElement(operParameters, index++, ctlTest); MmsValue* check = MmsValue_newBitString(2); MmsValue_setBitStringBit(check, 1, self->interlockCheck); MmsValue_setBitStringBit(check, 0, self->synchroCheck); MmsValue_setElement(operParameters, index++, check); char domainId[65]; char itemId[65]; MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); int controlObjectItemIdLen = strlen(itemId); strncat(itemId, "$Oper", 64 - controlObjectItemIdLen); if (DEBUG_IED_CLIENT) printf("IED_CLIENT: operate: %s/%s\n", domainId, itemId); MmsError mmsError; MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId, operParameters); MmsValue_setElement(operParameters, 0, NULL); MmsValue_delete(operParameters); if (mmsError != MMS_ERROR_NONE) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: operate failed!\n"); goto exit_function; } MmsValue_update(self->ctlVal, ctlVal); self->opertime = operTime; success = true; exit_function: return success; }
static MmsValue* parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLength, bool isStructure) { int bufPos = 0; int elementLength = 0; int elementIndex = 0; MmsValue* dataSetValues = NULL; while (bufPos < allDataLength) { uint8_t tag = buffer[bufPos++]; bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); if (bufPos + elementLength > allDataLength) { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); goto exit_with_error; } switch (tag) { case 0x80: /* reserved for access result */ break; case 0xa1: /* array */ break; case 0xa2: /* structure */ break; case 0x83: /* boolean */ break; case 0x84: /* BIT STRING */ break; case 0x85: /* integer */ break; case 0x86: /* unsigned integer */ break; case 0x87: /* Float */ break; case 0x89: /* octet string */ break; case 0x8a: /* visible string */ break; case 0x8c: /* binary time */ break; case 0x91: /* Utctime */ break; default: if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found unknown tag %02x\n", tag); goto exit_with_error; } bufPos += elementLength; elementIndex++; } if (isStructure) dataSetValues = MmsValue_createEmptyStructure(elementIndex); else dataSetValues = MmsValue_createEmptyArray(elementIndex); elementIndex = 0; bufPos = 0; while (bufPos < allDataLength) { uint8_t tag = buffer[bufPos++]; bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); if (bufPos + elementLength > allDataLength) { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); goto exit_with_error; } MmsValue* value = NULL; switch (tag) { case 0xa1: /* array */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found array\n"); value = parseAllDataUnknownValue(self, buffer + bufPos, elementLength, false); if (value == NULL) goto exit_with_error; break; case 0xa2: /* structure */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found structure\n"); value = parseAllDataUnknownValue(self, buffer + bufPos, elementLength, true); if (value == NULL) goto exit_with_error; break; case 0x83: /* boolean */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found boolean\n"); value = MmsValue_newBoolean(BerDecoder_decodeBoolean(buffer, bufPos)); break; case 0x84: /* BIT STRING */ { int padding = buffer[bufPos]; int bitStringLength = (8 * (elementLength - 1)) - padding; value = MmsValue_newBitString(bitStringLength); memcpy(value->value.bitString.buf, buffer + bufPos + 1, elementLength - 1); } break; case 0x85: /* integer */ value = MmsValue_newInteger(elementLength * 8); memcpy(value->value.integer->octets, buffer + bufPos, elementLength); value->value.integer->size = elementLength; break; case 0x86: /* unsigned integer */ value = MmsValue_newUnsigned(elementLength * 8); memcpy(value->value.integer->octets, buffer + bufPos, elementLength); value->value.integer->size = elementLength; break; case 0x87: /* Float */ if (elementLength == 9) value = MmsValue_newDouble(BerDecoder_decodeDouble(buffer, bufPos)); else if (elementLength == 5) value = MmsValue_newFloat(BerDecoder_decodeFloat(buffer, bufPos)); break; case 0x89: /* octet string */ value = MmsValue_newOctetString(elementLength, elementLength); memcpy(value->value.octetString.buf, buffer + bufPos, elementLength); break; case 0x8a: /* visible string */ value = MmsValue_newVisibleStringFromByteArray(buffer + bufPos, elementLength); break; case 0x8c: /* binary time */ if (elementLength == 4) value = MmsValue_newBinaryTime(true); else if (elementLength == 6) value = MmsValue_newBinaryTime(false); if ((elementLength == 4) || (elementLength == 6)) memcpy(value->value.binaryTime.buf, buffer + bufPos, elementLength); break; case 0x91: /* Utctime */ if (elementLength == 8) { value = MmsValue_newUtcTime(0); MmsValue_setUtcTimeByBuffer(value, buffer + bufPos); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: UTCTime element is of wrong size!\n"); break; default: if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found unkown tag %02x\n", tag); goto exit_with_error; } bufPos += elementLength; if (value != NULL) { MmsValue_setElement(dataSetValues, elementIndex, value); elementIndex++; } } self->dataSetValuesSelfAllocated = true; return dataSetValues; exit_with_error: if (dataSetValues != NULL) MmsValue_delete(dataSetValues); return NULL; }
/********************************************************************************************** * mmsServer_handleWriteRequest * возвращает MmsServiceError *********************************************************************************************/ int mmsServer_handleWriteRequest( MmsServerConnection* connection, WriteRequest_t* writeRequest, int invokeId, ByteBuffer* response) { ListOfVariableSeq_t* varSpec; Identifier_t domainId; char* domainIdStr; MmsDevice* device; MmsDomain* domain; Identifier_t nameId; char* nameIdStr; MmsTypeSpecification* variable; AlternateAccess_t* alternateAccess; Data_t* dataElement; MmsValue* value; MmsValueIndication valueIndication; if (writeRequest->variableAccessSpecification.choice.listOfVariable.list.count != 1) return -1; varSpec = writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[0]; if (varSpec->variableSpecification.present != VariableSpecification_PR_name) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } if (varSpec->variableSpecification.choice.name.present != ObjectName_PR_domainspecific) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId; domainIdStr = createStringFromBuffer(domainId.buf, domainId.size); device = MmsServer_getDevice(connection->server); domain = MmsDevice_getDomain(device, domainIdStr); free(domainIdStr); if (domain == NULL) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId; nameIdStr = createStringFromBuffer(nameId.buf, nameId.size); variable = MmsDomain_getNamedVariable(domain, nameIdStr); if (variable == NULL) goto return_access_denied; if (writeRequest->listOfData.list.count != 1) goto return_access_denied; alternateAccess = varSpec->alternateAccess; if (alternateAccess != NULL) { if (variable->type != MMS_ARRAY) goto return_access_denied; if (!mmsServer_isIndexAccess(alternateAccess)) goto return_access_denied; } dataElement = writeRequest->listOfData.list.array[0]; value = mmsMsg_parseDataElement(dataElement); if (value == NULL) goto return_access_denied; if (alternateAccess != NULL) { MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr); int index; MmsValue* elementValue; if (cachedArray == NULL) { MmsValue_delete(value); goto return_access_denied; } index = mmsServer_getLowIndex(alternateAccess); elementValue = MmsValue_getElement(cachedArray, index); if (elementValue == NULL) { MmsValue_delete(value); goto return_access_denied; } if (MmsValue_update(elementValue, value) == false) { MmsValue_delete(value); goto return_access_denied; } } MmsServer_lockModel(connection->server); valueIndication = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection); MmsServer_unlockModel(connection->server); createMmsWriteResponse(connection, invokeId, response, valueIndication); MmsValue_delete(value); free(nameIdStr); return 0; return_access_denied: createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); free(nameIdStr); return 0; }
ControlObjectClient ControlObjectClient_create(const char* objectReference, IedConnection connection) { ControlObjectClient self = NULL; /* request control model from server */ char domainId[65]; char itemId[65]; char* domainName = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainId); if (domainName == NULL) goto exit_function; convertToMmsAndInsertFC(itemId, objectReference + strlen(domainId) + 1, "CF"); int controlObjectItemIdLen = strlen(itemId); strncat(itemId, "$ctlModel", 64 - controlObjectItemIdLen); MmsError mmsError; MmsValue* ctlModel = MmsConnection_readVariable(IedConnection_getMmsConnection(connection), &mmsError, domainId, itemId); if (ctlModel == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: ControlObjectClient_create: failed to get ctlModel from server\n"); goto exit_function; } int ctlModelVal = MmsValue_toUint32(ctlModel); MmsValue_delete(ctlModel); IedClientError error; LinkedList dataDirectory = IedConnection_getDataDirectory(connection, &error, objectReference); if (dataDirectory == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: ControlObjectClient_create: failed to get data directory of control object\n"); goto exit_function; } /* check what control elements are available */ bool hasOper = false; LinkedList element = LinkedList_getNext(dataDirectory); while (element != NULL) { char* objectName = (char*) element->data; if (strcmp(objectName, "Oper") == 0) hasOper = true; element = LinkedList_getNext(element); } LinkedList_destroy(dataDirectory); if (hasOper == false) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: control is missing required element \"Oper\"\n"); goto exit_function; } /* check for time activated control */ bool hasTimeActivatedControl = false; strcpy(itemId, objectReference); strcat(itemId, ".Oper"); dataDirectory = IedConnection_getDataDirectory(connection, &error, itemId); if (dataDirectory == NULL) goto exit_function; element = LinkedList_getNext(dataDirectory); while (element != NULL) { char* objectName = (char*) element->data; if (strcmp(objectName, "operTm") == 0) { hasTimeActivatedControl = true; break; } element = LinkedList_getNext(element); } LinkedList_destroy(dataDirectory); /* get default parameters for Oper control variable */ MmsValue* oper = IedConnection_readObject(connection, &error, itemId, IEC61850_FC_CO); if (oper == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: reading \"Oper\" failed!\n"); goto exit_function; } self = (ControlObjectClient) GLOBAL_CALLOC(1, sizeof(struct sControlObjectClient)); if (self == NULL) goto exit_function; self->objectReference = copyString(objectReference); self->connection = connection; self->ctlModel = (ControlModel) ctlModelVal; self->hasTimeActivatedMode = hasTimeActivatedControl; self->ctlVal = MmsValue_getElement(oper, 0); /* Check for T element type (EntryTime -> Ed.1, Timestamp -> Ed.2) */ MmsValue* t; if (hasTimeActivatedControl) t = MmsValue_getElement(oper, 4); else t = MmsValue_getElement(oper, 3); if (MmsValue_getType(t) == MMS_BINARY_TIME) self->edition = 1; else self->edition = 2; if (DEBUG_IED_CLIENT) printf("IED_CLIENT: Detected edition %i control\n", self->edition); MmsValue_setElement(oper, 0, NULL); MmsValue_delete(oper); private_IedConnection_addControlClient(connection, self); exit_function: return self; }