diff --git a/config/stack_config.h b/config/stack_config.h
index 12dfd444..80f29ffe 100644
--- a/config/stack_config.h
+++ b/config/stack_config.h
@@ -219,6 +219,9 @@
/* maximum number of contemporary file upload tasks (obtainFile) per server instance */
#define CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS 5
+/* server side request timeout for file upload tasks (in milliseconds) */
+#define CONFIG_MMS_SERVER_REQUEST_TIMEOUT_MS 2000
+
/* Definition of supported services */
#define MMS_DEFAULT_PROFILE 1
diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index 44f36a05..bce0341a 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -2558,6 +2558,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_setListObjectsAccessHandler(IntPtr self, IedServer_ListObjectsAccessHandler handler, IntPtr parameter);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_setRequestTimeout(IntPtr self, Int32 timeoutMs);
+
///
/// Set a handler to control read and write access to control blocks and logs
///
@@ -3543,6 +3546,15 @@ namespace IEC61850
return IedServer_getNumberOfOpenConnections(self);
}
+ ///
+ /// Set the request timeout for the server (used for obtain file service)
+ ///
+ /// request timeout in milliseconds
+ public void SetRequestTimeout(int timeoutMs)
+ {
+ IedServer_setRequestTimeout(self, timeoutMs);
+ }
+
private ControlHandlerInfo GetControlHandlerInfo(DataObject controlObject)
{
ControlHandlerInfo info;
diff --git a/examples/server_example_files/server_example_files.c b/examples/server_example_files/server_example_files.c
index 9974fe6f..a8f0c7e4 100644
--- a/examples/server_example_files/server_example_files.c
+++ b/examples/server_example_files/server_example_files.c
@@ -5,12 +5,12 @@
* - How to control how files file services can be used
*/
-#include "iec61850_server.h"
#include "hal_thread.h"
+#include "iec61850_server.h"
+#include
#include
-#include
#include
-#include
+#include
#include "static_model.h"
@@ -24,7 +24,7 @@ sigint_handler(int signalId)
}
static void
-connectionHandler (IedServer self, ClientConnection connection, bool connected, void* parameter)
+connectionHandler(IedServer self, ClientConnection connection, bool connected, void* parameter)
{
if (connected)
printf("Connection opened\n");
@@ -33,8 +33,8 @@ connectionHandler (IedServer self, ClientConnection connection, bool connected,
}
static MmsError
-fileAccessHandler (void* parameter, MmsServerConnection connection, MmsFileServiceType service,
- const char* localFilename, const char* otherFilename)
+fileAccessHandler(void* parameter, MmsServerConnection connection, MmsFileServiceType service,
+ const char* localFilename, const char* otherFilename)
{
printf("fileAccessHandler: service = %i, local-file: %s other-file: %s\n", service, localFilename, otherFilename);
@@ -43,7 +43,8 @@ fileAccessHandler (void* parameter, MmsServerConnection connection, MmsFileServi
return MMS_ERROR_FILE_FILE_ACCESS_DENIED;
/* Don't allow client to delete file "IEDSERVER.BIN" */
- if (service == MMS_FILE_ACCESS_TYPE_DELETE) {
+ if (service == MMS_FILE_ACCESS_TYPE_DELETE)
+ {
if (strcmp(localFilename, "IEDSERVER.BIN") == 0)
return MMS_ERROR_FILE_FILE_ACCESS_DENIED;
}
@@ -57,7 +58,8 @@ main(int argc, char** argv)
{
int tcpPort = 102;
- if (argc > 1) {
+ if (argc > 1)
+ {
tcpPort = atoi(argv[1]);
}
@@ -70,15 +72,18 @@ main(int argc, char** argv)
IedServer_setFilestoreBasepath(iedServer, "./vmd-filestore/");
+ IedServer_setRequestTimeout(iedServer, 5000);
+
/* Set a callback handler to control file accesses */
MmsServer_installFileAccessHandler(mmsServer, fileAccessHandler, NULL);
- IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, NULL);
+ IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler)connectionHandler, NULL);
/* MMS server will be instructed to start listening to client connections. */
IedServer_start(iedServer, tcpPort);
- if (!IedServer_isRunning(iedServer)) {
+ if (!IedServer_isRunning(iedServer))
+ {
printf("Starting server failed! Exit.\n");
IedServer_destroy(iedServer);
exit(-1);
@@ -88,16 +93,14 @@ main(int argc, char** argv)
signal(SIGINT, sigint_handler);
-
while (running)
Thread_sleep(100);
-
/* stop MMS server - close TCP server socket and all client sockets */
IedServer_stop(iedServer);
/* Cleanup - free all resources */
IedServer_destroy(iedServer);
- return 0;
+ return 0;
} /* main() */
diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h
index cacbc524..80a71101 100644
--- a/src/iec61850/inc/iec61850_server.h
+++ b/src/iec61850/inc/iec61850_server.h
@@ -3,7 +3,7 @@
*
* IEC 61850 server API for libiec61850.
*
- * Copyright 2013-2024 Michael Zillgith
+ * Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -540,6 +540,15 @@ IedServer_setServerIdentity(IedServer self, const char* vendor, const char* mode
LIB61850_API void
IedServer_setFilestoreBasepath(IedServer self, const char* basepath);
+/**
+ * \brief Set the request timeout for the server (used for obtain file service)
+ *
+ * \param self the IedServer instance to operate on
+ * \param timeoutMs the timeout value in milliseconds
+ */
+LIB61850_API void
+IedServer_setRequestTimeout(IedServer self, int32_t timeoutMs);
+
/**
* \brief Assign a \ref LogStorage instance to a log reference
*
diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c
index 68c2232f..7496c495 100644
--- a/src/iec61850/server/impl/ied_server.c
+++ b/src/iec61850/server/impl/ied_server.c
@@ -937,6 +937,12 @@ IedServer_setFilestoreBasepath(IedServer self, const char* basepath)
MmsServer_setFilestoreBasepath(self->mmsServer, basepath);
}
+void
+IedServer_setRequestTimeout(IedServer self, int32_t timeoutMs)
+{
+ MmsServer_setRequestTimeout(self->mmsServer, timeoutMs);
+}
+
void
IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress)
{
diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h
index 3fae4f26..ed5933ed 100644
--- a/src/mms/inc_private/mms_server_internal.h
+++ b/src/mms/inc_private/mms_server_internal.h
@@ -105,8 +105,8 @@ struct sMmsObtainFileTask {
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
-struct sMmsServer {
-
+struct sMmsServer
+{
LinkedList /**/ isoServerList;
MmsDevice* device;
@@ -177,6 +177,8 @@ struct sMmsServer {
void* getFileCompleteHandlerParameter;
struct sMmsObtainFileTask fileUploadTasks[CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS];
+
+ int32_t requestTimeoutMs; /* request timeout in milliseconds */
#endif
#if (MMS_FILE_SERVICE == 1)
diff --git a/src/mms/inc_private/mms_server_libinternal.h b/src/mms/inc_private/mms_server_libinternal.h
index f7daa70c..70389297 100644
--- a/src/mms/inc_private/mms_server_libinternal.h
+++ b/src/mms/inc_private/mms_server_libinternal.h
@@ -205,4 +205,13 @@ MmsServer_stopListeningThreadless(MmsServer self);
LIB61850_INTERNAL const char*
MmsServer_getFilesystemBasepath(MmsServer self);
+/**
+ * \brief Set the request timeout for the server (used for obtain file service)
+ *
+ * \param self the MmsServer instance to operate on
+ * \param timeoutMs the timeout value in milliseconds
+ */
+LIB61850_INTERNAL void
+MmsServer_setRequestTimeout(MmsServer self, int32_t timeoutMs);
+
#endif /* MMS_SERVER_LIBINTERNAL_H_ */
diff --git a/src/mms/iso_mms/server/mms_file_service.c b/src/mms/iso_mms/server/mms_file_service.c
index ca5d80f7..d1367991 100644
--- a/src/mms/iso_mms/server/mms_file_service.c
+++ b/src/mms/iso_mms/server/mms_file_service.c
@@ -482,7 +482,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task, int taskState)
task->state = MMS_FILE_UPLOAD_STATE_FILE_READ_SENT;
IsoConnection_sendMessage(task->connection->isoConnection, message);
- task->nextTimeout = Hal_getTimeInMs() + 2000; /* timeout 2000 ms */
+ task->nextTimeout = Hal_getTimeInMs() + self->requestTimeoutMs;
}
break;
@@ -515,7 +515,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task, int taskState)
IsoConnection_sendMessage(task->connection->isoConnection, message);
- task->nextTimeout = Hal_getTimeInMs() + 2000; /* timeout 2000 ms */
+ task->nextTimeout = Hal_getTimeInMs() + self->requestTimeoutMs;
}
break;
@@ -783,7 +783,7 @@ mmsServer_handleObtainFileRequest(
MmsServer_releaseTransmitBuffer(connection->server);
- task->nextTimeout = Hal_getTimeInMs() + 2000; /* timeout 2000 ms */
+ task->nextTimeout = Hal_getTimeInMs() + connection->server->requestTimeoutMs;
task->state = MMS_FILE_UPLOAD_STATE_FILE_OPEN_SENT;
}
diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c
index a82627eb..aacf9118 100644
--- a/src/mms/iso_mms/server/mms_server.c
+++ b/src/mms/iso_mms/server/mms_server.c
@@ -28,6 +28,10 @@
#include "mms_server_internal.h"
#include "iso_server_private.h"
+#ifndef CONFIG_MMS_SERVER_REQUEST_TIMEOUT_MS
+#define CONFIG_MMS_SERVER_REQUEST_TIMEOUT_MS 2000
+#endif
+
static Map
createValueCaches(MmsDevice* device)
{
@@ -116,6 +120,8 @@ MmsServer_create(MmsDevice* device, TLSConfiguration tlsConfiguration)
#if (MMS_OBTAIN_FILE_SERVICE == 1)
{
+ self->requestTimeoutMs = CONFIG_MMS_SERVER_REQUEST_TIMEOUT_MS;
+
int i;
for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++)
@@ -921,6 +927,14 @@ MmsServer_getFilesystemBasepath(MmsServer self)
#endif
}
+void
+MmsServer_setRequestTimeout(MmsServer self, int32_t timeoutMs)
+{
+#if (MMS_OBTAIN_FILE_SERVICE == 1)
+ self->requestTimeoutMs = timeoutMs;
+#endif
+}
+
void
MmsServer_ignoreClientRequests(MmsServer self, bool enable)
{