Exemple #1
0
void
ControlObject_sendCommandTerminationPositive(ControlObject* self)
{
    char itemId[68]; /* 64 characters + space for FC + separator + string terminator */

    StringUtils_createStringInBuffer(itemId, 4, self->lnName, "$CO$", self->name, "$Oper");

    if (DEBUG_IED_SERVER)
        printf("IED_SERVER: send CommandTermination+: %s\n", itemId);

    char* domainId = MmsDomain_getName(self->mmsDomain);

    MmsVariableAccessSpecification varSpec;

    varSpec.itemId = itemId;
    varSpec.domainId = domainId;

    LinkedList varSpecList = LinkedList_create();
    LinkedList values = LinkedList_create();

    if ((varSpecList != NULL) && (values != NULL))
    {
        LinkedList_add(varSpecList, &varSpec);
        LinkedList_add(values, self->oper);

        MmsServerConnection_sendInformationReportListOfVariables(self->mmsConnection, varSpecList, values, false);

        LinkedList_destroyStatic(varSpecList);
        LinkedList_destroyStatic(values);
    }
}
Exemple #2
0
IsoServer
IsoServer_create()
{
    IsoServer self = (IsoServer) GLOBAL_CALLOC(1, sizeof(struct sIsoServer));

    self->state = ISO_SVR_STATE_IDLE;
    self->tcpPort = TCP_PORT;

#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1)
    self->openClientConnections = LinkedList_create();
#else
    self->openClientConnections = (IsoConnection*)
            GLOBAL_CALLOC(CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS, sizeof(IsoConnection));
#endif

#if (CONFIG_MMS_THREADLESS_STACK != 1)
    self->connectionCounterMutex = Semaphore_create(1);
#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1)
    self->openClientConnectionsMutex = Semaphore_create(1);
#endif

#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */

    self->connectionCounter = 0;

    return self;
}
LinkedList /*<char*>*/
IedConnection_getLogicalDeviceList(IedConnection self, IedClientError* error)
{
    *error = IED_ERROR_OK;

    if (self->logicalDevices == NULL) {
        IedConnection_getDeviceModelFromServer(self, error);

        if (*error != IED_ERROR_OK)
            return NULL;
    }

    if (self->logicalDevices != NULL) {
        LinkedList logicalDevice = LinkedList_getNext(self->logicalDevices);

        LinkedList logicalDeviceList = LinkedList_create();

        while (logicalDevice != NULL) {
            ICLogicalDevice* icLogicalDevice = (ICLogicalDevice*) logicalDevice->data;

            char* logicalDeviceName = copyString(icLogicalDevice->name);

            LinkedList_add(logicalDeviceList, logicalDeviceName);

            logicalDevice = LinkedList_getNext(logicalDevice);
        }

        *error = IED_ERROR_OK;
        return logicalDeviceList;
    }
    else {
        *error = IED_ERROR_UNKNOWN;
        return NULL;
    }
}
LinkedList /*<FileDirectoryEntry>*/
IedConnection_getFileDirectory(IedConnection self, IedClientError* error, char* directoryName)
{
    *error = IED_ERROR_OK;

    MmsError mmsError = MMS_ERROR_NONE;

    LinkedList fileNames = LinkedList_create();

    char* continueAfter = NULL;

    bool moreFollows = false;


    do {
        moreFollows =
                MmsConnection_getFileDirectory(self->connection, &mmsError, directoryName, continueAfter,
                        mmsFileDirectoryHandler, fileNames);

        if (mmsError != MMS_ERROR_NONE) {
            *error = iedConnection_mapMmsErrorToIedError(mmsError);
            LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);

            return NULL;
        }

    } while (moreFollows == true);

    return fileNames;
}
Exemple #5
0
Map
Map_create()
{
	Map map = calloc(1, sizeof(struct sMap));
	map->entries = LinkedList_create();
	map->compareKeys = comparePointerKeys;
	return map;
}
IedConnection
IedConnection_create()
{
    IedConnection self = (IedConnection) calloc(1, sizeof(struct sIedConnection));

    self->enabledReports = LinkedList_create();
    self->logicalDevices = NULL;
    self->clientControls = LinkedList_create();

    self->connection = MmsConnection_create();

    self->state = IED_STATE_IDLE;

    self->stateMutex = Semaphore_create(1);

    return self;
}
void
IedConnection_getDeviceModelFromServer(IedConnection self, IedClientError* error)
{
    MmsError mmsError = MMS_ERROR_NONE;
    *error = IED_ERROR_OK;

    LinkedList logicalDeviceNames = MmsConnection_getDomainNames(self->connection, &mmsError);

    if (logicalDeviceNames != NULL) {

        if (self->logicalDevices != NULL) {
            LinkedList_destroyDeep(self->logicalDevices, (LinkedListValueDeleteFunction) ICLogicalDevice_destroy);
            self->logicalDevices = NULL;
        }

        LinkedList logicalDevice = LinkedList_getNext(logicalDeviceNames);

        LinkedList logicalDevices = LinkedList_create();

        while (logicalDevice != NULL) {
            char* name = (char*) logicalDevice->data;

            ICLogicalDevice* icLogicalDevice = ICLogicalDevice_create(name);

            LinkedList variables = MmsConnection_getDomainVariableNames(self->connection,
                    &mmsError, name);

            if (variables != NULL)
                ICLogicalDevice_setVariableList(icLogicalDevice, variables);
            else {
                *error = iedConnection_mapMmsErrorToIedError(mmsError);
                break;
            }

            LinkedList dataSets = MmsConnection_getDomainVariableListNames(self->connection,
                    &mmsError, name);

            if (dataSets != NULL)
                ICLogicalDevice_setDataSetList(icLogicalDevice, dataSets);
            else {
                *error = iedConnection_mapMmsErrorToIedError(mmsError);
                break;
            }

            LinkedList_add(logicalDevices, icLogicalDevice);

            logicalDevice = LinkedList_getNext(logicalDevice);
        }

        self->logicalDevices = logicalDevices;

        LinkedList_destroy(logicalDeviceNames);
    }
    else {
        *error = iedConnection_mapMmsErrorToIedError(mmsError);
    }
}
Exemple #8
0
MmsDomain*
MmsDomain_create(char* domainName)
{
    MmsDomain* self = calloc(1, sizeof(MmsDomain));

    self->domainName = copyString(domainName);
    self->namedVariableLists = LinkedList_create();

    return self;
}
bool
mmsClient_parseGetNameListResponse(LinkedList* nameList, ByteBuffer* message, uint32_t* invokeId)
{
	MmsPdu_t* mmsPdu = 0;

	bool moreFollows = false;

	asn_dec_rval_t rval;
	/* Decoder return value  */
	rval = ber_decode(NULL, &asn_DEF_MmsPdu,
			(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));

	if (DEBUG) xer_fprint(stdout, &asn_DEF_MmsPdu, mmsPdu);

	if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {
		*invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu);

		if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present == ConfirmedServiceResponse_PR_getNameList) {
			GetNameListResponse_t* response =
				&(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.getNameList);
            int variableCount;
            int i;
            LinkedList element;

			if ((response->moreFollows != NULL) && (*(response->moreFollows) != 0))
				moreFollows = true;

			if (*nameList == NULL)
				*nameList = LinkedList_create();


			variableCount = response->listOfIdentifier.list.count;

			element = LinkedList_getLastElement(*nameList);

			for (i = 0; i < variableCount; i++) {
				char* variableName =
						createStringFromBuffer(response->listOfIdentifier.list.array[i]->buf,
								response->listOfIdentifier.list.array[i]->size);

				element = LinkedList_insertAfter(element, variableName);
			}
		}
		else {
			printf("parseMmsGetNameListResponse: NOT A GetNameList RESPONSE!\n");
		}
	}
	else {
		printf("parseMmsGetNameListResponse: NOT A CONFIRMED RESPONSE!\n");
	}

	asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

	return moreFollows;
}
void
LinkedList_add(LinkedList list, void* data)
{
	LinkedList newElement = LinkedList_create();

	newElement->data = data;

	LinkedList listEnd = LinkedList_getLastElement(list);

	listEnd->next = newElement;
}
LinkedList
LinkedList_insertAfter(LinkedList list, void* data)
{
	LinkedList originalNextElement = LinkedList_getNext(list);

	LinkedList newElement = LinkedList_create();

	newElement->data = data;
	newElement->next = originalNextElement;

	list->next = newElement;

	return newElement;
}
Exemple #12
0
void
IedConnection_createDataSet(IedConnection self, IedClientError* error, char* dataSetReference,
        LinkedList /* <char*> */dataSetElements)
{

    char domainIdBuffer[65];
    char itemIdBuffer[129];

    char* domainId;
    char* itemId;
    bool isAssociationSpecific = false;

    if (dataSetReference[0] != '@') {
        domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
        itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer);
        StringUtils_replace(itemId, '.', '$');
    }
    else {
        itemId = dataSetReference;
        isAssociationSpecific = true;
    }

    MmsError mmsError;

    LinkedList dataSetEntries = LinkedList_create();

    LinkedList dataSetElement = LinkedList_getNext(dataSetElements);

    while (dataSetElement != NULL) {

        MmsVariableAccessSpecification* dataSetEntry =
                MmsMapping_ObjectReferenceToVariableAccessSpec((char*) dataSetElement->data);

        LinkedList_add(dataSetEntries, (void*) dataSetEntry);

        dataSetElement = LinkedList_getNext(dataSetElement);
    }

    if (isAssociationSpecific)
        MmsConnection_defineNamedVariableListAssociationSpecific(self->connection, &mmsError,
                itemId, dataSetEntries);
    else
        MmsConnection_defineNamedVariableList(self->connection, &mmsError,
                domainId, itemId, dataSetEntries);

    /* delete list and all elements */
    LinkedList_destroyDeep(dataSetEntries, (LinkedListValueDeleteFunction) MmsVariableAccessSpecification_destroy);

    *error = iedConnection_mapMmsErrorToIedError(mmsError);
}
Exemple #13
0
GooseReceiver
GooseReceiver_create()
{
    GooseReceiver self = (GooseReceiver) GLOBAL_MALLOC(sizeof(struct sGooseReceiver));

    if (self != NULL) {
        self->running = false;
        self->interfaceId = NULL;
        self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
        self->ethSocket = NULL;
        self->subscriberList = LinkedList_create();
    }

    return self;
}
LinkedList
mmsClient_parseGetNameListResponse(ByteBuffer* message, uint32_t* invokeId)
{
	MmsPdu_t* mmsPdu = 0; /* allow asn1c to allocate structure */

	LinkedList returnList = NULL;

	asn_dec_rval_t rval;
	/* Decoder return value  */
	rval = ber_decode(NULL, &asn_DEF_MmsPdu,
			(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));

	if (DEBUG) xer_fprint(stdout, &asn_DEF_MmsPdu, mmsPdu);

	if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {
		*invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu);

		if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present == ConfirmedServiceResponse_PR_getNameList) {
			GetNameListResponse_t* response =
				&(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.getNameList);

			LinkedList variableNameList = LinkedList_create();

			int variableCount = response->listOfIdentifier.list.count;

			int i;

			for (i = 0; i < variableCount; i++) {
				char* variableName =
						createStringFromBuffer(response->listOfIdentifier.list.array[i]->buf,
								response->listOfIdentifier.list.array[i]->size);

				LinkedList_add(variableNameList, variableName);
			}
			returnList = variableNameList;
		}
		else {
			printf("parseMmsGetNameListResponse: NOT A GetNameList RESPONSE!\n");
		}
	}
	else {
		printf("parseMmsGetNameListResponse: NOT A CONFIRMED RESPONSE!\n");
	}

	asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

	return returnList;
}
static void
createNamedVariableListResponse(MmsServerConnection* connection, MmsNamedVariableList namedList,
		int invokeId, ByteBuffer* response, ReadRequest_t* read, VarAccessSpec* accessSpec)
{

	LinkedList /*<MmsValue>*/ values = LinkedList_create();
	LinkedList variables = MmsNamedVariableList_getVariableList(namedList);

	int variableCount = LinkedList_size(variables);

	MmsServer_lockModel(connection->server);

	int i;

	LinkedList variable = LinkedList_getNext(variables);

	for (i = 0; i < variableCount; i++) {

		MmsNamedVariableListEntry variableListEntry = (MmsNamedVariableListEntry) variable->data;

		MmsDomain* variableDomain = MmsNamedVariableListEntry_getDomain(variableListEntry);
		char* variableName = MmsNamedVariableListEntry_getVariableName(variableListEntry);

		MmsTypeSpecification* namedVariable = MmsDomain_getNamedVariable(variableDomain,
				variableName);

		addNamedVariableToResultList(namedVariable, variableDomain, variableName,
								values, connection, NULL);

		variable = LinkedList_getNext(variable);
	}

	if (isSpecWithResult(read)) /* add specification to result */
		encodeReadResponse(connection, invokeId, response, values, accessSpec);
	else
		encodeReadResponse(connection, invokeId, response, values, NULL);

	MmsServer_unlockModel(connection->server);

	deleteValueList(values);
}
/**********************************************************************************************
 * MMS server connection public API functions
 *********************************************************************************************/
