- fixed memory cleanup in GOOSE subscriber

- added GooseReceiver_isRunning function
- updated goose_subscriber example
This commit is contained in:
Michael Zillgith 2017-06-12 22:22:45 +02:00
parent dcbc3de0de
commit 3ac4cd88df
10 changed files with 65 additions and 28 deletions

View file

@ -17,7 +17,10 @@ add_subdirectory(iec61850_client_example2)
add_subdirectory(iec61850_client_example3)
add_subdirectory(iec61850_client_example4)
add_subdirectory(iec61850_client_example5)
IF(WIN32)
else()
add_subdirectory(iec61850_client_example_files)
endif()
add_subdirectory(iec61850_client_example_reporting)
add_subdirectory(iec61850_client_example_log)
add_subdirectory(mms_client_example1)

View file

@ -12,8 +12,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#define __STDC_FORMAT_MACROS /* otherwise PRIu64 is not defined for MinGW */
#include <inttypes.h>
static int running = 1;
@ -29,9 +27,10 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
printf(" stNum: %u sqNum: %u\n", GooseSubscriber_getStNum(subscriber),
GooseSubscriber_getSqNum(subscriber));
printf(" timeToLive: %u\n", GooseSubscriber_getTimeAllowedToLive(subscriber));
#ifndef _WIN32
printf(" timestamp: %"PRIu64"\n", GooseSubscriber_getTimestamp(subscriber));
#endif
uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber);
printf(" timestamp: %u.%u\n", (uint32_t) (timestamp / 1000), (uint32_t) (timestamp % 1000));
MmsValue* values = GooseSubscriber_getDataSetValues(subscriber);
@ -45,14 +44,6 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
int
main(int argc, char** argv)
{
MmsValue* dataSetValues = MmsValue_createEmptyArray(4);
int i;
for (i = 0; i < 4; i++) {
MmsValue* dataSetEntry = MmsValue_newBoolean(false);
MmsValue_setElement(dataSetValues, i, dataSetEntry);
}
GooseReceiver receiver = GooseReceiver_create();
if (argc > 1) {
@ -80,5 +71,7 @@ main(int argc, char** argv)
Thread_sleep(100);
}
GooseSubscriber_destroy(subscriber);
GooseReceiver_stop(receiver);
GooseReceiver_destroy(receiver);
}

View file

@ -8,6 +8,8 @@
*
* Note: intended to be used with server_example3 or server_example_files
*
* Note: DOES NOT WORK WITH VISUAL STUDIO because of libgen.h
*
*/
#include "iec61850_client.h"

View file

