Merge branch 'master' into master

This commit is contained in:
mzillgith 2017-06-10 17:48:43 +02:00 committed by GitHub
commit 0282459668
44 changed files with 3624 additions and 282 deletions

View file

@ -1,3 +1,19 @@
Changes to version 1.0.2
------------------------
- server: added MmsFileAccessHandler for server side monitoring and control of file services
- file services: added support to set filestore basepath at runtime
- added IedConnection_getFileDirectoryEx to better control receiving file directories
- common: added timestamp handling functions Timestamp_create, Timestamp_destroy, Timestamp_setByMmsUtcTime, Timestamp_toMmsValue
- .NET API: Added Timestamp class
- .NET API: Added missing UpdateAttribute methods to IedServer
- common: added support for Currency BasicType
- MMS file services: fixed problem with negative frsmId
- java scl tools: fixed bug with SDOs in dynamic code generator
- java scl tools: fixed parsing bug in OptionFields.java
- server: added functions to restrict local IP address IedServer_setLocalIpAddress, IedServer.SetLocalIpAddress
- .NET: IedConnection: added internal reference to IsoConnectionParameters object to avoid deletion of internal AcseAuthenticationParameters by garbage collector
Changes to version 1.0.1
------------------------
- server: fixed problem in COTP src/dst reference handling (returning zero src reference)

View file

@ -224,4 +224,9 @@
/* Support user access to raw messages */
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 1
/* Allow to set the virtual filestore basepath for MMS file services at runtime with the
* MmsServer_setFilestoreBasepath function
*/
#define CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME 1
#endif /* STACK_CONFIG_H_ */

View file

@ -29,6 +29,9 @@
#cmakedefine01 DEBUG_MMS_SERVER
#cmakedefine01 DEBUG_GOOSE_SUBSCRIBER
#cmakedefine01 DEBUG_GOOSE_PUBLISHER
#cmakedefine01 DEBUG_SV_SUBSCRIBER 0
#cmakedefine01 DEBUG_SV_PUBLISHER 0
#cmakedefine01 DEBUG_HAL_ETHERNET 0
/* 1 ==> server runs in single threaded mode (one dedicated thread for the server)
* 0 ==> server runs in multi threaded mode (one thread for each connection and
@ -103,14 +106,14 @@
#define CONFIG_GOOSE_EVENT_RETRANSMISSION_COUNT 2
/* Define if GOOSE control block elements are writable (1) or read-only (0) */
#define CONFIG_GOOSE_GOID_WRITABLE 1
#define CONFIG_GOOSE_DATSET_WRITABLE 1
#define CONFIG_GOOSE_CONFREV_WRITABLE 1
#define CONFIG_GOOSE_NDSCOM_WRITABLE 1
#define CONFIG_GOOSE_DSTADDRESS_WRITABLE 1
#define CONFIG_GOOSE_MINTIME_WRITABLE 1
#define CONFIG_GOOSE_MAXTIME_WRITABLE 1
#define CONFIG_GOOSE_FIXEDOFFS_WRITABLE 1
#define CONFIG_GOOSE_GOID_WRITABLE 0
#define CONFIG_GOOSE_DATSET_WRITABLE 0
#define CONFIG_GOOSE_CONFREV_WRITABLE 0
#define CONFIG_GOOSE_NDSCOM_WRITABLE 0
#define CONFIG_GOOSE_DSTADDRESS_WRITABLE 0
#define CONFIG_GOOSE_MINTIME_WRITABLE 0
#define CONFIG_GOOSE_MAXTIME_WRITABLE 0
#define CONFIG_GOOSE_FIXEDOFFS_WRITABLE 0
/* The default value for the priority field of the 802.1Q header (allowed range 0-7) */
#define CONFIG_GOOSE_DEFAULT_PRIORITY 4
@ -133,6 +136,9 @@
/* include support for IEC 61850 reporting services */
#cmakedefine01 CONFIG_IEC61850_REPORT_SERVICE
/* support buffered report control blocks with ResvTms field */
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
/* The default buffer size of buffered RCBs in bytes */
#cmakedefine CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE @CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE@
@ -194,10 +200,21 @@
#define CONFIG_IEC61850_CONTROL_SERVICE 0
#endif
/* Sort getNameList response according to the MMS specified collation order - this is required by the standard
* Set to 0 only for performance reasons and when no certification is required! */
#define CONFIG_MMS_SORT_NAME_LIST 1
#define CONFIG_INCLUDE_PLATFORM_SPECIFIC_HEADERS 0
/* use short FC defines as in old API */
#define CONFIG_PROVIDE_OLD_FC_DEFINES 0
/* Support user acccess to raw messages */
#cmakedefine01 CONFIG_MMS_RAW_MESSAGE_LOGGING
/* Allow to set the virtual filestore basepath for MMS file services at runtime with the
* MmsServer_setFilestoreBasepath function
*/
#define CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME 1
#endif /* STACK_CONFIG_H_ */

View file

@ -11,6 +11,7 @@ add_subdirectory(server_example_threadless)
add_subdirectory(server_example_61400_25)
add_subdirectory(server_example_setting_groups)
add_subdirectory(server_example_logging)
add_subdirectory(server_example_files)
add_subdirectory(iec61850_client_example1)
add_subdirectory(iec61850_client_example2)
add_subdirectory(iec61850_client_example3)

View file

@ -25,6 +25,7 @@ EXAMPLE_DIRS += server_example_61400_25
EXAMPLE_DIRS += server_example_threadless
EXAMPLE_DIRS += server_example_setting_groups
EXAMPLE_DIRS += server_example_logging
EXAMPLE_DIRS += server_example_files
EXAMPLE_DIRS += goose_subscriber
EXAMPLE_DIRS += goose_publisher
EXAMPLE_DIRS += sv_subscriber
@ -47,6 +48,7 @@ MODEL_DIRS += server_example_61400_25
MODEL_DIRS += server_example_threadless
MODEL_DIRS += server_example_setting_groups
MODEL_DIRS += server_example_logging
MODEL_DIRS += server_example_files
MODEL_DIRS += iec61850_9_2_LE_example
all: examples

View file

@ -0,0 +1,9 @@
The default ethernet interface is eth0. You can specify another interface at the command line.
./sv_9_2LE_example eth1
In order for the SV publisher to start the SVCB has to be enabled by an MMS client.

View file

