- implemented client side readJournal service

- extended service side readJournal with ReasonCode
- extende mms_utility example with read journal command
This commit is contained in:
Michael Zillgith 2016-05-24 00:14:23 +02:00
parent 9a55687379
commit fd4261cd2d
6 changed files with 216 additions and 82 deletions

View file

@ -20,6 +20,7 @@ print_help()
printf("-a <domain_name> specify domain for read or write command\n");
printf("-f show file list\n");
printf("-g <filename> get file attributes\n");
printf("-j <domainName/journalName> read journal\n");
}
static void
@ -43,6 +44,59 @@ mmsGetFileAttributeHandler (void* parameter, char* filename, uint32_t size, uint
printf("DATE: %s\n", gtString);
}
static void
printJournalEntries(LinkedList journalEntries)
{
char buf[1024];
LinkedList journalEntriesElem = LinkedList_getNext(journalEntries);
while (journalEntriesElem != NULL) {
MmsJournalEntry journalEntry = (MmsJournalEntry) LinkedList_getData(journalEntriesElem);
MmsValue_printToBuffer(journalEntry->entryID, buf, 1024);
printf("EntryID: %s\n", buf);
MmsValue_printToBuffer(journalEntry->occurenceTime, buf, 1024);
printf(" occurence time: %s\n", buf);
LinkedList journalVariableElem = LinkedList_getNext(journalEntry->journalVariables);
while (journalVariableElem != NULL) {
MmsJournalVariable journalVariable = (MmsJournalVariable) LinkedList_getData(journalVariableElem);
printf(" variable-tag: %s\n", journalVariable->tag);
MmsValue_printToBuffer(journalVariable->value, buf, 1024);
printf(" variable-value: %s\n", buf);
journalVariableElem = LinkedList_getNext(journalVariableElem);
}
journalEntriesElem = LinkedList_getNext(journalEntriesElem);
}
}
static void
MmsJournalVariable_destroy(MmsJournalVariable self)
{
if (self != NULL) {
GLOBAL_FREEMEM(self->tag);
MmsValue_delete(self->value);
GLOBAL_FREEMEM(self);
}
}
void
MmsJournalEntry_destroy(MmsJournalEntry self)
{
if (self != NULL) {
MmsValue_delete(self->entryID);
MmsValue_delete(self->occurenceTime);
LinkedList_destroyDeep(self->journalVariables, MmsJournalVariable_destroy);
GLOBAL_FREEMEM(self);
}
}
int main(int argc, char** argv) {
@ -53,6 +107,7 @@ int main(int argc, char** argv) {
char* domainName = NULL;
char* variableName = NULL;
char* filename = NULL;
char* journalName = NULL;
int readDeviceList = 0;
int getDeviceDirectory = 0;
@ -61,11 +116,11 @@ int main(int argc, char** argv) {
int readVariable = 0;
int showFileList = 0;
int getFileAttributes = 0;
int readJournal = 0;
int c;
while ((c = getopt(argc, argv, "ifdh:p:l:t:a:r:g:")) != -1)
while ((c = getopt(argc, argv, "ifdh:p:l:t:a:r:g:j:")) != -1)
switch (c) {
case 'h':
hostname = copyString(optarg);
@ -102,6 +157,11 @@ int main(int argc, char** argv) {
filename = copyString(optarg);
break;
case 'j':
readJournal = 1;
journalName = copyString(optarg);
break;
default:
print_help();
return 0;
@ -146,16 +206,20 @@ int main(int argc, char** argv) {
LinkedList variableList = MmsConnection_getDomainVariableNames(con, &error,
domainName);
LinkedList element = variableList;
LinkedList element = LinkedList_getNext(variableList);
printf("\nMMS domain variables for domain %s\n", domainName);
while ((element = LinkedList_getNext(element)) != NULL) {
while (element != NULL) {
char* name = (char*) element->data;
printf(" %s\n", name);
element = LinkedList_getNext(element);
}
LinkedList_destroy(variableList);
variableList = MmsConnection_getDomainJournals(con, &error, domainName);
if (variableList != NULL) {
@ -169,20 +233,9 @@ int main(int argc, char** argv) {
printf(" %s\n", name);
printf(" read journal...\n");
// MmsConnection_readJournal(con, &error, domainName, name);
#if 1
uint64_t timestamp = Hal_getTimeInMs();
MmsValue* startTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(startTime, timestamp - 6000000000);
MmsValue* endTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(endTime, timestamp);
MmsConnection_readJournalTimeRange(con, &error, domainName, name, startTime, endTime);
#endif
#if 0
uint64_t timestamp = Hal_getTimeInMs();
@ -195,9 +248,77 @@ int main(int argc, char** argv) {
MmsConnection_readJournalStartAfter(con, &error, domainName, name, startTime, entrySpec);
#endif
}
LinkedList_destroy(variableList);
}
}
if (readJournal) {
printf(" read journal %s...\n", journalName);
char* logDomain = journalName;
char* logName = strchr(journalName, '/');
if (logName != NULL) {
logName[0] = 0;
logName++;
uint64_t timestamp = Hal_getTimeInMs();
MmsValue* startTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(startTime, timestamp - 6000000000);
MmsValue* endTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(endTime, timestamp);
bool moreFollows;
LinkedList journalEntries = MmsConnection_readJournalTimeRange(con, &error, logDomain, logName, startTime, endTime,
&moreFollows);
MmsValue_delete(startTime);
MmsValue_delete(endTime);
if (journalEntries != NULL) {
bool readNext;
do {
readNext = false;
LinkedList lastEntry = LinkedList_getLastElement(journalEntries);
MmsJournalEntry lastJournalEntry = (MmsJournalEntry) LinkedList_getData(lastEntry);
MmsValue* nextEntryId = MmsValue_clone(lastJournalEntry->entryID);
MmsValue* nextTimestamp = MmsValue_clone(lastJournalEntry->occurenceTime);
printJournalEntries(journalEntries);
LinkedList_destroyDeep(journalEntries, MmsJournalEntry_destroy);
if (moreFollows) {
char buf[100];
MmsValue_printToBuffer(nextEntryId, buf, 100);
printf("READ NEXT AFTER entryID: %s ...\n", buf);
journalEntries = MmsConnection_readJournalStartAfter(con, &error, logDomain, logName, nextTimestamp, nextEntryId, &moreFollows);
MmsValue_delete(nextEntryId);
MmsValue_delete(nextTimestamp);
readNext = true;
}
} while ((moreFollows == true) || (readNext == true));
}
}
else
printf(" Invalid log name!\n");
}
if (readVariable) {
if (readWriteHasDomain) {
MmsValue* result = MmsConnection_readVariable(con, &error, domainName, variableName);

View file

@ -81,6 +81,8 @@ LogInstance_logSingleData(LogInstance* self, const char* dataRef, MmsValue* valu
LogStorage_addEntryData(logStorage, entryID, dataRef, data, dataSize, flag);
GLOBAL_FREEMEM(data);
self->newEntryId = entryID;
self->newEntryTime = timestamp;
@ -97,10 +99,6 @@ LogInstance_setLogStorage(LogInstance* self, LogStorage logStorage)
LogStorage_getOldestAndNewestEntries(logStorage, &(self->newEntryId), &(self->newEntryTime),
&(self->oldEntryId), &(self->oldEntryTime));
printf("Attached storage to log: %s\n", self->name);
printf(" oldEntryID: %llu oldEntryTm: %llu\n", self->oldEntryId, self->oldEntryTime);
printf(" newEntryID: %llu newEntryTm: %llu\n", self->newEntryId, self->newEntryTime);
}
LogControl*
@ -123,6 +121,13 @@ void
LogControl_destroy(LogControl* self)
{
if (self != NULL) {
MmsValue_delete(self->mmsValue);
GLOBAL_FREEMEM(self->name);
if (self->dataSetRef != NULL)
GLOBAL_FREEMEM(self->dataSetRef);
GLOBAL_FREEMEM(self);
}
}
@ -188,8 +193,8 @@ updateLogStatusInLCB(LogControl* self)
MmsValue_setBinaryTime(self->oldEntrTm, logInstance->oldEntryTime);
MmsValue_setBinaryTime(self->newEntrTm, logInstance->newEntryTime);
MmsValue_setOctetString(self->oldEntr, &(logInstance->oldEntryId), 8);
MmsValue_setOctetString(self->newEntr, &(logInstance->newEntryId), 8);
MmsValue_setOctetString(self->oldEntr, (uint8_t*) &(logInstance->oldEntryId), 8);
MmsValue_setOctetString(self->newEntr, (uint8_t*) &(logInstance->newEntryId), 8);
}
}
@ -365,12 +370,9 @@ createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock,
if (logControlBlock->dataSetName != NULL) {
char* dataSetReference = createDataSetReferenceForDefaultDataSet(logControlBlock, logControl);
printf("createLogControlBlock dataSetRef: %s\n", dataSetReference);
logControl->dataSetRef = dataSetReference;
mmsValue->value.structure.components[2] = MmsValue_newVisibleString(dataSetReference);
//GLOBAL_FREEMEM(dataSetReference);
}
else
mmsValue->value.structure.components[2] = MmsValue_newVisibleString("");
@ -611,7 +613,6 @@ MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logSto
strcat(journalName, self->name);
#endif
printf("Connect LogStorage to MMS journal %s\n", logRef);
MmsJournal mmsJournal = NULL;
@ -625,7 +626,7 @@ MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logSto
if (mmsJournal != NULL)
mmsJournal->logStorage = logStorage;
else
printf("Failed to retrieve MMS journal for log!\n");
printf("IED_SERVER: Failed to retrieve MMS journal for log!\n");
#endif
}

View file

@ -720,17 +720,29 @@ bool
MmsConnection_getFileDirectory(MmsConnection self, MmsError* mmsError, const char* fileSpecification, const char* continueAfter,
MmsFileDirectoryHandler handler, void* handlerParameter);
typedef struct sMmsJournalEntry* MmsJournalEntry;
typedef struct sMmsJournalVariable* MmsJournalVariable;
struct sMmsJournalEntry {
MmsValue* entryID; /* type MMS_OCTET_STRING */
MmsValue* occurenceTime; /* type MMS_BINARY_TIME */
LinkedList journalVariables;
};
struct sMmsJournalVariable {
char* tag;
MmsValue* value;
};
LinkedList
MmsConnection_readJournal(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId);
LinkedList
MmsConnection_readJournalTimeRange(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId,
MmsValue* startingTime, MmsValue* endingTime);
MmsValue* startingTime, MmsValue* endingTime, bool* moreFollows);
LinkedList
MmsConnection_readJournalStartAfter(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId,
MmsValue* timeSpecification, MmsValue* entrySpecification);
MmsValue* timeSpecification, MmsValue* entrySpecification, bool* moreFollows);
/**
* \brief Destroy (free) an MmsServerIdentity object

View file

@ -1643,18 +1643,19 @@ MmsConnection_getServerStatus(MmsConnection self, MmsError* mmsError, int* vmdLo
}
static LinkedList
readJournal(MmsConnection self, MmsError* mmsError, uint32_t invokeId, ByteBuffer* payload)
readJournal(MmsConnection self, MmsError* mmsError, uint32_t invokeId, ByteBuffer* payload, bool* moreFollows)
{
*mmsError = MMS_ERROR_NONE;
ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
LinkedList response = NULL;
if (self->lastResponseError != MMS_ERROR_NONE)
*mmsError = self->lastResponseError;
else if (responseMessage != NULL) {
bool moreFollows;
if (mmsClient_parseReadJournalResponse(self, &moreFollows) == false)
if (mmsClient_parseReadJournalResponse(self, moreFollows, &response) == false)
*mmsError = MMS_ERROR_PARSING_RESPONSE;
}
@ -1663,9 +1664,10 @@ readJournal(MmsConnection self, MmsError* mmsError, uint32_t invokeId, ByteBuff
if (self->associationState == MMS_STATE_CLOSED)
*mmsError = MMS_ERROR_CONNECTION_LOST;
return NULL;
return response;
}
#if 0
LinkedList
MmsConnection_readJournal(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId)
{
@ -1677,10 +1679,11 @@ MmsConnection_readJournal(MmsConnection self, MmsError* mmsError, const char* do
return readJournal(self, mmsError, invokeId, payload);
}
#endif
LinkedList
MmsConnection_readJournalTimeRange(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId,
MmsValue* startingTime, MmsValue* endingTime)
MmsValue* startingTime, MmsValue* endingTime, bool* moreFollows)
{
if ((MmsValue_getType(startingTime) != MMS_BINARY_TIME) ||
(MmsValue_getType(endingTime) != MMS_BINARY_TIME)) {
@ -1695,12 +1698,12 @@ MmsConnection_readJournalTimeRange(MmsConnection self, MmsError* mmsError, const
mmsClient_createReadJournalRequestWithTimeRange(invokeId, payload, domainId, itemId, startingTime, endingTime);
return readJournal(self, mmsError, invokeId, payload);
return readJournal(self, mmsError, invokeId, payload, moreFollows);
}
LinkedList
MmsConnection_readJournalStartAfter(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId,
MmsValue* timeSpecification, MmsValue* entrySpecification)
MmsValue* timeSpecification, MmsValue* entrySpecification, bool* moreFollows)
{
if ((MmsValue_getType(timeSpecification) != MMS_BINARY_TIME) ||
@ -1716,7 +1719,7 @@ MmsConnection_readJournalStartAfter(MmsConnection self, MmsError* mmsError, cons
mmsClient_createReadJournalRequestStartAfter(invokeId, payload, domainId, itemId, timeSpecification, entrySpecification);
return readJournal(self, mmsError, invokeId, payload);
return readJournal(self, mmsError, invokeId, payload, moreFollows);
}
int32_t

View file

@ -33,21 +33,6 @@
#include "conversions.h"
#include "mms_value_internal.h"
typedef struct sMmsJournalEntry* MmsJournalEntry;
typedef struct sMmsJournalVariable* MmsJournalVariable;
struct sMmsJournalEntry {
MmsValue* entryID; /* type MMS_OCTET_STRING */
MmsValue* occurenceTime; /* type MMS_BINARY_TIME */
LinkedList journalVariables;
};
struct sMmsJournalVariable {
char* tag;
MmsValue* value;
};
//TODO add event-based API to parse journal entries
static bool
@ -75,8 +60,6 @@ parseJournalVariable(uint8_t* buffer, int bufPos, int maxLength, MmsJournalVaria
journalVariable->tag = (char*) GLOBAL_MALLOC(length + 1);
memcpy(journalVariable->tag, buffer + bufPos, length);
journalVariable->tag[length] = 0;
printf(" tag: %s\n", journalVariable->tag);
}
break;
@ -201,8 +184,6 @@ parseEntryContent(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntry jo
switch (tag) {
case 0x80: /* occurenceTime */
printf(" parse occurenceTime\n");
if (length == 6)
journalEntry->occurenceTime = MmsValue_newBinaryTime(false);
else if (length == 4)
@ -304,7 +285,6 @@ parseListOfJournalEntries(uint8_t* buffer, int bufPos, int maxLength, LinkedList
switch (tag) {
case 0x30:
printf("Parse journalEntry\n");
if (parseJournalEntry(buffer, bufPos, length, journalEntries) == false)
return false;
break;
@ -323,7 +303,7 @@ parseListOfJournalEntries(uint8_t* buffer, int bufPos, int maxLength, LinkedList
}
bool
mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows)
mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows, LinkedList* result)
{
uint8_t* buffer = self->lastResponse->buffer;
int maxBufPos = self->lastResponse->size;
@ -388,9 +368,12 @@ mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows)
bufPos += length;
}
*result = journalEntries;
return true;
}
#if 0
void
mmsClient_createReadJournalRequest(uint32_t invokeId, ByteBuffer* request, const char* domainId, const char* itemId)
{
@ -433,6 +416,7 @@ mmsClient_createReadJournalRequest(uint32_t invokeId, ByteBuffer* request, const
request->size = bufPos;
}
#endif
void
mmsClient_createReadJournalRequestWithTimeRange(uint32_t invokeId, ByteBuffer* request, const char* domainId, const char* itemId,
@ -515,7 +499,7 @@ mmsClient_createReadJournalRequestStartAfter(uint32_t invokeId, ByteBuffer* requ
uint32_t objectIdSize = domainIdSize + itemIdSize;
uint32_t journalNameSize = 1 + BerEncoder_determineLengthSize(objectIdSize) + (objectIdSize);
uint32_t journalNameSize = 1 + BerEncoder_determineLengthSize(objectIdSize) + (objectIdSize);
uint32_t timeSpecificationSize = 2 + timeSpecification->value.binaryTime.size;

View file

@ -89,6 +89,8 @@ entryCallback(void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFo
return true;
}
static const char* REASON_CODE_STR = "ReasonCode";
static bool
entryDataCallback (void* parameter, const char* dataRef, uint8_t* data, int dataSize, uint8_t reasonCode, bool moreFollow)
{
@ -106,14 +108,32 @@ entryDataCallback (void* parameter, const char* dataRef, uint8_t* data, int data
uint32_t valueSpecLen = 1 + BerEncoder_determineLengthSize(dataSize) + dataSize;
if (bufPos > encoder->maxSize) {
uint32_t firstVariableLen = 1 + BerEncoder_determineLengthSize(valueSpecLen + dataRefLen)
+ valueSpecLen + dataRefLen;
uint8_t reasonCodeNBuf[2];
MmsValue reasonCodeValue;
reasonCodeValue.type = MMS_BIT_STRING;
reasonCodeValue.value.bitString.size = 7;
reasonCodeValue.value.bitString.buf = reasonCodeNBuf;
MmsValue_setBitStringFromInteger(&reasonCodeValue, reasonCode);
uint32_t reasonCodeValueLen = MmsValue_encodeMmsData(&reasonCodeValue, NULL, 0, false);
uint32_t reasonCodeContentLen = reasonCodeValueLen + 2 + 12;
uint32_t secondVariableLen = 1 + BerEncoder_determineLengthSize(reasonCodeContentLen)
+ reasonCodeContentLen;
uint32_t totalLen = firstVariableLen + secondVariableLen;
if ((bufPos + totalLen) > encoder->maxSize) {
encoder->moreFollows = true;
encoder->bufPos = encoder->currentEntryBufPos; /* remove last entry */
return false;
}
//TODO check if entry is too long for buffer!
bufPos = BerEncoder_encodeTL(0x30, valueSpecLen + dataRefLen, buffer, bufPos);
/* encode dataRef */
@ -122,7 +142,14 @@ entryDataCallback (void* parameter, const char* dataRef, uint8_t* data, int data
/* encode valueSpec */
bufPos = BerEncoder_encodeOctetString(0xa1, data, dataSize, buffer, bufPos);
//TODO optionally encode reasonCode
/* encode reasonCode */
bufPos = BerEncoder_encodeTL(0x30, reasonCodeContentLen , buffer, bufPos);
bufPos = BerEncoder_encodeOctetString(0x80, (uint8_t*) REASON_CODE_STR, 10, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0xa1, reasonCodeValueLen, buffer, bufPos);
bufPos = MmsValue_encodeMmsData(&reasonCodeValue, buffer, bufPos, true);
encoder->bufPos = bufPos;
}
@ -255,7 +282,6 @@ mmsServer_handleReadJournalRequest(
switch (objectIdTag) {
case 0xa1: /* domain-specific */
printf("domain-specific-log \n");
if (!parseStringWithMaxLength(domainId, 64, requestBuffer, &bufPos, bufPos + length, invokeId, response)) {
return;
@ -265,8 +291,6 @@ mmsServer_handleReadJournalRequest(
return;
}
printf(" domain: %s log: %s\n", domainId, logName);
hasNames = true;
break;
@ -301,8 +325,6 @@ mmsServer_handleReadJournalRequest(
char stringBuf[100];
MmsValue_printToBuffer(&rangeStart, stringBuf, 100);
printf("rangeStartSpec: %s\n", stringBuf);
hasRangeStartSpec = true;
}
else {
@ -325,7 +347,6 @@ mmsServer_handleReadJournalRequest(
return;
}
if ((length == 4) || (length == 6)) {
rangeStop.type = MMS_BINARY_TIME;
rangeStop.value.binaryTime.size = length;
@ -335,8 +356,6 @@ mmsServer_handleReadJournalRequest(
char stringBuf[100];
MmsValue_printToBuffer(&rangeStop, stringBuf, 100);
printf("rangeStopSpec: %s\n", stringBuf);
hasRangeStopSpec = true;
}
else {
@ -351,7 +370,6 @@ mmsServer_handleReadJournalRequest(
case 0xa5: /* entryToStartAfter */
{
printf("entryToStartAfter\n");
int maxSubBufPos = bufPos + length;
while (bufPos < maxSubBufPos) {
@ -370,9 +388,7 @@ mmsServer_handleReadJournalRequest(
char stringBuf[100];
MmsValue_printToBuffer(&rangeStart, stringBuf, 100);
printf("timeSpecification: %s\n", stringBuf);
hasRangeStopSpec = true;
hasTimeSpec = true;
}
else {
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
@ -387,8 +403,6 @@ mmsServer_handleReadJournalRequest(
memcpy(entrySpec.value.octetString.buf, requestBuffer + bufPos, length);
entrySpec.value.octetString.size = length;
printf("EntrySpecification with size %i\n", length);
hasEntrySpec = true;
}
else {
@ -492,9 +506,6 @@ mmsServer_handleReadJournalRequest(
else
moreFollowsLen = 0;
// uint32_t readJournalLen = 2 + BerEncoder_determineLengthSize(listOfEntriesLen + moreFollowsLen) +
// (listOfEntriesLen + moreFollowsLen);
uint32_t readJournalLen = 2 + BerEncoder_determineLengthSize(listOfEntriesLen + moreFollowsLen) +
(listOfEntriesLen + moreFollowsLen);
@ -514,7 +525,9 @@ mmsServer_handleReadJournalRequest(
/* move encoded JournalEntry data to continue the buffer header */
printf("Encoded message header with %i bytes\n", bufPos);
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: readJournal: Encoded message header with %i bytes\n", bufPos);
memmove(buffer + bufPos, buffer + RESERVED_SPACE_FOR_HEADER, dataSize);
bufPos = bufPos + dataSize;