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); } }
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; }
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); } }
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; }
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); }
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); }
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; }
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; }
/* 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); }
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); } }
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; }
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; }
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; }
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; }