MmsServerConnection*	MmsServerConnection_init(MmsServerConnection* connection, MmsServer server, IsoConnection isoCon)
{

	MmsServerConnection* self;

	if (connection == NULL)		self = calloc(1, sizeof(MmsServerConnection));
	else						self = connection;

	self->maxServOutstandingCalled = 0;
	self->maxServOutstandingCalling = 0;
	self->maxPduSize = MMS_MAXIMUM_PDU_SIZE;
	self->dataStructureNestingLevel = 0;
	self->server = server;
	self->isoConnection = isoCon;
	self->namedVariableLists = LinkedList_create();

	//IsoConnection_installListener(isoCon, messageReceived, (void*) self);

	return self;

}
// has to be executed as root!
int
main(int argc, char** argv)
{

	LinkedList dataSetValues = LinkedList_create();

	LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(1234));
	LinkedList_add(dataSetValues, MmsValue_newBinaryTime(false));
	LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(5678));

	CommParameters gooseCommParameters;

	gooseCommParameters.appId = 1000;
	gooseCommParameters.dstAddress[0] = 0x01;
	gooseCommParameters.dstAddress[1] = 0x0c;
	gooseCommParameters.dstAddress[2] = 0xcd;
	gooseCommParameters.dstAddress[3] = 0x01;
	gooseCommParameters.dstAddress[4] = 0x00;
	gooseCommParameters.dstAddress[5] = 0x01;
	gooseCommParameters.vlanId = 0;
	gooseCommParameters.vlanPriority = 4;

	GoosePublisher publisher = GoosePublisher_create(&gooseCommParameters, "eth0");

	GoosePublisher_setGoCbRef(publisher, "simpleIOGenericIO/LLN0$GO$gcbAnalogValues");
	GoosePublisher_setConfRev(publisher, 1);
	GoosePublisher_setDataSetRef(publisher, "simpleIOGenericIO/LLN0$AnalogValues");

	int i = 0;

	for (i = 0; i < 3; i++) {
		Thread_sleep(1000);

		if (GoosePublisher_publish(publisher, dataSetValues) == -1) {
			printf("Error sending message!\n");
		}
	}

	GoosePublisher_destroy(publisher);
}
Exemple #18
0
IedServer
IedServer_create(IedModel* iedModel)
{
    IedServer self = (IedServer) calloc(1, sizeof(struct sIedServer));

    self->model = iedModel;

    self->mmsMapping = MmsMapping_create(iedModel);

    self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping);

    self->isoServer = IsoServer_create();

    self->mmsServer = MmsServer_create(self->isoServer, self->mmsDevice);

    MmsMapping_setMmsServer(self->mmsMapping, self->mmsServer);

    MmsMapping_installHandlers(self->mmsMapping);

    MmsMapping_setIedServer(self->mmsMapping, self);

    createMmsServerCache(self);

    iedModel->initializer();

    installDefaultValuesInCache(self); /* This will also connect cached MmsValues to DataAttributes */

    updateDataSetsWithCachedValues(self);

    self->clientConnections = LinkedList_create();

    /* default write access policy allows access to SP and SV FCDAs but denies access to DC and CF FCDAs */
    self->writeAccessPolicies = ALLOW_WRITE_ACCESS_SP | ALLOW_WRITE_ACCESS_SV;

