int
main(int argc, char** argv)
{
    MmsValue* dataSetValues = MmsValue_createEmtpyArray(4);

    int i;
    for (i = 0; i < 4; i++) {
        MmsValue* dataSetEntry = MmsValue_newBoolean(false);
        MmsValue_setElement(dataSetValues, i, dataSetEntry);
    }

 //   GooseSubscriber subscriber = GooseSubscriber_create("simpleIOGenericIO/LLN0$GO$gcbEvents", dataSetValues);

    GooseSubscriber subscriber = GooseSubscriber_create("simpleIOGenericIO/LLN0$GO$gcbAnalogValues", NULL);

    if (argc > 1) {
    	printf("Set interface id: %s\n", argv[1]);
    	GooseSubscriber_setInterfaceId(subscriber, argv[1]);
    }

    GooseSubscriber_setAppId(subscriber, 1000);

    GooseSubscriber_setListener(subscriber, gooseListener, NULL);

    GooseSubscriber_subscribe(subscriber);

    signal(SIGINT, sigint_handler);

    while (running) {
        Thread_sleep(100);
    }

    GooseSubscriber_destroy(subscriber);
}
void
ClientReportControlBlock_setGI(ClientReportControlBlock self, bool gi)
{
    if (self->gi == NULL)
        self->gi = MmsValue_newBoolean(gi);
    else
        MmsValue_setBoolean(self->gi, gi);
}
void
ClientReportControlBlock_setPurgeBuf(ClientReportControlBlock self, bool purgeBuf)
{
    if (self->purgeBuf == NULL)
        self->purgeBuf = MmsValue_newBoolean(purgeBuf);
    else
        MmsValue_setBoolean(self->purgeBuf, purgeBuf);
}
void
ClientReportControlBlock_setResv(ClientReportControlBlock self, bool resv)
{
    if (self->resv == NULL)
        self->resv = MmsValue_newBoolean(resv);
    else
        MmsValue_setBoolean(self->resv, resv);
}
void
ClientReportControlBlock_setRptEna(ClientReportControlBlock self, bool rptEna)
{
    if (self->rptEna == NULL)
        self->rptEna = MmsValue_newBoolean(rptEna);
    else
        MmsValue_setBoolean(self->rptEna, rptEna);
}
void
ClientGooseControlBlock_setGoEna(ClientGooseControlBlock self, bool goEna)
{
    if (self->goEna == NULL)
        self->goEna = MmsValue_newBoolean(goEna);
    else
        MmsValue_setBoolean(self->goEna, goEna);
}
Exemple #7
0
bool
ControlObjectClient_cancel(ControlObjectClient self)
{
    resetLastApplError(self);

    MmsValue* cancelParameters;

    if (self->hasTimeActivatedMode)
        cancelParameters = MmsValue_createEmptyStructure(6);
    else
        cancelParameters = MmsValue_createEmptyStructure(5);

    MmsValue_setElement(cancelParameters, 0, self->ctlVal);

    int index = 1;

    if (self->hasTimeActivatedMode) {
        MmsValue* operTm = MmsValue_newUtcTimeByMsTime(self->opertime);
        MmsValue_setElement(cancelParameters, index++, operTm);
    }

    MmsValue* origin = createOriginValue(self);

    MmsValue_setElement(cancelParameters, index++, origin);

    MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
    MmsValue_setElement(cancelParameters, index++, ctlNum);

    uint64_t timestamp = Hal_getTimeInMs();
    MmsValue* ctlTime;

    if (self->edition == 2)
        ctlTime = MmsValue_newUtcTimeByMsTime(timestamp);
    else {
        ctlTime = MmsValue_newBinaryTime(false);
        MmsValue_setBinaryTime(ctlTime, timestamp);
    }
    MmsValue_setElement(cancelParameters, index++, ctlTime);

    MmsValue* ctlTest = MmsValue_newBoolean(self->test);
    MmsValue_setElement(cancelParameters, index++, ctlTest);

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

    MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId);

    convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO");

    strncat(itemId, "$Cancel", 64);

    if (DEBUG_IED_CLIENT)
        printf("IED_CLIENT: cancel: %s/%s\n", domainId, itemId);

    MmsError mmsError;

    MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection),
            &mmsError, domainId, itemId, cancelParameters);

    MmsValue_setElement(cancelParameters, 0, NULL);
    MmsValue_delete(cancelParameters);

    if (mmsError != MMS_ERROR_NONE) {
        if (DEBUG_IED_CLIENT)
            printf("IED_CLIENT: cancel failed!\n");
        return false;
    }

    return true;
}
Exemple #8
0
bool
ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t operTime)
{
    bool success = false;

    if (ctlVal == NULL) {
        if (DEBUG_IED_CLIENT)
            printf("IED_CLIENT: operate - (ctlVal == NULL)!\n");

        goto exit_function;
    }

    resetLastApplError(self);

    MmsValue* operParameters;

    if (self->hasTimeActivatedMode)
        operParameters = MmsValue_createEmptyStructure(7);
    else
        operParameters = MmsValue_createEmptyStructure(6);

    MmsValue_setElement(operParameters, 0, ctlVal);

    int index = 1;

    if (self->hasTimeActivatedMode) {
        MmsValue* operTm = MmsValue_newUtcTimeByMsTime(operTime);
        MmsValue_setElement(operParameters, index++, operTm);
    }

    MmsValue* origin = createOriginValue(self);
    MmsValue_setElement(operParameters, index++, origin);

    if (!((self->ctlModel == CONTROL_MODEL_SBO_NORMAL) ||
            (self->ctlModel == CONTROL_MODEL_SBO_ENHANCED)))
    {
        self->ctlNum++;
    }

    MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
    MmsValue_setElement(operParameters, index++, ctlNum);

    uint64_t timestamp = Hal_getTimeInMs();
    MmsValue* ctlTime;

    if (self->edition == 2)
        ctlTime = MmsValue_newUtcTimeByMsTime(timestamp);
    else {
        ctlTime = MmsValue_newBinaryTime(false);
        MmsValue_setBinaryTime(ctlTime, timestamp);
    }

    MmsValue_setElement(operParameters, index++, ctlTime);

    MmsValue* ctlTest = MmsValue_newBoolean(self->test);
    MmsValue_setElement(operParameters, index++, ctlTest);

    MmsValue* check = MmsValue_newBitString(2);
    MmsValue_setBitStringBit(check, 1, self->interlockCheck);
    MmsValue_setBitStringBit(check, 0, self->synchroCheck);
    MmsValue_setElement(operParameters, index++, check);

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

    MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId);

    convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO");

    int controlObjectItemIdLen = strlen(itemId);

    strncat(itemId, "$Oper", 64 - controlObjectItemIdLen);

    if (DEBUG_IED_CLIENT)
        printf("IED_CLIENT: operate: %s/%s\n", domainId, itemId);

    MmsError mmsError;

    MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection),
            &mmsError, domainId, itemId, operParameters);

    MmsValue_setElement(operParameters, 0, NULL);
    MmsValue_delete(operParameters);

    if (mmsError != MMS_ERROR_NONE) {
        if (DEBUG_IED_CLIENT)
            printf("IED_CLIENT: operate failed!\n");

        goto exit_function;
    }

    MmsValue_update(self->ctlVal, ctlVal);
    self->opertime = operTime;

    success = true;