@ -1,7 +1,7 @@
/*
* goose_receiver.c
*
* Copyright 2014, 2015 Michael Zillgith
* Copyright 2014-2017 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -52,6 +52,9 @@ struct sGooseReceiver {
uint8_t* buffer;
EthernetSocket ethSocket;
LinkedList subscriberList;
#if (CONFIG_MMS_THREADLESS_STACK == 0)
Thread thread;
#endif
};
@ -66,6 +69,9 @@ GooseReceiver_create()
self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
self->ethSocket = NULL;
self->subscriberList = LinkedList_create();
#if (CONFIG_MMS_THREADLESS_STACK == 0)
self->thread = NULL;
#endif
}
return self;
@ -712,33 +718,52 @@ gooseReceiverLoop(void* threadParameter)
void
GooseReceiver_start(GooseReceiver self)
{
Thread thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, true);
#if (CONFIG_MMS_THREADLESS_STACK == 0)
self->thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, false);
if (thread != NULL) {
if (self->thread != NULL) {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: GOOSE receiver started for interface %s\n", self->interfaceId);
Thread_start(thread);
Thread_start(self->thread);
}
else {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Starting GOOSE receiver failed for interface %s\n", self->interfaceId);
}
#endif
}
bool
GooseReceiver_isRunning(GooseReceiver self)
{
return self->running;
}
void
GooseReceiver_stop(GooseReceiver self)
{
#if (CONFIG_MMS_THREADLESS_STACK == 0)
self->running = false;
Thread_destroy(self->thread);
while (self->stopped == false)
Thread_sleep(1);
#endif
}
void
GooseReceiver_destroy(GooseReceiver self)
{
#if (CONFIG_MMS_THREADLESS_STACK == 0)
if ((self->thread != NULL) && (GooseReceiver_isRunning(self)))
GooseReceiver_stop(self);
#endif
if (self->interfaceId != NULL)
GLOBAL_FREEMEM(self->interfaceId);
LinkedList_destroyDeep(self->subscriberList,
(LinkedListValueDeleteFunction) GooseSubscriber_destroy);
@ -757,9 +782,12 @@ GooseReceiver_startThreadless(GooseReceiver self)
else
self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL);
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_GOOSE);
self->running = true;
if (self->ethSocket != NULL) {
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_GOOSE);
self->running = true;
}
else
self->running = false;
}
void
@ -770,7 +798,7 @@ GooseReceiver_stopThreadless(GooseReceiver self)
self->running = false;
}
// call after reception of ethernet frame and periodically to to house keeping tasks
// call after reception of ethernet frame
bool
GooseReceiver_tick(GooseReceiver self)
{

View file

@ -92,7 +92,7 @@ void
GooseReceiver_start(GooseReceiver self);
/**
* \brief stop the GOOSE receiver running in a speparate thread
* \brief stop the GOOSE receiver running in a separate thread
*
* This function is used to stop the receiver thread started with GooseReceiver_start
*
@ -101,6 +101,14 @@ GooseReceiver_start(GooseReceiver self);
void
GooseReceiver_stop(GooseReceiver self);
bool
GooseReceiver_isRunning(GooseReceiver self);
/**
* \brief Free all resource of the GooseReceiver and all installed GooseSubscribers
*
* \param self the GooseReceiver instance
*/
void
GooseReceiver_destroy(GooseReceiver self);

View file

@ -625,7 +625,7 @@ IedConnection_setGoCBValues(IedConnection self, IedClientError* error, ClientGoo
*
* The requested RCB has to be specified by its object reference. E.g.
*
* "simpleIOGernericIO/LLN0.RP.EventsRCB01"
* "simpleIOGenericIO/LLN0.RP.EventsRCB01"
*
* or
*
@ -1218,7 +1218,8 @@ IedConnection_readUnsigned32Value(IedConnection self, IedClientError* error, con
* \brief read a functional constrained data attribute (FCDA) of type Timestamp (UTC Time)
*
* NOTE: If the timestamp parameter is set to NULL the function allocates a new timestamp instance. Otherwise the
* return value is a pointer to the user provided timestamp instance.
* return value is a pointer to the user provided timestamp instance. The new timestamp instance has to be freed by
* the caller of the function.
*
* \param self the connection object to operate on
* \param error the error code if an error occurs

View file

@ -151,7 +151,8 @@ typedef enum {
GENERIC_BITSTRING = 26,
CONSTRUCTED = 27,
ENTRY_TIME = 28,
PHYCOMADDR = 29
PHYCOMADDR = 29,
CURRENCY = 30
#endif
} DataAttributeType;

View file

@ -2032,7 +2032,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
}
#endif
/* Call writer access handlers */
/* Call write access handlers */
LinkedList writeHandlerListElement = LinkedList_getNext(self->attributeAccessHandlers);
while (writeHandlerListElement != NULL) {

View file

@ -568,4 +568,4 @@ EXPORTS
MmsConnection_setFilestoreBasepath
IedConnection_setFilestoreBasepath
IedServer_setFilestoreBasepath
GooseReceiver_isRunning

View file

@ -646,3 +646,4 @@ EXPORTS
MmsConnection_setFilestoreBasepath
IedConnection_setFilestoreBasepath
IedServer_setFilestoreBasepath
GooseReceiver_isRunning