From 51c29fe9a7e2a9faffa05a419b66fcd095672723 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Sat, 1 Sep 2018 21:37:20 +0200 Subject: [PATCH] - IEC 61850 server/ MMS server: maximum number of client connections configurable at runtime --- config/stack_config.h | 2 +- dotnet/IEC61850forCSharp/IedServerConfig.cs | 41 +++++++++++++++++ .../server_example_basic_io.c | 6 ++- src/iec61850/inc/iec61850_server.h | 20 +++++++- src/iec61850/server/impl/ied_server.c | 1 + src/iec61850/server/impl/ied_server_config.c | 12 +++++ src/mms/inc/iso_server.h | 3 ++ src/mms/inc/mms_server.h | 8 ++++ src/mms/inc_private/mms_server_internal.h | 1 + src/mms/iso_mms/server/mms_server.c | 6 +++ src/mms/iso_server/iso_server.c | 46 ++++++++++++++----- src/vs/libiec61850-wo-goose.def | 2 + src/vs/libiec61850.def | 2 + 13 files changed, 135 insertions(+), 15 deletions(-) diff --git a/config/stack_config.h b/config/stack_config.h index 4cac7cfd..a3c419df 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -51,7 +51,7 @@ #define CONFIG_MMS_THREADLESS_STACK 0 /* number of concurrent MMS client connections the server accepts, -1 for no limit */ -#define CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 5 +#define CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 100 /* activate TCP keep alive mechanism. 1 -> activate */ #define CONFIG_ACTIVATE_TCP_KEEPALIVE 1 diff --git a/dotnet/IEC61850forCSharp/IedServerConfig.cs b/dotnet/IEC61850forCSharp/IedServerConfig.cs index 9f1d7bde..586f547b 100644 --- a/dotnet/IEC61850forCSharp/IedServerConfig.cs +++ b/dotnet/IEC61850forCSharp/IedServerConfig.cs @@ -56,6 +56,19 @@ namespace IEC61850.Server [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern byte IedServerConfig_getEdition(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void IedServerConfig_setMaxMmsConnections(IntPtr self, int maxConnections); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int IedServerConfig_getMaxMmsConnections(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IedServerConfig_isDynamicDataSetServiceEnabled(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void IedServerConfig_enableDynamicDataSetService(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable); + internal IntPtr self; public IedServerConfig () @@ -91,6 +104,10 @@ namespace IEC61850.Server } } + /// + /// Gets or sets the edition of the IEC 61850 standard to use + /// + /// The IEC 61850 edition to use. public Iec61850Edition Edition { get { @@ -101,6 +118,30 @@ namespace IEC61850.Server } } + /// + /// Gets or sets maximum number of MMS clients + /// + /// The max number of MMS client connections. + public int MaxMmsConnections + { + get { + return IedServerConfig_getMaxMmsConnections (self); + } + set { + IedServerConfig_setMaxMmsConnections (self, value); + } + } + + public bool DynamicDataSetServiceEnabled + { + get { + return IedServerConfig_isDynamicDataSetServiceEnabled (self); + } + set { + IedServerConfig_enableDynamicDataSetService (self, value); + } + } + /// /// Releases all resource used by the object. /// diff --git a/examples/server_example_basic_io/server_example_basic_io.c b/examples/server_example_basic_io/server_example_basic_io.c index 55e789ec..1f928531 100644 --- a/examples/server_example_basic_io/server_example_basic_io.c +++ b/examples/server_example_basic_io/server_example_basic_io.c @@ -90,6 +90,7 @@ main(int argc, char** argv) /* Set buffer size for buffered report control blocks to 200000 bytes */ IedServerConfig_setReportBufferSize(config, 200000); + /* Set stack compliance to a specific edition of the standard (WARNING: data model has also to be checked for compliance) */ IedServerConfig_setEdition(config, IEC_61850_EDITION_2); /* Set the base path for the MMS file services */ @@ -103,6 +104,9 @@ main(int argc, char** argv) IedServerConfig_enableLogService(config, true); + /* set maximum number of clients */ + IedServerConfig_setMaxMmsConnections(config, 2); + /* Create a new IEC 61850 server instance */ iedServer = IedServer_createWithConfig(&iedModel, NULL, config); @@ -132,7 +136,7 @@ main(int argc, char** argv) IedServer_start(iedServer, 102); if (!IedServer_isRunning(iedServer)) { - printf("Starting server failed! Exit.\n"); + printf("Starting server failed (maybe need root permissions or another server is already using the port)! Exit.\n"); IedServer_destroy(iedServer); exit(-1); } diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 8f6cabce..bffed036 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -65,6 +65,9 @@ struct sIedServerConfig /** IEC 61850 edition (0 = edition 1, 1 = edition 2, 2 = edition 2.1, ...) */ uint8_t edition; + + /** maximum number of MMS (TCP) connections */ + int maxMmsConnections; }; /** @@ -113,9 +116,22 @@ IedServerConfig_setReportBufferSize(IedServerConfig self, int reportBufferSize); int IedServerConfig_getReportBufferSize(IedServerConfig self); +/** + * \brief Set the maximum number of MMS (TCP) connections the server accepts + * + * NOTE: Parameter has to be smaller than CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS if + * CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS != -1 + * + * \param maxConnection maximum number of TCP connections + */ void IedServerConfig_setMaxMmsConnections(IedServerConfig self, int maxConnections); +/** + * \brief Get the maximum number of MMS (TCP) connections the server accepts + * + * \return maximum number of TCP connections + */ int IedServerConfig_getMaxMmsConnections(IedServerConfig self); @@ -150,10 +166,10 @@ bool IedServerConfig_isFileServiceEnabled(IedServerConfig self); void -IedServerConfig_enableFileWriteService(IedServerConfig self, bool enable); +IedServerConfig_enableSetFileService(IedServerConfig self, bool enable); bool -IedServerConfig_isFileWriteServiceEnabled(IedServerConfig self); +IedServerConfig_isSetFileServiceEnabled(IedServerConfig self); /** * \brief Enable/disable the dynamic data set service for MMS diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index d33a1e43..a1a351b6 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -439,6 +439,7 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio MmsServer_enableDynamicNamedVariableListService(self->mmsServer, serverConfiguration->enableDynamicDataSetService); MmsServer_enableJournalService(self->mmsServer, serverConfiguration->enableLogService); MmsServer_setFilestoreBasepath(self->mmsServer, serverConfiguration->fileServiceBasepath); + MmsServer_setMaxConnections(self->mmsServer, serverConfiguration->maxMmsConnections); } #endif diff --git a/src/iec61850/server/impl/ied_server_config.c b/src/iec61850/server/impl/ied_server_config.c index 6712c0b9..cc01c773 100644 --- a/src/iec61850/server/impl/ied_server_config.c +++ b/src/iec61850/server/impl/ied_server_config.c @@ -125,3 +125,15 @@ IedServerConfig_isLogServiceEnabled(IedServerConfig self) { return self->enableLogService; } + +void +IedServerConfig_setMaxMmsConnections(IedServerConfig self, int maxConnections) +{ + self->maxMmsConnections = maxConnections; +} + +int +IedServerConfig_getMaxMmsConnections(IedServerConfig self) +{ + return self->maxMmsConnections; +} diff --git a/src/mms/inc/iso_server.h b/src/mms/inc/iso_server.h index a5da6495..849df2cf 100644 --- a/src/mms/inc/iso_server.h +++ b/src/mms/inc/iso_server.h @@ -94,6 +94,9 @@ IsoServer_create(TLSConfiguration tlsConfiguration); void IsoServer_setTcpPort(IsoServer self, int port); +void +IsoServer_setMaxConnections(IsoServer self, int maxConnections); + void IsoServer_setLocalIpAddress(IsoServer self, const char* ipAddress); diff --git a/src/mms/inc/mms_server.h b/src/mms/inc/mms_server.h index 5d6cd93b..1780bc39 100644 --- a/src/mms/inc/mms_server.h +++ b/src/mms/inc/mms_server.h @@ -225,6 +225,14 @@ MmsServer_installFileAccessHandler(MmsServer self, MmsFileAccessHandler handler, void MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath); +/** + * \brief Set the maximum number of TCP client connections + * + * \param[in] maxConnections the maximum number of TCP client connections to accept + */ +void +MmsServer_setMaxConnections(MmsServer self, int maxConnections); + /** * \brief Enable/disable MMS file services at runtime * diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h index 37cffb35..62ea4061 100644 --- a/src/mms/inc_private/mms_server_internal.h +++ b/src/mms/inc_private/mms_server_internal.h @@ -165,6 +165,7 @@ struct sMmsServer { #endif #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) + int maxConnections; bool fileServiceEnabled; bool dynamicVariableListServiceEnabled; bool journalServiceEnabled; diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c index 2352926d..5cf57390 100644 --- a/src/mms/iso_mms/server/mms_server.c +++ b/src/mms/iso_mms/server/mms_server.c @@ -107,6 +107,12 @@ MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) +void +MmsServer_setMaxConnections(MmsServer self, int maxConnections) +{ + IsoServer_setMaxConnections(self->isoServer, maxConnections); +} + void MmsServer_enableFileService(MmsServer self, bool enable) { diff --git a/src/mms/iso_server/iso_server.c b/src/mms/iso_server/iso_server.c index f36af1dd..fe855496 100644 --- a/src/mms/iso_server/iso_server.c +++ b/src/mms/iso_server/iso_server.c @@ -72,10 +72,14 @@ struct sIsoServer { TLSConfiguration tlsConfiguration; +#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) + int maxConnections; +#endif + #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) LinkedList openClientConnections; #else - IsoConnection* openClientConnections; + IsoConnection openClientConnections[CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS]; #endif /* (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) */ #if (CONFIG_MMS_THREADLESS_STACK != 1) @@ -355,11 +359,6 @@ setupIsoServer(IsoServer self) setState(self, ISO_SVR_STATE_RUNNING); -#if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS != -1) - if (DEBUG_ISO_SERVER) - printf("ISO_SERVER: server is limited to %i client connections.\n", (int) CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS); -#endif - exit_function: return success; } @@ -374,6 +373,17 @@ handleIsoConnections(IsoServer self) if ((connectionSocket = ServerSocket_accept((ServerSocket) self->serverSocket)) != NULL) { +#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) + if (private_IsoServer_getConnectionCounter(self) >= self->maxConnections) { + if (DEBUG_ISO_SERVER) + printf("ISO_SERVER: maximum number of connections reached -> reject connection attempt.\n"); + + Socket_destroy(connectionSocket); + + return; + } +#endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ + #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS != -1) if (private_IsoServer_getConnectionCounter(self) >= CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS) { if (DEBUG_ISO_SERVER) @@ -416,6 +426,17 @@ handleIsoConnectionsThreadless(IsoServer self) if ((connectionSocket = ServerSocket_accept((ServerSocket) self->serverSocket)) != NULL) { +#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) + if (private_IsoServer_getConnectionCounter(self) >= self->maxConnections) { + if (DEBUG_ISO_SERVER) + printf("ISO_SERVER: maximum number of connections reached -> reject connection attempt.\n"); + + Socket_destroy(connectionSocket); + + return; + } +#endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ + #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS != -1) if (private_IsoServer_getConnectionCounter(self) >= CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS) { if (DEBUG_ISO_SERVER) @@ -499,9 +520,6 @@ IsoServer_create(TLSConfiguration tlsConfiguration) #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) self->openClientConnections = LinkedList_create(); -#else - self->openClientConnections = (IsoConnection*) - GLOBAL_CALLOC(CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS, sizeof(IsoConnection)); #endif #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) @@ -514,6 +532,14 @@ IsoServer_create(TLSConfiguration tlsConfiguration) return self; } +#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) +void +IsoServer_setMaxConnections(IsoServer self, int maxConnections) +{ + self->maxConnections = maxConnections; +} +#endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ + void IsoServer_setTcpPort(IsoServer self, int port) { @@ -769,8 +795,6 @@ IsoServer_destroy(IsoServer self) lockClientConnections(self); #endif -#else - GLOBAL_FREEMEM(self->openClientConnections); #endif /* (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) */ #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def index 30d98eb4..27a7b3d6 100644 --- a/src/vs/libiec61850-wo-goose.def +++ b/src/vs/libiec61850-wo-goose.def @@ -612,3 +612,5 @@ EXPORTS IedServerConfig_isLogServiceEnabled IedServerConfig_setEdition IedServerConfig_getEdition + IedServerConfig_setMaxMmsConnections + IedServerConfig_getMaxMmsConnections diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def index 039e5ea8..e90c3ff1 100644 --- a/src/vs/libiec61850.def +++ b/src/vs/libiec61850.def @@ -740,3 +740,5 @@ EXPORTS IedServerConfig_isLogServiceEnabled IedServerConfig_setEdition IedServerConfig_getEdition + IedServerConfig_setMaxMmsConnections + IedServerConfig_getMaxMmsConnections