exit_function:
    return success;
}
Exemple #9
0
MmsValue*
mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSize, bool createArray)
{
    MmsValue* valueList = NULL;
    MmsValue* value = NULL;

    int elementCount = listSize;

    if ((elementCount > 1) || createArray)
        valueList = MmsValue_createEmptyArray(elementCount);

    int i = 0;

    for (i = 0; i < elementCount; i++) {
        AccessResult_PR presentType = accessResultList[i]->present;

        if (presentType == AccessResult_PR_failure) {
            if (DEBUG_MMS_CLIENT) printf("access error!\n");

            if (accessResultList[i]->choice.failure.size > 0) {
                int errorCode = (int) accessResultList[i]->choice.failure.buf[0];

                MmsDataAccessError dataAccessError = DATA_ACCESS_ERROR_UNKNOWN;

                if ((errorCode >= 0) && (errorCode < 12))
                    dataAccessError = (MmsDataAccessError) errorCode;

                value = MmsValue_newDataAccessError(dataAccessError);
            }
            else
                value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_UNKNOWN);
        }
        else if (presentType == AccessResult_PR_array) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            value->type = MMS_ARRAY;

            int arrayElementCount =
                    accessResultList[i]->choice.array.list.count;

            value->value.structure.size = arrayElementCount;
            value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(arrayElementCount, sizeof(MmsValue*));

            int j;

            for (j = 0; j < arrayElementCount; j++) {
                value->value.structure.components[j] = mmsMsg_parseDataElement(
                        accessResultList[i]->choice.array.list.array[j]);
            }
        }
        else if (presentType == AccessResult_PR_structure) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            value->type = MMS_STRUCTURE;

            int componentCount =
                    accessResultList[i]->choice.structure.list.count;

            value->value.structure.size = componentCount;
            value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));

            int j;
            for (j = 0; j < componentCount; j++) {
                value->value.structure.components[j] = mmsMsg_parseDataElement(
                        accessResultList[i]->choice.structure.list.array[j]);
            }
        }
        else if (presentType == AccessResult_PR_bitstring) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            value->type = MMS_BIT_STRING;
            int size = accessResultList[i]->choice.bitstring.size;

            value->value.bitString.size = (size * 8)
               - accessResultList[i]->choice.bitstring.bits_unused;

            value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size);
            memcpy(value->value.bitString.buf,
                    accessResultList[i]->choice.bitstring.buf, size);

        }
        else if (presentType == AccessResult_PR_integer) {
            Asn1PrimitiveValue* berInteger =
                    BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf,
                                                accessResultList[i]->choice.integer.size);

            value = MmsValue_newIntegerFromBerInteger(berInteger);
        }
        else if (presentType == AccessResult_PR_unsigned) {
            Asn1PrimitiveValue* berInteger =
                    BerInteger_createFromBuffer(accessResultList[i]->choice.Unsigned.buf,
                                                                    accessResultList[i]->choice.Unsigned.size);

            value = MmsValue_newUnsignedFromBerInteger(berInteger);
        }
        else if (presentType == AccessResult_PR_floatingpoint) {
            int size = accessResultList[i]->choice.floatingpoint.size;

            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            value->type = MMS_FLOAT;

            if (size == 5) { /* FLOAT32 */
                value->value.floatingPoint.formatWidth = 32;
                value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0];

                uint8_t* floatBuf = (accessResultList[i]->choice.floatingpoint.buf + 1);

                value->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(4);

#if (ORDER_LITTLE_ENDIAN == 1)
                    memcpyReverseByteOrder(value->value.floatingPoint.buf, floatBuf, 4);
#else
                    memcpy(value->value.floatingPoint.buf, floatBuf, 4);
#endif

            }

            if (size == 9) { /* FLOAT64 */
                value->value.floatingPoint.formatWidth = 64;
                value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0];

                uint8_t* floatBuf = (accessResultList[i]->choice.floatingpoint.buf + 1);

                value->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(8);

