Skip to content

Commit

Permalink
- added function IedServer_getNumberOfOpenConnections
Browse files Browse the repository at this point in the history
- IEC 61850/MMS server: refactored connection handling
  • Loading branch information
mzillgith committed Jan 30, 2020
1 parent e834bd0 commit abcf934
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 190 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Changes to version 1.4.1
------------------------
- MMS server: refactored connection handling; more efficient use of HandleSet
- linux/bsd socket layer: replaced select by poll
- removed header dependencies from API headers
- IEC 61850 server: added support for transient data objects
- .NET API: added MmsValue methods BitStringToUInt32BigEndian and BitStringFromUInt32BigEndian
- fixed compilation problem when CONFIG_MMS_THREADLESS_STACK is defined
Expand Down
10 changes: 10 additions & 0 deletions src/iec61850/inc/iec61850_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,16 @@ IedServer_getDataModel(IedServer self);
LIB61850_API bool
IedServer_isRunning(IedServer self);

/**
* \brief Get number of open MMS connections
*
* \param self the instance of IedServer to operate on
*
* \return the number of open and accepted MMS connections
*/
LIB61850_API int
IedServer_getNumberOfOpenConnections(IedServer self);

/**
* \brief Get access to the underlying MmsServer instance.
*
Expand Down
13 changes: 7 additions & 6 deletions src/iec61850/server/impl/ied_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,14 +578,10 @@ singleThreadedServerThread(void* parameter)
printf("IED_SERVER: server thread started!\n");

while (running) {

if (IedServer_waitReady(self, 25) > 0)
MmsServer_handleIncomingMessages(self->mmsServer);
MmsServer_handleIncomingMessages(self->mmsServer);

IedServer_performPeriodicTasks(self);

Thread_sleep(1);

running = mmsMapping->reportThreadRunning;
}

Expand Down Expand Up @@ -613,7 +609,6 @@ IedServer_start(IedServer self, int tcpPort)

Thread_start(self->serverThread);
#else

MmsServer_startListening(self->mmsServer, tcpPort);
MmsMapping_startEventWorkerThread(self->mmsMapping);
#endif
Expand Down Expand Up @@ -683,6 +678,12 @@ IedServer_startThreadless(IedServer self, int tcpPort)
}
}

int
IedServer_getNumberOfOpenConnections(IedServer self)
{
return MmsServer_getConnectionCounter(self->mmsServer);
}

int
IedServer_waitReady(IedServer self, unsigned int timeoutMs)
{
Expand Down
2 changes: 0 additions & 2 deletions src/iec61850/server/mms_mapping/mms_mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -3004,8 +3004,6 @@ GOOSE_processGooseEvents(MmsMapping* self, uint64_t currentTimeInMs)

#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */



