pull/147/head
Michael Zillgith 7 years ago
commit 6f608c105f

@ -18,6 +18,7 @@ print_help()
printf("-i show server identity\n"); printf("-i show server identity\n");
printf("-t <domain_name> show domain directory\n"); printf("-t <domain_name> show domain directory\n");
printf("-r <variable_name> read domain variable\n"); printf("-r <variable_name> read domain variable\n");
printf("-c <component_name> specify component name for variable read\n");
printf("-a <domain_name> specify domain for read or write command\n"); printf("-a <domain_name> specify domain for read or write command\n");
printf("-f show file list\n"); printf("-f show file list\n");
printf("-g <filename> get file attributes\n"); printf("-g <filename> get file attributes\n");
@ -105,6 +106,7 @@ int main(int argc, char** argv) {
char* domainName = NULL; char* domainName = NULL;
char* variableName = NULL; char* variableName = NULL;
char* componentName = NULL;
char* filename = NULL; char* filename = NULL;
char* journalName = NULL; char* journalName = NULL;
@ -122,7 +124,7 @@ int main(int argc, char** argv) {
int c; int c;
while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:")) != -1) while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:c:")) != -1)
switch (c) { switch (c) {
case 'm': case 'm':
printRawMmsMessages = 1; printRawMmsMessages = 1;
@ -155,6 +157,9 @@ int main(int argc, char** argv) {
readVariable = 1; readVariable = 1;
variableName = StringUtils_copyString(optarg); variableName = StringUtils_copyString(optarg);
break; break;
case 'c':
componentName = StringUtils_copyString(optarg);
break;
case 'v': case 'v':
readVariableList = 1; readVariableList = 1;
variableName = StringUtils_copyString(optarg); variableName = StringUtils_copyString(optarg);
@ -323,7 +328,13 @@ int main(int argc, char** argv) {
if (readVariable) { if (readVariable) {
if (readWriteHasDomain) { if (readWriteHasDomain) {
MmsValue* result = MmsConnection_readVariable(con, &error, domainName, variableName);
MmsValue* result;
if (componentName == NULL)
result = MmsConnection_readVariable(con, &error, domainName, variableName);
else
result = MmsConnection_readVariableComponent(con, &error, domainName, variableName, componentName);
if (error != MMS_ERROR_NONE) { if (error != MMS_ERROR_NONE) {
printf("Reading variable failed: (ERROR %i)\n", error); printf("Reading variable failed: (ERROR %i)\n", error);

@ -34,7 +34,7 @@ swig_link_libraries(iec61850 ${PYTHON_LIBRARIES} ${LIBS})
# Finding python modules install path # Finding python modules install path
execute_process( execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c COMMAND ${PYTHON_EXECUTABLE} -c
"from distutils.sysconfig import get_python_lib; import.sys; sys.stdout.write(get_python_lib())" "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib())"
OUTPUT_VARIABLE PYTHON_SITE_DIR OUTPUT_VARIABLE PYTHON_SITE_DIR
) )

@ -43,6 +43,8 @@ struct sClientReport
char* dataSetName; char* dataSetName;
int dataSetNameSize; /* size of the dataSetName buffer */ int dataSetNameSize; /* size of the dataSetName buffer */
int dataSetSize;
MmsValue* entryId; MmsValue* entryId;
MmsValue* dataReferences; MmsValue* dataReferences;
MmsValue* dataSetValues; MmsValue* dataSetValues;
@ -93,6 +95,8 @@ ClientReport_create()
{ {
ClientReport self = (ClientReport) GLOBAL_CALLOC(1, sizeof(struct sClientReport)); ClientReport self = (ClientReport) GLOBAL_CALLOC(1, sizeof(struct sClientReport));
self->dataSetSize = -1;
return self; return self;
} }
@ -607,6 +611,18 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
int dataSetSize = MmsValue_getBitStringSize(inclusion); int dataSetSize = MmsValue_getBitStringSize(inclusion);
if (matchingReport->dataSetSize == -1) {
matchingReport->dataSetSize = dataSetSize;
}
else {
if (dataSetSize != matchingReport->dataSetSize) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (inclusion has no plausible size)\n");
goto exit_function;
}
}
int includedElements = MmsValue_getNumberOfSetBits(inclusion); int includedElements = MmsValue_getNumberOfSetBits(inclusion);
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)

@ -95,6 +95,9 @@ iedConnection_mapMmsErrorToIedError(MmsError mmsError)
case MMS_ERROR_ACCESS_OBJECT_VALUE_INVALID: case MMS_ERROR_ACCESS_OBJECT_VALUE_INVALID:
return IED_ERROR_OBJECT_VALUE_INVALID; return IED_ERROR_OBJECT_VALUE_INVALID;
case MMS_ERROR_PARSING_RESPONSE:
return IED_ERROR_OBJECT_VALUE_INVALID;
default: default:
return IED_ERROR_UNKNOWN; return IED_ERROR_UNKNOWN;
} }
@ -434,6 +437,7 @@ informationReportHandler(void* parameter, char* domainName,
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: received information report for %s\n", variableListName); printf("DEBUG_IED_CLIENT: received information report for %s\n", variableListName);
if (value) {
if (domainName == NULL) { if (domainName == NULL) {
if (isVariableListName) { if (isVariableListName) {
@ -467,6 +471,7 @@ informationReportHandler(void* parameter, char* domainName,
} }
MmsValue_delete(value); MmsValue_delete(value);
}
} }
static IedConnection static IedConnection
@ -2291,7 +2296,7 @@ exit_function:
} }
ClientDataSet ClientDataSet
IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const char* dataSetReference, IedConnection_readDataSetValues(IedConnection self, IedClientError* err, const char* dataSetReference,
ClientDataSet dataSet) ClientDataSet dataSet)
{ {
char domainIdBuffer[65]; char domainIdBuffer[65];
@ -2316,14 +2321,14 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
if (domainId == NULL) { if (domainId == NULL) {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID; *err = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function; goto exit_function;
} }
const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1; const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) { if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID; *err = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function; goto exit_function;
} }
@ -2346,15 +2351,15 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
dataSetVal = MmsConnection_readNamedVariableListValuesAssociationSpecific(self->connection, dataSetVal = MmsConnection_readNamedVariableListValuesAssociationSpecific(self->connection,
&mmsError, itemId, true); &mmsError, itemId, true);
else else
dataSetVal= MmsConnection_readNamedVariableListValues(self->connection, &mmsError, dataSetVal = MmsConnection_readNamedVariableListValues(self->connection, &mmsError,
domainId, itemId, true); domainId, itemId, true);
if (dataSetVal == NULL) { if (dataSetVal == NULL) {
*error = iedConnection_mapMmsErrorToIedError(mmsError); *err = iedConnection_mapMmsErrorToIedError(mmsError);
goto exit_function; goto exit_function;
} }
else else
*error = IED_ERROR_OK; *err = IED_ERROR_OK;
if (dataSet == NULL) { if (dataSet == NULL) {
dataSet = ClientDataSet_create(dataSetReference); dataSet = ClientDataSet_create(dataSetReference);

@ -316,9 +316,11 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char*
self->iedServer = iedServer; self->iedServer = iedServer;
MmsVariableSpecification* ctlValSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "ctlVal", NULL); MmsVariableSpecification* ctlValSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "ctlVal", NULL);
if (ctlValSpec != NULL)
self->ctlVal = MmsValue_newDefaultValue(ctlValSpec); self->ctlVal = MmsValue_newDefaultValue(ctlValSpec);
MmsVariableSpecification* originSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "origin", NULL); MmsVariableSpecification* originSpec = MmsVariableSpecification_getChildSpecificationByName(operSpec, "origin", NULL);
if (originSpec != NULL)
self->origin = MmsValue_newDefaultValue(originSpec); self->origin = MmsValue_newDefaultValue(originSpec);
self->ctlNum = MmsValue_newUnsigned(8); self->ctlNum = MmsValue_newUnsigned(8);

@ -2608,7 +2608,7 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li
if (listType == MMS_DOMAIN_SPECIFIC) { if (listType == MMS_DOMAIN_SPECIFIC) {
if (rc->dataSet->logicalDeviceName != NULL) { if (rc->dataSet->logicalDeviceName != NULL) {
if (strcmp(rc->dataSet->name, listName) == 0) { if (strcmp(rc->dataSet->name, listName) == 0) {
if (strcmp(rc->dataSet->logicalDeviceName, MmsDomain_getName(domain)) == 0) { if (strcmp(rc->dataSet->logicalDeviceName, MmsDomain_getName(domain) + strlen(self->model->name)) == 0) {
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT; allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break; break;
} }
@ -2650,7 +2650,7 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li
if (listType == MMS_DOMAIN_SPECIFIC) { if (listType == MMS_DOMAIN_SPECIFIC) {
if (lc->dataSet->logicalDeviceName != NULL) { if (lc->dataSet->logicalDeviceName != NULL) {
if (strcmp(lc->dataSet->name, listName) == 0) { if (strcmp(lc->dataSet->name, listName) == 0) {
if (strcmp(lc->dataSet->logicalDeviceName, MmsDomain_getName(domain)) == 0) { if (strcmp(lc->dataSet->logicalDeviceName, MmsDomain_getName(domain) + strlen(self->model->name)) == 0) {
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT; allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break; break;
} }
@ -3196,7 +3196,7 @@ MmsMapping_createDataSetByNamedVariableList(MmsMapping* self, MmsNamedVariableLi
DataSet* dataSet = (DataSet*) GLOBAL_MALLOC(sizeof(DataSet)); DataSet* dataSet = (DataSet*) GLOBAL_MALLOC(sizeof(DataSet));
if (variableList->domain != NULL) if (variableList->domain != NULL)
dataSet->logicalDeviceName = MmsDomain_getName(variableList->domain); dataSet->logicalDeviceName = MmsDomain_getName(variableList->domain) + strlen(self->model->name);
else else
dataSet->logicalDeviceName = NULL; /* name is not relevant for association specific data sets */ dataSet->logicalDeviceName = NULL; /* name is not relevant for association specific data sets */

@ -373,6 +373,23 @@ MmsConnection_getVariableListNamesAssociationSpecific(MmsConnection self, MmsErr
MmsValue* MmsValue*
MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId); MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId);
/**
* \brief Read a component of a single variable from the server.
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
* \param domainId the domain name of the variable to be read or NULL to read a VMD specific named variable
* \param itemId name of the variable to be read
* \param componentId the component name
*
* \return Returns a MmsValue object or NULL if the request failed. The MmsValue object can
* either be a simple value or a complex value or array. It is also possible that the return value is NULL
* even if mmsError = MMS_ERROR_NON. This is the case when the servers returns an empty result list.
*/
MmsValue*
MmsConnection_readVariableComponent(MmsConnection self, MmsError* mmsError,
const char* domainId, const char* itemId, const char* componentId);
/** /**
* \brief Read one or more elements of a single array variable from the server. * \brief Read one or more elements of a single array variable from the server.
* *

@ -160,6 +160,9 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create
int int
mmsClient_createReadRequest(uint32_t invokeId, const char* domainId, const char* itemId, ByteBuffer* writeBuffer); mmsClient_createReadRequest(uint32_t invokeId, const char* domainId, const char* itemId, ByteBuffer* writeBuffer);
int
mmsClient_createReadRequestComponent(uint32_t invokeId, const char* domainId, const char* itemId, const char* component, ByteBuffer* writeBuffer);
int int
mmsClient_createReadRequestAlternateAccessIndex(uint32_t invokeId, const char* domainId, const char* itemId, mmsClient_createReadRequestAlternateAccessIndex(uint32_t invokeId, const char* domainId, const char* itemId,
uint32_t index, uint32_t elementCount, ByteBuffer* writeBuffer); uint32_t index, uint32_t elementCount, ByteBuffer* writeBuffer);

@ -357,9 +357,13 @@ mmsServer_handleObtainFileRequest(
uint32_t invokeId, uint32_t invokeId,
ByteBuffer* response); ByteBuffer* response);
int
bool
mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess); mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess);
bool
mmsServer_isComponentAccess(AlternateAccess_t* alternateAccess);
int int
mmsServer_getLowIndex(AlternateAccess_t* alternateAccess); mmsServer_getLowIndex(AlternateAccess_t* alternateAccess);

@ -1589,6 +1589,34 @@ MmsConnection_readVariable(MmsConnection self, MmsError* mmsError,
return value; return value;
} }
MmsValue*
MmsConnection_readVariableComponent(MmsConnection self, MmsError* mmsError,
const char* domainId, const char* itemId, const char* componentId)
{
MmsValue* value = NULL;
if (getAssociationState(self) != MMS_STATE_CONNECTED) {
*mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function;
}
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createReadRequestComponent(invokeId, domainId, itemId, componentId, payload);
ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
if (responseMessage != NULL)
value = mmsClient_parseReadResponse(self->lastResponse, NULL, false);
releaseResponse(self);
exit_function:
return value;
}
MmsValue* MmsValue*
MmsConnection_readArrayElements(MmsConnection self, MmsError* mmsError, MmsConnection_readArrayElements(MmsConnection self, MmsError* mmsError,
const char* domainId, const char* itemId, const char* domainId, const char* itemId,
@ -1697,9 +1725,13 @@ MmsConnection_readNamedVariableListValues(MmsConnection self, MmsError* mmsError
ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError); ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
if (responseMessage != NULL) if (responseMessage != NULL) {
value = mmsClient_parseReadResponse(self->lastResponse, NULL, true); value = mmsClient_parseReadResponse(self->lastResponse, NULL, true);
if (value == NULL)
*mmsError = MMS_ERROR_PARSING_RESPONSE;
}
releaseResponse(self); releaseResponse(self);
exit_function: exit_function:

@ -138,8 +138,7 @@ mmsClient_parseGetVariableAccessAttributesResponse(ByteBuffer* message, uint32_t
asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu, asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu,
(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message)); (void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));
if (rval.code != RC_OK) if (rval.code == RC_OK) {
return NULL;
if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) { if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {
@ -157,6 +156,7 @@ mmsClient_parseGetVariableAccessAttributesResponse(ByteBuffer* message, uint32_t
typeSpec = createTypeSpecification(asnTypeSpec); typeSpec = createTypeSpecification(asnTypeSpec);
} }
} }
}
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

@ -46,6 +46,9 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
int i = 0; int i = 0;
for (i = 0; i < elementCount; i++) { for (i = 0; i < elementCount; i++) {
value = NULL;
AccessResult_PR presentType = accessResultList[i]->present; AccessResult_PR presentType = accessResultList[i]->present;
if (presentType == AccessResult_PR_failure) { if (presentType == AccessResult_PR_failure) {
@ -66,12 +69,13 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_UNKNOWN); value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_UNKNOWN);
} }
else if (presentType == AccessResult_PR_array) { else if (presentType == AccessResult_PR_array) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_ARRAY;
int arrayElementCount = int arrayElementCount =
accessResultList[i]->choice.array.list.count; accessResultList[i]->choice.array.list.count;
if (arrayElementCount > 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_ARRAY;
value->value.structure.size = arrayElementCount; value->value.structure.size = arrayElementCount;
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(arrayElementCount, sizeof(MmsValue*)); value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(arrayElementCount, sizeof(MmsValue*));
@ -80,15 +84,28 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
for (j = 0; j < arrayElementCount; j++) { for (j = 0; j < arrayElementCount; j++) {
value->value.structure.components[j] = mmsMsg_parseDataElement( value->value.structure.components[j] = mmsMsg_parseDataElement(
accessResultList[i]->choice.array.list.array[j]); accessResultList[i]->choice.array.list.array[j]);
if (value->value.structure.components[j] == NULL) {
MmsValue_delete(value);
value = NULL;
break;
} }
} }
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid array size)!\n");
}
}
else if (presentType == AccessResult_PR_structure) { else if (presentType == AccessResult_PR_structure) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_STRUCTURE;
int componentCount = int componentCount =
accessResultList[i]->choice.structure.list.count; accessResultList[i]->choice.structure.list.count;
if (componentCount > 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_STRUCTURE;
value->value.structure.size = componentCount; value->value.structure.size = componentCount;
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));
@ -96,12 +113,34 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
for (j = 0; j < componentCount; j++) { for (j = 0; j < componentCount; j++) {
value->value.structure.components[j] = mmsMsg_parseDataElement( value->value.structure.components[j] = mmsMsg_parseDataElement(
accessResultList[i]->choice.structure.list.array[j]); accessResultList[i]->choice.structure.list.array[j]);
if (value->value.structure.components[j] == NULL) {
MmsValue_delete(value);
value = NULL;
break;
} }
} }
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid structure size)!\n");
}
}
else if (presentType == AccessResult_PR_bitstring) { else if (presentType == AccessResult_PR_bitstring) {
int size = accessResultList[i]->choice.bitstring.size;
if (size > 0) {
int maxSize = (size * 8);
int bitSize = maxSize - accessResultList[i]->choice.bitstring.bits_unused;
if ((bitSize > 0) && (maxSize >= bitSize)) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_BIT_STRING; value->type = MMS_BIT_STRING;
int size = accessResultList[i]->choice.bitstring.size;
value->value.bitString.size = (size * 8) value->value.bitString.size = (size * 8)
- accessResultList[i]->choice.bitstring.bits_unused; - accessResultList[i]->choice.bitstring.bits_unused;
@ -109,29 +148,59 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size); value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size);
memcpy(value->value.bitString.buf, memcpy(value->value.bitString.buf,
accessResultList[i]->choice.bitstring.buf, size); accessResultList[i]->choice.bitstring.buf, size);
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (bit string padding problem)!\n");
}
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (bit string size 0 or negative)!\n");
}
} }
else if (presentType == AccessResult_PR_integer) { else if (presentType == AccessResult_PR_integer) {
int size = accessResultList[i]->choice.integer.size;
if (size > 0) {
Asn1PrimitiveValue* berInteger = Asn1PrimitiveValue* berInteger =
BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf, BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf, size);
accessResultList[i]->choice.integer.size);
value = MmsValue_newIntegerFromBerInteger(berInteger); value = MmsValue_newIntegerFromBerInteger(berInteger);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid integer size)!\n");
}
}
else if (presentType == AccessResult_PR_unsigned) { else if (presentType == AccessResult_PR_unsigned) {
int size = accessResultList[i]->choice.Unsigned.size;
if (size > 0) {
Asn1PrimitiveValue* berInteger = Asn1PrimitiveValue* berInteger =
BerInteger_createFromBuffer(accessResultList[i]->choice.Unsigned.buf, BerInteger_createFromBuffer(accessResultList[i]->choice.Unsigned.buf,
accessResultList[i]->choice.Unsigned.size); accessResultList[i]->choice.Unsigned.size);
value = MmsValue_newUnsignedFromBerInteger(berInteger); value = MmsValue_newUnsignedFromBerInteger(berInteger);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid unsigned size)!\n");
}
}
else if (presentType == AccessResult_PR_floatingpoint) { else if (presentType == AccessResult_PR_floatingpoint) {
int size = accessResultList[i]->choice.floatingpoint.size; int size = accessResultList[i]->choice.floatingpoint.size;
if (size == 5) { /* FLOAT32 */
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_FLOAT; value->type = MMS_FLOAT;
if (size == 5) { /* FLOAT32 */
value->value.floatingPoint.formatWidth = 32; value->value.floatingPoint.formatWidth = 32;
value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0]; value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0];
@ -146,8 +215,11 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
#endif #endif
} }
else if (size == 9) { /* FLOAT64 */
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_FLOAT;
if (size == 9) { /* FLOAT64 */
value->value.floatingPoint.formatWidth = 64; value->value.floatingPoint.formatWidth = 64;
value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0]; value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0];
@ -161,15 +233,20 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
memcpy(value->value.floatingPoint.buf, floatBuf, 8); memcpy(value->value.floatingPoint.buf, floatBuf, 8);
#endif #endif
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing float (size must be 5 or 9, is %i)\n", size);
}
} }
else if (presentType == AccessResult_PR_visiblestring) { else if (presentType == AccessResult_PR_visiblestring) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_VISIBLE_STRING;
int strSize = accessResultList[i]->choice.visiblestring.size; int strSize = accessResultList[i]->choice.visiblestring.size;
if (strSize >= 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_VISIBLE_STRING;
value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1); value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1);
value->value.visibleString.size = strSize; value->value.visibleString.size = strSize;
@ -179,13 +256,20 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
value->value.visibleString.buf[strSize] = 0; value->value.visibleString.buf[strSize] = 0;
} }
else if (presentType == AccessResult_PR_mMSString) { else {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid visible-string size)\n");
}
value->type = MMS_STRING; }
else if (presentType == AccessResult_PR_mMSString) {
int strSize = accessResultList[i]->choice.mMSString.size; int strSize = accessResultList[i]->choice.mMSString.size;
if (strSize >= 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_STRING;
value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1); value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1);
value->value.visibleString.size = strSize; value->value.visibleString.size = strSize;
@ -193,14 +277,26 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
accessResultList[i]->choice.mMSString.buf, strSize); accessResultList[i]->choice.mMSString.buf, strSize);
value->value.visibleString.buf[strSize] = 0; value->value.visibleString.buf[strSize] = 0;
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid mms-string size)\n");
}
} }
else if (presentType == AccessResult_PR_utctime) { else if (presentType == AccessResult_PR_utctime) {
int size = accessResultList[i]->choice.utctime.size;
if (size == 8) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_UTC_TIME; value->type = MMS_UTC_TIME;
memcpy(value->value.utcTime, memcpy(value->value.utcTime, accessResultList[i]->choice.utctime.buf, 8);
accessResultList[i]->choice.utctime.buf, 8); }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing UTC time (size is %i instead of 8\n", size);
}
} }
else if (presentType == AccessResult_PR_boolean) { else if (presentType == AccessResult_PR_boolean) {
value = MmsValue_newBoolean(accessResultList[i]->choice.boolean); value = MmsValue_newBoolean(accessResultList[i]->choice.boolean);
@ -208,16 +304,21 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
else if (presentType == AccessResult_PR_binarytime) { else if (presentType == AccessResult_PR_binarytime) {
int size = accessResultList[i]->choice.binarytime.size; int size = accessResultList[i]->choice.binarytime.size;
if (size <= 6) { if ((size == 4) || (size == 6)) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_BINARY_TIME; value->type = MMS_BINARY_TIME;
value->value.binaryTime.size = size; value->value.binaryTime.size = size;
memcpy(value->value.binaryTime.buf, accessResultList[i]->choice.binarytime.buf, size); memcpy(value->value.binaryTime.buf, accessResultList[i]->choice.binarytime.buf, size);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing binary time (size must be 4 or 6, is %i\n", size);
}
} }
else if (presentType == AccessResult_PR_octetstring) { else if (presentType == AccessResult_PR_octetstring) {
int size = accessResultList[i]->choice.octetstring.size; int size = accessResultList[i]->choice.octetstring.size;
if (size >= 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_OCTET_STRING; value->type = MMS_OCTET_STRING;
value->value.octetString.maxSize = size; value->value.octetString.maxSize = size;
@ -226,7 +327,13 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
memcpy(value->value.octetString.buf, accessResultList[i]->choice.octetstring.buf, size); memcpy(value->value.octetString.buf, accessResultList[i]->choice.octetstring.buf, size);
} }
else { else {
printf("unknown type %i\n", presentType); if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing access result (invalid octet-string size)\n");
}
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: unknown type %i in access result\n", presentType);
value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID); value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID);
} }
@ -254,9 +361,7 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create
asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu, asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu,
(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message)); (void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));
if (rval.code != RC_OK) if (rval.code == RC_OK) {
return NULL;
if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) { if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {
if (invokeId != NULL) if (invokeId != NULL)
@ -271,6 +376,7 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create
elementCount, createArray); elementCount, createArray);
} }
} }
}
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
@ -422,7 +528,7 @@ mmsClient_createReadRequest(uint32_t invokeId, const char* domainId, const char*
} }
static AlternateAccess_t* static AlternateAccess_t*
createAlternateAccess(uint32_t index, uint32_t elementCount) createAlternateAccessComponent(const char* componentName)
{ {
AlternateAccess_t* alternateAccess = (AlternateAccess_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccess_t)); AlternateAccess_t* alternateAccess = (AlternateAccess_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccess_t));
alternateAccess->list.count = 1; alternateAccess->list.count = 1;
@ -432,37 +538,114 @@ createAlternateAccess(uint32_t index, uint32_t elementCount)
alternateAccess->list.array[0]->choice.unnamed = (AlternateAccessSelection_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccessSelection_t)); alternateAccess->list.array[0]->choice.unnamed = (AlternateAccessSelection_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccessSelection_t));
const char* separator = strchr(componentName, '$');
if (separator) {
int size = separator - componentName;
alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAlternateAccess;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present =
AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_component;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.buf =
(uint8_t*) StringUtils_copySubString((char*) componentName, (char*) separator);
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.size = size;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess = createAlternateAccessComponent(separator + 1);
}
else {
int size = strlen(componentName);
alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAccess; alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAccess;
if (elementCount > 0) {
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present = alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present =
AlternateAccessSelection__selectAccess_PR_indexRange; AlternateAccessSelection__selectAccess_PR_component;
INTEGER_t* asnIndex = alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.buf =
&(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.lowIndex); (uint8_t*) StringUtils_copyString(componentName);
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.size = size;
}
asn_long2INTEGER(asnIndex, index); return alternateAccess;
}
asnIndex = static void
&(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.numberOfElements); deleteAlternateAccessComponent(AlternateAccess_t* alternateAccess)
{
GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed);
GLOBAL_FREEMEM(alternateAccess->list.array[0]);
GLOBAL_FREEMEM(alternateAccess->list.array);
GLOBAL_FREEMEM(alternateAccess);
}
asn_long2INTEGER(asnIndex, elementCount); static ListOfVariableSeq_t*
createNewVariableSpecification(const char* domainId, const char* itemId, const char* componentName, bool associationSpecific)
{
ListOfVariableSeq_t* varSpec = (ListOfVariableSeq_t*) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t));
varSpec->variableSpecification.present = VariableSpecification_PR_name;
if (domainId) {
varSpec->variableSpecification.choice.name.present = ObjectName_PR_domainspecific;
varSpec->variableSpecification.choice.name.choice.domainspecific.domainId.buf = (uint8_t*) domainId;
varSpec->variableSpecification.choice.name.choice.domainspecific.domainId.size = strlen(domainId);
varSpec->variableSpecification.choice.name.choice.domainspecific.itemId.buf = (uint8_t*) itemId;
varSpec->variableSpecification.choice.name.choice.domainspecific.itemId.size = strlen(itemId);
}
else if (associationSpecific) {
varSpec->variableSpecification.choice.name.present = ObjectName_PR_aaspecific;
varSpec->variableSpecification.choice.name.choice.aaspecific.buf = (uint8_t*) itemId;
varSpec->variableSpecification.choice.name.choice.aaspecific.size = strlen(itemId);
} }
else { else {
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present = varSpec->variableSpecification.choice.name.present = ObjectName_PR_vmdspecific;
AlternateAccessSelection__selectAccess_PR_index; varSpec->variableSpecification.choice.name.choice.vmdspecific.buf = (uint8_t*) itemId;
varSpec->variableSpecification.choice.name.choice.vmdspecific.size = strlen(itemId);
}
INTEGER_t* asnIndex = if (componentName)
&(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index); varSpec->alternateAccess = createAlternateAccessComponent(componentName);
asn_long2INTEGER(asnIndex, index); return varSpec;
} }
return alternateAccess; /**
* Request a single value with optional component
*/
int
mmsClient_createReadRequestComponent(uint32_t invokeId, const char* domainId, const char* itemId, const char* component, ByteBuffer* writeBuffer)
{
MmsPdu_t* mmsPdu = mmsClient_createConfirmedRequestPdu(invokeId);
ReadRequest_t* readRequest = createReadRequest(mmsPdu);
readRequest->specificationWithResult = NULL;
readRequest->variableAccessSpecification.present = VariableAccessSpecification_PR_listOfVariable;
readRequest->variableAccessSpecification.choice.listOfVariable.list.count = 1;
readRequest->variableAccessSpecification.choice.listOfVariable.list.size = 1;
readRequest->variableAccessSpecification.choice.listOfVariable.list.array =
(ListOfVariableSeq_t**) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t*));
readRequest->variableAccessSpecification.choice.listOfVariable.list.array[0] = createNewVariableSpecification(domainId, itemId, component, false);
asn_enc_rval_t rval;
rval = der_encode(&asn_DEF_MmsPdu, mmsPdu,
(asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
/* clean up data structures */
deleteAlternateAccessComponent(readRequest->variableAccessSpecification.choice.listOfVariable.list.array[0]->alternateAccess);
GLOBAL_FREEMEM(readRequest->variableAccessSpecification.choice.listOfVariable.list.array);
readRequest->variableAccessSpecification.choice.listOfVariable.list.array = NULL;
readRequest->variableAccessSpecification.choice.listOfVariable.list.count = 0;
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
return rval.encoded;
} }
static AlternateAccess_t* static AlternateAccess_t*
createAlternateAccessComponent(const char* componentName) createAlternateAccess(uint32_t index, uint32_t elementCount)
{ {
AlternateAccess_t* alternateAccess = (AlternateAccess_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccess_t)); AlternateAccess_t* alternateAccess = (AlternateAccess_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccess_t));
alternateAccess->list.count = 1; alternateAccess->list.count = 1;
@ -472,32 +655,30 @@ createAlternateAccessComponent(const char* componentName)
alternateAccess->list.array[0]->choice.unnamed = (AlternateAccessSelection_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccessSelection_t)); alternateAccess->list.array[0]->choice.unnamed = (AlternateAccessSelection_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccessSelection_t));
const char* separator = strchr(componentName, '$'); alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAccess;
if (separator) { if (elementCount > 0) {
int size = separator - componentName; alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present =
AlternateAccessSelection__selectAccess_PR_indexRange;
alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAlternateAccess; INTEGER_t* asnIndex =
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present = &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.lowIndex);
AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_component;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.buf = asn_long2INTEGER(asnIndex, index);
(uint8_t*) StringUtils_copySubString((char*) componentName, (char*) separator);
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.size = size;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess = createAlternateAccessComponent(separator + 1); asnIndex =
&(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.numberOfElements);
asn_long2INTEGER(asnIndex, elementCount);
} }
else { else {
int size = strlen(componentName);
alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAccess;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present = alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present =
AlternateAccessSelection__selectAccess_PR_component; AlternateAccessSelection__selectAccess_PR_index;
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.buf = INTEGER_t* asnIndex =
(uint8_t*) StringUtils_copyString(componentName); &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index);
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.size = size;
asn_long2INTEGER(asnIndex, index);
} }
return alternateAccess; return alternateAccess;