#if (ORDER_LITTLE_ENDIAN == 1)
                memcpyReverseByteOrder(value->value.floatingPoint.buf, floatBuf, 8);
#else
                memcpy(value->value.floatingPoint.buf, floatBuf, 8);
#endif
            }

        }
        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;

            value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1);
            value->value.visibleString.size = strSize;

            memcpy(value->value.visibleString.buf,
                    accessResultList[i]->choice.visiblestring.buf,
                    strSize);

            value->value.visibleString.buf[strSize] = 0;
        }
        else if (presentType == AccessResult_PR_mMSString) {
        	value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));

        	value->type = MMS_STRING;

        	int strSize = accessResultList[i]->choice.mMSString.size;

        	value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1);
        	value->value.visibleString.size = strSize;

        	memcpy(value->value.visibleString.buf,
        			accessResultList[i]->choice.mMSString.buf, strSize);

        	value->value.visibleString.buf[strSize] = 0;

        }
        else if (presentType == AccessResult_PR_utctime) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));

            value->type = MMS_UTC_TIME;
            memcpy(value->value.utcTime,
                    accessResultList[i]->choice.utctime.buf, 8);
        }
        else if (presentType == AccessResult_PR_boolean) {
            value = MmsValue_newBoolean(accessResultList[i]->choice.boolean);
        }
        else if (presentType == AccessResult_PR_binarytime) {
            int size = accessResultList[i]->choice.binarytime.size;

            if (size <= 6) {
                value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
                value->type = MMS_BINARY_TIME;
                value->value.binaryTime.size = size;
                memcpy(value->value.binaryTime.buf, accessResultList[i]->choice.binarytime.buf, size);
            }
        }
        else if (presentType == AccessResult_PR_octetstring) {
        	int size = accessResultList[i]->choice.octetstring.size;

        	value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
        	value->type = MMS_OCTET_STRING;
        	value->value.octetString.maxSize = size;
        	value->value.octetString.size = size;
        	value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size);
        	memcpy(value->value.octetString.buf, accessResultList[i]->choice.octetstring.buf, size);
        }
        else {
            printf("unknown type %i\n", presentType);
            value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID);
        }

        if ((elementCount > 1) || createArray)
            MmsValue_setElement(valueList, i, value);
    }

    if (valueList == NULL)
        valueList = value;

    return valueList;
}
Exemple #10
0
MmsValue*
mmsMsg_parseDataElement(Data_t* dataElement)
{
    MmsValue* value = NULL;

    if (dataElement->present == Data_PR_structure) {
        value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));

        int componentCount = dataElement->choice.structure->list.count;

        value->type = MMS_STRUCTURE;
        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.structure->list.array[i]);
        }
    }
    else if (dataElement->present == Data_PR_array) {
        value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));

        int componentCount = dataElement->choice.array->list.count;

        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]);
        }
    }
    else {
        if (dataElement->present == Data_PR_integer) {
            Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer(
                    dataElement->choice.integer.buf, dataElement->choice.integer.size);

            value = MmsValue_newIntegerFromBerInteger(berInteger);
        }
        else if (dataElement->present == Data_PR_unsigned) {
            Asn1PrimitiveValue* berInteger = BerInteger_createFromBuffer(
                    dataElement->choice.Unsigned.buf, dataElement->choice.Unsigned.size);

            value = MmsValue_newUnsignedFromBerInteger(berInteger);
        }
        else if (dataElement->present == Data_PR_visiblestring) {
            value = MmsValue_newVisibleStringFromByteArray(dataElement->choice.visiblestring.buf,
                    dataElement->choice.visiblestring.size);
        }
        else if (dataElement->present == Data_PR_mMSString) {
            value = MmsValue_newMmsStringFromByteArray(dataElement->choice.mMSString.buf,
                    dataElement->choice.mMSString.size);
        }
        else if (dataElement->present == Data_PR_bitstring) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));

            value->type = MMS_BIT_STRING;
            int size = dataElement->choice.bitstring.size;

            value->value.bitString.size = (size * 8)
                    - dataElement->choice.bitstring.bits_unused;

            value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size);
            memcpy(value->value.bitString.buf,
                    dataElement->choice.bitstring.buf, size);

        }
        else if (dataElement->present == Data_PR_floatingpoint) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            int size = dataElement->choice.floatingpoint.size;

            value->type = MMS_FLOAT;

            if (size == 5) { /* FLOAT32 */
                value->value.floatingPoint.formatWidth = 32;
                value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0];

                uint8_t* floatBuf = (dataElement->choice.floatingpoint.buf + 1);

                value->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(4);
