Example #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);
    }
}
Example #2
0
void
IsoServer_destroy(IsoServer self)
{

#if (CONFIG_MMS_THREADLESS_STACK != 1)
    if (self->state == ISO_SVR_STATE_RUNNING)
        IsoServer_stopListening(self);
#endif

#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1)

#if (CONFIG_MMS_SINGLE_THREADED == 1)
    if (self->openClientConnections != NULL)
        LinkedList_destroy(self->openClientConnections);
#else
    if (self->openClientConnections != NULL)
        LinkedList_destroyStatic(self->openClientConnections);
#endif /* (CONFIG_MMS_SINGLE_THREADED == 1) */

#if (CONFIG_MMS_THREADLESS_STACK != 1)
    lockClientConnections(self);
    Semaphore_destroy(self->openClientConnectionsMutex);
#endif

#else
    GLOBAL_FREEMEM(self->openClientConnections);
#endif /* (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) */

#if (CONFIG_MMS_THREADLESS_STACK != 1)
    Semaphore_destroy(self->connectionCounterMutex);
#endif

    GLOBAL_FREEMEM(self);
}
Example #3
0
static void
closeAllOpenClientConnections(IsoServer self)
{

#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1)

#if (CONFIG_MMS_THREADLESS_STACK != 1)
    lockClientConnections(self);
#endif

    LinkedList openConnection = LinkedList_getNext(self->openClientConnections);
    while (openConnection != NULL) {
        IsoConnection isoConnection = (IsoConnection) openConnection->data;

        IsoConnection_close(isoConnection);

#if (CONFIG_MMS_SINGLE_THREADED == 1)
            /* if CONFIG_MMS_SINGLE_THREADED == 0 connection instance will be destroyed by connection thread. */
        IsoConnection_destroy(isoConnection);
#endif

        openConnection = LinkedList_getNext(openConnection);
    }

#if (CONFIG_MMS_SINGLE_THREADED == 1)
    LinkedList_destroyStatic(self->openClientConnections);
    self->openClientConnections = NULL;
#endif


#if (CONFIG_MMS_THREADLESS_STACK != 1)
    unlockClientConnections(self);
#endif

#else
    int i;

    for (i = 0; i < CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; i++) {
        if (self->openClientConnections[i] != NULL) {

            IsoConnection_close(self->openClientConnections[i]);

#if (CONFIG_MMS_SINGLE_THREADED == 1)
            /* if CONFIG_MMS_SINGLE_THREADED == 0 connection instance will be destroyed by connection thread. */
            IsoConnection_destroy(self->openClientConnections[i]);
#endif

        }
    }
#endif
}
static void
deleteValueList(LinkedList values)
{
	LinkedList value = values;
	MmsValue* typedValue;
	while ((value = LinkedList_getNext(value)) != NULL ) {
		typedValue = (MmsValue*) (value->data);

		if (typedValue->deleteValue == 1) {
			MmsValue_delete(typedValue);
		}
	}
	LinkedList_destroyStatic(values);
}
Example #5
0
static void
deleteValueList(LinkedList values)
{
    LinkedList value = LinkedList_getNext(values);

	while (value != NULL ) {
	    MmsValue* typedValue = (MmsValue*) (value->data);

		MmsValue_deleteConditional(typedValue);

		value = LinkedList_getNext(value);
	}

	LinkedList_destroyStatic(values);
}
Example #6
0
void
IedConnection_destroy(IedConnection self)
{
    IedConnection_close(self);

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

    if (self->enabledReports != NULL)
        LinkedList_destroyDeep(self->enabledReports, (LinkedListValueDeleteFunction) ClientReport_destroy);

    LinkedList_destroyStatic(self->clientControls);

    Semaphore_destroy(self->stateMutex);

    free(self);
}
Example #7
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);
    }
}
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);
}
Example #9
0
void
ControlObject_sendCommandTerminationNegative(ControlObject* self)
{
    /* create LastApplError */

    MmsValue lastApplErrorMemory;

    MmsValue* lastApplError = &lastApplErrorMemory;
    lastApplError->type = MMS_STRUCTURE;
    lastApplError->value.structure.size = 5;

    MmsValue* componentContainer[5];

    lastApplError->value.structure.components = componentContainer;

    char ctlObj[130];

    StringUtils_createStringInBuffer(ctlObj, 2, self->ctlObjectName, "$Oper");

    MmsValue ctlObjValueMemory;

    MmsValue* ctlObjValue = &ctlObjValueMemory;
    ctlObjValue->type = MMS_VISIBLE_STRING;
    ctlObjValue->value.visibleString.buf = ctlObj;
    ctlObjValue->value.visibleString.size = sizeof(ctlObj);

    MmsValue_setElement(lastApplError, 0, ctlObjValue);

    MmsValue_setInt32(self->error, CONTROL_ERROR_UNKOWN);
    MmsValue_setInt32(self->addCause, ADD_CAUSE_UNKNOWN);

    MmsValue_setElement(lastApplError, 1, self->error);
    MmsValue_setElement(lastApplError, 2, self->origin);
    MmsValue_setElement(lastApplError, 3, self->ctlNum);
    MmsValue_setElement(lastApplError, 4, self->addCause);

    MmsVariableAccessSpecification lastApplErrorVarSpec;

    lastApplErrorVarSpec.itemId = "LastApplError";
    lastApplErrorVarSpec.domainId = NULL;

    /* create oper variable */

    char itemId[130];

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

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

    MmsVariableAccessSpecification operVarSpec;

    operVarSpec.itemId = itemId;
    operVarSpec.domainId = domainId;


    /* create response */

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

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

    LinkedList_add(varSpecList, &lastApplErrorVarSpec);
    LinkedList_add(varSpecList, &operVarSpec);
    LinkedList_add(values, lastApplError);
    LinkedList_add(values, self->oper);

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

    LinkedList_destroyStatic(varSpecList);
    LinkedList_destroyStatic(values);
} /* ControlObject_sendCommandTerminationNegative() */
Example #10
0
void
IedConnection_setGoCBValues(IedConnection self, IedClientError* error, ClientGooseControlBlock goCB,
        uint32_t parametersMask, bool singleRequest)
{
    *error = IED_ERROR_OK;

    MmsError mmsError = MMS_ERROR_NONE;

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

    MmsMapping_getMmsDomainFromObjectReference(goCB->objectReference, domainId);

    char* itemIdStart = goCB->objectReference + strlen(domainId) + 1;

    char* separator = strchr(itemIdStart, '.');

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

    int separatorOffset = separator - itemIdStart;

    memcpy(itemId, itemIdStart, separatorOffset);

    itemId[separatorOffset] = '$';
    itemId[separatorOffset + 1] = 'G';
    itemId[separatorOffset + 2] = 'O';
    itemId[separatorOffset + 3] = '$';

    strcpy(itemId + separatorOffset + 4, separator + 1);

    if (DEBUG_IED_CLIENT)
        printf("DEBUG_IED_CLIENT: setGoCBValues for %s\n", goCB->objectReference);

    int itemIdLen = strlen(itemId);

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

    /* add rGoEna as last element */
    if (parametersMask & GOCB_ELEMENT_GO_ID) {
        strcpy(itemId + itemIdLen, "$GoID");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->goID);
    }

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

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

    if (parametersMask & GOCB_ELEMENT_CONF_REV) {
        strcpy(itemId + itemIdLen, "$ConfRev");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->confRev);
    }

    if (parametersMask & GOCB_ELEMENT_NDS_COMM) {
        strcpy(itemId + itemIdLen, "$NdsCom");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->ndsCom);
    }

    if (parametersMask & GOCB_ELEMENT_DST_ADDRESS) {
        strcpy(itemId + itemIdLen, "$DstAddress");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->dstAddress);
    }

    if (parametersMask & GOCB_ELEMENT_MIN_TIME) {
        strcpy(itemId + itemIdLen, "$MinTime");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->minTime);
    }

    if (parametersMask & GOCB_ELEMENT_MAX_TIME) {
        strcpy(itemId + itemIdLen, "$MaxTime");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->maxTime);
    }

    if (parametersMask & GOCB_ELEMENT_FIXED_OFFS) {
        strcpy(itemId + itemIdLen, "$FixedOffs");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->fixedOffs);
    }


    if (parametersMask & GOCB_ELEMENT_GO_ENA) {
        strcpy(itemId + itemIdLen, "$GoEna");

        LinkedList_add(itemIds, copyString(itemId));
        LinkedList_add(values, goCB->goEna);
    }

    if (singleRequest) {
        LinkedList accessResults = NULL;

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

        if (accessResults != NULL) {
            LinkedList element = LinkedList_getNext(accessResults);

            while (element != NULL) {
                MmsValue* accessResult = (MmsValue*) element->data;

                if (MmsValue_getDataAccessError(accessResult) != DATA_ACCESS_ERROR_SUCCESS) {
                    mmsError = MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT;
                    break;
                }

                element = LinkedList_getNext(element);
            }

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

exit_function:
    LinkedList_destroy(itemIds);
    LinkedList_destroyStatic(values);
}