@ -36,7 +36,7 @@
extern IedModel iedModel;
static int running = 0;
static int svcbEnabled = 0;
static int svcbEnabled = 1;
void sigint_handler(int signalId)
{
@ -57,9 +57,9 @@ static SampledValuesPublisher svPublisher;
static SV_ASDU asdu;
static void
setupSVPublisher()
setupSVPublisher(const char* svInterface)
{
svPublisher = SampledValuesPublisher_create("eth1");
svPublisher = SampledValuesPublisher_create(svInterface);
asdu = SampledValuesPublisher_addASDU(svPublisher, "xxxxMUnn01", NULL, 1);
@ -87,6 +87,13 @@ static void sVCBEventHandler (SVControlBlock* svcb, int event, void* parameter)
int
main(int argc, char** argv)
{
char* svInterface;
if (argc > 1)
svInterface = argv[1];
else
svInterface = "eth0";
IedServer iedServer = IedServer_create(&iedModel);
/* MMS server will be instructed to start listening to client connections. */
@ -102,7 +109,7 @@ main(int argc, char** argv)
signal(SIGINT, sigint_handler);
setupSVPublisher();
setupSVPublisher(svInterface);
int voltage = 1;
int current = 1;

View file

@ -1,6 +1,6 @@
set(iec61850_client_example_files_SRCS
client_example_files.c
file-tool.c
)
IF(MSVC)
@ -8,10 +8,10 @@ set_source_files_properties(${iec61850_client_example_files_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(MSVC)
add_executable(iec61850_client_example_files
add_executable(file-tool
${iec61850_client_example_files_SRCS}
)
target_link_libraries(iec61850_client_example_files
target_link_libraries(file-tool
iec61850
)

View file

@ -1,7 +1,7 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = client_example_files
PROJECT_SOURCES = client_example_files.c
PROJECT_BINARY_NAME = file-tool
PROJECT_SOURCES = file-tool.c
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk

View file

@ -1,107 +0,0 @@
/*
* client_example_files.c
*
* This example demonstrates the usage of the file services
*
* - How to browse the file system of the server
* - How to download a file from the server
*
* Note: intended to be used with server_example3
*
*/
#include "iec61850_client.h"
#include <stdlib.h>
#include <stdio.h>
#include "hal_thread.h"
#define MAX_BUFFER_SIZE 2000000
static uint8_t downloadBuffer[MAX_BUFFER_SIZE];
static int bufferPosition = 0;
static bool
downloadHandler(void* parameter, uint8_t* buffer, uint32_t bytesRead)
{
printf("received %i bytes\n", bytesRead);
if (bufferPosition + bytesRead < MAX_BUFFER_SIZE) {
memcpy(downloadBuffer + bufferPosition, buffer, bytesRead);
bufferPosition += bytesRead;
return true;
}
else
return false;
}
int main(int argc, char** argv) {
char* hostname;
int tcpPort = 102;
if (argc > 1)
hostname = argv[1];
else
hostname = "localhost";
if (argc > 2)
tcpPort = atoi(argv[2]);
IedClientError error;
IedConnection con = IedConnection_create();
IedConnection_connect(con, &error, hostname, tcpPort);
if (error == IED_ERROR_OK) {
/* Get the root directory */
LinkedList rootDirectory =
IedConnection_getFileDirectory(con, &error, NULL);
if (error != IED_ERROR_OK) {
printf("Error retrieving file directory\n");
goto abort_connection;
}
LinkedList directoryEntry = LinkedList_getNext(rootDirectory);
while (directoryEntry != NULL) {
FileDirectoryEntry entry = (FileDirectoryEntry) directoryEntry->data;
printf("%s %i\n", FileDirectoryEntry_getFileName(entry), FileDirectoryEntry_getFileSize(entry));
directoryEntry = LinkedList_getNext(directoryEntry);
}
/* Download a file from the server */
IedConnection_getFile(con, &error, "IEDSERVER.BIN", downloadHandler, NULL);
if (error != IED_ERROR_OK)
printf("Failed to get file!\n");
/* Delete file at server */
IedConnection_deleteFile(con, &error, "IEDSERVER.BIN");
if (error != IED_ERROR_OK)
printf("Failed to delete file! (code=%i)\n", error);
abort_connection:
IedConnection_abort(con, &error);
}
else {
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
IedConnection_destroy(con);
}

View file

@ -0,0 +1,261 @@
/*
* file-tool.c
*
* This example demonstrates the usage of the file services
*
* - How to browse the file system of the server
* - How to download a file from the server
*
* Note: intended to be used with server_example3 or server_example_files
*
*/
#include "iec61850_client.h"
#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
static char* hostname = "localhost";
static int tcpPort = 102;
static char* filename = NULL;
typedef enum {
FileOperationType_None = 0,
FileOperationType_Dir,
FileOperationType_Info,
FileOperationType_Del,
FileOperationType_Get,
FileOperationType_Set
} FileOperationType;
static FileOperationType operation = FileOperationType_None;
static bool
downloadHandler(void* parameter, uint8_t* buffer, uint32_t bytesRead)
{
FILE* fp = (FILE*) parameter;
printf("received %i bytes\n", bytesRead);
if (fwrite(buffer, bytesRead, 1, fp) == 1)
return true;
else {
printf("Failed to write local file!\n");
return false;
}
}
static void
printHelp()
{
printf("file-tool [options] <operation> [<parameters>]\n");
printf(" Options:\n");
printf(" -h <hostname/IP>\n");
printf(" -p portnumber\n");
printf(" Operations\n");
printf(" dir - show directory\n");
printf(" info <filename> - show file info\n");
printf(" del <filename> - delete file\n");
printf(" get <filename> - get file\n");
printf(" set <filename> - set file\n");
}
static int
parseOptions(int argc, char** argv)
{
int currentArgc = 1;
int retVal = 0;
while (currentArgc < argc) {
if (strcmp(argv[currentArgc], "-h") == 0) {
hostname = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "-p") == 0) {
tcpPort = atoi(argv[++currentArgc]);
}
else if (strcmp(argv[currentArgc], "del") == 0) {
operation = FileOperationType_Del;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "dir") == 0) {
operation = FileOperationType_Dir;
}
else if (strcmp(argv[currentArgc], "info") == 0) {
operation = FileOperationType_Info;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "get") == 0) {
operation = FileOperationType_Get;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "set") == 0) {
operation = FileOperationType_Set;
filename = argv[++currentArgc];
}
else {
printf("Unknown operation!\n");
return 1;
}
currentArgc++;
}
return retVal;
}
void
showDirectory(IedConnection con)
{
IedClientError error;
/* Get the root directory */
LinkedList rootDirectory =
IedConnection_getFileDirectory(con, &error, NULL);
if (error != IED_ERROR_OK) {
printf("Error retrieving file directory\n");
}
else {
LinkedList directoryEntry = LinkedList_getNext(rootDirectory);
while (directoryEntry != NULL) {
FileDirectoryEntry entry = (FileDirectoryEntry) directoryEntry->data;
printf("%s %i\n", FileDirectoryEntry_getFileName(entry), FileDirectoryEntry_getFileSize(entry));
directoryEntry = LinkedList_getNext(directoryEntry);
}
LinkedList_destroyDeep(rootDirectory, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
}
}
void
getFile(IedConnection con)
{
IedClientError error;
char* bname = strdup(filename);
char* localFilename = basename(bname);
FILE* fp = fopen(localFilename, "w");
if (fp != NULL) {
/* Download a file from the server */
IedConnection_getFile(con, &error, filename, downloadHandler, (void*) fp);
if (error != IED_ERROR_OK)
printf("Failed to get file!\n");
fclose(fp);
}
else
printf("Failed to open file %s\n", localFilename);
free(bname);
}
void
setFile(IedConnection con)
{
IedClientError error;
char* dirc = strdup(filename);
char* basec = strdup(filename);
char* localDirName = dirname(dirc);
char* localFileName = basename(basec);
printf("local dir: %s\n", localDirName);
printf("local file: %s\n", localFileName);
/* IedConnection_setFilestoreBasepath requires the file separator at the end! */
strcpy(dirc, localDirName);
strcat(dirc, "/");
printf("filestore basepath: %s\n", dirc);
IedConnection_setFilestoreBasepath(con, dirc);
IedConnection_setFile(con, &error, localFileName, localFileName);
if (error != IED_ERROR_OK)
printf("Failed to set file! (code=%i)\n", error);
free(dirc);
free(basec);
}
void
deleteFile(IedConnection con)
{
IedClientError error;
/* Delete file at server */
IedConnection_deleteFile(con, &error, filename);
if (error != IED_ERROR_OK)
printf("Failed to delete file! (code=%i)\n", error);
}
int
main(int argc, char** argv)
{
if (argc < 2) {
printHelp();
return 0;
}
parseOptions(argc, argv);
if (operation == FileOperationType_None) {
printHelp();
return 0;
}
IedClientError error;
IedConnection con = IedConnection_create();
IedConnection_connect(con, &error, hostname, tcpPort);
if (error == IED_ERROR_OK) {
switch (operation) {
case FileOperationType_Dir:
showDirectory(con);
break;
case FileOperationType_Get:
getFile(con);
break;
case FileOperationType_Del:
deleteFile(con);
break;
case FileOperationType_Info:
break;
case FileOperationType_Set:
setFile(con);
break;
}
IedConnection_abort(con, &error);
}
else {
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
IedConnection_destroy(con);
}

View file

@ -132,7 +132,9 @@ int main(int argc, char** argv) {
Thread_sleep(1000);
IedConnection_triggerGIReport(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB01");
/* Trigger GI Report */
ClientReportControlBlock_setGI(rcb, true);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);
if (error != IED_ERROR_OK) {
printf("Error triggering a GI report (code: %i)\n", error);

View file

@ -21,6 +21,7 @@ print_help()
printf("-a <domain_name> specify domain for read or write command\n");
printf("-f show file list\n");
printf("-g <filename> get file attributes\n");
printf("-x <filename> delete file\n");
printf("-j <domainName/journalName> read journal\n");
printf("-m print raw MMS messages\n");
}
@ -115,10 +116,11 @@ int main(int argc, char** argv) {
int getFileAttributes = 0;
int readJournal = 0;
int printRawMmsMessages = 0;
int deleteFile = 0;
int c;
while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:")) != -1)
while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:")) != -1)
switch (c) {
case 'm':
printRawMmsMessages = 1;
@ -158,6 +160,10 @@ int main(int argc, char** argv) {
getFileAttributes = 1;
filename = StringUtils_copyString(optarg);
break;
case 'x':
deleteFile = 1;
filename = StringUtils_copyString(optarg);
break;
case 'j':
readJournal = 1;
@ -351,6 +357,17 @@ int main(int argc, char** argv) {
MmsConnection_getFileDirectory(con, &error, filename, NULL, mmsGetFileAttributeHandler, NULL);
}
if (deleteFile) {
MmsConnection_fileDelete(con, &error, filename);
if (error != MMS_ERROR_NONE) {
printf("Delete file failed: (ERROR %i)\n", error);
}
else {
printf("File deleted\n");
}
}
exit:
free(hostname);
MmsConnection_destroy(con);

View file

@ -85,6 +85,10 @@ main(int argc, char** argv)
iedServer = IedServer_create(&iedModel);
/* Set the base path for the MMS file services */
MmsServer mmsServer = IedServer_getMmsServer(iedServer);
MmsServer_setFilestoreBasepath(mmsServer, "./vmd-filestore/");
/* Install handler for operate command */
IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1,
(ControlHandler) controlHandlerForBinaryOutput,

View file

@ -0,0 +1,21 @@
include_directories(
.
)
set(server_example_SRCS
server_example_files.c
static_model.c
)
IF(WIN32)
set_source_files_properties(${server_example_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
add_executable(server_example_files
${server_example_SRCS}
)
target_link_libraries(server_example_files
iec61850
)

View file

@ -0,0 +1,31 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = server_example_files
PROJECT_SOURCES = server_example_files.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = simpleIO_direct_control.icd
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
LDLIBS += -lm
CP = cp
model: $(PROJECT_ICD_FILE)
java -jar $(LIBIEC_HOME)/tools/model_generator/genmodel.jar $(PROJECT_ICD_FILE)
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
$(CP) $(PROJECT_BINARY_NAME) vmd-filestore/IEDSERVER.BIN
clean:
rm -f $(PROJECT_BINARY_NAME)
rm -f vmd-filestore/IEDSERVER.BIN

View file

@ -0,0 +1,98 @@
/*
* server_example_files.c
*
* - How to use some special MMS file service features
* - How to control how files file services can be used
*/
#include "iec61850_server.h"
#include "hal_thread.h"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
static int running = 0;
static IedServer iedServer = NULL;
void
sigint_handler(int signalId)
{
running = 0;
}
static void
connectionHandler (IedServer self, ClientConnection connection, bool connected, void* parameter)
{
if (connected)
printf("Connection opened\n");
else
printf("Connection closed\n");
}
static MmsError
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);
/* Don't allow client to rename files */
if (service == MMS_FILE_ACCESS_TYPE_RENAME)
return MMS_ERROR_FILE_FILE_ACCESS_DENIED;
/* Don't allow client to delete fike "IEDSERVER.BIN" */
if (service == MMS_FILE_ACCESS_TYPE_DELETE) {
if (strcmp(localFilename, "IEDSERVER.BIN") == 0)
return MMS_ERROR_FILE_FILE_ACCESS_DENIED;
}
/* allow all other accesses */
return MMS_ERROR_NONE;
}
int
main(int argc, char** argv)
{
printf("Using libIEC61850 version %s\n", LibIEC61850_getVersionString());
iedServer = IedServer_create(&iedModel);
/* Set the base path for the MMS file services */
MmsServer mmsServer = IedServer_getMmsServer(iedServer);
MmsServer_setFilestoreBasepath(mmsServer, "./vmd-filestore/");
/* Set a callback handler to control file accesses */
MmsServer_installFileAccessHandler(mmsServer, fileAccessHandler, NULL);
IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, NULL);
/* MMS server will be instructed to start listening to client connections. */
IedServer_start(iedServer, 102);
if (!IedServer_isRunning(iedServer)) {
printf("Starting server failed! Exit.\n");
IedServer_destroy(iedServer);
exit(-1);
}
running = 1;
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);
} /* main() */

View file

@ -0,0 +1,281 @@
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
<Header id="" nameStructure="IEDName">
</Header>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS">
<Text>Station bus</Text>
<BitRate unit="b/s">10</BitRate>
<ConnectedAP iedName="simpleIO" apName="accessPoint1">
<Address>
<P type="IP">10.0.0.2</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">10.0.0.1</P>
<P type="OSI-TSEL">0001</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</P>
</Address>
</ConnectedAP>
</SubNetwork>
</Communication>
<IED name="simpleIO">
<Services>
<DynAssociation />
<GetDirectory />
<GetDataObjectDefinition />
<GetDataSetValue />
<DataSetDirectory />
<ReadWrite />
<GetCBValues />
<ConfLNs fixPrefix="true" fixLnInst="true" />
<GOOSE max="5" />
<GSSE max="5" />
<FileHandling />
<GSEDir />
<TimerActivatedControl />
</Services>
<AccessPoint name="accessPoint1">
<Server>
<Authentication />
<LDevice inst="GenericIO">
<LN0 lnClass="LLN0" lnType="LLN01" inst="">
<DataSet name="Events" desc="Events">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="stVal" />
</DataSet>
<DataSet name="Events2" desc="Events2">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" />
</DataSet>
<DataSet name="Measurements" desc="Measurements">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn3" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn3" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn4" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn4" daName="q" />
</DataSet>
<ReportControl name="EventsRCB" confRev="4294967295" datSet="Events" rptID="Events1" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="1" />
</ReportControl>
<ReportControl name="EventsIndexed" indexed="true" confRev="1" datSet="Events" rptID="Events2" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="3" />
</ReportControl>
<ReportControl name="Measurements" indexed="true" confRev="1" datSet="Measurements" rptID="Measurements" buffered="true" intgPd="1000" bufTime="50">
<TrgOps period="false" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="3" />
</ReportControl>
<LogControl name="EventLog" datSet="Events" logName="EventLog">
<TrgOps dchg="true" qchg="true"/>
</LogControl>
<LogControl name="GeneralLog" logName="">
<TrgOps dchg="true" qchg="true"/>
</LogControl>
<Log />
<Log name="EventLog" />
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
<DOI name="NamPlt">
<DAI name="vendor">
<Val>MZ Automation</Val>
</DAI>
<DAI name="swRev">
<Val>0.7.3</Val>
</DAI>
<DAI name="d">
<Val>libiec61850 server example</Val>
</DAI>
</DOI>
</LN0>
<LN lnClass="LPHD" lnType="LPHD1" inst="1" prefix="" />
<LN lnClass="GGIO" lnType="GGIO1" inst="1" prefix="">
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
<DOI name="SPCSO1">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO2">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO3">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO4">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
</LN>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="LLN01" lnClass="LLN0">
<DO name="Mod" type="INC_1_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_1_NamPlt" />
</LNodeType>
<LNodeType id="LPHD1" lnClass="LPHD">
<DO name="PhyNam" type="DPL_1_PhyNam" />
<DO name="PhyHealth" type="INS_1_Beh" />
<DO name="Proxy" type="SPS_1_Proxy" />
</LNodeType>
<LNodeType id="GGIO1" lnClass="GGIO">
<DO name="Mod" type="INC_2_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_2_NamPlt" />
<DO name="AnIn1" type="MV_1_AnIn1" />
<DO name="AnIn2" type="MV_1_AnIn1" />
<DO name="AnIn3" type="MV_1_AnIn1" />
<DO name="AnIn4" type="MV_1_AnIn1" />
<DO name="SPCSO1" type="SPC_2_SPCSO1" />
<DO name="SPCSO2" type="SPC_1_SPCSO2" />
<DO name="SPCSO3" type="SPC_1_SPCSO3" />
<DO name="SPCSO4" type="SPC_1_SPCSO1" />
<DO name="Ind1" type="SPS_1_Proxy" />
<DO name="Ind2" type="SPS_1_Proxy" />
<DO name="Ind3" type="SPS_1_Proxy" />
<DO name="Ind4" type="SPS_1_Proxy" />
</LNodeType>
<DOType id="INC_1_Mod" cdc="INC">
<DA name="stVal" bType="INT32" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="INS_1_Beh" cdc="INS">
<DA name="stVal" bType="INT32" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="LPL_1_NamPlt" cdc="LPL">
<DA name="vendor" bType="VisString255" fc="DC" />
<DA name="swRev" bType="VisString255" fc="DC" />
<DA name="d" bType="VisString255" fc="DC" />
<DA name="configRev" bType="VisString255" fc="DC" />
<DA name="ldNs" bType="VisString255" fc="EX" />
</DOType>
<DOType id="DPL_1_PhyNam" cdc="DPL">
<DA name="vendor" bType="VisString255" fc="DC" />
</DOType>
<DOType id="SPS_1_Proxy" cdc="SPS">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="LPL_2_NamPlt" cdc="LPL">
<DA name="vendor" bType="VisString255" fc="DC" />
<DA name="swRev" bType="VisString255" fc="DC" />
<DA name="d" bType="VisString255" fc="DC" />
</DOType>
<DOType id="MV_1_AnIn1" cdc="MV">
<DA name="mag" type="AnalogueValue_1" bType="Struct" fc="MX" dchg="true" />
<DA name="q" bType="Quality" fc="MX" qchg="true" />
<DA name="t" bType="Timestamp" fc="MX" />
</DOType>
<DOType id="SPC_1_SPCSO1" cdc="SPC">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="INC_2_Mod" cdc="INC">
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="SPC_2_SPCSO1" cdc="SPC">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="SPC_1_SPCSO2" cdc="SPC">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="SPC_1_SPCSO3" cdc="SPC">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DAType id="AnalogueValue_1">
<BDA name="f" bType="FLOAT32" />
</DAType>
<DAType id="Originator_1">
<BDA name="orCat" type="OrCat" bType="Enum" />
<BDA name="orIdent" bType="Octet64" />
</DAType>
<DAType id="SPCOperate_1">
<BDA name="ctlVal" bType="BOOLEAN" />
<BDA name="origin" type="Originator_1" bType="Struct" />
<BDA name="ctlNum" bType="INT8U" />
<BDA name="T" bType="Timestamp" />
<BDA name="Test" bType="BOOLEAN" />
<BDA name="Check" bType="Check" />
</DAType>
<EnumType id="CtlModels">
<EnumVal ord="0">status-only</EnumVal>
<EnumVal ord="1">direct-with-normal-security</EnumVal>
<EnumVal ord="2">sbo-with-normal-security</EnumVal>
<EnumVal ord="3">direct-with-enhanced-security</EnumVal>
<EnumVal ord="4">sbo-with-enhanced-security</EnumVal>
</EnumType>
<EnumType id="OrCat">
<EnumVal ord="0">not-supported</EnumVal>
<EnumVal ord="1">bay-control</EnumVal>
<EnumVal ord="2">station-control</EnumVal>
<EnumVal ord="3">remote-control</EnumVal>
<EnumVal ord="4">automatic-bay</EnumVal>
<EnumVal ord="5">automatic-station</EnumVal>
<EnumVal ord="6">automatic-remote</EnumVal>
<EnumVal ord="7">maintenance</EnumVal>
<EnumVal ord="8">process</EnumVal>
</EnumType>
</DataTypeTemplates>
</SCL>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,301 @@
/*
* static_model.h
*
* automatically generated from simpleIO_direct_control.icd
*/
#ifndef STATIC_MODEL_H_
#define STATIC_MODEL_H_
#include <stdlib.h>
#include "iec61850_model.h"
extern IedModel iedModel;
extern LogicalDevice iedModel_GenericIO;
extern LogicalNode iedModel_GenericIO_LLN0;
extern DataObject iedModel_GenericIO_LLN0_Mod;
extern DataAttribute iedModel_GenericIO_LLN0_Mod_stVal;
extern DataAttribute iedModel_GenericIO_LLN0_Mod_q;
extern DataAttribute iedModel_GenericIO_LLN0_Mod_t;
extern DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel;
extern DataObject iedModel_GenericIO_LLN0_Beh;
extern DataAttribute iedModel_GenericIO_LLN0_Beh_stVal;
extern DataAttribute iedModel_GenericIO_LLN0_Beh_q;
extern DataAttribute iedModel_GenericIO_LLN0_Beh_t;
extern DataObject iedModel_GenericIO_LLN0_Health;
extern DataAttribute iedModel_GenericIO_LLN0_Health_stVal;
extern DataAttribute iedModel_GenericIO_LLN0_Health_q;
extern DataAttribute iedModel_GenericIO_LLN0_Health_t;
extern DataObject iedModel_GenericIO_LLN0_NamPlt;
extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_vendor;
extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_swRev;
extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_d;
extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_configRev;
extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_ldNs;
extern LogicalNode iedModel_GenericIO_LPHD1;
extern DataObject iedModel_GenericIO_LPHD1_PhyNam;
extern DataAttribute iedModel_GenericIO_LPHD1_PhyNam_vendor;
extern DataObject iedModel_GenericIO_LPHD1_PhyHealth;
extern DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_stVal;
extern DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_q;
extern DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_t;
extern DataObject iedModel_GenericIO_LPHD1_Proxy;
extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_stVal;
extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_q;
extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_t;
extern LogicalNode iedModel_GenericIO_GGIO1;
extern DataObject iedModel_GenericIO_GGIO1_Mod;
extern DataAttribute iedModel_GenericIO_GGIO1_Mod_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Mod_t;
extern DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel;
extern DataObject iedModel_GenericIO_GGIO1_Beh;
extern DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_Beh_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Beh_t;
extern DataObject iedModel_GenericIO_GGIO1_Health;
extern DataAttribute iedModel_GenericIO_GGIO1_Health_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_Health_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Health_t;
extern DataObject iedModel_GenericIO_GGIO1_NamPlt;
extern DataAttribute iedModel_GenericIO_GGIO1_NamPlt_vendor;
extern DataAttribute iedModel_GenericIO_GGIO1_NamPlt_swRev;
extern DataAttribute iedModel_GenericIO_GGIO1_NamPlt_d;
extern DataObject iedModel_GenericIO_GGIO1_AnIn1;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag_f;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_q;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_t;
extern DataObject iedModel_GenericIO_GGIO1_AnIn2;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag_f;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_q;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_t;
extern DataObject iedModel_GenericIO_GGIO1_AnIn3;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag_f;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_q;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_t;
extern DataObject iedModel_GenericIO_GGIO1_AnIn4;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag_f;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_q;
extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_t;
extern DataObject iedModel_GenericIO_GGIO1_SPCSO1;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_q;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_T;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_ctlModel;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_t;
extern DataObject iedModel_GenericIO_GGIO1_SPCSO2;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_q;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_T;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_ctlModel;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_t;
extern DataObject iedModel_GenericIO_GGIO1_SPCSO3;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_q;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_T;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_ctlModel;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_t;
extern DataObject iedModel_GenericIO_GGIO1_SPCSO4;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_q;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_T;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_ctlModel;
extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_t;
extern DataObject iedModel_GenericIO_GGIO1_Ind1;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind1_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind1_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind1_t;
extern DataObject iedModel_GenericIO_GGIO1_Ind2;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind2_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind2_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind2_t;
extern DataObject iedModel_GenericIO_GGIO1_Ind3;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind3_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind3_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind3_t;
extern DataObject iedModel_GenericIO_GGIO1_Ind4;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_stVal;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_q;
extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_t;
#define IEDMODEL_GenericIO (&iedModel_GenericIO)
#define IEDMODEL_GenericIO_LLN0 (&iedModel_GenericIO_LLN0)
#define IEDMODEL_GenericIO_LLN0_Mod (&iedModel_GenericIO_LLN0_Mod)
#define IEDMODEL_GenericIO_LLN0_Mod_stVal (&iedModel_GenericIO_LLN0_Mod_stVal)
#define IEDMODEL_GenericIO_LLN0_Mod_q (&iedModel_GenericIO_LLN0_Mod_q)
#define IEDMODEL_GenericIO_LLN0_Mod_t (&iedModel_GenericIO_LLN0_Mod_t)
#define IEDMODEL_GenericIO_LLN0_Mod_ctlModel (&iedModel_GenericIO_LLN0_Mod_ctlModel)
#define IEDMODEL_GenericIO_LLN0_Beh (&iedModel_GenericIO_LLN0_Beh)
#define IEDMODEL_GenericIO_LLN0_Beh_stVal (&iedModel_GenericIO_LLN0_Beh_stVal)
#define IEDMODEL_GenericIO_LLN0_Beh_q (&iedModel_GenericIO_LLN0_Beh_q)
#define IEDMODEL_GenericIO_LLN0_Beh_t (&iedModel_GenericIO_LLN0_Beh_t)
#define IEDMODEL_GenericIO_LLN0_Health (&iedModel_GenericIO_LLN0_Health)
#define IEDMODEL_GenericIO_LLN0_Health_stVal (&iedModel_GenericIO_LLN0_Health_stVal)
#define IEDMODEL_GenericIO_LLN0_Health_q (&iedModel_GenericIO_LLN0_Health_q)
#define IEDMODEL_GenericIO_LLN0_Health_t (&iedModel_GenericIO_LLN0_Health_t)
#define IEDMODEL_GenericIO_LLN0_NamPlt (&iedModel_GenericIO_LLN0_NamPlt)
#define IEDMODEL_GenericIO_LLN0_NamPlt_vendor (&iedModel_GenericIO_LLN0_NamPlt_vendor)
#define IEDMODEL_GenericIO_LLN0_NamPlt_swRev (&iedModel_GenericIO_LLN0_NamPlt_swRev)
#define IEDMODEL_GenericIO_LLN0_NamPlt_d (&iedModel_GenericIO_LLN0_NamPlt_d)
#define IEDMODEL_GenericIO_LLN0_NamPlt_configRev (&iedModel_GenericIO_LLN0_NamPlt_configRev)
#define IEDMODEL_GenericIO_LLN0_NamPlt_ldNs (&iedModel_GenericIO_LLN0_NamPlt_ldNs)
#define IEDMODEL_GenericIO_LPHD1 (&iedModel_GenericIO_LPHD1)
#define IEDMODEL_GenericIO_LPHD1_PhyNam (&iedModel_GenericIO_LPHD1_PhyNam)
#define IEDMODEL_GenericIO_LPHD1_PhyNam_vendor (&iedModel_GenericIO_LPHD1_PhyNam_vendor)
#define IEDMODEL_GenericIO_LPHD1_PhyHealth (&iedModel_GenericIO_LPHD1_PhyHealth)
#define IEDMODEL_GenericIO_LPHD1_PhyHealth_stVal (&iedModel_GenericIO_LPHD1_PhyHealth_stVal)
#define IEDMODEL_GenericIO_LPHD1_PhyHealth_q (&iedModel_GenericIO_LPHD1_PhyHealth_q)
#define IEDMODEL_GenericIO_LPHD1_PhyHealth_t (&iedModel_GenericIO_LPHD1_PhyHealth_t)
#define IEDMODEL_GenericIO_LPHD1_Proxy (&iedModel_GenericIO_LPHD1_Proxy)
#define IEDMODEL_GenericIO_LPHD1_Proxy_stVal (&iedModel_GenericIO_LPHD1_Proxy_stVal)
#define IEDMODEL_GenericIO_LPHD1_Proxy_q (&iedModel_GenericIO_LPHD1_Proxy_q)
#define IEDMODEL_GenericIO_LPHD1_Proxy_t (&iedModel_GenericIO_LPHD1_Proxy_t)
#define IEDMODEL_GenericIO_GGIO1 (&iedModel_GenericIO_GGIO1)
#define IEDMODEL_GenericIO_GGIO1_Mod (&iedModel_GenericIO_GGIO1_Mod)
#define IEDMODEL_GenericIO_GGIO1_Mod_q (&iedModel_GenericIO_GGIO1_Mod_q)
#define IEDMODEL_GenericIO_GGIO1_Mod_t (&iedModel_GenericIO_GGIO1_Mod_t)
#define IEDMODEL_GenericIO_GGIO1_Mod_ctlModel (&iedModel_GenericIO_GGIO1_Mod_ctlModel)
#define IEDMODEL_GenericIO_GGIO1_Beh (&iedModel_GenericIO_GGIO1_Beh)
#define IEDMODEL_GenericIO_GGIO1_Beh_stVal (&iedModel_GenericIO_GGIO1_Beh_stVal)
#define IEDMODEL_GenericIO_GGIO1_Beh_q (&iedModel_GenericIO_GGIO1_Beh_q)
#define IEDMODEL_GenericIO_GGIO1_Beh_t (&iedModel_GenericIO_GGIO1_Beh_t)
#define IEDMODEL_GenericIO_GGIO1_Health (&iedModel_GenericIO_GGIO1_Health)
#define IEDMODEL_GenericIO_GGIO1_Health_stVal (&iedModel_GenericIO_GGIO1_Health_stVal)
#define IEDMODEL_GenericIO_GGIO1_Health_q (&iedModel_GenericIO_GGIO1_Health_q)
#define IEDMODEL_GenericIO_GGIO1_Health_t (&iedModel_GenericIO_GGIO1_Health_t)
#define IEDMODEL_GenericIO_GGIO1_NamPlt (&iedModel_GenericIO_GGIO1_NamPlt)
#define IEDMODEL_GenericIO_GGIO1_NamPlt_vendor (&iedModel_GenericIO_GGIO1_NamPlt_vendor)
#define IEDMODEL_GenericIO_GGIO1_NamPlt_swRev (&iedModel_GenericIO_GGIO1_NamPlt_swRev)
#define IEDMODEL_GenericIO_GGIO1_NamPlt_d (&iedModel_GenericIO_GGIO1_NamPlt_d)
#define IEDMODEL_GenericIO_GGIO1_AnIn1 (&iedModel_GenericIO_GGIO1_AnIn1)
#define IEDMODEL_GenericIO_GGIO1_AnIn1_mag (&iedModel_GenericIO_GGIO1_AnIn1_mag)
#define IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f (&iedModel_GenericIO_GGIO1_AnIn1_mag_f)
#define IEDMODEL_GenericIO_GGIO1_AnIn1_q (&iedModel_GenericIO_GGIO1_AnIn1_q)
#define IEDMODEL_GenericIO_GGIO1_AnIn1_t (&iedModel_GenericIO_GGIO1_AnIn1_t)
#define IEDMODEL_GenericIO_GGIO1_AnIn2 (&iedModel_GenericIO_GGIO1_AnIn2)
#define IEDMODEL_GenericIO_GGIO1_AnIn2_mag (&iedModel_GenericIO_GGIO1_AnIn2_mag)
#define IEDMODEL_GenericIO_GGIO1_AnIn2_mag_f (&iedModel_GenericIO_GGIO1_AnIn2_mag_f)
#define IEDMODEL_GenericIO_GGIO1_AnIn2_q (&iedModel_GenericIO_GGIO1_AnIn2_q)
#define IEDMODEL_GenericIO_GGIO1_AnIn2_t (&iedModel_GenericIO_GGIO1_AnIn2_t)
#define IEDMODEL_GenericIO_GGIO1_AnIn3 (&iedModel_GenericIO_GGIO1_AnIn3)
#define IEDMODEL_GenericIO_GGIO1_AnIn3_mag (&iedModel_GenericIO_GGIO1_AnIn3_mag)
#define IEDMODEL_GenericIO_GGIO1_AnIn3_mag_f (&iedModel_GenericIO_GGIO1_AnIn3_mag_f)
#define IEDMODEL_GenericIO_GGIO1_AnIn3_q (&iedModel_GenericIO_GGIO1_AnIn3_q)
#define IEDMODEL_GenericIO_GGIO1_AnIn3_t (&iedModel_GenericIO_GGIO1_AnIn3_t)
#define IEDMODEL_GenericIO_GGIO1_AnIn4 (&iedModel_GenericIO_GGIO1_AnIn4)
#define IEDMODEL_GenericIO_GGIO1_AnIn4_mag (&iedModel_GenericIO_GGIO1_AnIn4_mag)
#define IEDMODEL_GenericIO_GGIO1_AnIn4_mag_f (&iedModel_GenericIO_GGIO1_AnIn4_mag_f)
#define IEDMODEL_GenericIO_GGIO1_AnIn4_q (&iedModel_GenericIO_GGIO1_AnIn4_q)
#define IEDMODEL_GenericIO_GGIO1_AnIn4_t (&iedModel_GenericIO_GGIO1_AnIn4_t)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1 (&iedModel_GenericIO_GGIO1_SPCSO1)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_stVal (&iedModel_GenericIO_GGIO1_SPCSO1_stVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_q (&iedModel_GenericIO_GGIO1_SPCSO1_q)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper (&iedModel_GenericIO_GGIO1_SPCSO1_Oper)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_T)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO1_ctlModel)
#define IEDMODEL_GenericIO_GGIO1_SPCSO1_t (&iedModel_GenericIO_GGIO1_SPCSO1_t)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2 (&iedModel_GenericIO_GGIO1_SPCSO2)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_stVal (&iedModel_GenericIO_GGIO1_SPCSO2_stVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_q (&iedModel_GenericIO_GGIO1_SPCSO2_q)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper (&iedModel_GenericIO_GGIO1_SPCSO2_Oper)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_T)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO2_ctlModel)
#define IEDMODEL_GenericIO_GGIO1_SPCSO2_t (&iedModel_GenericIO_GGIO1_SPCSO2_t)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3 (&iedModel_GenericIO_GGIO1_SPCSO3)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_stVal (&iedModel_GenericIO_GGIO1_SPCSO3_stVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_q (&iedModel_GenericIO_GGIO1_SPCSO3_q)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper (&iedModel_GenericIO_GGIO1_SPCSO3_Oper)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_T)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO3_ctlModel)
#define IEDMODEL_GenericIO_GGIO1_SPCSO3_t (&iedModel_GenericIO_GGIO1_SPCSO3_t)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4 (&iedModel_GenericIO_GGIO1_SPCSO4)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_stVal (&iedModel_GenericIO_GGIO1_SPCSO4_stVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_q (&iedModel_GenericIO_GGIO1_SPCSO4_q)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper (&iedModel_GenericIO_GGIO1_SPCSO4_Oper)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_T)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO4_ctlModel)
#define IEDMODEL_GenericIO_GGIO1_SPCSO4_t (&iedModel_GenericIO_GGIO1_SPCSO4_t)
#define IEDMODEL_GenericIO_GGIO1_Ind1 (&iedModel_GenericIO_GGIO1_Ind1)
#define IEDMODEL_GenericIO_GGIO1_Ind1_stVal (&iedModel_GenericIO_GGIO1_Ind1_stVal)
#define IEDMODEL_GenericIO_GGIO1_Ind1_q (&iedModel_GenericIO_GGIO1_Ind1_q)
#define IEDMODEL_GenericIO_GGIO1_Ind1_t (&iedModel_GenericIO_GGIO1_Ind1_t)
#define IEDMODEL_GenericIO_GGIO1_Ind2 (&iedModel_GenericIO_GGIO1_Ind2)
#define IEDMODEL_GenericIO_GGIO1_Ind2_stVal (&iedModel_GenericIO_GGIO1_Ind2_stVal)
#define IEDMODEL_GenericIO_GGIO1_Ind2_q (&iedModel_GenericIO_GGIO1_Ind2_q)
#define IEDMODEL_GenericIO_GGIO1_Ind2_t (&iedModel_GenericIO_GGIO1_Ind2_t)
#define IEDMODEL_GenericIO_GGIO1_Ind3 (&iedModel_GenericIO_GGIO1_Ind3)
#define IEDMODEL_GenericIO_GGIO1_Ind3_stVal (&iedModel_GenericIO_GGIO1_Ind3_stVal)
#define IEDMODEL_GenericIO_GGIO1_Ind3_q (&iedModel_GenericIO_GGIO1_Ind3_q)
#define IEDMODEL_GenericIO_GGIO1_Ind3_t (&iedModel_GenericIO_GGIO1_Ind3_t)
#define IEDMODEL_GenericIO_GGIO1_Ind4 (&iedModel_GenericIO_GGIO1_Ind4)
#define IEDMODEL_GenericIO_GGIO1_Ind4_stVal (&iedModel_GenericIO_GGIO1_Ind4_stVal)
#define IEDMODEL_GenericIO_GGIO1_Ind4_q (&iedModel_GenericIO_GGIO1_Ind4_q)
#define IEDMODEL_GenericIO_GGIO1_Ind4_t (&iedModel_GenericIO_GGIO1_Ind4_t)
#endif /* STATIC_MODEL_H_ */

View file

@ -0,0 +1 @@
test

View file

@ -20,13 +20,13 @@ void sigint_handler(int signalId)
int
main(int argc, char** argv)
{
char * interface;
if (argc > 1) {
interface=argv[1];
}
else {
interface = "vboxnet0";
}
char* interface;
if (argc > 1)
interface = argv[1];
else
interface = "eth0";
printf("Using interface %s\n", interface);
SampledValuesPublisher svPublisher = SampledValuesPublisher_create(interface);

View file

@ -1131,6 +1131,32 @@ IedConnection_getFileDirectory(IedConnection self, IedClientError* error, const
return fileNames;
}
LinkedList /*<FileDirectoryEntry>*/
IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
bool* moreFollows)
{
*error = IED_ERROR_OK;
MmsError mmsError = MMS_ERROR_NONE;
LinkedList fileNames = LinkedList_create();
bool moreFollowsInternal = MmsConnection_getFileDirectory(self->connection, &mmsError, directoryName, continueAfter,
mmsFileDirectoryHandler, fileNames);
if (mmsError != MMS_ERROR_NONE) {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
return NULL;
}
if (moreFollows != NULL)
*moreFollows = moreFollowsInternal;
return fileNames;
}
struct sClientProvidedFileReadHandler {
IedClientGetFileHandler handler;
@ -1201,6 +1227,13 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil
return clientFileReadHandler.byteReceived;
}
void
IedConnection_setFilestoreBasepath(IedConnection self, const char* basepath)
{
/* simply pass the call to MMS client API */
MmsConnection_setFilestoreBasepath(self->connection, basepath);
}
void
IedConnection_setFile(IedConnection self, IedClientError* error, const char* sourceFilename, const char* destinationFilename)
{

View file

@ -405,6 +405,20 @@ Timestamp_setByMmsUtcTime(Timestamp* self, MmsValue* mmsValue)
memcpy(self->val, mmsValue->value.utcTime, 8);
}
MmsValue*
Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue)
{
MmsValue* convertedValue = mmsValue;
if (convertedValue == NULL)
convertedValue = MmsValue_newUtcTime(0);
if (convertedValue != NULL)
memcpy(convertedValue->value.utcTime, self->val, 8);
return convertedValue;
}
char*
LibIEC61850_getVersionString()
{

View file

@ -810,6 +810,8 @@ IedConnection_uninstallReportHandler(IedConnection self, const char* rcbReferenc
*
* The RCB must have been enabled and GI set as trigger option before this command can be performed.
*
* \deprecated Use ClientReportControlBlock_setGI instead
*
* \param connection the connection object
* \param error the error code if an error occurs
* \param rcbReference object reference of the report control block
@ -1869,6 +1871,38 @@ FileDirectoryEntry_getLastModified(FileDirectoryEntry self);
LinkedList /*<FileDirectoryEntry>*/
IedConnection_getFileDirectory(IedConnection self, IedClientError* error, const char* directoryName);
/**
* \brief returns the directory entries of the specified file directory returned by a single file directory request.
*
* This function will only create a single request and the result may only be the directory that fits
* into a single MMS PDU. If the server contains more directory entries, this will be indicated by setting
* the moreFollows variable (if provided by the caller). If the directory entry does not fit into a single MMS
* PDU the next part of the directory list can be requested by setting the continueAfter parameter with the value
* of the last filename of the received list.
*
* Requires the server to support file services.
*
* NOTE: the returned linked list has to be freed by the user. You can user the following statement
* to free the list of directory entries:
*
* LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
*
* where fileNames is the return value of this function.
*
* \param self the connection object
* \param error the error code if an error occurs
* \param directoryName the name of the directory or NULL to get the entries of the root directory
* \param continueAfter last received filename to continue after, or NULL for the first request
* \param moreFollows if provided by the caller (non NULL) the function will indicate if more directory entries
* are available.
*
* \return the list of directory entries. The return type is a LinkedList with FileDirectoryEntry elements
*/
LinkedList /*<FileDirectoryEntry>*/
IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
bool* moreFollows);
/**
* \brief user provided handler to receive the data of the GetFile request
*
@ -1901,6 +1935,19 @@ uint32_t
IedConnection_getFile(IedConnection self, IedClientError* error, const char* fileName, IedClientGetFileHandler handler,
void* handlerParameter);
/**
* \brief Set the virtual filestore basepath for the setFile service
*
* All external file service accesses will be mapped to paths relative to the base directory.
* NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
* option in stack_config.h is set.
*
* \param self the connection object
* \param basepath the new virtual filestore basepath
*/
void
IedConnection_setFilestoreBasepath(IedConnection, const char* basepath);
/**
* \brief Implementation of the SetFile ACSI service
*

View file

@ -406,6 +406,15 @@ Timestamp_setTimeInMilliseconds(Timestamp* self, uint64_t millisSinceEpoch);
void
Timestamp_setByMmsUtcTime(Timestamp* self, MmsValue* mmsValue);
/**
* \brief Set an MmsValue instance of type UTCTime to the timestamp value
*
* \param self the Timestamp instance
* \param mmsValue the mmsValue instance, if NULL a new instance will be created
*/
MmsValue*
Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue);
/**
* \brief Get the version of the library as string
*

View file

@ -85,6 +85,19 @@ IedServer_destroy(IedServer self);
void
IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress);
/**
* \brief Set the virtual filestore basepath for the MMS file services
*
* All external file service accesses will be mapped to paths relative to the base directory.
* NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
* option in stack_config.h is set.
*
* \param self the IedServer instance
* \param basepath the new virtual filestore basepath
*/
void
IedServer_setFilestoreBasepath(IedServer self, const char* basepath);
/**
* \brief Start handling client connections
*

View file

@ -604,6 +604,13 @@ IedServer_stop(IedServer self)
}
#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */
void
IedServer_setFilestoreBasepath(IedServer self, const char* basepath)
{
/* simply pass to MMS server API */
MmsServer_setFilestoreBasepath(self->mmsServer, basepath);
}
void
IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress)
{

View file

@ -106,6 +106,19 @@ typedef void (*MmsRawMessageHandler) (void* parameter, uint8_t* message, int mes
void
MmsConnection_setRawMessageHandler(MmsConnection self, MmsRawMessageHandler handler, void* parameter);
/**
* \brief Set the virtual filestore basepath for the MMS obtain file services
*
* All external file service accesses will be mapped to paths relative to the base directory.
* NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
* option in stack_config.h is set.
*
* \param self the MmsServer instance
* \param basepath the new virtual filestore basepath
*/
void
MmsConnection_setFilestoreBasepath(MmsConnection self, const char* basepath);
/**
* \brief Set the request timeout in ms for this connection
*

View file

@ -164,13 +164,61 @@ typedef void (*MmsGetFileCompleteHandler)(void* parameter, MmsServerConnection c
* \brief Install callback handler that is invoked when the file upload (obtainFile service) is completed and the
* file has been uploaded.
*
* \param self the MmsServer instance to operate on
* \param self the MmsServer instance
* \param handler the callback handler function
* \param parameter user provided parameter that is passed to the callback handler
*/
void
MmsServer_installGetFileCompleteHandler(MmsServer self, MmsGetFileCompleteHandler handler, void* parameter);
typedef enum {
MMS_FILE_ACCESS_TYPE_READ_DIRECTORY,
MMS_FILE_ACCESS_TYPE_OPEN,
MMS_FILE_ACCESS_TYPE_OBTAIN,
MMS_FILE_ACCESS_TYPE_DELETE,
MMS_FILE_ACCESS_TYPE_RENAME
} MmsFileServiceType;
/**
* \brief MmsFileAccessHandler callback function. Use to monitor and control file access
*
* \param parameter user provided parameter that is passed to the callback handler
* \param connection the connection that requested the service
* \param service the requested file service
* \param localFilename the requested file or directory name at the server
* \param otherFilename a second file name parameter (e.g. source file of the ObtainFile or new file of rename file)
*
* \return MMS_ERROR_NONE when the request is accepted, otherwise use the appropriate error code (e.g. MMS_ERROR_FILE_FILE_ACCESS_DENIED)
*/
typedef MmsError (*MmsFileAccessHandler) (void* parameter, MmsServerConnection connection, MmsFileServiceType service,
const char* localFilename, const char* otherFilename);
/**
* \brief Install a callback handler this is invoked when the client requests a file server. This function can be
* used to monitor and control file access
*
* \param self the MmsServer instance
* \param handler the callback handler function
* \param parameter user provided parameter that is passed to the callback handler
*/
void
MmsServer_installFileAccessHandler(MmsServer self, MmsFileAccessHandler handler, void* parameter);
/**
* \brief Set the virtual filestore basepath for the MMS file services
*
* All external file service accesses will be mapped to paths relative to the base directory.
* NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
* option in stack_config.h is set.
*
* \param self the MmsServer instance
* \param basepath the new virtual filestore basepath
*/
void
MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath);
/**
* \brief lock the cached server data model
*
@ -198,9 +246,6 @@ void
MmsServer_insertIntoCache(MmsServer self, MmsDomain* domain, char* itemId,
MmsValue* value);
void
MmsServer_setDevice(MmsServer self, MmsDevice* device);
/***************************************************
* Functions for multi-threaded operation mode
***************************************************/
@ -391,6 +436,7 @@ MmsServerConnection_getClientAddress(MmsServerConnection self);
IsoConnection
MmsServerConnection_getIsoConnection(MmsServerConnection self);
/**@}*/
#ifdef __cplusplus

View file

@ -102,7 +102,12 @@ struct sMmsConnection {
#if (MMS_OBTAIN_FILE_SERVICE == 1)
int32_t nextFrsmId;
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char* filestoreBasepath;
#endif
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
};
@ -116,6 +121,9 @@ typedef enum {
MMS_OBJECT_CLASS_DOMAIN = 9
} MmsObjectClass;
char*
MmsConnection_getFilestoreBasepath(MmsConnection self);
MmsValue*
mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSize, bool createArray);

View file

@ -28,6 +28,7 @@
#include "MmsPdu.h"
#include "conversions.h"
#include "byte_buffer.h"
#include "mms_server.h"
#if (MMS_FILE_SERVICE == 1)
@ -60,8 +61,16 @@ void
mmsMsg_createFileCloseResponse(uint32_t invokeId, ByteBuffer* response);
void
mmsMsg_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm);
mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm);
bool
mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response);
void
mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName);
FileHandle
mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite);
#endif /* (MMS_FILE_SERVICE == 1) */

View file

@ -101,6 +101,9 @@ MmsServerConnection_getLastInvokeId(MmsServerConnection self);
uint32_t
MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self);
const char*
MmsServerConnection_getFilesystemBasepath(MmsServerConnection self);
#endif /* MMS_SERVER_CONNECTION_H_ */