#if (ORDER_LITTLE_ENDIAN == 1)
                memcpyReverseByteOrder(value->value.floatingPoint.buf, floatBuf, 4);
#else
                memcpy(value->value.floatingPoint.buf, floatBuf, 4);
#endif
            }

            if (size == 9) { /* FLOAT64 */
                value->value.floatingPoint.formatWidth = 64;
                value->value.floatingPoint.exponentWidth = dataElement->choice.floatingpoint.buf[0];

                uint8_t* floatBuf = (dataElement->choice.floatingpoint.buf + 1);

                value->value.floatingPoint.buf = (uint8_t*) GLOBAL_MALLOC(8);
#if (ORDER_LITTLE_ENDIAN == 1)
                memcpyReverseByteOrder(value->value.floatingPoint.buf, floatBuf, 8);
#else
                memcpy(value->value.floatingPoint.buf, floatBuf, 8);
#endif
            }
        }
        else if (dataElement->present == Data_PR_utctime) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            value->type = MMS_UTC_TIME;
            memcpy(value->value.utcTime, dataElement->choice.utctime.buf, 8);
        }
        else if (dataElement->present == Data_PR_octetstring) {
            value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
            value->type = MMS_OCTET_STRING;
            int size = dataElement->choice.octetstring.size;
            value->value.octetString.size = size;
            value->value.octetString.maxSize = size;
            value->value.octetString.buf = (uint8_t*) GLOBAL_MALLOC(size);
            memcpy(value->value.octetString.buf, dataElement->choice.octetstring.buf, size);
        }
        else if (dataElement->present == Data_PR_binarytime) {
            int size = dataElement->choice.binarytime.size;

            if (size <= 6) {
                value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
                value->type = MMS_BINARY_TIME;
                value->value.binaryTime.size = size;
                memcpy(value->value.binaryTime.buf, dataElement->choice.binarytime.buf, size);
            }
        }
        else if (dataElement->present == Data_PR_boolean) {
            value = MmsValue_newBoolean(dataElement->choice.boolean);
        }

    }

    return value;
}
Exemple #11
0
static MmsVariableSpecification*
createBufferedReportControlBlock(ReportControlBlock* reportControlBlock,
        ReportControl* reportControl)
{
    MmsVariableSpecification* rcb = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    rcb->name = copyString(reportControlBlock->name);
    rcb->type = MMS_STRUCTURE;

    MmsValue* mmsValue = (MmsValue*) calloc(1, sizeof(MmsValue));
    mmsValue->deleteValue = false;
    mmsValue->type = MMS_STRUCTURE;
    mmsValue->value.structure.size = 15;
    mmsValue->value.structure.components = (MmsValue**) calloc(15, sizeof(MmsValue*));

    rcb->typeSpec.structure.elementCount = 15;

    rcb->typeSpec.structure.elements = (MmsVariableSpecification**) calloc(15,
            sizeof(MmsVariableSpecification*));

    MmsVariableSpecification* namedVariable = 
			(MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("RptID");
    namedVariable->typeSpec.visibleString = -129;
    namedVariable->type = MMS_VISIBLE_STRING;
    rcb->typeSpec.structure.elements[0] = namedVariable;
    mmsValue->value.structure.components[0] = MmsValue_newVisibleString(
            reportControlBlock->rptId);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("RptEna");
    namedVariable->type = MMS_BOOLEAN;
    rcb->typeSpec.structure.elements[1] = namedVariable;
    mmsValue->value.structure.components[1] = MmsValue_newBoolean(false);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("DatSet");
    namedVariable->typeSpec.visibleString = -129;
    namedVariable->type = MMS_VISIBLE_STRING;
    rcb->typeSpec.structure.elements[2] = namedVariable;

    if (reportControlBlock->dataSetName != NULL) {
    	char* dataSetReference = createDataSetReferencForDefaultDataSet(reportControlBlock,
    	            reportControl);
    	mmsValue->value.structure.components[2] = MmsValue_newVisibleString(dataSetReference);
    	free(dataSetReference);
    }
    else
    	mmsValue->value.structure.components[2] = MmsValue_newVisibleString("");

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("ConfRev");
    namedVariable->type = MMS_UNSIGNED;
    namedVariable->typeSpec.unsignedInteger = 32;
    rcb->typeSpec.structure.elements[3] = namedVariable;
    mmsValue->value.structure.components[3] =
            MmsValue_newUnsignedFromUint32(reportControlBlock->confRef);

    reportControl->confRev = mmsValue->value.structure.components[3];

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("OptFlds");
    namedVariable->type = MMS_BIT_STRING;
    namedVariable->typeSpec.bitString = 10;
    rcb->typeSpec.structure.elements[4] = namedVariable;
    mmsValue->value.structure.components[4] = createOptFlds(reportControlBlock);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("BufTm");
    namedVariable->type = MMS_UNSIGNED;
    namedVariable->typeSpec.unsignedInteger = 32;
    rcb->typeSpec.structure.elements[5] = namedVariable;
    mmsValue->value.structure.components[5] =
            MmsValue_newUnsignedFromUint32(reportControlBlock->bufferTime);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("SqNum");
    namedVariable->type = MMS_UNSIGNED;
    namedVariable->typeSpec.unsignedInteger = 16;
    rcb->typeSpec.structure.elements[6] = namedVariable;
    mmsValue->value.structure.components[6] = MmsValue_newUnsigned(16);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("TrgOps");
    namedVariable->type = MMS_BIT_STRING;
    namedVariable->typeSpec.bitString = 6;
    rcb->typeSpec.structure.elements[7] = namedVariable;
    mmsValue->value.structure.components[7] = createTrgOps(reportControlBlock);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("IntgPd");
    namedVariable->type = MMS_UNSIGNED;
    namedVariable->typeSpec.unsignedInteger = 32;
    rcb->typeSpec.structure.elements[8] = namedVariable;
    mmsValue->value.structure.components[8] =
            MmsValue_newUnsignedFromUint32(reportControlBlock->intPeriod);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("GI");
    namedVariable->type = MMS_BOOLEAN;
    rcb->typeSpec.structure.elements[9] = namedVariable;
    mmsValue->value.structure.components[9] = MmsValue_newBoolean(false);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("PurgeBuf");
    namedVariable->type = MMS_BOOLEAN;
    rcb->typeSpec.structure.elements[10] = namedVariable;
    mmsValue->value.structure.components[10] = MmsValue_newBoolean(false);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("EntryID");
    namedVariable->type = MMS_OCTET_STRING;
    namedVariable->typeSpec.octetString = 8;
    rcb->typeSpec.structure.elements[11] = namedVariable;
    mmsValue->value.structure.components[11] = MmsValue_newOctetString(8, 8);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("TimeOfEntry");
    namedVariable->type = MMS_BINARY_TIME;
    rcb->typeSpec.structure.elements[12] = namedVariable;
    mmsValue->value.structure.components[12] = MmsValue_newBinaryTime(false);

    reportControl->timeOfEntry = mmsValue->value.structure.components[12];

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("ResvTms");
    namedVariable->type = MMS_UNSIGNED;
    namedVariable->typeSpec.unsignedInteger = 32;
    rcb->typeSpec.structure.elements[13] = namedVariable;
    mmsValue->value.structure.components[13] = MmsValue_newUnsigned(32);

    namedVariable = (MmsVariableSpecification*) calloc(1, sizeof(MmsVariableSpecification));
    namedVariable->name = copyString("Owner");
    namedVariable->type = MMS_OCTET_STRING;
    namedVariable->typeSpec.octetString = -128;
    rcb->typeSpec.structure.elements[14] = namedVariable;
    mmsValue->value.structure.components[14] = MmsValue_newOctetString(0, 128);

    reportControl->rcbValues = mmsValue;

    return rcb;
}
Exemple #12
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 #13
0
static MmsValue*
parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLength, bool isStructure)
{
    int bufPos = 0;
    int elementLength = 0;

    int elementIndex = 0;

    MmsValue* dataSetValues = NULL;

    while (bufPos < allDataLength) {
        uint8_t tag = buffer[bufPos++];

        bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);

        if (bufPos + elementLength > allDataLength) {
            if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n");
            goto exit_with_error;
        }

        switch (tag) {
        case 0x80: /* reserved for access result */
            break;
        case 0xa1: /* array */
            break;
        case 0xa2: /* structure */
            break;
        case 0x83: /* boolean */
            break;
        case 0x84: /* BIT STRING */
            break;
        case 0x85: /* integer */
            break;
        case 0x86: /* unsigned integer */
            break;
        case 0x87: /* Float */
            break;
        case 0x89: /* octet string */
            break;
        case 0x8a: /* visible string */
            break;
        case 0x8c: /* binary time */
            break;
        case 0x91: /* Utctime */
            break;
        default:
            if (DEBUG_GOOSE_SUBSCRIBER)
                printf("GOOSE_SUBSCRIBER:    found unknown tag %02x\n", tag);
            goto exit_with_error;
        }

        bufPos += elementLength;

        elementIndex++;
    }

    if (isStructure)
        dataSetValues = MmsValue_createEmptyStructure(elementIndex);
    else
        dataSetValues = MmsValue_createEmptyArray(elementIndex);

    elementIndex = 0;
    bufPos = 0;

    while (bufPos < allDataLength) {
        uint8_t tag = buffer[bufPos++];

        bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);

        if (bufPos + elementLength > allDataLength) {
            if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n");
            goto exit_with_error;
        }

        MmsValue* value = NULL;

        switch (tag) {
        case 0xa1: /* array */
            if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER:    found array\n");

            value = parseAllDataUnknownValue(self, buffer + bufPos, elementLength, false);

            if (value == NULL)
                goto exit_with_error;

            break;
        case 0xa2: /* structure */
            if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER:    found structure\n");

            value = parseAllDataUnknownValue(self, buffer + bufPos, elementLength, true);

            if (value == NULL)
                goto exit_with_error;

            break;
        case 0x83: /* boolean */
            if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER:    found boolean\n");
            value = MmsValue_newBoolean(BerDecoder_decodeBoolean(buffer, bufPos));

            break;

        case 0x84: /* BIT STRING */
            {
                int padding = buffer[bufPos];
                int bitStringLength = (8 * (elementLength - 1)) - padding;
                value = MmsValue_newBitString(bitStringLength);
                memcpy(value->value.bitString.buf, buffer + bufPos + 1, elementLength - 1);

            }
            break;
        case 0x85: /* integer */
            value = MmsValue_newInteger(elementLength * 8);
            memcpy(value->value.integer->octets, buffer + bufPos, elementLength);
            value->value.integer->size = elementLength;
            break;
        case 0x86: /* unsigned integer */
            value = MmsValue_newUnsigned(elementLength * 8);
            memcpy(value->value.integer->octets, buffer + bufPos, elementLength);
            value->value.integer->size = elementLength;
            break;
        case 0x87: /* Float */
                if (elementLength == 9)
                    value = MmsValue_newDouble(BerDecoder_decodeDouble(buffer, bufPos));
                else if (elementLength == 5)
                    value = MmsValue_newFloat(BerDecoder_decodeFloat(buffer, bufPos));
            break;

        case 0x89: /* octet string */
            value = MmsValue_newOctetString(elementLength, elementLength);
            memcpy(value->value.octetString.buf, buffer + bufPos, elementLength);
            break;
        case 0x8a: /* visible string */
            value = MmsValue_newVisibleStringFromByteArray(buffer + bufPos, elementLength);
            break;
        case 0x8c: /* binary time */
            if (elementLength == 4)
                value = MmsValue_newBinaryTime(true);
            else if (elementLength == 6)
                value = MmsValue_newBinaryTime(false);

            if ((elementLength == 4) || (elementLength == 6))
                memcpy(value->value.binaryTime.buf, buffer + bufPos, elementLength);

            break;
        case 0x91: /* Utctime */
            if (elementLength == 8) {
                value = MmsValue_newUtcTime(0);
                MmsValue_setUtcTimeByBuffer(value, buffer + bufPos);
            }
            else
                if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER:      UTCTime element is of wrong size!\n");
            break;
        default:
            if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER:    found unkown tag %02x\n", tag);
            goto exit_with_error;
        }

        bufPos += elementLength;

        if (value != NULL) {
            MmsValue_setElement(dataSetValues, elementIndex, value);
            elementIndex++;
        }
    }

    self->dataSetValuesSelfAllocated = true;

    return dataSetValues;

