diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c index 8b43d9d7..24c909c9 100644 --- a/examples/mms_utility/mms_utility.c +++ b/examples/mms_utility/mms_utility.c @@ -101,6 +101,7 @@ printRawMmsMessage(void* parameter, uint8_t* message, int messageLength, bool re int main(int argc, char** argv) { + int returnCode = 0; char* hostname = StringUtils_copyString("localhost"); int tcpPort = 102; @@ -213,6 +214,10 @@ int main(int argc, char** argv) if (!MmsConnection_connect(con, &error, hostname, tcpPort)) { printf("MMS connect failed!\n"); + + if (error != MMS_ERROR_NONE) + returnCode = error; + goto exit; } else @@ -222,6 +227,9 @@ int main(int argc, char** argv) MmsServerIdentity* identity = MmsConnection_identify(con, &error); + if (error != MMS_ERROR_NONE) + returnCode = error; + if (identity != NULL) { printf("\nServer identity:\n----------------\n"); printf(" vendor:\t%s\n", identity->vendorName); @@ -235,14 +243,23 @@ int main(int argc, char** argv) if (readDeviceList) { printf("\nDomains present on server:\n--------------------------\n"); LinkedList nameList = MmsConnection_getDomainNames(con, &error); - LinkedList_printStringList(nameList); - LinkedList_destroy(nameList); + + if (error != MMS_ERROR_NONE) + returnCode = error; + + if (nameList) { + LinkedList_printStringList(nameList); + LinkedList_destroy(nameList); + } } if (getDeviceDirectory) { LinkedList variableList = MmsConnection_getDomainVariableNames(con, &error, domainName); + if (error != MMS_ERROR_NONE) + returnCode = error; + if (variableList) { LinkedList element = LinkedList_getNext(variableList); @@ -264,6 +281,9 @@ int main(int argc, char** argv) variableList = MmsConnection_getDomainJournals(con, &error, domainName); + if (error != MMS_ERROR_NONE) + returnCode = error; + if (variableList) { LinkedList element = variableList; @@ -309,6 +329,9 @@ int main(int argc, char** argv) LinkedList journalEntries = MmsConnection_readJournalTimeRange(con, &error, logDomain, logName, startTime, endTime, &moreFollows); + if (error != MMS_ERROR_NONE) + returnCode = error; + MmsValue_delete(startTime); MmsValue_delete(endTime); @@ -375,6 +398,8 @@ int main(int argc, char** argv) if (error != MMS_ERROR_NONE) { printf("Reading variable failed: (ERROR %i)\n", error); + + returnCode = error; } else { printf("Read SUCCESS\n"); @@ -403,6 +428,8 @@ int main(int argc, char** argv) if (error != MMS_ERROR_NONE) { printf("Reading variable failed: (ERROR %i)\n", error); + + returnCode = error; } else { printf("Read SUCCESS\n"); @@ -421,6 +448,8 @@ int main(int argc, char** argv) if (error != MMS_ERROR_NONE) { printf("Reading variable list directory failed: (ERROR %i)\n", error); + + returnCode = error; } else { LinkedList varListElem = LinkedList_getNext(varListDir); @@ -454,12 +483,19 @@ int main(int argc, char** argv) char* continueAfter = NULL; while (MmsConnection_getFileDirectory(con, &error, "", continueAfter, mmsFileDirectoryHandler, lastName)) { + + if (error != MMS_ERROR_NONE) + returnCode = error; + continueAfter = lastName; } } if (getFileAttributes) { MmsConnection_getFileDirectory(con, &error, filename, NULL, mmsGetFileAttributeHandler, NULL); + + if (error != MMS_ERROR_NONE) + returnCode = error; } if (deleteFile) { @@ -467,13 +503,14 @@ int main(int argc, char** argv) if (error != MMS_ERROR_NONE) { printf("Delete file failed: (ERROR %i)\n", error); + returnCode = error; } else { printf("File deleted\n"); } } - exit: +exit: free(hostname); free(domainName); free(variableName); @@ -482,6 +519,6 @@ int main(int argc, char** argv) MmsConnection_destroy(con); - return 0; + return returnCode; } diff --git a/src/mms/inc_private/cotp.h b/src/mms/inc_private/cotp.h index b7877cc8..3cbe2681 100644 --- a/src/mms/inc_private/cotp.h +++ b/src/mms/inc_private/cotp.h @@ -114,4 +114,7 @@ CotpConnection_getRemoteRef(CotpConnection* self); LIB61850_INTERNAL int CotpConnection_getLocalRef(CotpConnection* self); +LIB61850_INTERNAL void +CotpConnection_flushBuffer(CotpConnection* self); + #endif /* COTP_H_ */ diff --git a/src/mms/iso_cotp/cotp.c b/src/mms/iso_cotp/cotp.c index f57e05bc..2b4e43e6 100644 --- a/src/mms/iso_cotp/cotp.c +++ b/src/mms/iso_cotp/cotp.c @@ -5,7 +5,7 @@ * * Partial implementation of the ISO 8073 COTP (ISO TP0) protocol for MMS. * - * Copyright 2013-2018 Michael Zillgith + * Copyright 2013-2023 Michael Zillgith * * This file is part of libIEC61850. * @@ -174,6 +174,38 @@ writeToSocket(CotpConnection* self, uint8_t* buf, int size) #endif } +static bool +flushBuffer(CotpConnection* self) +{ + if (self->socketExtensionBufferFill > 0) { + + int sentBytes = writeToSocket(self, self->socketExtensionBuffer, self->socketExtensionBufferFill); + + if (sentBytes > 0) { + + if (sentBytes != self->socketExtensionBufferFill) { + int target = 0; + int i; + uint8_t* buf = self->socketExtensionBuffer; + + for (i = sentBytes; i < self->socketExtensionBufferFill; i++) { + buf[target++] = buf[i]; + } + + self->socketExtensionBufferFill = self->socketExtensionBufferFill - sentBytes; + } + else { + self->socketExtensionBufferFill = 0; + } + } + else if (sentBytes == -1) { + return false; + } + } + + return true; +} + static bool sendBuffer(CotpConnection* self) { @@ -182,7 +214,15 @@ sendBuffer(CotpConnection* self) bool retVal = false; - int sentBytes = writeToSocket(self, buffer, remainingSize); + if (flushBuffer(self) == false) { + goto exit_function; + } + + int sentBytes = 0; + + if (self->socketExtensionBufferFill == 0) { + sentBytes = writeToSocket(self, buffer, remainingSize); + } if (sentBytes == -1) goto exit_function; @@ -215,33 +255,6 @@ exit_function: return retVal; } -static void -flushBuffer(CotpConnection* self) -{ - if (self->socketExtensionBufferFill > 0) { - - int sentBytes = writeToSocket(self, self->socketExtensionBuffer, self->socketExtensionBufferFill); - - if (sentBytes > 0) { - - if (sentBytes != self->socketExtensionBufferFill) { - int target = 0; - int i; - uint8_t* buf = self->socketExtensionBuffer; - - for (i = sentBytes; i < self->socketExtensionBufferFill; i++) { - buf[target++] = buf[i]; - } - - self->socketExtensionBufferFill = self->socketExtensionBufferFill - sentBytes; - } - else { - self->socketExtensionBufferFill = 0; - } - } - } -} - CotpIndication CotpConnection_sendDataMessage(CotpConnection* self, BufferChain payload) { @@ -262,7 +275,9 @@ CotpConnection_sendDataMessage(CotpConnection* self, BufferChain payload) int totalSize = (fragments * (COTP_DATA_HEADER_SIZE + 4)) + payload->length; /* try to flush extension buffer */ - flushBuffer(self); + if (flushBuffer(self) == false) { + return COTP_ERROR; + } /* check if totalSize will fit in extension buffer */ if (self->socketExtensionBuffer) { @@ -281,7 +296,7 @@ CotpConnection_sendDataMessage(CotpConnection* self, BufferChain payload) int currentChainIndex = 0; if (DEBUG_COTP) - printf("\nCOTP: nextBufferPart: len:%i partLen:%i\n", currentChain->length, currentChain->partLength); + printf("COTP: nextBufferPart: len:%i partLen:%i\n", currentChain->length, currentChain->partLength); uint8_t* buffer = self->writeBuffer->buffer; @@ -307,7 +322,7 @@ CotpConnection_sendDataMessage(CotpConnection* self, BufferChain payload) if (currentChainIndex >= currentChain->partLength) { currentChain = currentChain->nextPart; if (DEBUG_COTP) - printf("\nCOTP: nextBufferPart: len:%i partLen:%i\n", currentChain->length, currentChain->partLength); + printf("COTP: nextBufferPart: len:%i partLen:%i\n", currentChain->length, currentChain->partLength); currentChainIndex = 0; } @@ -756,6 +771,13 @@ readFromSocket(CotpConnection* self, uint8_t* buf, int size) #endif } +void +CotpConnection_flushBuffer(CotpConnection* self) +{ + if (self->socketExtensionBufferFill > 0) + flushBuffer(self); +} + TpktState CotpConnection_readToTpktBuffer(CotpConnection* self) { @@ -765,6 +787,14 @@ CotpConnection_readToTpktBuffer(CotpConnection* self) assert (bufferSize > 4); + if (self->socketExtensionBufferFill > 0) { + if (flushBuffer(self) == false) + goto exit_error; + + if (self->socketExtensionBufferFill > 0) + goto exit_waiting; + } + int readBytes; if (bufPos < 4) { diff --git a/src/mms/iso_server/iso_connection.c b/src/mms/iso_server/iso_connection.c index 7f997a9b..795b0636 100644 --- a/src/mms/iso_server/iso_connection.c +++ b/src/mms/iso_server/iso_connection.c @@ -1,7 +1,7 @@ /* * iso_connection.c * - * Copyright 2013-2022 Michael Zillgith + * Copyright 2013-2023 Michael Zillgith * * This file is part of libIEC61850. * @@ -160,6 +160,8 @@ IsoConnection_removeFromHandleSet(const IsoConnection self, HandleSet handles) void IsoConnection_callTickHandler(IsoConnection self) { + CotpConnection_flushBuffer(self->cotpConnection); + if (self->tickHandler) { self->tickHandler(self->handlerParameter); } @@ -171,10 +173,7 @@ IsoConnection_handleTcpConnection(IsoConnection self, bool isSingleThread) #if (CONFIG_MMS_SINGLE_THREADED != 1) if (isSingleThread == false) { - /* call tick handler */ - if (self->tickHandler) { - self->tickHandler(self->handlerParameter); - } + IsoConnection_callTickHandler(self); if (Handleset_waitReady(self->handleSet, 10) < 1) goto exit_function; diff --git a/src/mms/iso_server/iso_server.c b/src/mms/iso_server/iso_server.c index 62c43ebb..a2daa6ad 100644 --- a/src/mms/iso_server/iso_server.c +++ b/src/mms/iso_server/iso_server.c @@ -455,7 +455,6 @@ exit_function: return success; } - /** used by single and multi-threaded versions * * \param isSingleThread when true server is running in single thread or non-thread mode