#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
    Reporting_activateBufferedReports(self->mmsMapping);
#endif

    return self;
}
Exemple #19
0
LinkedList /*<char*>*/
IedConnection_getLogicalDeviceDirectory(IedConnection self, IedClientError* error,
        char* logicalDeviceName)
{
    if (self->logicalDevices == NULL)
        IedConnection_getDeviceModelFromServer(self, error);

    if (self->logicalDevices == NULL)
        return NULL;

    LinkedList logicalDevice = LinkedList_getNext(self->logicalDevices);

    while (logicalDevice != NULL) {
        ICLogicalDevice* device = (ICLogicalDevice*) logicalDevice->data;

        if (strcmp(device->name, logicalDeviceName) == 0) {
            LinkedList logicalNodeNames = LinkedList_create();

            LinkedList variable = LinkedList_getNext(device->variables);

            while (variable != NULL) {
                char* variableName = (char*) variable->data;

                if (strchr(variableName, '$') == NULL)
                    LinkedList_add(logicalNodeNames, copyString((char*) variable->data));

                variable = LinkedList_getNext(variable);
            }

            return logicalNodeNames;
        }

        logicalDevice = LinkedList_getNext(logicalDevice);
    }

    *error = IED_ERROR_OBJECT_REFERENCE_INVALID;

    return NULL;
}
Exemple #20
0
/* clone a list */
LinkedList *LinkedList_clone(LinkedList *lst) {
    if (lst == NULL)
        return NULL;

    LinkedList *copy = LinkedList_create(lst->compare, lst->clone);
    copy->size = lst->size;

    Node *tmp, *prev = NULL, *current;

    for (current = lst->head; current; current = current->next) {
        tmp = malloc(sizeof(Node));
        tmp->data = lst->clone(current->data);
        tmp->next = NULL;
        if (!prev) 
            copy->head = tmp;
        else
           prev->next = tmp;
       prev = tmp; 
    }

    return copy;
}
bool
mmsClient_parseGetNameListResponse(LinkedList* nameList, ByteBuffer* message, uint32_t* invokeId)
{
	bool moreFollows = true;

	uint8_t* buffer = message->buffer;
	int maxBufPos = message->size;
	int bufPos = 0;
	int length;

	uint8_t tag = buffer[bufPos++];
	if (tag == 0xa2) {
	    // TODO parse confirmed error PDU
	    goto exit_error;
	}
	if (tag != 0xa1) goto exit_error;

	bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
	if (bufPos < 0) goto exit_error;

	/* get invokeId */
	tag = buffer[bufPos++];
	if (tag != 0x02) goto exit_error;

	bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
    if (bufPos < 0) goto exit_error;

    if (invokeId != NULL)
        *invokeId = BerDecoder_decodeUint32(buffer, length, bufPos);

    bufPos += length;

    tag = buffer[bufPos++];
    if (tag != 0xa1) goto exit_error;

    bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
    if (bufPos < 0) goto exit_error;

    tag = buffer[bufPos++];
    if (tag != 0xa0) goto exit_error;

    bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
    if (bufPos < 0) goto exit_error;

    int listEndPos = bufPos + length;
    if (listEndPos > maxBufPos) goto exit_error;

    if (*nameList == NULL)
        *nameList = LinkedList_create();

    LinkedList element = LinkedList_getLastElement(*nameList);

    while (bufPos < listEndPos) {
        tag = buffer[bufPos++];
        if (tag != 0x1a) goto exit_error;

        bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
        if (bufPos < 0) goto exit_error;

        char* variableName = createStringFromBuffer(buffer + bufPos, length);

        element = LinkedList_insertAfter(element, variableName);

        bufPos += length;
    }

    if (bufPos < maxBufPos) {
		tag = buffer[bufPos++];
		if (tag != 0x81) goto exit_error;
		bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
		if (bufPos < 0) goto exit_error;
		if (length != 1) goto exit_error;
		if (buffer[bufPos++] > 0)
			moreFollows = true;
		else
			moreFollows = false;
    }

	return moreFollows;

exit_error:
    if (*nameList != NULL) {
        LinkedList_destroy(*nameList);
    }

    if (DEBUG) printf("parseNameListResponse: error parsing message!\n");
    return false;
}
static void
handleReadListOfVariablesRequest(
		MmsServerConnection* connection,
		ReadRequest_t* read,
		uint32_t invokeId,
		ByteBuffer* response)
{
	int variableCount = read->variableAccessSpecification.choice.listOfVariable.list.count;

	LinkedList /*<MmsValue>*/ values = LinkedList_create();

	if (isSpecWithResult(read)) { /* add specification to result */
		//TODO add va spec to result
	}

	MmsServer_lockModel(connection->server);

	int i;

	for (i = 0; i < variableCount; i++) {
		VariableSpecification_t varSpec =
			read->variableAccessSpecification.choice.listOfVariable.list.array[i]->variableSpecification;

		AlternateAccess_t* alternateAccess =
			read->variableAccessSpecification.choice.listOfVariable.list.array[i]->alternateAccess;

		if (varSpec.present == VariableSpecification_PR_name) {

			if (varSpec.choice.name.present == ObjectName_PR_domainspecific) {
				char* domainIdStr = mmsMsg_createStringFromAsnIdentifier(
						varSpec.choice.name.choice.domainspecific.domainId);


				char* nameIdStr = mmsMsg_createStringFromAsnIdentifier(
						varSpec.choice.name.choice.domainspecific.itemId);

				MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainIdStr);

				if (domain == NULL) {
					if (DEBUG) printf("MMS read: domain %s not found!\n", domainIdStr);

					appendErrorToResultList(values, 10 /* object-non-existant*/);
					break;
				}

				MmsTypeSpecification* namedVariable = MmsDomain_getNamedVariable(domain, nameIdStr);

				addNamedVariableToResultList(namedVariable, domain, nameIdStr,
						values, connection, alternateAccess);

				free(domainIdStr);
				free(nameIdStr);
			}
			else {
                appendErrorToResultList(values, 10 /* object-non-existant*/);

				if (DEBUG) printf("MMS read: object name type not supported!\n");
			}
		}
		else {
			//TODO should we send a ConfirmedErrorPdu here?
			if (DEBUG) printf("MMS read: varspec type not supported!\n");
		}
	}

	encodeReadResponse(connection, invokeId, response, values, NULL);

	MmsServer_unlockModel(connection->server);

