From 6d03f18748600f7298f2927f6484f1a9e9fd4682 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Mon, 2 May 2016 17:46:57 +0200 Subject: [PATCH] - started to implement MMS journals server side --- config/stack_config.h | 3 ++ examples/mms_utility/mms_utility.c | 3 ++ src/iec61850/inc_private/logging.h | 46 ++++++++++++++++++ src/iec61850/server/impl/ied_server.c | 14 +++++- src/iec61850/server/mms_mapping/logging.c | 47 +++++++++++++++++++ src/iec61850/server/mms_mapping/reporting.c | 2 +- src/mms/inc/mms_client_connection.h | 4 ++ src/mms/inc/mms_device_model.h | 19 +++++++- src/mms/inc_private/mms_client_internal.h | 3 ++ .../iso_mms/client/mms_client_connection.c | 28 +++++++++++ src/mms/iso_mms/client/mms_client_files.c | 45 ++++++++++++++++++ src/mms/iso_mms/server/mms_domain.c | 14 ++++++ src/mms/iso_mms/server/mms_journal.c | 41 ++++++++++++++++ 13 files changed, 265 insertions(+), 4 deletions(-) create mode 100644 src/iec61850/inc_private/logging.h create mode 100644 src/iec61850/server/mms_mapping/logging.c create mode 100644 src/mms/iso_mms/server/mms_journal.c diff --git a/config/stack_config.h b/config/stack_config.h index 3e900e11..a1a9170f 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -153,6 +153,9 @@ /* default reservation time of a setting group control block in s */ #define CONFIG_IEC61850_SG_RESVTMS 300 +/* include support for IEC 61850 log services */ +#define CONFIG_IEC61850_LOG_SERVICE 1 + /* default results for MMS identify service */ #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" #define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c index 792833be..b56ea13b 100644 --- a/examples/mms_utility/mms_utility.c +++ b/examples/mms_utility/mms_utility.c @@ -168,6 +168,9 @@ int main(int argc, char** argv) { char* name = (char*) element->data; printf(" %s\n", name); + + printf(" read journal...\n"); + MmsConnection_readJournal(con, &error, domainName, name); } } } diff --git a/src/iec61850/inc_private/logging.h b/src/iec61850/inc_private/logging.h new file mode 100644 index 00000000..33de8a89 --- /dev/null +++ b/src/iec61850/inc_private/logging.h @@ -0,0 +1,46 @@ +/* + * logging.h + * + * Copyright 2016 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + + +#ifndef LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_ +#define LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_ + +typedef struct { + char* name; + + DataSet* dataSet; + + bool enabled; + + int triggerOps; + +} LogControl; + +LogControl* +LogControl_create(bool buffered, LogicalNode* parentLN); + +void +LogControl_destroy(LogControl* self); + + +#endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_ */ diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index f18bebd8..e212db2d 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -773,12 +773,22 @@ IedServer_getStringAttributeValue(IedServer self, const DataAttribute* dataAttri static inline void checkForUpdateTrigger(IedServer self, DataAttribute* dataAttribute) { -#if (CONFIG_IEC61850_REPORT_SERVICE== 1) +#if ((CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_IEC61850_LOG_SERVICE == 1)) if (dataAttribute->triggerOptions & TRG_OPT_DATA_UPDATE) { + +#if (CONFIG_IEC61850_REPORT_SERVICE == 1) MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, REPORT_CONTROL_VALUE_UPDATE); - } #endif + +#if (CONFIG_IEC61850_LOG_SERVICE == 1) + //MmsMapping_triggerLogObserver(self->mmsMapping, dataAttribute->mmsValue,...) + +#endif + + + } +#endif /* ((CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_IEC61850_LOG_SERVICE == 1)) */ } static inline void diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c new file mode 100644 index 00000000..a7fddee5 --- /dev/null +++ b/src/iec61850/server/mms_mapping/logging.c @@ -0,0 +1,47 @@ +/* + * logging.c + * + * Copyright 2016 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + +#include "libiec61850_platform_includes.h" +#include "stack_config.h" +#include "logging.h" + + +LogControl* +LogControl_create(bool buffered, LogicalNode* parentLN) +{ + LogControl* self = (LogControl*) GLOBAL_MALLOC(sizeof(LogControl)); + + self->enabled = false; + self->dataSet = NULL; + self->triggerOps = 0; + + return self; +} + +void +LogControl_destroy(LogControl* self) +{ + if (self != NULL) { + GLOBAL_FREEMEM(self); + } +} diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index b0e052dc..03d29fd3 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -31,7 +31,7 @@ #include "simple_allocator.h" #include "mem_alloc_linked_list.h" -#include "reporting.h" +#include "stack_config.h" #include "mms_mapping_internal.h" #include "mms_value_internal.h" #include "conversions.h" diff --git a/src/mms/inc/mms_client_connection.h b/src/mms/inc/mms_client_connection.h index 85794d2a..9b895e65 100644 --- a/src/mms/inc/mms_client_connection.h +++ b/src/mms/inc/mms_client_connection.h @@ -711,6 +711,10 @@ MmsConnection_getFileDirectory(MmsConnection self, MmsError* mmsError, const cha MmsFileDirectoryHandler handler, void* handlerParameter); +LinkedList +MmsConnection_readJournal(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId); + + /** * \brief Destroy (free) an MmsServerIdentity object * diff --git a/src/mms/inc/mms_device_model.h b/src/mms/inc/mms_device_model.h index 218bdeff..6bed93ee 100644 --- a/src/mms/inc/mms_device_model.h +++ b/src/mms/inc/mms_device_model.h @@ -49,14 +49,22 @@ typedef struct { MmsDomain** domains; } MmsDevice; + +struct sMmsJournal { + char* name; +}; + +typedef struct sMmsJournal* MmsJournal; + /* - * Server side data structure to hold informations for a MMS domain (Logical Device) + * Server side data structure to hold information of an MMS domain (Logical Device) */ struct sMmsDomain { char* domainName; int namedVariablesCount; MmsVariableSpecification** namedVariables; LinkedList /**/ namedVariableLists; + LinkedList /* */ journals; }; /** @@ -80,6 +88,9 @@ MmsDomain_create(char* domainName); char* MmsDomain_getName(MmsDomain* self); +void +MmsDomain_addJournal(MmsDomain* self, MmsJournal journal); + /** * Delete a MmsDomain instance * @@ -185,6 +196,12 @@ MmsDevice_getNamedVariableLists(MmsDevice* self); MmsNamedVariableList MmsDevice_getNamedVariableListWithName(MmsDevice* self, const char* variableListName); +MmsJournal +MmsJournal_create(const char* name); + +void +MmsJournal_destroy(MmsJournal self); + /**@}*/ #ifdef __cplusplus diff --git a/src/mms/inc_private/mms_client_internal.h b/src/mms/inc_private/mms_client_internal.h index b31891b0..95f4a8b8 100644 --- a/src/mms/inc_private/mms_client_internal.h +++ b/src/mms/inc_private/mms_client_internal.h @@ -260,4 +260,7 @@ int mmsClient_createMmsGetNameListRequestAssociationSpecific(long invokeId, ByteBuffer* writeBuffer, const char* continueAfter); +void +mmsClient_createReadJournalRequest(uint32_t invokeId, ByteBuffer* request, const char* domainId, const char* itemId); + #endif /* MMS_MSG_INTERNAL_H_ */ diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index f76e28ff..dd4dbff7 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -1637,6 +1637,34 @@ MmsConnection_getServerStatus(MmsConnection self, MmsError* mmsError, int* vmdLo } +LinkedList +MmsConnection_readJournal(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId) +{ + ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient); + + *mmsError = MMS_ERROR_NONE; + + uint32_t invokeId = getNextInvokeId(self); + + mmsClient_createReadJournalRequest(invokeId, payload, domainId, itemId); + + ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload); + + if (self->lastResponseError != MMS_ERROR_NONE) + *mmsError = self->lastResponseError; + else if (responseMessage != NULL) { + // if (mmsClient_parseFileOpenResponse(self, &frsmId, fileSize, lastModified) == false) + // *mmsError = MMS_ERROR_PARSING_RESPONSE; + } + + releaseResponse(self); + + if (self->associationState == MMS_STATE_CLOSED) + *mmsError = MMS_ERROR_CONNECTION_LOST; + + return NULL; +} + int32_t MmsConnection_fileOpen(MmsConnection self, MmsError* mmsError, const char* filename, uint32_t initialPosition, uint32_t* fileSize, uint64_t* lastModified) diff --git a/src/mms/iso_mms/client/mms_client_files.c b/src/mms/iso_mms/client/mms_client_files.c index 81b18bb2..2ecf29a1 100644 --- a/src/mms/iso_mms/client/mms_client_files.c +++ b/src/mms/iso_mms/client/mms_client_files.c @@ -32,6 +32,51 @@ #include "ber_decode.h" #include "conversions.h" +void +mmsClient_createReadJournalRequest(uint32_t invokeId, ByteBuffer* request, const char* domainId, const char* itemId) +{ + /* calculate sizes */ + uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId); + + uint32_t domainIdStringSize = strlen(domainId); + uint32_t domainIdSize = 1 + BerEncoder_determineLengthSize(domainIdStringSize) + domainIdStringSize; + + uint32_t itemIdStringSize = strlen(itemId); + uint32_t itemIdSize = 1 + BerEncoder_determineLengthSize(itemIdStringSize) + itemIdStringSize; + + uint32_t objectIdSize = domainIdSize + itemIdSize; + + uint32_t journalNameSize = 1 + BerEncoder_determineLengthSize(objectIdSize) + (objectIdSize); + + uint32_t journalReadSize = 1 + BerEncoder_determineLengthSize(journalNameSize) + (journalNameSize); + + uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize + journalReadSize; + + /* encode to buffer */ + int bufPos = 0; + uint8_t* buffer = request->buffer; + + bufPos = BerEncoder_encodeTL(0xa0, confirmedRequestPduSize, buffer, bufPos); + bufPos = BerEncoder_encodeTL(0x02, invokeIdSize, buffer, bufPos); + bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos); + + /* Encode FileOpen tag (context | structured ) [65 = 41h] */ + buffer[bufPos++] = 0xbf; + buffer[bufPos++] = 0x41; + + bufPos = BerEncoder_encodeLength(journalReadSize, buffer, bufPos); + bufPos = BerEncoder_encodeTL(0xa0, journalNameSize, buffer, bufPos); + + bufPos = BerEncoder_encodeTL(0xa1, objectIdSize, buffer, bufPos); + +// bufPos = BerEncoder_encodeTL(0xa1, domainIdStringSize, buffer, bufPos); + + bufPos = BerEncoder_encodeOctetString(0x1a, (uint8_t*) domainId, domainIdStringSize, buffer, bufPos); + bufPos = BerEncoder_encodeOctetString(0x1a, (uint8_t*) itemId, itemIdStringSize, buffer, bufPos); + + request->size = bufPos; +} + void mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const char* fileName, uint32_t initialPosition) { diff --git a/src/mms/iso_mms/server/mms_domain.c b/src/mms/iso_mms/server/mms_domain.c index 5e22fe29..b2ceb194 100644 --- a/src/mms/iso_mms/server/mms_domain.c +++ b/src/mms/iso_mms/server/mms_domain.c @@ -41,6 +41,7 @@ MmsDomain_create(char* domainName) self->domainName = copyString(domainName); self->namedVariableLists = LinkedList_create(); + self->journals = NULL; return self; } @@ -57,6 +58,10 @@ MmsDomain_destroy(MmsDomain* self) GLOBAL_FREEMEM(self->namedVariables); } + if (self->journals != NULL) { + LinkedList_destroyDeep(self->journals, (LinkedListValueDeleteFunction) MmsJournal_destroy); + } + LinkedList_destroyDeep(self->namedVariableLists, (LinkedListValueDeleteFunction) MmsNamedVariableList_destroy); GLOBAL_FREEMEM(self); @@ -68,6 +73,15 @@ MmsDomain_getName(MmsDomain* self) return self->domainName; } +void +MmsDomain_addJournal(MmsDomain* self, MmsJournal journal) +{ + if (self->journals == NULL) + self->journals = LinkedList_create(); + + LinkedList_add(self->journals, (void*) journal); +} + bool MmsDomain_addNamedVariableList(MmsDomain* self, MmsNamedVariableList variableList) { diff --git a/src/mms/iso_mms/server/mms_journal.c b/src/mms/iso_mms/server/mms_journal.c new file mode 100644 index 00000000..48758333 --- /dev/null +++ b/src/mms/iso_mms/server/mms_journal.c @@ -0,0 +1,41 @@ +/* + * mms_journal.c + * + * Copyright 2016 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + +#include "mms_device_model.h" + +MmsJournal +MmsJournal_create(const char* name) +{ + MmsJournal self = (MmsJournal) GLOBAL_MALLOC(sizeof(struct sMmsJournal)); + + self->name = copyString(name); + + return self; +} + +void +MmsJournal_destroy(MmsJournal self) +{ + GLOBAL_FREEMEM(self->name); + GLOBAL_FREEMEM(self); +}