static void
processPeriodicTasks(MmsMapping* self)
{
Expand Down
3 changes: 3 additions & 0 deletions src/mms/inc_private/iso_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ IsoServer_startListeningThreadless(IsoServer self);
LIB61850_INTERNAL void
IsoServer_processIncomingMessages(IsoServer self);

LIB61850_INTERNAL int
IsoServer_getConnectionCounter(IsoServer self);

LIB61850_INTERNAL int
IsoServer_waitReady(IsoServer self, unsigned int timeoutMs);

Expand Down
22 changes: 19 additions & 3 deletions src/mms/inc_private/iso_server_private.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* iso_server_private.h
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2020 Michael Zillgith
*
* This file is part of libIEC61850.
*
Expand All @@ -28,7 +28,7 @@
#include "hal_socket.h"

LIB61850_INTERNAL IsoConnection
IsoConnection_create(Socket socket, IsoServer isoServer);
IsoConnection_create(Socket socket, IsoServer isoServer, bool isSingleThread);

LIB61850_INTERNAL void
IsoConnection_start(IsoConnection self);
Expand All @@ -37,14 +37,30 @@ LIB61850_INTERNAL void
IsoConnection_destroy(IsoConnection self);

LIB61850_INTERNAL void
IsoConnection_handleTcpConnection(IsoConnection self);
IsoConnection_callTickHandler(IsoConnection self);

LIB61850_INTERNAL void
IsoConnection_handleTcpConnection(IsoConnection self, bool isSingleThread);

#define ISO_CON_STATE_TERMINATED 2 /* connection has terminated and is ready to be destroyed */
#define ISO_CON_STATE_RUNNING 1 /* connection is newly started */
#define ISO_CON_STATE_STOPPED 0 /* connection is being stopped */

LIB61850_INTERNAL int
IsoConnection_getState(IsoConnection self);

/**
* \brief Add the connection socket to the given HandleSet instance
*/
LIB61850_INTERNAL void
IsoConnection_addToHandleSet(const IsoConnection self, HandleSet handles);

/**
* \brief Remove the connection socket from the given HandleSet instance
*/
LIB61850_INTERNAL void
IsoConnection_removeFromHandleSet(const IsoConnection self, HandleSet handles);

LIB61850_INTERNAL void
private_IsoServer_increaseConnectionCounter(IsoServer self);

Expand Down
10 changes: 10 additions & 0 deletions src/mms/inc_private/mms_server_libinternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,16 @@ MmsServer_handleIncomingMessages(MmsServer self);
LIB61850_INTERNAL void
MmsServer_handleBackgroundTasks(MmsServer self);

/**
* \brief Get number of open connections
*
* \param self the MmsServer instance to operate on
*
* \return the number of open MMS connections
*/
LIB61850_INTERNAL int
MmsServer_getConnectionCounter(MmsServer self);

/**
* \brief Stop the server (for non-threaded operation mode)
*
Expand Down
10 changes: 8 additions & 2 deletions src/mms/iso_mms/server/mms_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ isoConnectionIndicationHandler(IsoConnectionIndication indication,
}
}

#if (CONFIG_MMS_THREADLESS_STACK != 1)
#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED != 1)
void
MmsServer_startListening(MmsServer server, int tcpPort)
{
Expand All @@ -463,7 +463,7 @@ MmsServer_stopListening(MmsServer server)
{
IsoServer_stopListening(server->isoServer);
}
#endif /* (CONFIG_MMS_THREADLESS_STACK != 1)*/
#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED != 1)*/

void
MmsServer_startListeningThreadless(MmsServer self, int tcpPort)
Expand Down Expand Up @@ -504,6 +504,12 @@ MmsServer_handleBackgroundTasks(MmsServer self)
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
}

int
MmsServer_getConnectionCounter(MmsServer self)
{
return IsoServer_getConnectionCounter(self->isoServer);
}

void
MmsServer_callConnectionHandler(MmsServer self, MmsServerConnection connection)
{
Expand Down
106 changes: 76 additions & 30 deletions src/mms/iso_server/iso_connection.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* iso_connection.c
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2020 Michael Zillgith
*
* This file is part of libIEC61850.
*
Expand Down Expand Up @@ -48,9 +48,6 @@

#define TPKT_RFC1006_HEADER_SIZE 4

#define ISO_CON_STATE_RUNNING 1
#define ISO_CON_STATE_STOPPED 0

struct sIsoConnection
{
uint8_t* receiveBuffer;
Expand Down Expand Up @@ -89,6 +86,10 @@ struct sIsoConnection
Thread thread;
Semaphore conMutex;
#endif

#if (CONFIG_MMS_SINGLE_THREADED != 1) || (CONFIG_MMS_THREADLESS_STACK == 1)
HandleSet handleSet;
#endif
};

static void
Expand All @@ -97,15 +98,19 @@ finalizeIsoConnection(IsoConnection self)
if (DEBUG_ISO_SERVER)
printf("ISO_SERVER: finalizeIsoConnection (%p)--> close transport connection\n", self);

IsoServer_closeConnection(self->isoServer, self);

#if (CONFIG_MMS_SUPPORT_TLS == 1)
if (self->tlsSocket)
TLSSocket_close(self->tlsSocket);
#endif

if (self->socket != NULL)
Socket_destroy(self->socket);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
#if (CONFIG_MMS_SINGLE_THREADED != 1)
if (self->handleSet) {
Handleset_destroy(self->handleSet);
self->handleSet = NULL;
}
#endif
#endif

GLOBAL_FREEMEM(self->session);
GLOBAL_FREEMEM(self->presentation);
Expand All @@ -126,7 +131,7 @@ finalizeIsoConnection(IsoConnection self)
GLOBAL_FREEMEM(self->clientAddress);
GLOBAL_FREEMEM(self->localAddress);
IsoServer isoServer = self->isoServer;
GLOBAL_FREEMEM(self);

if (DEBUG_ISO_SERVER)
printf("ISO_SERVER: connection %p closed\n", self);

Expand All @@ -140,17 +145,34 @@ IsoConnection_addToHandleSet(const IsoConnection self, HandleSet handles)
}

void
IsoConnection_handleTcpConnection(IsoConnection self)
IsoConnection_removeFromHandleSet(const IsoConnection self, HandleSet handles)
{
Handleset_removeSocket(handles, self->socket);
}

