- file provider functions don't change file names; VMD_FILESTORE base part is now added in MMS server file service handling code

- IedConnection_readObject and IedConnection_getVariableSpecification can now read whole LNs
pull/6/head
Michael Zillgith 9 years ago
parent 52e712437b
commit 787d7fc270

@ -1,3 +1,11 @@
Changes to version 0.9.2
------------------------
- client/server: support for MMS journals and IEC 61850 log service
- Abstract interface for log storage providers: logging_api.h and LogStorage class
- log storage implementation using sqlite
- added CDC_DPL_create function
Changes to version 0.9.1
------------------------
- client: added function MmsConnection_getMmsConnectionParameters

@ -90,6 +90,12 @@ C# client API
A C#/.NET wrapper and examples and Visual Studio/MonoDevelop project files can be found in the dotnet folder. The examples and the C# wrapper API can be build and run on .NET or Mono.
Experimental Python bindings
----------------------------
The experimental Python binding can be created using SWIG with cmake.
To enable the bindings you have to select the phyton configuration option with ccmake of cmake-gui.
Commercial licenses
-------------------

@ -161,7 +161,7 @@
//#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850"
//#define CONFIG_DEFAULT_MMS_REVISION "0.9.2"
/* MMS virtual file store base path - where file services are looking for files */
/* MMS virtual file store base path - where MMS file services are looking for files */
#define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/"
/* Maximum number of open file per MMS connection (for MMS file read service) */