@ -185,11 +185,43 @@ mmsMsg_parseDataElement(Data_t* dataElement)
{ {
MmsValue* value = NULL; MmsValue* value = NULL;
if (dataElement->present == Data_PR_structure) { if (dataElement->present == Data_PR_array) {
int componentCount = dataElement->choice.array->list.count;
if (componentCount > 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_ARRAY;
value->value.structure.size = componentCount;
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));
int i;
for (i = 0; i < componentCount; i++) {
value->value.structure.components[i] =
mmsMsg_parseDataElement(dataElement->choice.array->list.array[i]);
if (value->value.structure.components[i] == NULL) {
MmsValue_delete(value);
value = NULL;
break;
}
}
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (invalid array size)!\n");
}
}
else if (dataElement->present == Data_PR_structure) {
int componentCount = dataElement->choice.structure->list.count; int componentCount = dataElement->choice.structure->list.count;
if (componentCount > 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_STRUCTURE; value->type = MMS_STRUCTURE;
value->value.structure.size = componentCount; value->value.structure.size = componentCount;
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));
@ -199,13 +231,26 @@ mmsMsg_parseDataElement(Data_t* dataElement)
for (i = 0; i < componentCount; i++) { for (i = 0; i < componentCount; i++) {
value->value.structure.components[i] = value->value.structure.components[i] =
mmsMsg_parseDataElement(dataElement->choice.structure->list.array[i]); mmsMsg_parseDataElement(dataElement->choice.structure->list.array[i]);
if (value->value.structure.components[i] == NULL) {
MmsValue_delete(value);
value = NULL;
break;
}
}
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (invalid structure size)!\n");
} }
} }
else if (dataElement->present == Data_PR_array) { else if (dataElement->present == Data_PR_array) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
int componentCount = dataElement->choice.array->list.count; int componentCount = dataElement->choice.array->list.count;
if (componentCount > 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_ARRAY; value->type = MMS_ARRAY;
value->value.structure.size = componentCount; value->value.structure.size = componentCount;
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));
@ -215,50 +260,100 @@ mmsMsg_parseDataElement(Data_t* dataElement)
for (i = 0; i < componentCount; i++) { for (i = 0; i < componentCount; i++) {
value->value.structure.components[i] = value->value.structure.components[i] =
mmsMsg_parseDataElement(dataElement->choice.array->list.array[i]); mmsMsg_parseDataElement(dataElement->choice.array->list.array[i]);
if (value->value.structure.components[i] == NULL) {
MmsValue_delete(value);
value = NULL;
break;
}
}
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (invalid array size)!\n");
}
} }
else { else {
if (dataElement->present == Data_PR_integer) { if (dataElement->present == Data_PR_integer) {
if (dataElement->choice.integer.size > 0) {
Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer( Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer(
dataElement->choice.integer.buf, dataElement->choice.integer.size); dataElement->choice.integer.buf, dataElement->choice.integer.size);
value = MmsValue_newIntegerFromBerInteger(berInteger); value = MmsValue_newIntegerFromBerInteger(berInteger);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (invalid integer size)!\n");
}
}
else if (dataElement->present == Data_PR_unsigned) { else if (dataElement->present == Data_PR_unsigned) {
if (dataElement->choice.Unsigned.size > 0) {
Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer( Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer(
dataElement->choice.Unsigned.buf, dataElement->choice.Unsigned.size); dataElement->choice.Unsigned.buf, dataElement->choice.Unsigned.size);
value = MmsValue_newUnsignedFromBerInteger(berInteger); value = MmsValue_newUnsignedFromBerInteger(berInteger);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (invalid unsigned size)!\n");
}
}
else if (dataElement->present == Data_PR_visiblestring) { else if (dataElement->present == Data_PR_visiblestring) {
if (dataElement->choice.visiblestring.size >= 0) {
value = MmsValue_newVisibleStringFromByteArray(dataElement->choice.visiblestring.buf, value = MmsValue_newVisibleStringFromByteArray(dataElement->choice.visiblestring.buf,
dataElement->choice.visiblestring.size); dataElement->choice.visiblestring.size);
} }
}
else if (dataElement->present == Data_PR_mMSString) { else if (dataElement->present == Data_PR_mMSString) {
if ( dataElement->choice.mMSString.size >= 0) {
value = MmsValue_newMmsStringFromByteArray(dataElement->choice.mMSString.buf, value = MmsValue_newMmsStringFromByteArray(dataElement->choice.mMSString.buf,
dataElement->choice.mMSString.size); dataElement->choice.mMSString.size);
} }
}
else if (dataElement->present == Data_PR_bitstring) { else if (dataElement->present == Data_PR_bitstring) {
int size = dataElement->choice.bitstring.size;
if (size > 0) {
int maxSize = (size * 8);
int bitSize = maxSize - dataElement->choice.bitstring.bits_unused;
if ((bitSize > 0) && (maxSize >= bitSize)) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_BIT_STRING; value->type = MMS_BIT_STRING;
int size = dataElement->choice.bitstring.size;
value->value.bitString.size = (size * 8) value->value.bitString.size = bitSize;
- dataElement->choice.bitstring.bits_unused;
value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size); value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size);
memcpy(value->value.bitString.buf, memcpy(value->value.bitString.buf,
dataElement->choice.bitstring.buf, size); dataElement->choice.bitstring.buf, size);
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (bit string padding problem)!\n");
}
}
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing data element (bit string size 0 or negative)!\n");
}
} }
else if (dataElement->present == Data_PR_floatingpoint) { else if (dataElement->present == Data_PR_floatingpoint) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
int size = dataElement->choice.floatingpoint.size; int size = dataElement->choice.floatingpoint.size;
if (size == 5) { /* FLOAT32 */
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_FLOAT; value->type = MMS_FLOAT;
if (size == 5) { /* FLOAT32 */
value->value.floatingPoint.formatWidth = 32; value->value.floatingPoint.formatWidth = 32;
value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0]; value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0];
@ -273,6 +368,10 @@ mmsMsg_parseDataElement(Data_t* dataElement)
} }
if (size == 9) { /* FLOAT64 */ if (size == 9) { /* FLOAT64 */
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_FLOAT;
value->value.floatingPoint.formatWidth = 64; value->value.floatingPoint.formatWidth = 64;
value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0]; value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0];
@ -287,11 +386,22 @@ mmsMsg_parseDataElement(Data_t* dataElement)
} }
} }
else if (dataElement->present == Data_PR_utctime) { else if (dataElement->present == Data_PR_utctime) {
int size = dataElement->choice.utctime.size;
if (size == 8) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_UTC_TIME; value->type = MMS_UTC_TIME;
memcpy(value->value.utcTime, dataElement->choice.utctime.buf, 8); memcpy(value->value.utcTime, dataElement->choice.utctime.buf, 8);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing UTC time (size is %i instead of 8\n", size);
}
}
else if (dataElement->present == Data_PR_octetstring) { else if (dataElement->present == Data_PR_octetstring) {
if (dataElement->choice.octetstring.size >= 0) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_OCTET_STRING; value->type = MMS_OCTET_STRING;
int size = dataElement->choice.octetstring.size; int size = dataElement->choice.octetstring.size;
@ -300,20 +410,34 @@ mmsMsg_parseDataElement(Data_t* dataElement)
value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size); value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size);
memcpy(value->value.octetString.buf, dataElement->choice.octetstring.buf, size); memcpy(value->value.octetString.buf, dataElement->choice.octetstring.buf, size);
} }
}
else if (dataElement->present == Data_PR_binarytime) { else if (dataElement->present == Data_PR_binarytime) {
int size = dataElement->choice.binarytime.size; int size = dataElement->choice.binarytime.size;
if (size <= 6) { if ((size == 4) || (size == 6)) {
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
value->type = MMS_BINARY_TIME; value->type = MMS_BINARY_TIME;
value->value.binaryTime.size = size; value->value.binaryTime.size = size;
memcpy(value->value.binaryTime.buf, dataElement->choice.binarytime.buf, size); memcpy(value->value.binaryTime.buf, dataElement->choice.binarytime.buf, size);
} }
else {
if (DEBUG_MMS_CLIENT)
printf("MMS CLIENT: error parsing binary time (size must be 4 or 6, is %i\n", size);
}
} }
else if (dataElement->present == Data_PR_boolean) { else if (dataElement->present == Data_PR_boolean) {
value = MmsValue_newBoolean(dataElement->choice.boolean); value = MmsValue_newBoolean(dataElement->choice.boolean);
} }
else if (dataElement->present == Data_PR_booleanArray) {
}
}
if (DEBUG_MMS_CLIENT) {
if (value == NULL)
printf("MMS CLIENT: error parsing data element\n");
} }
return value; return value;
@ -350,7 +474,6 @@ void
mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName) mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName)
{ {
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) #if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
// strncpy(extendedFileName, MmsServerConnection_getFilesystemBasepath(self), 512);
strncpy(extendedFileName, basepath, 512); strncpy(extendedFileName, basepath, 512);
strncat(extendedFileName, fileName, 512); strncat(extendedFileName, fileName, 512);
#else #else

@ -1081,10 +1081,12 @@ MmsValue_cloneToBuffer(const MmsValue* self, uint8_t* destinationAddress)
return destinationAddress; return destinationAddress;
} }
// create a deep clone
MmsValue* MmsValue*
MmsValue_clone(const MmsValue* self) MmsValue_clone(const MmsValue* self)
{ {
if (self == NULL)
return NULL;
MmsValue* newValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); MmsValue* newValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
if (newValue == NULL) if (newValue == NULL)
@ -1188,6 +1190,9 @@ MmsValue_deleteIfNotNull(MmsValue* self)
void void
MmsValue_delete(MmsValue* self) MmsValue_delete(MmsValue* self)
{ {
if (self == NULL)
return;
switch (self->type) switch (self->type)
{ {
case MMS_INTEGER: case MMS_INTEGER:
@ -2010,6 +2015,16 @@ MmsValue_getTypeString(MmsValue* self)
const char* const char*
MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize) MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
{ {
if (self == NULL) {
strncpy(buffer, "(null)", bufferSize);
/* Ensure buffer is always 0 terminated */
if (bufferSize > 0)
buffer[bufferSize - 1] = 0;
return buffer;
}
switch (MmsValue_getType(self)) switch (MmsValue_getType(self))
{ {
case MMS_STRUCTURE: case MMS_STRUCTURE:

@ -155,6 +155,51 @@ isAccessToArrayComponent(AlternateAccess_t* alternateAccess)
return false; return false;
} }
static MmsValue*
getComponent(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable, MmsValue* variableValue)
{
MmsValue* retValue = NULL;
if (mmsServer_isComponentAccess(alternateAccess)) {
Identifier_t component =
alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component;
if (component.size > 129)
goto exit_function;
if (namedVariable->type == MMS_STRUCTURE) {
int i;
for (i = 0; i < namedVariable->typeSpec.structure.elementCount;
i++) {
if (strlen(namedVariable->typeSpec.structure.elements[i]->name)
== component.size) {
if (strncmp(
namedVariable->typeSpec.structure.elements[i]->name,
(char*) component.buf, component.size) == 0) {
MmsValue* value = MmsValue_getElement(variableValue, i);
if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess
!= NULL) {
retValue =
getComponent(
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess,
namedVariable->typeSpec.structure.elements[i],
value);
}
else
retValue = value;
}
}
}
}
}
exit_function: return retValue;
}
static MmsValue* static MmsValue*
getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable, getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable,
MmsValue* structuredValue) MmsValue* structuredValue)
@ -180,14 +225,20 @@ getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecif
int i; int i;
for (i = 0; i < structSpec->typeSpec.structure.elementCount; i++) { for (i = 0; i < structSpec->typeSpec.structure.elementCount; i++) {
if (strncmp (structSpec->typeSpec.structure.elements[i]->name, (char*) component.buf,
component.size) == 0) if (strlen(structSpec->typeSpec.structure.elements[i]->name)
{ == component.size) {
if (strncmp(structSpec->typeSpec.structure.elements[i]->name,
(char*) component.buf, component.size) == 0) {
MmsValue* value = MmsValue_getElement(structuredValue, i); MmsValue* value = MmsValue_getElement(structuredValue, i);
if (isAccessToArrayComponent(alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess)) { if (isAccessToArrayComponent(
retValue = getComponentOfArrayElement(alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess, alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess)) {
structSpec->typeSpec.structure.elements[i], value); retValue =
getComponentOfArrayElement(
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess,
structSpec->typeSpec.structure.elements[i],
value);
} }
else else
retValue = value; retValue = value;
@ -196,6 +247,7 @@ getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecif
} }
} }
} }
}
exit_function: exit_function:
return retValue; return retValue;
@ -288,6 +340,17 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain*
MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection);
if (alternateAccess != NULL) {
value = getComponent(alternateAccess, namedVariable, value);
if (value != NULL) {
appendValueToResultList(value, values);
}
else {
appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
}
}
else {
if (value != NULL) { if (value != NULL) {
appendValueToResultList(value, values); appendValueToResultList(value, values);
} }
@ -296,6 +359,7 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain*
values, connection, domain, nameIdStr); values, connection, domain, nameIdStr);
} }
} }
}
else if (namedVariable->type == MMS_ARRAY) { else if (namedVariable->type == MMS_ARRAY) {
if (alternateAccess != NULL) { if (alternateAccess != NULL) {

@ -208,7 +208,7 @@ mmsMsg_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError e
mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, NULL, 0); mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, NULL, 0);
} }
int bool
mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess) mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess)
{ {
if (alternateAccess->list.array[0]->present == AlternateAccess__Member_PR_unnamed) { if (alternateAccess->list.array[0]->present == AlternateAccess__Member_PR_unnamed) {
@ -217,13 +217,25 @@ mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess)
(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present
== AlternateAccessSelection__selectAccess_PR_indexRange)) == AlternateAccessSelection__selectAccess_PR_indexRange))
{ {
return 1; return true;
} }
else
return 0;
} }
else
return 0; return false;
}
bool
mmsServer_isComponentAccess(AlternateAccess_t* alternateAccess)
{
if (alternateAccess->list.array[0]->present
== AlternateAccess__Member_PR_unnamed) {
if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present
== AlternateAccessSelection__selectAccess_PR_component) {
return true;
}
}
return false;
} }
int int

@ -94,7 +94,7 @@ public class OptionFields {
if (boolVal != null) if (boolVal != null)
this.configRef = boolVal; this.configRef = boolVal;
boolVal = ParserUtils.parseBooleanAttribute(optFieldsNode, "bufOvlf"); boolVal = ParserUtils.parseBooleanAttribute(optFieldsNode, "bufOvfl");
if (boolVal != null) if (boolVal != null)
this.bufOvfl = boolVal; this.bufOvfl = boolVal;
} }

Loading…
Cancel
Save