- prevent server from crashing when reports are too large for maximum PDU size

- improved memory handling for reports
pull/6/head
Michael Zillgith 11 years ago
parent 95bc26883e
commit 98d91464cb

@ -33,7 +33,6 @@ reportCallbackFunction(void* parameter, ClientReport report)
if (ClientReport_hasTimestamp(report)) {
time_t unixTime = ClientReport_getTimestamp(report) / 1000;
//#ifdef _MSC_VER
#ifdef WIN32
char* timeBuf = ctime(&unixTime);
#else

@ -2510,7 +2510,7 @@ eventWorkerThread(MmsMapping* self)
while (running) {
processPeriodicTasks(self);
Thread_sleep(10); /* hand-over control to other threads */
Thread_sleep(1); /* hand-over control to other threads */
running = self->reportThreadRunning;
}

@ -83,6 +83,8 @@ struct sMmsServer {
Map valueCaches;
bool isLocked;
ByteBuffer* reportBuffer; /* global buffer for encoding reports */
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore modelMutex;
#endif

@ -1,7 +1,7 @@
/*
* mms_information_report.c
*
* Copyright 2013 Michael Zillgith
* Copyright 2013, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -49,9 +49,18 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
uint32_t informationReportSize = 1 + BerEncoder_determineLengthSize(informationReportContentSize) +
informationReportContentSize;
uint32_t completeMessageSize = 1 + informationReportSize + BerEncoder_determineLengthSize(informationReportSize);
if (completeMessageSize > self->maxPduSize) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: report message too large %i (max = %i) -> skip message!\n", completeMessageSize, self->maxPduSize);
goto exit_function;
}
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: sendInfReportSingle variable: %s\n", itemId);
ByteBuffer* reportBuffer = ByteBuffer_create(NULL, self->maxPduSize);
ByteBuffer* reportBuffer = self->server->reportBuffer;
uint8_t* buffer = reportBuffer->buffer;
int bufPos = 0;
@ -74,7 +83,8 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
ByteBuffer_destroy(reportBuffer);
exit_function:
return;
}
void
@ -132,8 +142,17 @@ MmsServerConnection_sendInformationReportListOfVariables(
uint32_t informationReportSize = 1 + BerEncoder_determineLengthSize(informationReportContentSize) +
informationReportContentSize;
uint32_t completeMessageSize = 1 + informationReportSize + BerEncoder_determineLengthSize(informationReportSize);
if (completeMessageSize > self->maxPduSize) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: report message too large %i (max = %i) -> skip message!\n", completeMessageSize, self->maxPduSize);
goto exit_function;
}
/* encode message */
ByteBuffer* reportBuffer = ByteBuffer_create(NULL, self->maxPduSize);
ByteBuffer* reportBuffer = self->server->reportBuffer;
uint8_t* buffer = reportBuffer->buffer;
int bufPos = 0;
@ -145,8 +164,6 @@ MmsServerConnection_sendInformationReportListOfVariables(
/* encode list of variable access specifications */
bufPos = BerEncoder_encodeTL(0xa0, listOfVariableSize, buffer, bufPos);
specElement = LinkedList_getNext(variableAccessDeclarations);
i = 0;
@ -196,7 +213,8 @@ MmsServerConnection_sendInformationReportListOfVariables(
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
ByteBuffer_destroy(reportBuffer);
exit_function:
return;
}
@ -240,9 +258,18 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
informationReportSize = 1 + informationReportContentSize +
BerEncoder_determineLengthSize(informationReportContentSize);
uint32_t completeMessageSize = 1 + informationReportSize + BerEncoder_determineLengthSize(informationReportSize);
if (completeMessageSize > self->maxPduSize) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: report message too large %i (max = %i) -> skip message!\n", completeMessageSize, self->maxPduSize);
goto exit_function;
}
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: sendInfReport: %i items\n", variableCount);
ByteBuffer* reportBuffer = ByteBuffer_create(NULL, self->maxPduSize);
ByteBuffer* reportBuffer = self->server->reportBuffer;
uint8_t* buffer = reportBuffer->buffer;
int bufPos = 0;
@ -272,7 +299,8 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
IsoConnection_sendMessage(self->isoConnection, reportBuffer, false);
ByteBuffer_destroy(reportBuffer);
exit_function:
return;
}

@ -55,9 +55,8 @@ addNamedVariableValue(MmsVariableSpecification* namedVariable, MmsServerConnecti
value = mmsServer_getValue(connection->server, domain, itemId, connection);
if (value != NULL) {
return value;
}
if (value != NULL)
goto exit_function;
else {
int componentCount = namedVariable->typeSpec.structure.elementCount;
@ -92,6 +91,7 @@ addNamedVariableValue(MmsVariableSpecification* namedVariable, MmsServerConnecti
value = mmsServer_getValue(connection->server, domain, itemId, connection);
}
exit_function:
return value;
}
@ -153,13 +153,15 @@ static MmsValue*
getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable,
MmsValue* structuredValue)
{
MmsValue* retValue = NULL;
if (isAccessToArrayComponent(alternateAccess))
{
Identifier_t component = alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess
->list.array[0]->choice.unnamed->choice.selectAccess.choice.component;
if (component.size > 129)
return NULL;
goto exit_function;
int elementCount = namedVariable->typeSpec.structure.elementCount;
@ -172,12 +174,16 @@ getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecif
component.size) == 0)
{
MmsValue* value = MmsValue_getElement(structuredValue, i);
return value;
retValue = value;
goto exit_function;
}
}
}
return NULL;
exit_function:
return retValue;
}
static void
@ -246,6 +252,7 @@ alternateArrayAccess(MmsServerConnection connection,
}
else { // invalid access
if (DEBUG_MMS_SERVER) printf("Invalid alternate access\n");
appendErrorToResultList(values, 10 /* object-non-existant*/);
}
}
@ -339,8 +346,10 @@ encodeVariableAccessSpecification(VarAccessSpec* accessSpec, uint8_t* buffer, in
varAccessSpecSize += 1 + BerEncoder_determineLengthSize(varAccessSpecLength);
if (encode == false)
return varAccessSpecSize;
if (encode == false) {
bufPos = varAccessSpecSize;
goto exit_function;
}
/* encode to buffer */
bufPos = BerEncoder_encodeTL(0xa0, varAccessSpecLength, buffer, bufPos);
@ -367,6 +376,7 @@ encodeVariableAccessSpecification(VarAccessSpec* accessSpec, uint8_t* buffer, in
bufPos = BerEncoder_encodeStringWithTag(0x1a, accessSpec->itemId, buffer, bufPos);
}
exit_function:
return bufPos;
}
@ -424,7 +434,8 @@ encodeReadResponse(MmsServerConnection connection,
mmsServer_createConfirmedErrorPdu(invokeId, response,
MMS_ERROR_SERVICE_OTHER);
return;
goto exit_function;
}
/* encode message */
@ -465,6 +476,8 @@ encodeReadResponse(MmsServerConnection connection,
if (DEBUG_MMS_SERVER)
printf("MMS read: sent message for request with id %u (size = %i)\n", invokeId, bufPos);
exit_function:
return;
}
static void

@ -1,7 +1,7 @@
/*
* mms_server.c
*
* Copyright 2013, 2014 Michael Zillgith
* Copyright 2013, 2014, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -59,6 +59,8 @@ MmsServer_create(IsoServer isoServer, MmsDevice* device)
self->valueCaches = createValueCaches(device);
self->isLocked = false;
self->reportBuffer = ByteBuffer_create(NULL, CONFIG_MMS_MAXIMUM_PDU_SIZE);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
self->modelMutex = Semaphore_create(1);
@ -150,6 +152,8 @@ MmsServer_destroy(MmsServer self)
Semaphore_destroy(self->modelMutex);
#endif
ByteBuffer_destroy(self->reportBuffer);
GLOBAL_FREEMEM(self);
}

Loading…
Cancel
Save