exit_with_error:

    if (dataSetValues != NULL)
        MmsValue_delete(dataSetValues);

    return NULL;
}
Exemple #14
0
IedModel*
ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
{
    int bytesRead = 1;

    bool stateInModel = false;
    int indendation = 0;

    IedModel* model = NULL;
    LogicalDevice* currentLD = NULL;
    LogicalNode* currentLN = NULL;
    ModelNode* currentModelNode = NULL;
    DataSet* currentDataSet = NULL;
    GSEControlBlock* currentGoCB = NULL;

    char nameString[130];
    char nameString2[130];
    char nameString3[130];

    int currentLine = 0;

    while (bytesRead > 0) {
        bytesRead = readLine(fileHandle, lineBuffer, READ_BUFFER_MAX_SIZE);

        currentLine++;

        if (bytesRead > 0) {
            lineBuffer[bytesRead] = 0;

            if (stateInModel) {

                if (StringUtils_startsWith((char*) lineBuffer, "}")) {
                    if (indendation == 1) {
                        stateInModel = false;
                        indendation = 0;
                    }
                    else if (indendation == 2) {
                        indendation = 1;
                    }
                    else if (indendation == 3) {
                        indendation = 2;
                    }
                    else if (indendation == 4) {
                        indendation = 3;
                    }
                    else if (indendation > 4) {
                        currentModelNode = currentModelNode->parent;
                        indendation--;
                    }
                }

                else if (indendation == 1) {
                    if (StringUtils_startsWith((char*) lineBuffer, "LD")) {
                        indendation = 2;

                        if (sscanf((char*) lineBuffer, "LD(%s)", nameString) < 1)
                            goto exit_error;

                        terminateString(nameString, ')');

                        currentLD = LogicalDevice_create(nameString, model);
                    }
                    else
                        goto exit_error;
                }
                else if (indendation == 2) {
                    if (StringUtils_startsWith((char*) lineBuffer, "LN")) {
                        indendation = 3;

                        if (sscanf((char*) lineBuffer, "LN(%s)", nameString) < 1)
                            goto exit_error;

                        terminateString(nameString, ')');

                        currentLN = LogicalNode_create(nameString, currentLD);
                    }
                    else
                        goto exit_error;
                }
                else if (indendation == 3) {
                    if (StringUtils_startsWith((char*) lineBuffer, "DO")) {
                        indendation = 4;

                        int arrayElements = 0;

                        sscanf((char*) lineBuffer, "DO(%s %i)", nameString, &arrayElements);

                        currentModelNode = (ModelNode*)
                                DataObject_create(nameString, (ModelNode*) currentLN, arrayElements);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "DS")) {
                        indendation = 4;

                        sscanf((char*) lineBuffer, "DS(%s)", nameString);
                        terminateString(nameString, ')');

                        currentDataSet = DataSet_create(nameString, currentLN);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "RC")) {
                        int isBuffered;
                        uint32_t confRef;
                        int trgOps;
                        int options;
                        uint32_t bufTm;
                        uint32_t intgPd;

                        int matchedItems = sscanf((char*) lineBuffer, "RC(%s %s %i %s %u %i %i %u %u)",
                                nameString, nameString2, &isBuffered, nameString3, &confRef,
                                &trgOps, &options, &bufTm, &intgPd);

                        if (matchedItems < 9) goto exit_error;

                        char* rptId = NULL;

                        if (strcmp(nameString2, "-") != 0)
                            rptId = nameString2;

                        char* dataSetName = NULL;

                        if (strcmp(nameString3, "-") != 0)
                            dataSetName = nameString3;

                        ReportControlBlock_create(nameString, currentLN, rptId,
                                (bool) isBuffered, dataSetName, confRef, trgOps, options, bufTm, intgPd);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "LC")) {
                        uint32_t trgOps;
                        uint32_t intgPd;
                        int logEna;
                        int withReasonCode;

                        int matchedItems = sscanf((char*) lineBuffer, "LC(%s %s %s %u %u %i %i)",
                                nameString, nameString2, nameString3, &trgOps, &intgPd, &logEna, &withReasonCode);

                        if (matchedItems < 7) goto exit_error;

                        char* dataSet = NULL;
                        if (strcmp(nameString2, "-") != 0)
                            dataSet = nameString2;

                        char* logRef = NULL;
                        if (strcmp(nameString3, "-") != 0)
                            logRef = nameString3;

                        LogControlBlock_create(nameString, currentLN, dataSet, logRef, trgOps, intgPd, logEna, withReasonCode);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "LOG")) {
                        int matchedItems = sscanf((char*) lineBuffer, "LOG(%s)", nameString);

                        if (matchedItems < 1) goto exit_error;

                        /* remove trailing ')' character */
                        int nameLen = strlen(nameString);
                        nameString[nameLen - 1] = 0;

                        Log_create(nameString, currentLN);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "GC")) {
                        uint32_t confRef;
                        int fixedOffs;
                        int minTime = -1;
                        int maxTime = -1;

                        int matchedItems = sscanf((char*) lineBuffer, "GC(%s %s %s %u %i %i %i)",
                                nameString, nameString2, nameString3, &confRef, &fixedOffs, &minTime, &maxTime);

                        if (matchedItems < 5) goto exit_error;

                        currentGoCB = GSEControlBlock_create(nameString, currentLN, nameString2,
                                nameString3, confRef, fixedOffs, minTime, maxTime);

                        indendation = 4;

                    }
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
                    else if (StringUtils_startsWith((char*) lineBuffer, "SG")) {

                        if (strcmp(currentLN->name, "LLN0") != 0) {
                            if (DEBUG_IED_SERVER)
                                printf("Setting group control is not defined in LLN0\n");

                            goto exit_error;
                        }

                        int actSG;
                        int numOfSGs;

                        int matchedItems = sscanf((char*) lineBuffer, "SG(%i %i)", &actSG, &numOfSGs);

                        if (matchedItems < 2)
                            goto exit_error;

                        SettingGroupControlBlock_create(currentLN, actSG, numOfSGs);
                    }
#endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */

                    else {
                        if (DEBUG_IED_SERVER)
                            printf("IED_SERVER: Unknown identifier (%s)\n", lineBuffer);

                        goto exit_error;
                    }

                }
                else if (indendation > 3) {
                    if (StringUtils_startsWith((char*) lineBuffer, "DO")) {
                        indendation++;

                        int arrayElements = 0;

                        int matchedItems = sscanf((char*) lineBuffer, "DO(%s %i)", nameString, &arrayElements);

                        if (matchedItems != 2) goto exit_error;

                        currentModelNode = (ModelNode*) DataObject_create(nameString, currentModelNode, arrayElements);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "DA")) {

                        int arrayElements = 0;

                        int attributeType = 0;
                        int functionalConstraint = 0;
                        int triggerOptions = 0;
                        uint32_t sAddr = 0;

                        sscanf((char*) lineBuffer, "DA(%s %i %i %i %i %u)", nameString, &arrayElements,  &attributeType, &functionalConstraint, &triggerOptions, &sAddr);

                        DataAttribute* dataAttribute = DataAttribute_create(nameString, currentModelNode,
                                (DataAttributeType) attributeType, (FunctionalConstraint) functionalConstraint, triggerOptions, arrayElements, sAddr);

                        char* valueIndicator = strchr((char*) lineBuffer, '=');

                        if (valueIndicator != NULL) {
                            switch (dataAttribute->type) {
                            case IEC61850_UNICODE_STRING_255:
                                {
                                    char* stringStart = valueIndicator + 2;
                                    terminateString(stringStart, '"');
                                    dataAttribute->mmsValue = MmsValue_newMmsString(stringStart);
                                }
                                break;

                            case IEC61850_VISIBLE_STRING_255:
                            case IEC61850_VISIBLE_STRING_129:
                            case IEC61850_VISIBLE_STRING_65:
                            case IEC61850_VISIBLE_STRING_64:
                            case IEC61850_VISIBLE_STRING_32:
                                {
                                    char* stringStart = valueIndicator + 2;
                                    terminateString(stringStart, '"');
                                    dataAttribute->mmsValue = MmsValue_newVisibleString(stringStart);
                                }
                                break;

                            case IEC61850_INT8:
                            case IEC61850_INT16:
                            case IEC61850_INT32:
                            case IEC61850_INT64:
                            case IEC61850_INT128:
                            case IEC61850_ENUMERATED:
                                {
                                    int32_t intValue;
                                    if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error;
                                    dataAttribute->mmsValue = MmsValue_newIntegerFromInt32(intValue);
                                }
                                break;

                            case IEC61850_INT8U:
                            case IEC61850_INT16U:
                            case IEC61850_INT24U:
                            case IEC61850_INT32U:
                                {
                                    uint32_t uintValue;
                                    if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error;
                                    dataAttribute->mmsValue = MmsValue_newUnsignedFromUint32(uintValue);
                                }
                                break;

                            case IEC61850_FLOAT32:
                                {
                                    float floatValue;
                                    if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error;
                                    dataAttribute->mmsValue = MmsValue_newFloat(floatValue);
                                }
                                break;

                            case IEC61850_FLOAT64:
                                {
                                    double doubleValue;
                                    if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error;
                                    dataAttribute->mmsValue = MmsValue_newDouble(doubleValue);
                                }
                                break;

                            case IEC61850_BOOLEAN:
                                {
                                    int boolean;
                                    if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error;
                                    dataAttribute->mmsValue = MmsValue_newBoolean((bool) boolean);
                                }
                                break;

                            default:
                                break;

                            }
                        }

                        int lineLength = strlen((char*) lineBuffer);

                        if (lineBuffer[lineLength - 1] == '{') {
                            indendation++;
                            currentModelNode = (ModelNode*) dataAttribute;
                        }
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "DE")) {
                        sscanf((char*) lineBuffer, "DE(%s)", nameString);
                        terminateString(nameString, ')');

                        DataSetEntry_create(currentDataSet, nameString, -1, NULL);
                    }
                    else if (StringUtils_startsWith((char*) lineBuffer, "PA")) {
                        uint32_t vlanPrio;
                        uint32_t vlanId;
                        uint32_t appId;

                        int matchedItems = sscanf((char*) lineBuffer, "PA(%u %u %u %s)", &vlanPrio, &vlanId, &appId, nameString);

                        if ((matchedItems != 4) || (currentGoCB == NULL)) goto exit_error;

                        terminateString(nameString, ')');

                        if (strlen(nameString) != 12) goto exit_error;

                        if (StringUtils_createBufferFromHexString(nameString, (uint8_t*) nameString2) != 6)
                            goto exit_error;


                        PhyComAddress* dstAddress =
                                PhyComAddress_create((uint8_t) vlanPrio, (uint16_t) vlanId, (uint16_t) appId,
                                        (uint8_t*) nameString2);

                        GSEControlBlock_addPhyComAddress(currentGoCB, dstAddress);

                    }
                    else
                        goto exit_error;
                }


            }
            else {
                if (StringUtils_startsWith((char*) lineBuffer, "MODEL{")) {

                    model = IedModel_create("");
                    stateInModel = true;
                    indendation = 1;
                }
                else if (StringUtils_startsWith((char*) lineBuffer, "MODEL(")) {
                    sscanf((char*) lineBuffer, "MODEL(%s)", nameString);
                    terminateString(nameString, ')');
                    model = IedModel_create(nameString);
                    stateInModel = true;
                    indendation = 1;
                }
                else
                    goto exit_error;
            }
        }
    }

    return model;

exit_error:
    if (DEBUG_IED_SERVER)
        printf("IED_SERVER: error parsing line %i (indendation level = %i)\n", currentLine, indendation);
    IedModel_destroy(model);
    return NULL;
}