void
IsoConnection_callTickHandler(IsoConnection self)
{
/* call tick handler */
if (self->tickHandler) {
self->tickHandler(self->handlerParameter);
}
}

#if (CONFIG_MMS_SINGLE_THREADED == 0)
if (IsoServer_waitReady(self->isoServer, 10) < 1)
goto exit_function;
#endif /* (CONFIG_MMS_SINGLE_THREADED == 0) */
void
IsoConnection_handleTcpConnection(IsoConnection self, bool isSingleThread)
{
#if (CONFIG_MMS_SINGLE_THREADED != 1)
if (isSingleThread == false) {

/* call tick handler */
if (self->tickHandler) {
self->tickHandler(self->handlerParameter);
}

if (Handleset_waitReady(self->handleSet, 10) < 1)
goto exit_function;
}
#endif

TpktState tpktState = CotpConnection_readToTpktBuffer(self->cotpConnection);

Expand Down Expand Up @@ -439,20 +461,25 @@ IsoConnection_handleTcpConnection(IsoConnection self)
}

#if ((CONFIG_MMS_SINGLE_THREADED == 0) && (CONFIG_MMS_THREADLESS_STACK == 0))
/* only for multi-thread mode */
static void
handleTcpConnection(void* parameter)
{
IsoConnection self = (IsoConnection) parameter;

while(self->state == ISO_CON_STATE_RUNNING)
IsoConnection_handleTcpConnection(self);
IsoConnection_handleTcpConnection(self, false);

IsoServer_closeConnection(self->isoServer, self);

finalizeIsoConnection(self);

self->state = ISO_CON_STATE_TERMINATED;
}
#endif /* (CONFIG_MMS_SINGLE_THREADED == 0) */

IsoConnection
IsoConnection_create(Socket socket, IsoServer isoServer)
IsoConnection_create(Socket socket, IsoServer isoServer, bool isSingleThread)
{
IsoConnection self = (IsoConnection) GLOBAL_CALLOC(1, sizeof(struct sIsoConnection));
self->socket = socket;
Expand Down Expand Up @@ -524,13 +551,23 @@ IsoConnection_create(Socket socket, IsoServer isoServer)

#if (CONFIG_MMS_SINGLE_THREADED == 0)
#if (CONFIG_MMS_THREADLESS_STACK == 0)
self->thread = Thread_create((ThreadExecutionFunction) handleTcpConnection, self, true);
if (isSingleThread == false) {
self->handleSet = Handleset_new();
Handleset_addSocket(self->handleSet, self->socket);
self->thread = Thread_create((ThreadExecutionFunction) handleTcpConnection, self, false);
}
#endif
#endif

return self;
}

int
IsoConnection_getState(IsoConnection self)
{
return self->state;
}

void
IsoConnection_start(IsoConnection self)
{
Expand All @@ -544,10 +581,15 @@ IsoConnection_start(IsoConnection self)
void
IsoConnection_destroy(IsoConnection self)
{
if (DEBUG_ISO_SERVER)
printf("ISO_SERVER: destroy called for IsoConnection.\n");
#if (CONFIG_MMS_THREADLESS_STACK == 0) && (CONFIG_MMS_SINGLE_THREADED == 0)
if (self->thread)
Thread_destroy(self->thread);
#endif

finalizeIsoConnection(self);
if (self->socket != NULL)
Socket_destroy(self->socket);

GLOBAL_FREEMEM(self);
}

char*
Expand Down Expand Up @@ -627,19 +669,23 @@ IsoConnection_sendMessage(IsoConnection self, ByteBuffer* message)
void
IsoConnection_close(IsoConnection self)
{
if (self->state != ISO_CON_STATE_STOPPED) {
Socket socket = self->socket;
if (self->state != ISO_CON_STATE_TERMINATED) {
self->state = ISO_CON_STATE_STOPPED;
self->socket = NULL;

#if (CONFIG_MMS_SUPPORT_TLS == 1)
if (self->tlsSocket) {
TLSSocket_close(self->tlsSocket);
self->tlsSocket = NULL;
#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED != 1)
/* wait for connection thread to terminate */
if (self->thread) {
Thread_destroy(self->thread);
self->thread = NULL;
}
else {
finalizeIsoConnection(self);
self->state = ISO_CON_STATE_TERMINATED;
}
#else
finalizeIsoConnection(self);
self->state = ISO_CON_STATE_TERMINATED;
#endif

Socket_destroy(socket);
}
}

Expand Down
Loading

0 comments on commit abcf934

Please sign in to comment.