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

@ -1957,14 +1957,32 @@ ControlObjectClient_createEx(const char* objectReference, IedConnection connecti
LIB61850_API void LIB61850_API void
ControlObjectClient_destroy(ControlObjectClient self); ControlObjectClient_destroy(ControlObjectClient self);
/**
* Cause of the \ref ControlObjectClient_ControlActionHandler invocation
*/
typedef enum typedef enum
{ {
CONTROL_ACTION_TYPE_SELECT = 0, CONTROL_ACTION_TYPE_SELECT = 0, /** < callback was invoked because of a select command */
CONTROL_ACTION_TYPE_OPERATE = 1, CONTROL_ACTION_TYPE_OPERATE = 1, /** < callback was invoked because of an operate command */
CONTROL_ACTION_TYPE_CANCEL = 2 CONTROL_ACTION_TYPE_CANCEL = 2 /** < callback was invoked because of a cancel command */
} ControlActionType; } 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 typedef void
(*ControlObjectClient_ControlActionHandler) (uint32_t invokeId, void* parameter, IedClientError err, ControlActionType type, bool success); (*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 * NOTE: Some non-standard compliant servers may require this to accept oper/cancel requests
* *
* \param self the ControlObjectClient instance * \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 LIB61850_API void
ControlObjectClient_useConstantT(ControlObjectClient self, bool useConstantT); 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. * This callback is invoked whenever a CommandTermination+ or CommandTermination- message is received.
* To distinguish between a CommandTermination+ and CommandTermination- please use the * To distinguish between a CommandTermination+ and CommandTermination- please use the
* ControlObjectClient_getLastApplError function. * 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 * \param controlClient the ControlObjectClient instance
*/ */
typedef void (*CommandTerminationHandler) (void* parameter, ControlObjectClient controlClient); typedef void (*CommandTerminationHandler) (void* parameter, ControlObjectClient controlClient);

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

Loading…
Cancel
Save