@ -34,52 +34,20 @@
#include "stack_config.h"
#ifndef CONFIG_VIRTUAL_FILESTORE_BASEPATH
#define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/"
#endif
static char fileBasePath[256];
static bool fileBasePathInitialized = false;
struct sDirectoryHandle {
DIR* handle;
};
static void
createFullPathFromFileName(char* fullPath, char* filename)
{
if (!fileBasePathInitialized) {
strcpy(fileBasePath, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
fileBasePathInitialized = true;
}
strcpy(fullPath, fileBasePath);
if (filename != NULL)
strcat(fullPath, filename);
}
void
FileSystem_setBasePath(char* basePath)
{
strcpy(fileBasePath, basePath);
fileBasePathInitialized = true;
}
FileHandle
FileSystem_openFile(char* fileName, bool readWrite)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(fullPath, fileName);
FileHandle newHandle = NULL;
if (readWrite)
newHandle = (FileHandle) fopen(fullPath, "w");
newHandle = (FileHandle) fopen(fileName, "w");
else
newHandle = (FileHandle) fopen(fullPath, "r");
newHandle = (FileHandle) fopen(fileName, "r");
return newHandle;
}
@ -99,11 +67,7 @@ FileSystem_closeFile(FileHandle handle)
bool
FileSystem_deleteFile(char* filename)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(fullPath, filename);
if (remove(fullPath) == 0)
if (remove(filename) == 0)
return true;
else
return false;
@ -112,13 +76,7 @@ FileSystem_deleteFile(char* filename)
bool
FileSystem_renameFile(char* oldFilename, char* newFilename)
{
char oldFullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
char newFullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(oldFullPath, oldFilename);
createFullPathFromFileName(newFullPath, newFilename);
if (rename(oldFullPath, newFullPath) == 0)
if (rename(oldFilename, newFilename) == 0)
return true;
else
return false;
@ -130,11 +88,7 @@ FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModific
{
struct stat fileStats;
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createFullPathFromFileName(fullPath, filename);
if (stat(fullPath, &fileStats) == -1)
if (stat(filename, &fileStats) == -1)
return false;
if (lastModificationTimestamp != NULL)
@ -150,11 +104,7 @@ FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModific
DirectoryHandle
FileSystem_openDirectory(char* directoryName)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(fullPath, directoryName);
DIR* dirHandle = opendir(fullPath);
DIR* dirHandle = opendir(directoryName);
DirectoryHandle handle = NULL;

@ -37,15 +37,6 @@
#include <windows.h>
#ifndef CONFIG_VIRTUAL_FILESTORE_BASEPATH
#define CONFIG_VIRTUAL_FILESTORE_BASEPATH ".\\vmd-filestore\\"
#endif
//static char* fileBasePath = CONFIG_VIRTUAL_FILESTORE_BASEPATH;
static char fileBasePath[256];
static bool fileBasePathInitialized = false;
struct sDirectoryHandle {
HANDLE handle;
WIN32_FIND_DATAW findData;
@ -53,40 +44,16 @@ struct sDirectoryHandle {
bool available;
};
static void
createFullPathFromFileName(char* fullPath, char* filename)
{
if (!fileBasePathInitialized) {
strcpy(fileBasePath, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
fileBasePathInitialized = true;
}
strcpy(fullPath, fileBasePath);
if (filename != NULL)
strcat(fullPath, filename);
}
void
FileSystem_setBasePath(char* basePath)
{
strcpy(fileBasePath, basePath);
fileBasePathInitialized = true;
}
FileHandle
FileSystem_openFile(char* fileName, bool readWrite)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(fullPath, fileName);
FileHandle newHandle = NULL;
if (readWrite)
newHandle = (FileHandle) fopen(fullPath, "wb");
newHandle = (FileHandle) fopen(fileName, "wb");
else
newHandle = (FileHandle) fopen(fullPath, "rb");
newHandle = (FileHandle) fopen(fileName, "rb");
return newHandle;
}
@ -106,13 +73,9 @@ FileSystem_closeFile(FileHandle handle)
bool
FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModificationTimestamp)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createFullPathFromFileName(fullPath, filename);
WIN32_FILE_ATTRIBUTE_DATA fad;
if (GetFileAttributesEx(fullPath, GetFileExInfoStandard, &fad) == 0)
if (GetFileAttributesEx(filename, GetFileExInfoStandard, &fad) == 0)
return false;
if (lastModificationTimestamp != NULL) {
@ -136,13 +99,12 @@ FileSystem_getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModific
DirectoryHandle
FileSystem_openDirectory(char* directoryName)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(fullPath, directoryName);
DirectoryHandle dirHandle = (DirectoryHandle) GLOBAL_CALLOC(1, sizeof(struct sDirectoryHandle));
strcat(fullPath, "\\*");
char fullPath[MAX_PATH + 1];
strncpy(fullPath, directoryName, MAX_PATH - 3);
strncat(fullPath, "\\*", MAX_PATH);
/* convert UTF-8 path name to WCHAR */
WCHAR unicodeFullPath[MAX_PATH + 1];
@ -201,11 +163,7 @@ getNextDirectoryEntry(DirectoryHandle directory, bool* isDirectory)
bool
FileSystem_deleteFile(char* filename)
{
char fullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(fullPath, filename);
if (remove(fullPath) == 0)
if (remove(filename) == 0)
return true;
else
return false;
@ -214,13 +172,7 @@ FileSystem_deleteFile(char* filename)
bool
FileSystem_renameFile(char* oldFilename, char* newFilename)
{
char oldFullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
char newFullPath[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 255];
createFullPathFromFileName(oldFullPath, oldFilename);
createFullPathFromFileName(newFullPath, newFilename);
if (rename(oldFullPath, newFullPath) == 0)
if (rename(oldFilename, newFilename) == 0)
return true;
else
return false;

@ -2901,10 +2901,27 @@ MmsMapping_createMmsVariableNameFromObjectReference(const char* objectReference,
return NULL;
if (i == objRefLength)
i = 0;
i = 0; /* for the case when no LD name is present */
else
i++;
if (fc == IEC61850_FC_NONE) {
int len = objRefLength - i;
char* mmsVariableName;
if (buffer == NULL)
mmsVariableName = (char*) GLOBAL_MALLOC(len);
else
mmsVariableName = buffer;
strcpy(mmsVariableName, objectReference + i);
return mmsVariableName;
}
char* fcString = FunctionalConstraint_toString(fc);
if (fcString == NULL)

@ -76,6 +76,18 @@ static const char* GET_ENTRY_DATA = "select dataRef, value, reasonCode from Entr
static const char* GET_OLD_ENTRY = "select * from Entries where entryID = (select min(entryID) from Entries where timeOfEntry = (select min(timeOfEntry) from Entries))";
static const char* GET_NEW_ENTRY = "select * from Entries where entryID = (select max(entryID) from Entries where timeOfEntry = (select max(timeOfEntry) from Entries))";
static char*
copyStringInternal(const char* string)
{
int newStringLength = strlen(string) + 1;
char* newString = (char*) malloc(newStringLength);
memcpy(newString, string, newStringLength);
return newString;
}
LogStorage
SqliteLogStorage_createInstance(const char* filename)
{
@ -131,10 +143,11 @@ SqliteLogStorage_createInstance(const char* filename)
if (rc != SQLITE_OK)
goto exit_with_error;
LogStorage self = (LogStorage) GLOBAL_CALLOC(1, sizeof(struct sLogStorage));
LogStorage self = (LogStorage) calloc(1, sizeof(struct sLogStorage));
SqliteLogStorage* instanceData = (SqliteLogStorage*) calloc(1, sizeof(struct sSqliteLogStorage));
SqliteLogStorage* instanceData = (SqliteLogStorage*) GLOBAL_CALLOC(1, sizeof(struct sSqliteLogStorage));
instanceData->filename = copyString(filename);
instanceData->filename = copyStringInternal(filename);
instanceData->db = db;
instanceData->insertEntryStmt = insertEntryStmt;
instanceData->insertEntryDataStmt = insertEntryDataStmt;
@ -263,8 +276,10 @@ getEntryData(LogStorage self, uint64_t entryID, LogEntryDataCallback entryDataCa
rc = sqlite3_bind_int64(instanceData->getEntryData, 1, entryID);
if (rc != SQLITE_OK)
printf("getEntryData 1 rc:%i\n", rc);
if (rc != SQLITE_OK) {
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - getEntryData 1 rc:%i\n", rc);
}
bool sendFinalEvent = true;
@ -292,7 +307,8 @@ getEntryData(LogStorage self, uint64_t entryID, LogEntryDataCallback entryDataCa
rc = sqlite3_reset(instanceData->getEntryData);
if (rc != SQLITE_OK)
printf("getEntryData reset rc:%i\n", rc);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - getEntryData reset rc:%i\n", rc);
}
static bool
@ -308,12 +324,14 @@ SqliteLogStorage_getEntries(LogStorage self, uint64_t startingTime, uint64_t end
rc = sqlite3_bind_int64(instanceData->getEntriesWithRange, 1, startingTime);
if (rc != SQLITE_OK)
printf("SqliteLogStorage_getEntries 1 rc:%i\n", rc);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - SqliteLogStorage_getEntries 1 rc:%i\n", rc);
rc = sqlite3_bind_int64(instanceData->getEntriesWithRange, 2, endingTime);
if (rc != SQLITE_OK)
printf("SqliteLogStorage_getEntries 2 rc:%i\n", rc);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - SqliteLogStorage_getEntries 2 rc:%i\n", rc);
bool sendFinalEvent = true;
@ -341,7 +359,8 @@ SqliteLogStorage_getEntries(LogStorage self, uint64_t startingTime, uint64_t end
rc = sqlite3_reset(instanceData->getEntriesWithRange);
if (rc != SQLITE_OK)
printf("SqliteLogStorage_getEntries reset rc:%i\n", rc);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - SqliteLogStorage_getEntries reset rc:%i\n", rc);
return true;
}
@ -407,7 +426,8 @@ SqliteLogStorage_getEntriesAfter(LogStorage self, uint64_t startingTime, uint64_
rc = sqlite3_bind_int64(instanceData->getEntriesAfter, 1, entryID);
if (rc != SQLITE_OK)
printf("SqliteLogStorage_getEntriesAfter 1 rc:%i\n", rc);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - SqliteLogStorage_getEntriesAfter 1 rc:%i\n", rc);
bool sendFinalEvent = true;
@ -433,7 +453,8 @@ SqliteLogStorage_getEntriesAfter(LogStorage self, uint64_t startingTime, uint64_
rc = sqlite3_reset(instanceData->getEntriesAfter);
if (rc != SQLITE_OK)
printf("SqliteLogStorage_getEntriesAfter reset rc:%i\n", rc);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - SqliteLogStorage_getEntriesAfter reset rc:%i\n", rc);
return true;
}
@ -452,11 +473,12 @@ SqliteLogStorage_destroy(LogStorage self)
sqlite3_finalize(instanceData->getNewEntry);
if (sqlite3_close(instanceData->db) != SQLITE_OK)
printf("SqliteLogStorage: failed to close database %s!\n", instanceData->filename);
if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - SqliteLogStorage: failed to close database %s!\n", instanceData->filename);
GLOBAL_FREEMEM(instanceData->filename);
GLOBAL_FREEMEM(instanceData);
GLOBAL_FREEMEM(self);
free(instanceData->filename);
free(instanceData);
free(self);
}

@ -1605,7 +1605,7 @@ MmsValue_setBinaryTime(MmsValue* self, uint64_t timestamp)
if (timestamp > 441763200000LL)
mmsTime = timestamp - (441763200000LL);
else
timestamp = 0;
mmsTime = 0;
uint8_t* binaryTimeBuf = self->value.binaryTime.buf;

@ -123,13 +123,69 @@ 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)
{
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedFileName, filename);
return FileSystem_getFileInfo(extendedFileName, fileSize, lastModificationTimestamp);
}
static FileHandle
openFile(char* fileName, bool readWrite)
{
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedFileName, fileName);
return FileSystem_openFile(extendedFileName, readWrite);
}
static DirectoryHandle
openDirectory(char* directoryName)
{
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedFileName, directoryName);
return FileSystem_openDirectory(extendedFileName);
}
static bool
renameFile(char* oldFilename, char* newFilename) {
char extendedOldFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
char extendedNewFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedOldFileName, oldFilename);
createExtendedFilename(extendedNewFileName, newFilename);
return FileSystem_renameFile(extendedOldFileName, extendedNewFileName);
}
static bool
deleteFile(char* fileName) {
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
createExtendedFilename(extendedFileName, fileName);
return FileSystem_deleteFile(extendedFileName);
}
static void
createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
{
uint64_t msTime;
FileSystem_getFileInfo(fullPath, &(frsm->fileSize), &msTime);
getFileInfo(fullPath, &(frsm->fileSize), &msTime);
char gtString[30];
@ -216,7 +272,7 @@ mmsServer_handleFileDeleteRequest(
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename);
if (!FileSystem_getFileInfo(filename, NULL, NULL)) {
if (!getFileInfo(filename, NULL, NULL)) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: File (%s) not found\n", filename);
@ -224,7 +280,7 @@ mmsServer_handleFileDeleteRequest(
return;
}
if (!FileSystem_deleteFile(filename)) {
if (!deleteFile(filename)) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s) failed\n", filename);
@ -284,7 +340,7 @@ mmsServer_handleFileOpenRequest(
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (frsm != NULL) {
FileHandle fileHandle = FileSystem_openFile(filename, false);
FileHandle fileHandle = openFile(filename, false);
if (fileHandle != NULL) {
frsm->fileHandle = fileHandle;
@ -441,9 +497,10 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
{
int directoryNameLength = strlen(directoryName);
DirectoryHandle directory = FileSystem_openDirectory(directoryName);
DirectoryHandle directory = openDirectory(directoryName);
if (directory != NULL) {
bool isDirectory;
char* fileName = FileSystem_readDirectory(directory, &isDirectory);
@ -457,13 +514,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
strcat(directoryName, fileName);
if (isDirectory) {
bufPos = addFileEntriesToResponse(buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
}
else {
bufPos = addFileEntriesToResponse(buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
}
bufPos = addFileEntriesToResponse(buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
if (*moreFollows == true)
break;
@ -485,8 +536,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
uint32_t fileSize;
if (FileSystem_getFileInfo(directoryName, &fileSize, &msTime)) {
if (getFileInfo(directoryName, &fileSize, &msTime)) {
char gtString[30];
Conversions_msTimeToGeneralizedTime(msTime, (uint8_t*) gtString);
@ -642,7 +692,7 @@ mmsServer_handleFileRenameRequest(
}
if ((strlen(currentFileName) != 0) && (strlen(newFileName) != 0)) {
if (FileSystem_renameFile(currentFileName, newFileName)){
if (renameFile(currentFileName, newFileName)){
/* send positive response */
createNullResponseExtendedTag(invokeId, response, 0x4b);
}

@ -1,7 +1,7 @@
/*
* mms_server_connection.c
*
* Copyright 2013 Michael Zillgith
* Copyright 2013-2016 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -108,8 +108,6 @@ handleConfirmedRequestPdu(
return;
}
if (DEBUG_MMS_SERVER) printf("tag %02x extended tag: %i size: %i\n", tag, extendedTag, length);
if (extendedTag) {
switch(tag) {
@ -155,7 +153,8 @@ handleConfirmedRequestPdu(
switch(tag) {
case 0x02: /* invoke Id */
invokeId = BerDecoder_decodeUint32(buffer, length, bufPos);
if (DEBUG_MMS_SERVER) printf("invokeId: %i\n", invokeId);
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: received request with invokeId: %i\n", invokeId);
self->lastInvokeId = invokeId;
break;
@ -256,7 +255,7 @@ MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message,
return MMS_ERROR;
if (DEBUG_MMS_SERVER)
printf("mms_server: recvd MMS-PDU type: %02x size: %i\n", pduType, pduLength);
printf("MMS_SERVER: recvd MMS-PDU type: %02x size: %i\n", pduType, pduLength);
switch (pduType) {
case 0xa8: /* Initiate request PDU */
@ -272,7 +271,8 @@ MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message,
retVal = MMS_CONCLUDE;
break;
case 0xa4: /* Reject PDU - silently ignore */
if (DEBUG) printf("received reject PDU!\n");
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: received reject PDU!\n");
retVal = MMS_OK;
break;
default:

Loading…
Cancel
Save