exit:
    deleteValueList(values);
}
Clause* DIMACSParser_parse_clause(char* line, LinkedList* all_literals) {
    // Empty lines are not permitted
    if (strcmp(line, "") == 0) {
        fprintf(stderr, "Error - empty lines are not permitted!\n");
        return NULL;
    }
    
    // Split line by space
    unsigned int line_c = 30;
    char** line_v = malloc(line_c * sizeof(char*));
    {
        unsigned int line_filled = 0;
        
        char* tmp = strtok(line, " ");
        while (tmp != NULL) {
            // Resize if necessary
            if (line_filled + 1 > line_c) {
                line_c *= 4;
                line_v = realloc(line_v, line_c * sizeof(char*));
            }
            
            // Add to array
            line_v[line_filled++] = tmp;
            
            // Split off next line from string
            tmp = strtok(NULL, " ");
        }
        
        // Shrink array to minimum size required
        line_c = line_filled;
        line_v = realloc(line_v, line_c * sizeof(char*));
    }
    
    // Create list of Literals in Clause
    LinkedList* clause_literals = LinkedList_create((void(*)(void*))Literal_destroy);
    
    // Parse each Literal separately
    for (int i = 0; i < line_c; i++) {
        // Parse Literal int (name)
        signed int a = strtol(line_v[i], NULL, 10);
        
        // The last element of each line has to be 0
        if (i == line_c - 1) {
            if (a != 0) {
                fprintf(stderr, "Error - Last element of line was not 0!\n");
                return NULL;
            }
            break;
        }
        
        // 0 is only allowed to be the last element of each line.
        if (a == 0) {
            fprintf(stderr, "Error - Found Literal 0, which is not permitted!\n");
            return NULL;
        }
        
        // Parse Literal
        bool negated = false;
        char* name = malloc(sizeof(int) * sizeof(char) + 1 * sizeof(char));
        
        if (a < 0) {
            negated = true;
            a = abs(a);
        }
        snprintf(name, 33, "%d", a);
        name = realloc(name, (strlen(name) + 1) * sizeof(char));
        
        // Create new GenericLiteral
        GenericLiteral* new_literal = GenericLiteral_create(name, LiteralAssignment_UNSET);
        
        // Check if Literal is already contained in list of all Literals
        // If it is take that one, if not create a new one and add it to
        // the list of all Literals.
        bool literal_already_contained = false;
        for (LinkedListNode* iter = all_literals->head; iter != NULL; iter = iter->next) {
            GenericLiteral* found_literal = iter->data;
            
            if (GenericLiteral_equals(found_literal, new_literal)) {
                GenericLiteral_destroy(new_literal);
                
                new_literal = found_literal;
                literal_already_contained = true;
                break;
            }
        }
        
        if (!literal_already_contained) {
            LinkedList_append(all_literals, new_literal);
        }
        
        // Create new Literal
        Literal* literal = Literal_create(new_literal, negated);
        GenericLiteral_increase_occurrences(new_literal);
        
        // Add Literal to list of Literals
        LinkedList_append(clause_literals, literal);
    }
    free(line_v);
    
    // Create array of Literals from list of Literals
    unsigned int literals_c = clause_literals->size;
    Literal** literals_v = malloc(sizeof(Literal*) * literals_c);
    {
        int i = 0;
        for (LinkedListNode* iter = clause_literals->head; iter != NULL; iter = iter->next) {
            literals_v[i] = iter->data;
            i++;
        }
    }
    LinkedList_destroy(clause_literals, false);
    
    return Clause_create(literals_v, literals_c);
}
void
IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientReportControlBlock rcb,
        uint32_t parametersMask, bool singleRequest)
{
    *error = IED_ERROR_OK;

    MmsError mmsError = MMS_ERROR_NONE;

    bool isBuffered = ClientReportControlBlock_isBuffered(rcb);

    char domainId[65];
    char itemId[129];

    char* rcbReference = ClientReportControlBlock_getObjectReference(rcb);

    MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId);

    strcpy(itemId, rcbReference + strlen(domainId) + 1);

    StringUtils_replace(itemId, '.', '$');

    if (DEBUG_IED_CLIENT)
        printf("DEBUG_IED_CLIENT: setRCBValues for %s\n", rcbReference);

    int itemIdLen = strlen(itemId);

    /* create the list of requested itemIds references */
    LinkedList itemIds = LinkedList_create();
    LinkedList values = LinkedList_create();

    /* add resv/resvTms as first element and rptEna as last element */
    if (parametersMask & RCB_ELEMENT_RESV) {
        if (isBuffered)
            goto error_invalid_parameter;

        strcpy(itemId + itemIdLen, "$Resv");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->resv);
    }

    if (parametersMask & RCB_ELEMENT_RESV_TMS) {
        if (!isBuffered)
            goto error_invalid_parameter;

        strcpy(itemId + itemIdLen, "$ResvTms");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->resvTms);
    }

    if (parametersMask & RCB_ELEMENT_RPT_ID) {
        strcpy(itemId + itemIdLen, "$RptID");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->rptId);
    }

    if (parametersMask & RCB_ELEMENT_DATSET) {
        strcpy(itemId + itemIdLen, "$DatSet");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->datSet);
    }

    if (parametersMask & RCB_ELEMENT_ENTRY_ID) {
        strcpy(itemId + itemIdLen, "$EntryID");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->entryId);
    }

    if (parametersMask & RCB_ELEMENT_OPT_FLDS) {
        strcpy(itemId + itemIdLen, "$OptFlds");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->optFlds);
    }

    if (parametersMask & RCB_ELEMENT_BUF_TM) {
        strcpy(itemId + itemIdLen, "$BufTm");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->bufTm);
    }

    if (parametersMask & RCB_ELEMENT_TRG_OPS) {
        strcpy(itemId + itemIdLen, "$TrgOps");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->trgOps);
    }

    if (parametersMask & RCB_ELEMENT_INTG_PD) {
        strcpy(itemId + itemIdLen, "$IntgPd");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->intgPd);
    }

    if (parametersMask & RCB_ELEMENT_GI) {
        strcpy(itemId + itemIdLen, "$GI");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->gi);
    }

    if (parametersMask & RCB_ELEMENT_PURGE_BUF) {
        if (!isBuffered)
            goto error_invalid_parameter;

        strcpy(itemId + itemIdLen, "$PurgeBuf");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->purgeBuf);
    }

    if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY) {
        if (!isBuffered)
            goto error_invalid_parameter;

        strcpy(itemId + itemIdLen, "$TimeOfEntry");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->timeOfEntry);
    }

    if (parametersMask & RCB_ELEMENT_RPT_ENA) {
        strcpy(itemId + itemIdLen, "$RptEna");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, rcb->rptEna);
    }

    if (singleRequest) {
        LinkedList accessResults = NULL;

        MmsConnection_writeMultipleVariables(self->connection, &mmsError, domainId, itemIds, values, &accessResults);

        if (accessResults != NULL)
            LinkedList_destroyDeep(accessResults, (LinkedListValueDeleteFunction) MmsValue_delete);

        *error = iedConnection_mapMmsErrorToIedError(mmsError);
        goto exit_function;
    }
    else {
        LinkedList itemIdElement = LinkedList_getNext(itemIds);
        LinkedList valueElement = LinkedList_getNext(values);

        while (itemIdElement != NULL) {
            char* rcbItemId = (char*) itemIdElement->data;
            MmsValue* value = (MmsValue*) valueElement->data;

            MmsConnection_writeVariable(self->connection, &mmsError, domainId, rcbItemId, value);

            if (mmsError != MMS_ERROR_NONE)
                break;

            itemIdElement = LinkedList_getNext(itemIdElement);
            valueElement = LinkedList_getNext(valueElement);
        }

        *error = iedConnection_mapMmsErrorToIedError(mmsError);
        goto exit_function;
    }

    error_invalid_parameter:
    *error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;

    exit_function:
    LinkedList_destroy(itemIds);
    LinkedList_destroyStatic(values);
}
Formula* DIMACSParser_parse_formula(char* str) {
    // Split string into array of lines
    unsigned int lines_c = 10;
    char** lines_v = malloc(lines_c * sizeof(char*));
    {
        unsigned int lines_filled = 0;
        
        char* tmp = strtok(str, "\n");
        while (tmp != NULL) {
            // Resize if necessary
            if (lines_filled + 1 > lines_c) {
                lines_c *= 4;
                lines_v = realloc(lines_v, lines_c * sizeof(char*));
            }
            
            // Add to array
            lines_v[lines_filled++] = tmp;
            
            // Split off next line from string
            tmp = strtok(NULL, "\n");
        }
        
        // Shrink array to minimum size required
        lines_c = lines_filled;
        lines_v = realloc(lines_v, lines_c * sizeof(char*));
    }
    
    // Skip first lines with comments
    unsigned int linec = 0;
    for (linec = 0; linec < lines_c; linec++) {
        if (lines_v[linec][0] == 'c') {
            // skip
        } else {
            break;
        }
    }
    
    unsigned int literals_count = 0;
    unsigned int clauses_count = 0;
    
    // Parse problem line
    {
        bool problem_line_error = false;
        
        // Check if problem line has exactly these values separated by whitespaces:
        // "p"
        // "cnf"
        // <Number of Literals>
        // <Number of Clauses>
        int i = 0;
        char* tmp = strtok(lines_v[linec], " ");
        while (tmp != NULL) {
            if (i == 0 && !strcmp(tmp, "p") == 0) {
                problem_line_error = true;
            } else if (i == 1 && !strcmp(tmp, "cnf") == 0) {
                problem_line_error = true;
            } else if (i == 2) {
                literals_count = strtol(tmp, NULL, 10);
            } else if (i == 3) {
                clauses_count = strtol(tmp, NULL, 10);
            }
            
            i++;
            tmp = strtok(NULL, " ");
        }
        
        if (i != 4) {
            problem_line_error = true;
        }
        
        if (problem_line_error) {
            fprintf(stderr, "Error - missing/malformed problem line\n");
            free(lines_v);
            return NULL;
        }
        
        if (literals_count == 0) {
            fprintf(stderr, "Error - number of literals is 0 according to problem line!\n");
            fprintf(stderr, " - this can't be right\n");
            free(lines_v);
            return NULL;
        }
        
        if (clauses_count == 0) {
            fprintf(stderr, "Error - number of clauses is 0 according to problem line!\n");
            fprintf(stderr, " - this can't be right\n");
            free(lines_v);
            return NULL;
        }
    }
    linec++;
    
    // Create list of ALL Literals in this Formula
    LinkedList* all_literals = LinkedList_create((void(*)(void*))GenericLiteral_destroy);
    
    // Create list of Clauses in this Formula
    LinkedList* clauses = LinkedList_create((void(*)(void*))Clause_destroy);
    
    // Parse Clauses
    unsigned int clauses_found = 0;
    
    for (; linec < lines_c; linec++) {
        // Ignore it if the last line is empty
        if (linec == lines_c - 1) {
            if (strcmp(lines_v[linec],"") == 0) {
                continue;
            }
        }
        
        Clause* clause = DIMACSParser_parse_clause(lines_v[linec], all_literals);
        if (clause == NULL) {
            free(lines_v);
            LinkedList_destroy(all_literals, true);
            LinkedList_destroy(clauses, true);
            return NULL;
        }
        
        LinkedList_append(clauses, clause);
        clauses_found++;
    }
    free(lines_v);
    
    // Check if given number of Clauses was correct
    if (clauses_count != clauses_found) {
        fprintf(stderr, "Error - number of clauses given in problem line is not correct!\n");
        LinkedList_destroy(all_literals, true);
        LinkedList_destroy(clauses, true);
        return NULL;
    }
    
    // Check if given number of Literals was correct
    if (literals_count != all_literals->size) {
        fprintf(stderr, "Error - number of literals given in problem line is not correct!\n");
        LinkedList_destroy(all_literals, true);
        LinkedList_destroy(clauses, true);
        return NULL;
    }
    
    // Convert list of all literals to array
    int all_literals_c = all_literals->size;
    GenericLiteral** all_literals_v = malloc(all_literals_c * sizeof(GenericLiteral*));
    {
        int i = 0;
        for (LinkedListNode* iter = all_literals->head; iter != NULL; iter = iter->next) {
            GenericLiteral* lit = iter->data;
            
            all_literals_v[i] = lit;
            
            i++;
        }
    }
    LinkedList_destroy(all_literals, false);
    
    // Create Formula from list of Clauses and array of all Literals
    return Formula_create(clauses, all_literals_v, all_literals_c);
}
Exemple #26
0
static void
sendReport(ReportControl* self, bool isIntegrity, bool isGI)
{
    LinkedList reportElements = LinkedList_create();

    LinkedList deletableElements = LinkedList_create();

    MmsValue* rptId = ReportControl_getRCBValue(self, "RptID");
    MmsValue* optFlds = ReportControl_getRCBValue(self, "OptFlds");
    MmsValue* datSet = ReportControl_getRCBValue(self, "DatSet");

    LinkedList_add(reportElements, rptId);
    LinkedList_add(reportElements, optFlds);

    /* delete option fields for unsupported options */
    MmsValue_setBitStringBit(optFlds, 5, false); /* data-reference */
    MmsValue_setBitStringBit(optFlds, 7, false); /* entryID */
    MmsValue_setBitStringBit(optFlds, 9, false); /* segmentation */

    MmsValue* sqNum = ReportControl_getRCBValue(self, "SqNum");

    if (MmsValue_getBitStringBit(optFlds, 1)) /* sequence number */
        LinkedList_add(reportElements, sqNum);

    if (MmsValue_getBitStringBit(optFlds, 2)) { /* report time stamp */
        LinkedList_add(reportElements, self->timeOfEntry);
    }

    if (MmsValue_getBitStringBit(optFlds, 4)) /* data set reference */
        LinkedList_add(reportElements, datSet);

    if (MmsValue_getBitStringBit(optFlds, 6)) { /* bufOvfl */
        MmsValue* bufOvfl = MmsValue_newBoolean(false);

        LinkedList_add(reportElements, bufOvfl);
        LinkedList_add(deletableElements, bufOvfl);
    }

    if (MmsValue_getBitStringBit(optFlds, 8))
        LinkedList_add(reportElements, self->confRev);

    if (isGI || isIntegrity)
        MmsValue_setAllBitStringBits(self->inclusionField);
    else
        MmsValue_deleteAllBitStringBits(self->inclusionField);

    LinkedList_add(reportElements, self->inclusionField);


    /* add data set value elements */
    int i = 0;
    for (i = 0; i < self->dataSet->elementCount; i++) {

        if (isGI || isIntegrity)
            LinkedList_add(reportElements, self->dataSet->fcda[i]->value);
        else {
            if (self->inclusionFlags[i] != REPORT_CONTROL_NONE) {
                LinkedList_add(reportElements, self->dataSet->fcda[i]->value);
                MmsValue_setBitStringBit(self->inclusionField, i, true);
            }
        }
    }

    /* add reason code to report if requested */
    if (MmsValue_getBitStringBit(optFlds, 3)) {
        for (i = 0; i < self->dataSet->elementCount; i++) {

            if (isGI || isIntegrity) {
                MmsValue* reason = MmsValue_newBitString(6);

                if (isGI)
                    MmsValue_setBitStringBit(reason, 5, true);

                if (isIntegrity)
                    MmsValue_setBitStringBit(reason, 4, true);

                LinkedList_add(reportElements, reason);
                LinkedList_add(deletableElements, reason);
            }
            else if (self->inclusionFlags[i] != REPORT_CONTROL_NONE) {
                MmsValue* reason = MmsValue_newBitString(6);

                switch(self->inclusionFlags[i]) {
                case REPORT_CONTROL_QUALITY_CHANGED:
                    MmsValue_setBitStringBit(reason, 2, true);
                    break;
                case REPORT_CONTROL_VALUE_CHANGED:
                    MmsValue_setBitStringBit(reason, 1, true);
                    break;
                case REPORT_CONTROL_VALUE_UPDATE:
                    MmsValue_setBitStringBit(reason, 3, true);
                    break;
                }

                LinkedList_add(reportElements, reason);
                LinkedList_add(deletableElements, reason);
            }
        }
    }

    /* clear inclusion flags */
    for (i = 0; i < self->dataSet->elementCount; i++) {
        self->inclusionFlags[i] = REPORT_CONTROL_NONE;
    }

    MmsServerConnection_sendInformationReportVMDSpecific(self->clientConnection, "RPT", reportElements);

    /* Increase sequence number */
    self->sqNum++;
    MmsValue_setUint16(sqNum, self->sqNum);

    LinkedList_destroyDeep(deletableElements, (LinkedListValueDeleteFunction) MmsValue_delete);
    LinkedList_destroyStatic(reportElements);

    /* clear GI flag */
    if (isGI) {
        MmsValue* gi = ReportControl_getRCBValue(self, "GI");
        self->gi = false;
        MmsValue_setBoolean(gi, false);
    }
}
Exemple #27
0
LinkedList /*<char*>*/
IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
        char* logicalNodeReference, ACSIClass acsiClass)
{
    if (self->logicalDevices == NULL)
        IedConnection_getDeviceModelFromServer(self, error);

    char lnRefCopy[193];

    strncpy(lnRefCopy, logicalNodeReference, 192);
	lnRefCopy[192] = 0;

    char* ldSep = strchr(lnRefCopy, '/');

    if (ldSep == NULL) {
        *error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT;
        return NULL;
    }

    *ldSep = 0;

    char* logicalDeviceName = lnRefCopy;

    char* logicalNodeName = ldSep + 1;

    // search for logical device

    LinkedList device = LinkedList_getNext(self->logicalDevices);

    bool deviceFound = false;

    ICLogicalDevice* ld;

    while (device != NULL) {
        ld = (ICLogicalDevice*) device->data;

        if (strcmp(logicalDeviceName, ld->name) == 0) {
            deviceFound = true;
            break;
        }

        device = LinkedList_getNext(device);
    }

    if (!deviceFound) {
        *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
        return NULL;
    }

    LinkedList lnDirectory = LinkedList_create();

    switch (acsiClass) {

    case ACSI_CLASS_DATA_OBJECT:
        {
            LinkedList variable = LinkedList_getNext(ld->variables);

            while (variable != NULL) {
                char* variableName = (char*) variable->data;

                char* fcPos = strchr(variableName, '$');

                if (fcPos != NULL) {
                    if (memcmp(fcPos + 1, "RP", 2) == 0)
                        goto next_element;

                    if (memcmp(fcPos + 1, "BR", 2) == 0)
                        goto next_element;

                    if (memcmp(fcPos + 1, "GO", 2) == 0)
                        goto next_element;

                    int lnNameLen = fcPos - variableName;

                    if (strncmp(variableName, logicalNodeName, lnNameLen) == 0) {
                        char* fcEndPos = strchr(fcPos + 1, '$');

                        if (fcEndPos != NULL) {
                            char* nameEndPos = strchr(fcEndPos + 1, '$');

                            if (nameEndPos == NULL) {
                                char* dataObjectName = copyString(fcEndPos + 1);

                                if (!addToStringSet(lnDirectory, dataObjectName))
                                    free(dataObjectName);
                            }
                        }
                    }
                }

                next_element:

                variable = LinkedList_getNext(variable);
            }
        }
        break;

    case ACSI_CLASS_BRCB:
        addVariablesWithFc("BR", logicalNodeName, ld->variables, lnDirectory);
        break;

    case ACSI_CLASS_URCB:
        addVariablesWithFc("RP", logicalNodeName, ld->variables, lnDirectory);
        break;

    case ACSI_CLASS_GoCB:
        addVariablesWithFc("GO", logicalNodeName, ld->variables, lnDirectory);
        break;

    case ACSI_CLASS_DATA_SET:
        {
            LinkedList dataSet = LinkedList_getNext(ld->dataSets);

            while (dataSet != NULL) {
                char* dataSetName = (char*) dataSet->data;

                char* fcPos = strchr(dataSetName, '$');

                if (fcPos == NULL)
                    goto next_data_set_element;

                size_t lnNameLen = fcPos - dataSetName;

                if (strlen(logicalNodeName) != lnNameLen)
                    goto next_data_set_element;

                if (memcmp(dataSetName, logicalNodeName, lnNameLen) != 0)
                    goto next_data_set_element;

                LinkedList_add(lnDirectory, copyString(fcPos + 1));

                next_data_set_element:

                dataSet = LinkedList_getNext(dataSet);
            }
        }
        break;

    default:
        printf("ACSI class not yet supported!\n");
        break;
    }

    *error = IED_ERROR_OK;
    return lnDirectory;
}
Exemple #28
0
LinkedList /*<char*>*/
IedConnection_getLogicalNodeVariables(IedConnection self, IedClientError* error,
        char* logicalNodeReference)
{
    if (self->logicalDevices == NULL)
        IedConnection_getDeviceModelFromServer(self, error);

    char lnRefCopy[193];

    strncpy(lnRefCopy, logicalNodeReference, 192);
	lnRefCopy[192] = 0;

    char* ldSep = strchr(lnRefCopy, '/');

    *ldSep = 0;

    char* logicalDeviceName = lnRefCopy;

    char* logicalNodeName = ldSep + 1;

    // search for logical device

    LinkedList device = LinkedList_getNext(self->logicalDevices);

    bool deviceFound = false;

    ICLogicalDevice* ld;

    while (device != NULL) {
        ld = (ICLogicalDevice*) device->data;

        if (strcmp(logicalDeviceName, ld->name) == 0) {
            deviceFound = true;
            break;
        }

        device = LinkedList_getNext(device);
    }

    if (!deviceFound) {
        *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
        return NULL;
    }

    if (DEBUG_IED_CLIENT)
        printf("DEBUG_IED_CLIENT: Found LD %s search for variables of LN %s ...\n", logicalDeviceName, logicalNodeName);

    LinkedList variable = LinkedList_getNext(ld->variables);

    LinkedList lnDirectory = LinkedList_create();

    while (variable != NULL) {
        char* variableName = (char*) variable->data;

        char* fcPos = strchr(variableName, '$');

        if (fcPos != NULL) {
            int lnNameLen = fcPos - variableName;

            if (strncmp(variableName, logicalNodeName, lnNameLen) == 0) {
                LinkedList_add(lnDirectory, copyString(fcPos + 1));
            }
        }

        variable = LinkedList_getNext(variable);
    }

    *error = IED_ERROR_OK;
    return lnDirectory;
}
Exemple #29
0
LinkedList /* <char*> */
IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, char* dataSetReference, bool* isDeletable)
{
    bool deletable = false;

    LinkedList dataSetMembers = NULL;

    char domainIdBuffer[65];
    char itemIdBuffer[129];

    char* domainId = NULL;
    char* itemId = NULL;

    bool isAssociationSpecific = false;

    if (dataSetReference[0] != '@') {
        domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
        itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer);
        StringUtils_replace(itemId, '.', '$');
    }
    else {
        itemId = dataSetReference;
        isAssociationSpecific = true;
    }

    MmsError mmsError;

    LinkedList entries;

    if (isAssociationSpecific)
        entries = MmsConnection_readNamedVariableListDirectoryAssociationSpecific(self->connection,
                &mmsError, itemId, &deletable);
    else
        entries = MmsConnection_readNamedVariableListDirectory(self->connection,
                &mmsError, domainId, itemId, &deletable);

    if (mmsError == MMS_ERROR_NONE) {

        LinkedList entry = LinkedList_getNext(entries);

        dataSetMembers = LinkedList_create();

        while (entry != NULL) {
            MmsVariableAccessSpecification* varAccessSpec = (MmsVariableAccessSpecification*) entry->data;

            char* objectReference = MmsMapping_varAccessSpecToObjectReference(varAccessSpec);

            LinkedList_add(dataSetMembers, objectReference);

            entry = LinkedList_getNext(entry);
        }

        if (isDeletable != NULL)
            *isDeletable = deletable;

        LinkedList_destroyDeep(entries, (LinkedListValueDeleteFunction) MmsVariableAccessSpecification_destroy);
    }

    *error = iedConnection_mapMmsErrorToIedError(mmsError);

    return dataSetMembers;
}
Exemple #30
0
static LinkedList
getDataDirectory(IedConnection self, IedClientError* error,
        char* dataReference, bool withFc)
{
    if (self->logicalDevices == NULL)
        IedConnection_getDeviceModelFromServer(self, error);

    char dataRefCopy[193];

    strncpy(dataRefCopy, dataReference, 192);
	dataRefCopy[192] = 0;

    char* ldSep = strchr(dataRefCopy, '/');

    *ldSep = 0;

    char* logicalDeviceName = dataRefCopy;

    char* logicalNodeName = ldSep + 1;

    char* logicalNodeNameEnd = strchr(logicalNodeName, '.');

    if (logicalNodeNameEnd == NULL) {
        *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
        return NULL;
    }

    int logicalNodeNameLen = logicalNodeNameEnd - logicalNodeName;

    char* dataNamePart = logicalNodeNameEnd + 1;

    int dataNamePartLen = strlen(dataNamePart);

    if (dataNamePartLen < 1) {
        *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
        return NULL;
    }

    StringUtils_replace(dataNamePart, '.', '$');

    // search for logical device

    LinkedList device = LinkedList_getNext(self->logicalDevices);

    bool deviceFound = false;

    ICLogicalDevice* ld;

    while (device != NULL) {
        ld = (ICLogicalDevice*) device->data;

        if (strcmp(logicalDeviceName, ld->name) == 0) {
            deviceFound = true;
            break;
        }

        device = LinkedList_getNext(device);
    }

    if (!deviceFound) {
        *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
        return NULL;
    }

    LinkedList variable = LinkedList_getNext(ld->variables);

    LinkedList dataDirectory = LinkedList_create();

    while (variable != NULL) {
        char* variableName = (char*) variable->data;

        char* fcPos = strchr(variableName, '$');

        if (fcPos != NULL) {
            int lnNameLen = fcPos - variableName;

            if (logicalNodeNameLen == lnNameLen) {

                if (memcmp(variableName, logicalNodeName, lnNameLen) == 0) {

                    /* ok we are in the correct logical node */

                    /* skip FC */
                    char* fcEnd = strchr(fcPos + 1, '$');

                    if (fcEnd == NULL)
                        goto next_variable;

                    char* remainingPart = fcEnd + 1;

                    int remainingLen = strlen(remainingPart);

                    if (remainingLen <= dataNamePartLen)
                        goto next_variable;

                    if (remainingPart[dataNamePartLen] == '$') {

                        if (memcmp(dataNamePart, remainingPart, dataNamePartLen) == 0) {

                            char* subElementName = remainingPart + dataNamePartLen + 1;

                            char* subElementNameSep = strchr(subElementName, '$');

                            if (subElementNameSep != NULL)
                                goto next_variable;

                            char* elementName;

                            if (withFc) {
                                int elementNameLen = strlen(subElementName);

                                elementName = (char*) malloc(elementNameLen + 5);
                                memcpy(elementName, subElementName, elementNameLen);
                                elementName[elementNameLen] = '[';
                                elementName[elementNameLen + 1] = *(fcPos + 1);
                                elementName[elementNameLen + 2] = *(fcPos + 2);
                                elementName[elementNameLen + 3] = ']';
                                elementName[elementNameLen + 4] = 0;
                            }
                            else
                                elementName = copyString(subElementName);

                            if (!addToStringSet(dataDirectory, elementName))
                                free(elementName);
                        }
                    }
                }
            }
        }

        next_variable:

        variable = LinkedList_getNext(variable);
    }

    *error = IED_ERROR_OK;
    return dataDirectory;

}