/*
* mms_server.h
*
* Copyright 2013, 2014 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see .
*
* See COPYING file for the complete license text.
*/
#ifndef MMS_SERVER_H_
#define MMS_SERVER_H_
/** \addtogroup mms_server_api_group
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "mms_device_model.h"
#include "mms_value.h"
#include "iso_server.h"
typedef enum {
MMS_SERVER_NEW_CONNECTION, MMS_SERVER_CONNECTION_CLOSED
} MmsServerEvent;
typedef struct sMmsServer* MmsServer;
#if (MMS_FILE_SERVICE == 1)
#ifndef CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION
#define CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION 5
#endif
#include "hal_filesystem.h"
typedef struct {
int32_t frsmId;
uint32_t readPosition;
uint32_t fileSize;
FileHandle fileHandle;
} MmsFileReadStateMachine;
#endif /* (MMS_FILE_SERVICE == 1) */
typedef struct sMmsServerConnection {
int maxServOutstandingCalling;
int maxServOutstandingCalled;
int dataStructureNestingLevel;
int maxPduSize; /* local detail */
IsoConnection isoConnection;
MmsServer server;
LinkedList /**/namedVariableLists; /* aa-specific named variable lists */
uint32_t lastInvokeId;
#if (MMS_FILE_SERVICE == 1)
int32_t nextFrsmId;
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
#endif
} MmsServerConnection;
typedef MmsValue* (*MmsReadVariableHandler)(void* parameter, MmsDomain* domain,
char* variableId, MmsServerConnection* connection);
typedef MmsDataAccessError (*MmsReadAccessHandler) (void* parameter, MmsDomain* domain,
char* variableId, MmsServerConnection* connection);
typedef MmsDataAccessError (*MmsWriteVariableHandler)(void* parameter,
MmsDomain* domain, char* variableId, MmsValue* value,
MmsServerConnection* connection);
typedef void (*MmsConnectionHandler)(void* parameter,
MmsServerConnection* connection, MmsServerEvent event);
MmsServer
MmsServer_create(IsoServer isoServer, MmsDevice* device);
void
MmsServer_destroy(MmsServer self);
void
MmsServer_installReadHandler(MmsServer self, MmsReadVariableHandler,
void* parameter);
void
MmsServer_installReadAccessHandler(MmsServer self, MmsReadAccessHandler, void* parameter);
void
MmsServer_installWriteHandler(MmsServer self, MmsWriteVariableHandler,
void* parameter);
/**
* A connection handler will be invoked whenever a new client connection is opened or closed
*/
void
MmsServer_installConnectionHandler(MmsServer self, MmsConnectionHandler,
void* parameter);
void
MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator, void* authenticatorParameter);
MmsDevice*
MmsServer_getDevice(MmsServer self);
MmsValue*
MmsServer_getValueFromCache(MmsServer self, MmsDomain* domain, char* itemId);
bool
MmsServer_isLocked(MmsServer self);
/**
* \brief lock the cached server data model
*
* NOTE: This method should never be called inside of a library callback function. In the context of
* a library callback the data model is always already locked! Calling this function inside of a
* library callback may lead to a deadlock condition.
*
* \param self the MmsServer instance to operate on
*/
void
MmsServer_lockModel(MmsServer self);
/**
* \brief unlock the cached server data model
*
* NOTE: This method should never be called inside of a library callback function. In the context of
* a library callback the data model is always already locked!
*
* \param self the MmsServer instance to operate on
*/
void
MmsServer_unlockModel(MmsServer self);
void
MmsServer_insertIntoCache(MmsServer self, MmsDomain* domain, char* itemId,
MmsValue* value);
void
MmsServer_setDevice(MmsServer self, MmsDevice* device);
/***************************************************
* Functions for multi-threaded operation mode
***************************************************/
/**
* \brief Start a new server thread and listen for incoming connections
*
* \param self the MmsServer instance to operate on
* \param tcpPort the TCP port the server is listening on.
*/
void
MmsServer_startListening(MmsServer self, int tcpPort);
/**
* \brief Stop server thread an all open connection threads
*
* \param self the MmsServer instance to operate on
*/
void
MmsServer_stopListening(MmsServer self);
/***************************************************
* Functions for threadless operation mode
***************************************************/
/**
* \brief Start a new server in non-threaded operation mode
*
* \param self the MmsServer instance to operate on
* \param tcpPort the TCP port the server is listening on.
*/
void
MmsServer_startListeningThreadless(MmsServer self, int tcpPort);
/**
* \brief Wait for the server to come ready in non-threaded operation mode
*
* \param self the MmsServer instance to operate on
* \param timeoutMs maximum number of milliseconds to wait
* \return 1 if the server is ready, 0 if not or -1 on error
*/
int
MmsServer_waitReady(MmsServer self, unsigned int timeoutMs);
/**
* \brief Handle client connections (for non-threaded operation mode)
*
* This function is listening for new client connections and handles incoming
* requests for existing client connections.
*
* \param self the MmsServer instance to operate on
*/
void
MmsServer_handleIncomingMessages(MmsServer self);
/**
* \brief Stop the server (for non-threaded operation mode)
*
* \param self the MmsServer instance to operate on
*/
void
MmsServer_stopListeningThreadless(MmsServer self);
/***************************************************
* Functions for MMS identify service
***************************************************/
/**
* \brief set the values that the server will give as response for an MMS identify request
*
* With this function the VMD identity attributes can be set programmatically. If not set by this
* function the default values form stack_config.h are used.
*
* \param self the MmsServer instance to operate on
* \param vendorName the vendor name attribute of the VMD
* \param modelName the model name attribute of the VMD
* \param revision the revision attribute of the VMD
*/
void
MmsServer_setServerIdentity(MmsServer self, char* vendorName, char* modelName, char* revision);
/**
* \brief get the vendor name attribute of the VMD identity
*
* \param self the MmsServer instance to operate on
* \return the vendor name attribute of the VMD as C string
*/
char*
MmsServer_getVendorName(MmsServer self);
/**
* \brief get the model name attribute of the VMD identity
*
* \param self the MmsServer instance to operate on
* \return the model name attribute of the VMD as C string
*/
char*
MmsServer_getModelName(MmsServer self);
/**
* \brief get the revision attribute of the VMD identity
*
* \param self the MmsServer instance to operate on
* \return the revision attribute of the VMD as C string
*/
char*
MmsServer_getRevision(MmsServer self);
/***************************************************
* Functions for MMS status service
***************************************************/
#define MMS_LOGICAL_STATE_STATE_CHANGES_ALLOWED 0
#define MMS_LOGICAL_STATE_NO_STATE_CHANGES_ALLOWED 1
#define MMS_LOGICAL_STATE_LIMITED_SERVICES_PERMITTED 2
#define MMS_LOGICAL_STATE_SUPPORT_SERVICES_ALLOWED 3
#define MMS_PHYSICAL_STATE_OPERATIONAL 0
#define MMS_PHYSICAL_STATE_PARTIALLY_OPERATIONAL 1
#define MMS_PHYSICAL_STATE_INOPERATIONAL 2
#define MMS_PHYSICAL_STATE_NEEDS_COMMISSIONING 3
/**
* \brief User provided handler that is invoked on a MMS status request
*
* The extendedDerivation parameter indicates that the client requests the server to perform
* self diagnosis tests before answering the request.
*
* \param parameter is a user provided parameter
* \param mmsServer is the MmsServer instance
* \param connection is the MmsServerConnection instance that received the MMS status request
* \param extendedDerivation indicates if the request contains the extendedDerivation parameter
*/
typedef void (*MmsStatusRequestListener)(void* parameter, MmsServer mmsServer, MmsServerConnection* connection, bool extendedDerivation);
/**
* \brief set the VMD state values for the VMD status service
*
* \param self the MmsServer instance to operate on
* \param vmdLogicalStatus the logical status attribute of the VMD
* \param vmdPhysicalStatus the physical status attribute of the VMD
*/
void
MmsServer_setVMDStatus(MmsServer self, int vmdLogicalStatus, int vmdPhysicalStatus);
/**
* \brief get the logical status attribute of the VMD
*
* \param self the MmsServer instance to operate on
*/
int
MmsServer_getVMDLogicalStatus(MmsServer self);
/**
* \brief get the physical status attribute of the VMD
*
* \param self the MmsServer instance to operate on
*/
int
MmsServer_getVMDPhysicalStatus(MmsServer self);
/**
* \brief set the MmsStatusRequestListener for this MmsServer
*
* With this function the API user can register a listener that is invoked whenever a
* MMS status request is received from a client. Inside of the handler the user can
* provide new status values with the MmsServer_setVMDStatus function.
*
* \param self the MmsServer instance to operate on
* \param listener the listener that is called when a MMS status request is received
* \param parameter a user provided parameter that is handed over to the listener
*/
void
MmsServer_setStatusRequestListener(MmsServer self, MmsStatusRequestListener listener, void* parameter);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* MMS_SERVER_H_ */