View file

@ -156,6 +156,15 @@ struct sMmsServer {
struct sMmsObtainFileTask fileUploadTasks[CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS];
#endif
#if (MMS_FILE_SERVICE == 1)
MmsFileAccessHandler fileAccessHandler;
void* fileAccessHandlerParameter;
#endif
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char* filestoreBasepath;
#endif
};
struct sMmsServerConnection {

View file

@ -947,9 +947,50 @@ MmsConnection_destroy(MmsConnection self)
GLOBAL_FREEMEM(self->outstandingCalls);
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
if (self->filestoreBasepath != NULL)
GLOBAL_FREEMEM(self->filestoreBasepath);
#endif
#endif
GLOBAL_FREEMEM(self);
}
void
MmsConnection_setFilestoreBasepath(MmsConnection self, const char* basepath)
{
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
if (self->filestoreBasepath != NULL) {
GLOBAL_FREEMEM(self->filestoreBasepath);
self->filestoreBasepath = NULL;
}
if (basepath != NULL)
self->filestoreBasepath = StringUtils_copyString(basepath);
#endif
#endif
}
char*
MmsConnection_getFilestoreBasepath(MmsConnection self)
{
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
if (self->filestoreBasepath != NULL)
return self->filestoreBasepath;
else
return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
#else
return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
#endif
#else
return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
#endif
}
void
MmsConnection_setRawMessageHandler(MmsConnection self, MmsRawMessageHandler handler, void* parameter)
{

View file

@ -80,57 +80,6 @@ getNextFrsmId(MmsConnection connection)
return nextFrsmId;
}
//TODO remove redundancy (with server implementation)
static void
createExtendedFilename(char* extendedFileName, char* fileName)
{
strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
}
//TODO remove redundancy (with server implementation)
static FileHandle
openFile(char* fileName, bool readWrite)
{
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedFileName, fileName);
return FileSystem_openFile(extendedFileName, readWrite);
}
//TODO remove redundancy (with server implementation)
static bool
parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
{
uint8_t tag = buffer[(*bufPos)++];
int length;
if (tag != 0x19) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return false;
}
*bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
if (*bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return false;
}
if (length > 255) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
return false;
}
memcpy(filename, buffer + *bufPos, length);
filename[length] = 0;
*bufPos += length;
return true;
}
void
mmsClient_handleFileOpenRequest(
MmsConnection connection,
@ -152,7 +101,7 @@ mmsClient_handleFileOpenRequest(
switch(tag) {
case 0xa0: /* filename */
if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasFileName = true;
@ -175,14 +124,15 @@ mmsClient_handleFileOpenRequest(
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (frsm != NULL) {
FileHandle fileHandle = openFile(filename, false);
FileHandle fileHandle = mmsMsg_openFile(MmsConnection_getFilestoreBasepath(connection), filename, false);
if (fileHandle != NULL) {
frsm->fileHandle = fileHandle;
frsm->readPosition = filePosition;
frsm->frsmId = getNextFrsmId(connection);
mmsMsg_createFileOpenResponse(invokeId, response, filename, frsm);
mmsMsg_createFileOpenResponse(MmsConnection_getFilestoreBasepath(connection),
invokeId, response, filename, frsm);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);

View file

@ -1,7 +1,7 @@
/*
* mms_common_msg.c
*
* Copyright 2013 Michael Zillgith
* Copyright 2013 - 2017 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -25,6 +25,7 @@
#include "mms_common_internal.h"
#include "stack_config.h"
#include "mms_value_internal.h"
#include "ber_decode.h"
static void
mmsMsg_createFloatData(MmsValue* value, int* size, uint8_t** buf)
@ -342,3 +343,72 @@ mmsMsg_copyAsn1IdentifierToStringBuffer(Identifier_t identifier, char* buffer, i
buffer[0] = 0;
}
}
void
mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
// strncpy(extendedFileName, MmsServerConnection_getFilesystemBasepath(self), 512);
strncpy(extendedFileName, basepath, 512);
strncat(extendedFileName, fileName, 512);
#else
strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
#endif
}
FileHandle
mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedFileName[512];
#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
#endif
mmsMsg_createExtendedFilename(basepath, extendedFileName, fileName);
return FileSystem_openFile(extendedFileName, readWrite);
}
bool
mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
{
uint8_t tag = buffer[(*bufPos)++];
int length;
if (tag != 0x19) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return false;
}
*bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
if (*bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return false;
}
if (length > 255) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
return false;
}
memcpy(filename, buffer + *bufPos, length);
filename[length] = 0;
*bufPos += length;
/* Check if path contains invalid characters (prevent escaping the virtual filestore by using "..")
* TODO this may be platform dependent. Also depending of the platform there might be other evil
* characters.
*/
if (strstr(filename, "..") != NULL) {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILENAME_SYNTAX_ERROR);
return false;
}
return true;
}

View file

@ -122,69 +122,85 @@ encodeFileAttributes(uint8_t tag, uint32_t fileSize, char* gtString, uint8_t* bu
}
}
static void
createExtendedFilename(char* extendedFileName, char* fileName)
{
strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
}
static bool
getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModificationTimestamp)
getFileInfo(const char* basepath, char* filename, uint32_t* fileSize, uint64_t* lastModificationTimestamp)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedFileName[512];
#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
#endif
createExtendedFilename(extendedFileName, filename);
mmsMsg_createExtendedFilename(basepath, extendedFileName, filename);
return FileSystem_getFileInfo(extendedFileName, fileSize, lastModificationTimestamp);
}
static FileHandle
openFile(char* fileName, bool readWrite)
openFile(const char* basepath, char* fileName, bool readWrite)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedFileName[512];
#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
#endif
createExtendedFilename(extendedFileName, fileName);
mmsMsg_createExtendedFilename(basepath, extendedFileName, fileName);
return FileSystem_openFile(extendedFileName, readWrite);
}
static DirectoryHandle
openDirectory(char* directoryName)
openDirectory(const char* basepath, char* directoryName)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedFileName[512];
#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
#endif
createExtendedFilename(extendedFileName, directoryName);
mmsMsg_createExtendedFilename(basepath, extendedFileName, directoryName);
return FileSystem_openDirectory(extendedFileName);
}
static bool
renameFile(char* oldFilename, char* newFilename) {
renameFile(const char* basepath, char* oldFilename, char* newFilename) {
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedOldFileName[512];
char extendedNewFileName[512];
#else
char extendedOldFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
char extendedNewFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
#endif
createExtendedFilename(extendedOldFileName, oldFilename);
createExtendedFilename(extendedNewFileName, newFilename);
mmsMsg_createExtendedFilename(basepath, extendedOldFileName, oldFilename);
mmsMsg_createExtendedFilename(basepath, extendedNewFileName, newFilename);
return FileSystem_renameFile(extendedOldFileName, extendedNewFileName);
}
static bool
deleteFile(char* fileName) {
deleteFile(const char* basepath, char* fileName) {
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedFileName[512];
#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
#endif
createExtendedFilename(extendedFileName, fileName);
mmsMsg_createExtendedFilename(basepath, extendedFileName, fileName);
return FileSystem_deleteFile(extendedFileName);
}
void
mmsMsg_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffer* response,
char* filename, MmsFileReadStateMachine* frsm)
{
uint64_t msTime;
getFileInfo(fullPath, &(frsm->fileSize), &msTime);
getFileInfo(basepath, filename, &(frsm->fileSize), &msTime);
char gtString[30];
@ -219,35 +235,7 @@ mmsMsg_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* ful
response->size = bufPos;
}
static bool
parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
{
uint8_t tag = buffer[(*bufPos)++];
int length;
if (tag != 0x19) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return false;
}
*bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
if (*bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return false;
}
if (length > 255) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
return false;
}
memcpy(filename, buffer + *bufPos, length);
filename[length] = 0;
*bufPos += length;
return true;
}
void
mmsServer_handleFileDeleteRequest(
@ -271,7 +259,17 @@ mmsServer_handleFileDeleteRequest(
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename);
if (!getFileInfo(filename, NULL, NULL)) {
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_DELETE, filename, NULL);
if (access != MMS_ERROR_NONE) {
mmsMsg_createServiceErrorPdu(invokeId, response, access);
return;
}
}
if (!getFileInfo(MmsServerConnection_getFilesystemBasepath(connection), filename, NULL, NULL)) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: File (%s) not found\n", filename);
@ -279,7 +277,7 @@ mmsServer_handleFileDeleteRequest(
return;
}
if (!deleteFile(filename)) {
if (!deleteFile(MmsServerConnection_getFilesystemBasepath(connection), filename)) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s) failed\n", filename);
@ -316,7 +314,7 @@ mmsServer_handleFileOpenRequest(
switch(tag) {
case 0xa0: /* filename */
if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasFileName = true;
@ -336,17 +334,28 @@ mmsServer_handleFileOpenRequest(
if (hasFileName) {
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_OPEN, filename, NULL);
if (access != MMS_ERROR_NONE) {
mmsMsg_createServiceErrorPdu(invokeId, response, access);
return;
}
}
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (frsm != NULL) {
FileHandle fileHandle = openFile(filename, false);
FileHandle fileHandle = openFile(MmsServerConnection_getFilesystemBasepath(connection), filename, false);
if (fileHandle != NULL) {
frsm->fileHandle = fileHandle;
frsm->readPosition = filePosition;
frsm->frsmId = getNextFrsmId(connection);
mmsMsg_createFileOpenResponse(invokeId, response, filename, frsm);
mmsMsg_createFileOpenResponse(MmsServerConnection_getFilesystemBasepath(connection),
invokeId, response, filename, frsm);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
@ -394,9 +403,6 @@ createObtainFileResponse(uint32_t invokeId, ByteBuffer* response)
void
mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
{
//printf("mmsServer_fileUploadTask: state: %i\n", task->state);
switch (task->state) {
case MMS_FILE_UPLOAD_STATE_NOT_USED:
@ -412,7 +418,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
FileSystem_closeFile(task->fileHandle);
deleteFile(task->destinationFilename);
deleteFile(MmsServerConnection_getFilesystemBasepath(task->connection), task->destinationFilename);
}
}
break;
@ -446,7 +452,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
FileSystem_closeFile(task->fileHandle);
deleteFile(task->destinationFilename);
deleteFile(MmsServerConnection_getFilesystemBasepath(task->connection), task->destinationFilename);
}
break;
@ -479,7 +485,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
FileSystem_closeFile(task->fileHandle);
deleteFile(task->destinationFilename);
deleteFile(MmsServerConnection_getFilesystemBasepath(task->connection), task->destinationFilename);
}
break;
@ -568,7 +574,7 @@ mmsServer_handleObtainFileRequest(
case 0xa1: /* source filename */
if (!parseFileName(sourceFilename, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(sourceFilename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasSourceFileName = true;
@ -577,7 +583,7 @@ mmsServer_handleObtainFileRequest(
case 0xa2: /* destination filename */
if (!parseFileName(destinationFilename, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(destinationFilename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasDestinationFilename = true;
@ -592,14 +598,31 @@ mmsServer_handleObtainFileRequest(
if (hasSourceFileName && hasDestinationFilename) {
/* call callback to check if access is allowed */
/* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_OBTAIN, destinationFilename, sourceFilename);
if (access != MMS_ERROR_NONE) {
mmsMsg_createServiceErrorPdu(invokeId, response, access);
return;
}
}
/* call callback to check if access is allowed -- DEPRECATED */
if (connection->server->obtainFileHandler)
if (connection->server->obtainFileHandler(connection->server->obtainFileHandlerParameter, connection, sourceFilename, destinationFilename) == false)
goto exit_access_denied;
/* check if destination file already exists. If exists return error message */
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
char extendedFileName[512];
#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedFileName, destinationFilename);
#endif
mmsMsg_createExtendedFilename(MmsServerConnection_getFilesystemBasepath(connection),
extendedFileName, destinationFilename);
if (FileSystem_getFileInfo(extendedFileName, NULL, NULL)) {
if (DEBUG_MMS_SERVER)
@ -614,7 +637,8 @@ mmsServer_handleObtainFileRequest(
if (task != NULL) {
FileHandle fileHandle = openFile(destinationFilename, true);
FileHandle fileHandle = openFile(MmsServerConnection_getFilesystemBasepath(connection),
destinationFilename, true);
if (fileHandle == NULL) {
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_DESTINATION;
@ -792,11 +816,11 @@ encodeFileSpecification(uint8_t tag, char* fileSpecification, uint8_t* buffer, i
}
static int
addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char** continueAfterFileName, bool* moreFollows)
addFileEntriesToResponse(const char* basepath, uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char** continueAfterFileName, bool* moreFollows)
{
int directoryNameLength = strlen(directoryName);
DirectoryHandle directory = openDirectory(directoryName);
DirectoryHandle directory = openDirectory(basepath, directoryName);
if (directory != NULL) {
@ -813,7 +837,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
strcat(directoryName, fileName);
bufPos = addFileEntriesToResponse(buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
bufPos = addFileEntriesToResponse(basepath, buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
if (*moreFollows == true)
break;
@ -835,7 +859,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
uint32_t fileSize;
if (getFileInfo(directoryName, &fileSize, &msTime)) {
if (getFileInfo(basepath, directoryName, &fileSize, &msTime)) {
char gtString[30];
Conversions_msTimeToGeneralizedTime(msTime, (uint8_t*) gtString);
@ -873,7 +897,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
}
static void
createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduSize, char* directoryName, char* continueAfterFileName)
createFileDirectoryResponse(const char* basepath, uint32_t invokeId, ByteBuffer* response, int maxPduSize, char* directoryName, char* continueAfterFileName)
{
int maxSize = maxPduSize - 3; /* reserve space for moreFollows */
uint8_t* buffer = response->buffer;
@ -889,7 +913,7 @@ createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduS
continueAfterFileName = NULL;
}
tempCurPos = addFileEntriesToResponse(buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);
tempCurPos = addFileEntriesToResponse(basepath, buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);
if (tempCurPos < 0) {
@ -965,7 +989,7 @@ mmsServer_handleFileRenameRequest(
switch(tag) {
case 0xa0: /* currentFilename */
if (!parseFileName(currentFileName, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(currentFileName, buffer, &bufPos, bufPos + length, invokeId, response))
return;
if (DEBUG_MMS_SERVER)
@ -974,7 +998,7 @@ mmsServer_handleFileRenameRequest(
break;
case 0xa1: /* newFilename */
if (!parseFileName(newFileName, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(newFileName, buffer, &bufPos, bufPos + length, invokeId, response))
return;
if (DEBUG_MMS_SERVER)
@ -991,7 +1015,19 @@ mmsServer_handleFileRenameRequest(
}
if ((strlen(currentFileName) != 0) && (strlen(newFileName) != 0)) {
if (renameFile(currentFileName, newFileName)){
/* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_RENAME, currentFileName, newFileName);
if (access != MMS_ERROR_NONE) {
mmsMsg_createServiceErrorPdu(invokeId, response, access);
return;
}
}
if (renameFile(MmsServerConnection_getFilesystemBasepath(connection), currentFileName, newFileName)){
/* send positive response */
createNullResponseExtendedTag(invokeId, response, 0x4b);
}
@ -1037,7 +1073,7 @@ mmsServer_handleFileDirectoryRequest(
switch(tag) {
case 0xa0: /* filename */
if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
/* check for wildcard character(*) */
@ -1047,7 +1083,7 @@ mmsServer_handleFileDirectoryRequest(
break;
case 0xa1: /* continue-after */
if (!parseFileName(continueAfterFileName, buffer, &bufPos, bufPos + length, invokeId, response))
if (!mmsMsg_parseFileName(continueAfterFileName, buffer, &bufPos, bufPos + length, invokeId, response))
return;
continueAfter = continueAfterFileName;
@ -1066,7 +1102,19 @@ mmsServer_handleFileDirectoryRequest(
int maxPduSize = connection->maxPduSize;
createFileDirectoryResponse(invokeId, response, maxPduSize, filename, continueAfter);
/* Call user to check if access is allowed */
if (connection->server->fileAccessHandler != NULL) {
MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
connection, MMS_FILE_ACCESS_TYPE_READ_DIRECTORY, filename, continueAfter);
if (access != MMS_ERROR_NONE) {
mmsMsg_createServiceErrorPdu(invokeId, response, access);
return;
}
}
createFileDirectoryResponse(MmsServerConnection_getFilesystemBasepath(connection),
invokeId, response, maxPduSize, filename, continueAfter);
}
#endif /* MMS_FILE_SERVICE == 1 */

View file

@ -50,9 +50,7 @@ createValueCaches(MmsDevice* device)
MmsServer
MmsServer_create(IsoServer isoServer, MmsDevice* device)
{
MmsServer self = (MmsServer) GLOBAL_MALLOC(sizeof(struct sMmsServer));
memset(self, 0, sizeof(struct sMmsServer));
MmsServer self = (MmsServer) GLOBAL_CALLOC(1, sizeof(struct sMmsServer));
self->isoServer = isoServer;
self->device = device;
@ -72,6 +70,22 @@ MmsServer_create(IsoServer isoServer, MmsDevice* device)
return self;
}
void
MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
if (self->filestoreBasepath != NULL) {
GLOBAL_FREEMEM(self->filestoreBasepath);
self->filestoreBasepath = NULL;
}
if (basepath != NULL)
self->filestoreBasepath = StringUtils_copyString(basepath);
#endif /* (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) */
}
void
MmsServer_lockModel(MmsServer self)
{
@ -169,6 +183,15 @@ MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator
IsoServer_setAuthenticator(self->isoServer, authenticator, authenticatorParameter);
}
#if (MMS_FILE_SERVICE == 1)
void
MmsServer_installFileAccessHandler(MmsServer self, MmsFileAccessHandler handler, void* parameter)
{
self->fileAccessHandler = handler;
self->fileAccessHandlerParameter = parameter;
}
#endif /* (MMS_FILE_SERVICE == 1) */
#if (MMS_OBTAIN_FILE_SERVICE == 1)
void
MmsServer_installObtainFileHandler(MmsServer self, MmsObtainFileHandler handler, void* parameter)
@ -212,6 +235,11 @@ MmsServer_destroy(MmsServer self)
ByteBuffer_destroy(self->transmitBuffer);
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
if (self->filestoreBasepath != NULL)
GLOBAL_FREEMEM(self->filestoreBasepath);
#endif
GLOBAL_FREEMEM(self);
}
@ -298,12 +326,6 @@ MmsServer_getDevice(MmsServer self)
return self->device;
}
inline void
MmsServer_setDevice(MmsServer server, MmsDevice* device)
{
server->device = device;
}
static void /* will be called by ISO server stack */
isoConnectionIndicationHandler(IsoConnectionIndication indication,
void* parameter, IsoConnection connection)

View file

@ -634,3 +634,20 @@ MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self)
return self->lastRequestInvokeId;
}
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
const char*
MmsServerConnection_getFilesystemBasepath(MmsServerConnection self)
{
#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
if (self->server->filestoreBasepath != NULL)
return self->server->filestoreBasepath;
else
return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
#else
return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
#endif
}

View file

@ -561,4 +561,11 @@ EXPORTS
Timestamp_create
Timestamp_destroy
Timestamp_setByMmsUtcTime
IedServer_setLocalIpAddress
IedServer_setLocalIpAddress
Timestamp_toMmsValue
MmsServer_installFileAccessHandler
MmsServer_setFilestoreBasepath
MmsConnection_setFilestoreBasepath
IedConnection_setFilestoreBasepath
IedServer_setFilestoreBasepath

View file

@ -639,4 +639,10 @@ EXPORTS
Timestamp_create
Timestamp_destroy
Timestamp_setByMmsUtcTime
IedServer_setLocalIpAddress
IedServer_setLocalIpAddress
Timestamp_toMmsValue
MmsServer_installFileAccessHandler
MmsServer_setFilestoreBasepath
MmsConnection_setFilestoreBasepath
IedConnection_setFilestoreBasepath
IedServer_setFilestoreBasepath

Binary file not shown.

View file

@ -189,8 +189,8 @@ public class DynamicCodeGenerator {
for (DataObjectDefinition dod : doType.getSubDataObjects()) {
out.print(" DO_" + dod.getType() + "_createInstance(\"" + dod.getName() + "\")");
out.println("(ModelNode*) newDo);");
out.print(" DO_" + dod.getType() + "_createInstance(\"" + dod.getName() + "\", ");
out.println("(ModelNode*) newDo, " + dod.getCount() + ");");
}
out.println("\n return newDo;");