- IEC 61850 client: IedConnection - list of client control objects is protected by a lock

pull/298/head
Michael Zillgith 5 years ago
parent 884c9a8667
commit 77481bbed9

@ -473,8 +473,12 @@ handleLastApplErrorMessage(IedConnection self, MmsValue* lastApplError)
self->lastApplError.ctlNum = MmsValue_toUint32(ctlNum);
self->lastApplError.addCause = (ControlAddCause) MmsValue_toInt32(addCause);
self->lastApplError.error = (ControlLastApplError) MmsValue_toInt32(error);
Semaphore_wait(self->clientControlsLock);
LinkedList control = LinkedList_getNext(self->clientControls);
while (control != NULL) {
while (control) {
ControlObjectClient object = (ControlObjectClient) control->data;
const char* objectRef = ControlObjectClient_getObjectReference(object);
@ -485,6 +489,8 @@ handleLastApplErrorMessage(IedConnection self, MmsValue* lastApplError)
control = LinkedList_getNext(control);
}
Semaphore_post(self->clientControlsLock);
}
static void
@ -515,9 +521,11 @@ informationReportHandler(void* parameter, char* domainName,
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: RCVD CommandTermination for %s/%s\n", domainName, variableListName);
Semaphore_wait(self->clientControlsLock);
LinkedList control = LinkedList_getNext(self->clientControls);
while (control != NULL) {
while (control) {
ControlObjectClient object = (ControlObjectClient) control->data;
const char* objectRef = ControlObjectClient_getObjectReference(object);
@ -527,6 +535,8 @@ informationReportHandler(void* parameter, char* domainName,
control = LinkedList_getNext(control);
}
Semaphore_post(self->clientControlsLock);
}
MmsValue_delete(value);
@ -585,6 +595,7 @@ createNewConnectionObject(TLSConfiguration tlsConfig, bool useThreads)
if (self) {
self->enabledReports = LinkedList_create();
self->logicalDevices = NULL;
self->clientControlsLock = Semaphore_create(1);
self->clientControls = LinkedList_create();
@ -810,6 +821,7 @@ IedConnection_destroy(IedConnection self)
LinkedList_destroyStatic(self->clientControls);
Semaphore_destroy(self->clientControlsLock);
Semaphore_destroy(self->outstandingCallsLock);
Semaphore_destroy(self->stateMutex);
Semaphore_destroy(self->reportHandlerMutex);
@ -3796,13 +3808,21 @@ IedConnection_getLastApplError(IedConnection self)
void
iedConnection_addControlClient(IedConnection self, ControlObjectClient control)
{
Semaphore_wait(self->clientControlsLock);
LinkedList_add(self->clientControls, control);
Semaphore_post(self->clientControlsLock);
}
void
iedConnection_removeControlClient(IedConnection self, ControlObjectClient control)
{
Semaphore_wait(self->clientControlsLock);
LinkedList_remove(self->clientControls, control);
Semaphore_post(self->clientControlsLock);
}
FileDirectoryEntry

@ -1957,14 +1957,32 @@ ControlObjectClient_createEx(const char* objectReference, IedConnection connecti
LIB61850_API void
ControlObjectClient_destroy(ControlObjectClient self);
/**
* Cause of the \ref ControlObjectClient_ControlActionHandler invocation
*/
typedef enum
{
CONTROL_ACTION_TYPE_SELECT = 0,
CONTROL_ACTION_TYPE_OPERATE = 1,
CONTROL_ACTION_TYPE_CANCEL = 2
CONTROL_ACTION_TYPE_SELECT = 0, /** < callback was invoked because of a select command */
CONTROL_ACTION_TYPE_OPERATE = 1, /** < callback was invoked because of an operate command */
CONTROL_ACTION_TYPE_CANCEL = 2 /** < callback was invoked because of a cancel command */
} ControlActionType;
/**
* \brief A callback handler that is invoked when a command termination message is received.
*
* This callback is invoked whenever a CommandTermination+ or CommandTermination- message is received.
* To distinguish between a CommandTermination+ and CommandTermination- please use the
* ControlObjectClient_getLastApplError function.
*
* NOTE: Do not call \ref ControlObjectClient_destroy inside of this callback! Doing so will cause a dead-lock.
*
* \param invokeId invoke ID of the command sent by the client
* \param parameter the user parameter that is passed to the callback function
* \param err the error code when an error occurred, or IED_ERROR_OK
* \param type control action type that caused the callback
* \param success true, when the command was successful, false otherwise
*
*/
typedef void
(*ControlObjectClient_ControlActionHandler) (uint32_t invokeId, void* parameter, IedClientError err, ControlActionType type, bool success);
@ -2196,7 +2214,7 @@ ControlObjectClient_setOrigin(ControlObjectClient self, const char* orIdent, int
* NOTE: Some non-standard compliant servers may require this to accept oper/cancel requests
*
* \param self the ControlObjectClient instance
* \param useContantT enable this behaviour with true, disable with false
* \param useContantT enable this behavior with true, disable with false
*/
LIB61850_API void
ControlObjectClient_useConstantT(ControlObjectClient self, bool useConstantT);
@ -2233,13 +2251,15 @@ ControlObjectClient_setSynchroCheck(ControlObjectClient self, bool value);
/**
* \brief Private a callback handler that is invoked when a command termination message is received.
* \brief A callback handler that is invoked when a command termination message is received.
*
* This callback is invoked whenever a CommandTermination+ or CommandTermination- message is received.
* To distinguish between a CommandTermination+ and CommandTermination- please use the
* ControlObjectClient_getLastApplError function.
*
* \param parameter the user paramter that is passed to the callback function
* NOTE: Do not call \ref ControlObjectClient_destroy inside of this callback! Doing so will cause a dead-lock.
*
* \param parameter the user parameter that is passed to the callback function
* \param controlClient the ControlObjectClient instance
*/
typedef void (*CommandTerminationHandler) (void* parameter, ControlObjectClient controlClient);

@ -56,7 +56,10 @@ struct sIedConnection
IedConnectionState state;
LinkedList enabledReports;
LinkedList logicalDevices;
Semaphore clientControlsLock;
LinkedList clientControls;
LastApplError lastApplError;
Semaphore stateMutex;

Loading…
Cancel
Save