|
|
@ -1,7 +1,7 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* iso_server.c
|
|
|
|
* iso_server.c
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Copyright 2013, 2014 Michael Zillgith
|
|
|
|
* Copyright 2013-2018 Michael Zillgith
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -51,6 +51,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
struct sIsoServer {
|
|
|
|
struct sIsoServer {
|
|
|
|
IsoServerState state;
|
|
|
|
IsoServerState state;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
Semaphore stateLock;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
ConnectionIndicationHandler connectionHandler;
|
|
|
|
ConnectionIndicationHandler connectionHandler;
|
|
|
|
void* connectionHandlerParameter;
|
|
|
|
void* connectionHandlerParameter;
|
|
|
|
|
|
|
|
|
|
|
@ -83,6 +88,34 @@ struct sIsoServer {
|
|
|
|
int connectionCounter;
|
|
|
|
int connectionCounter;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
setState(IsoServer self, IsoServerState newState)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
Semaphore_wait(self->stateLock);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
self->state = newState;
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
Semaphore_post(self->stateLock);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static IsoServerState
|
|
|
|
|
|
|
|
getState(IsoServer self)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IsoServerState state;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
Semaphore_wait(self->stateLock);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
state = self->state;
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
Semaphore_post(self->stateLock);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return state;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0)
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0)
|
|
|
|
static inline void
|
|
|
|
static inline void
|
|
|
|
lockClientConnections(IsoServer self)
|
|
|
|
lockClientConnections(IsoServer self)
|
|
|
@ -301,7 +334,7 @@ setupIsoServer(IsoServer self)
|
|
|
|
self->serverSocket = (Socket) TcpServerSocket_create(self->localIpAddress, self->tcpPort);
|
|
|
|
self->serverSocket = (Socket) TcpServerSocket_create(self->localIpAddress, self->tcpPort);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->serverSocket == NULL) {
|
|
|
|
if (self->serverSocket == NULL) {
|
|
|
|
self->state = ISO_SVR_STATE_ERROR;
|
|
|
|
setState(self, ISO_SVR_STATE_ERROR);
|
|
|
|
success = false;
|
|
|
|
success = false;
|
|
|
|
|
|
|
|
|
|
|
|
goto exit_function;
|
|
|
|
goto exit_function;
|
|
|
@ -311,7 +344,7 @@ setupIsoServer(IsoServer self)
|
|
|
|
|
|
|
|
|
|
|
|
ServerSocket_listen((ServerSocket) self->serverSocket);
|
|
|
|
ServerSocket_listen((ServerSocket) self->serverSocket);
|
|
|
|
|
|
|
|
|
|
|
|
self->state = ISO_SVR_STATE_RUNNING;
|
|
|
|
setState(self, ISO_SVR_STATE_RUNNING);
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS != -1)
|
|
|
|
#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS != -1)
|
|
|
|
if (DEBUG_ISO_SERVER)
|
|
|
|
if (DEBUG_ISO_SERVER)
|
|
|
@ -438,6 +471,10 @@ IsoServer_create()
|
|
|
|
self->state = ISO_SVR_STATE_IDLE;
|
|
|
|
self->state = ISO_SVR_STATE_IDLE;
|
|
|
|
self->tcpPort = TCP_PORT;
|
|
|
|
self->tcpPort = TCP_PORT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
self->stateLock = Semaphore_create(1);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1)
|
|
|
|
#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1)
|
|
|
|
self->openClientConnections = LinkedList_create();
|
|
|
|
self->openClientConnections = LinkedList_create();
|
|
|
|
#else
|
|
|
|
#else
|
|
|
@ -470,7 +507,7 @@ IsoServer_setLocalIpAddress(IsoServer self, char* ipAddress)
|
|
|
|
IsoServerState
|
|
|
|
IsoServerState
|
|
|
|
IsoServer_getState(IsoServer self)
|
|
|
|
IsoServer_getState(IsoServer self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return self->state;
|
|
|
|
return getState(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@ -531,7 +568,7 @@ IsoServer_startListeningThreadless(IsoServer self)
|
|
|
|
self->serverSocket = NULL;
|
|
|
|
self->serverSocket = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
self->state = ISO_SVR_STATE_RUNNING;
|
|
|
|
setState(self, ISO_SVR_STATE_RUNNING);
|
|
|
|
|
|
|
|
|
|
|
|
if (DEBUG_ISO_SERVER)
|
|
|
|
if (DEBUG_ISO_SERVER)
|
|
|
|
printf("ISO_SERVER: new iso server (threadless) started\n");
|
|
|
|
printf("ISO_SERVER: new iso server (threadless) started\n");
|
|
|
@ -543,7 +580,7 @@ IsoServer_waitReady(IsoServer self, unsigned int timeoutMs)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
|
|
if (self->state == ISO_SVR_STATE_RUNNING) {
|
|
|
|
if (getState(self) == ISO_SVR_STATE_RUNNING) {
|
|
|
|
HandleSet handles;
|
|
|
|
HandleSet handles;
|
|
|
|
|
|
|
|
|
|
|
|
handles = Handleset_new();
|
|
|
|
handles = Handleset_new();
|
|
|
@ -613,14 +650,15 @@ IsoServer_waitReady(IsoServer self, unsigned int timeoutMs)
|
|
|
|
void
|
|
|
|
void
|
|
|
|
IsoServer_processIncomingMessages(IsoServer self)
|
|
|
|
IsoServer_processIncomingMessages(IsoServer self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->state == ISO_SVR_STATE_RUNNING)
|
|
|
|
if (getState(self) == ISO_SVR_STATE_RUNNING)
|
|
|
|
handleIsoConnectionsThreadless(self);
|
|
|
|
handleIsoConnectionsThreadless(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
stopListening(IsoServer self)
|
|
|
|
stopListening(IsoServer self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self->state = ISO_SVR_STATE_STOPPED;
|
|
|
|
setState(self, ISO_SVR_STATE_STOPPED);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->serverSocket != NULL) {
|
|
|
|
if (self->serverSocket != NULL) {
|
|
|
|
ServerSocket_destroy((ServerSocket) self->serverSocket);
|
|
|
|
ServerSocket_destroy((ServerSocket) self->serverSocket);
|
|
|
|
self->serverSocket = NULL;
|
|
|
|
self->serverSocket = NULL;
|
|
|
@ -661,7 +699,7 @@ IsoServer_stopListening(IsoServer self)
|
|
|
|
void
|
|
|
|
void
|
|
|
|
IsoServer_closeConnection(IsoServer self, IsoConnection isoConnection)
|
|
|
|
IsoServer_closeConnection(IsoServer self, IsoConnection isoConnection)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->state != ISO_SVR_STATE_IDLE) {
|
|
|
|
if (getState(self) != ISO_SVR_STATE_IDLE) {
|
|
|
|
self->connectionHandler(ISO_CONNECTION_CLOSED, self->connectionHandlerParameter,
|
|
|
|
self->connectionHandler(ISO_CONNECTION_CLOSED, self->connectionHandlerParameter,
|
|
|
|
isoConnection);
|
|
|
|
isoConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -709,6 +747,10 @@ IsoServer_destroy(IsoServer self)
|
|
|
|
Semaphore_destroy(self->openClientConnectionsMutex);
|
|
|
|
Semaphore_destroy(self->openClientConnectionsMutex);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
|
|
|
|
Semaphore_destroy(self->stateLock);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
GLOBAL_FREEMEM(self);
|
|
|
|
GLOBAL_FREEMEM(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|