- R-GOOSE/R-SMV can now also be compiled on Windows without winpcap

- SMV subscriber: removed legacy compatibility functions
pull/521/head
Michael Zillgith 1 year ago
parent 3b1758c713
commit 34366ce284

@ -17,6 +17,7 @@ Other changes:
- Ethernet(Linux): Set to promisc mode by default
- removed legacy defines for report reasons (#449)
- removed legacy compatibility functions for SV subscriner ("SVClientaSDU_")
Fixed bugs and vulnerabilities:

@ -52,6 +52,8 @@ option(CONFIG_IEC61850_SERVICE_TRACKING "Build with support for IEC 61850 servic
option(CONFIG_IEC61850_SETTING_GROUPS "Build with support for IEC 61850 setting group services" ON)
option(CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL "Allow user provided callback to control read access" ON)
option(CONFIG_IEC61850_RCB_ALLOW_ONLY_PRECONFIGURED_CLIENT "allow only configured clients (when pre-configured by ClientLN)" OFF)
option(CONFIG_IEC61850_L2_GOOSE "Build with support for L2 GOOSE (winpcap required on windows)" ON)
option(CONFIG_IEC61850_L2_SMV "Build with support for L2 SMV (winpcap required on windows)" ON)
option(CONFIG_IEC61850_R_GOOSE "Build with support for R-GOOSE (mbedtls required)" ON)
option(CONFIG_IEC61850_R_SMV "Build with support for R-SMV (mbedtls required)" ON)
option(CONFIG_IEC61850_SNTP_CLIENT "Build with SNTP client code" ON)

@ -53,8 +53,8 @@ The library support the following IEC 61850 protocol features:
* Setting group handling
* Support for service tracking
* GOOSE and SV control block handling
* Support for R-session protocol/R-GOOSE/R-SMV
* Simple SNTP client code
* Support for R-session protocol/R-GOOSE/R-SMV (BETA)
* Simple SNTP client code (BETA)
* TLS support
* C and C#/.NET API

@ -68,36 +68,20 @@
/* maximum COTP (ISO 8073) TPDU size - valid range is 1024 - 8192 */
#define CONFIG_COTP_MAX_TPDU_SIZE 8192
/* Ethernet interface ID for GOOSE and SV */
/* Ethernet interface ID for L2 GOOSE and SV */
#define CONFIG_ETHERNET_INTERFACE_ID "eth0"
/* #define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0" */
/* #define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names. */
/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */
/* Set to 1 to include generic GOOSE support in the build. Otherwise set to 0 */
#define CONFIG_INCLUDE_GOOSE_SUPPORT 1
/* Set to 1 to include Sampled Values support in the build. Otherwise set to 0 */
/* Set to 1 to include generic Sampled Values support in the build. Otherwise set to 0 */
#define CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT 1
/* Set to 1 to compile for edition 1 server - default is 0 to compile for edition 2 */
#define CONFIG_IEC61850_EDITION_1 0
#ifdef _WIN32
/* GOOSE will be disabled for Windows if ethernet support (winpcap) is not available */
#ifdef EXCLUDE_ETHERNET_WINDOWS
#ifdef CONFIG_INCLUDE_GOOSE_SUPPORT
#undef CONFIG_INCLUDE_GOOSE_SUPPORT
#endif
#define CONFIG_INCLUDE_GOOSE_SUPPORT 0
#define CONFIG_INCUDE_ETHERNET_WINDOWS 0
#else
#define CONFIG_INCLUDE_ETHERNET_WINDOWS 1
#undef CONFIG_ETHERNET_INTERFACE_ID
#define CONFIG_ETHERNET_INTERFACE_ID "0"
#endif
#endif
/* The GOOSE retransmission interval in ms for the stable condition - i.e. no monitored value changed */
#define CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL 5000
@ -179,9 +163,36 @@
/* compile with support for R-SMV (mbedtls required) */
#define CONFIG_IEC61850_R_SMV 0
/* compile with support for L2 GOOSE */
#define CONFIG_IEC61850_L2_GOOSE 0
/* compile with support for L2 SMV */
#define CONFIG_IEC61850_L2_SMV 0
/* compile SNTP client code */
#define CONFIG_IEC61850_SNTP_CLIENT 0
#ifdef _WIN32
/* L2 GOOSE/SMV will be disabled for Windows if ethernet support (winpcap) is not available */
#ifdef EXCLUDE_ETHERNET_WINDOWS
#ifdef CONFIG_IEC61850_L2_GOOSE
#undef CONFIG_IEC61850_L2_GOOSE
#endif
#ifdef CONFIG_IEC61850_L2_SMV
#undef CONFIG_IEC61850_L2_SMV
#endif
#define CONFIG_IEC61850_L2_GOOSE 0
#define CONFIG_IEC61850_L2_SMV 0
#define CONFIG_INCUDE_ETHERNET_WINDOWS 0
#else
#define CONFIG_INCLUDE_ETHERNET_WINDOWS 1
#undef CONFIG_ETHERNET_INTERFACE_ID
#define CONFIG_ETHERNET_INTERFACE_ID "0"
#endif
#endif
/* overwrite default results for MMS identify service */
/* #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" */
/* #define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" */

@ -68,10 +68,10 @@
/* #define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0" */
/* #define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names. */
/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */
/* Set to 1 to include generic GOOSE support in the build. Otherwise set to 0 */
#cmakedefine01 CONFIG_INCLUDE_GOOSE_SUPPORT
/* Set to 1 to include Sampled Values support in the build. Otherwise set to 0 */
/* Set to 1 to include generic Sampled Values support in the build. Otherwise set to 0 */
#define CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT 1
/* compile with support for R-GOOSE (mbedtls requried) */
@ -80,6 +80,12 @@
/* compile with support for R-SMV (mbedtls required) */
#cmakedefine01 CONFIG_IEC61850_R_SMV
/* compile with support for L2 GOOSE */
#cmakedefine01 CONFIG_IEC61850_L2_GOOSE
/* compile with support for L2 SMV */
#cmakedefine01 CONFIG_IEC61850_L2_SMV
/* compile SNTP client code */
#cmakedefine01 CONFIG_IEC61850_SNTP_CLIENT
@ -88,12 +94,16 @@
#ifdef _WIN32
/* GOOSE will be disabled for Windows if ethernet support (winpcap) is not available */
/* L2 GOOSE/SMV will be disabled for Windows if ethernet support (winpcap) is not available */
#ifdef EXCLUDE_ETHERNET_WINDOWS
#ifdef CONFIG_INCLUDE_GOOSE_SUPPORT
#undef CONFIG_INCLUDE_GOOSE_SUPPORT
#ifdef CONFIG_IEC61850_L2_GOOSE
#undef CONFIG_IEC61850_L2_GOOSE
#endif
#ifdef CONFIG_IEC61850_L2_SMV
#undef CONFIG_IEC61850_L2_SMV
#endif
#define CONFIG_INCLUDE_GOOSE_SUPPORT 0
#define CONFIG_IEC61850_L2_GOOSE 0
#define CONFIG_IEC61850_L2_SMV 0
#define CONFIG_INCUDE_ETHERNET_WINDOWS 0
#else
#define CONFIG_INCLUDE_ETHERNET_WINDOWS 1

@ -28,7 +28,7 @@ message("Found winpcap -> compile ethernet HAL layer (required for GOOSE/SV supp
set(WITH_WPCAP 1)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Include")
else()
message("winpcap not found -> skip ethernet HAL layer (no GOOSE/SV support)")
message("winpcap not found -> skip ethernet HAL layer (no L2 GOOSE/SV support)")
endif()
endif(WIN32)

@ -220,7 +220,7 @@ set (lib_bsd_SRCS
IF(WIN32)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib")
message("Found winpcap -> can compile with GOOSE support")
message("Found winpcap -> can compile with L2 GOOSE/SMV support")
set(WITH_WPCAP 1)
endif()
@ -232,16 +232,13 @@ set_source_files_properties(${lib_common_SRCS} ${lib_windows_SRCS}
PROPERTIES LANGUAGE CXX)
set_source_files_properties(${lib_rsession_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF()
IF(WITH_WPCAP)
IF(MSVC)
set_source_files_properties(${lib_goose_SRCS}
PROPERTIES LANGUAGE CXX)
set_source_files_properties(${lib_sv_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF()
IF(WITH_WPCAP)
ELSE()
add_definitions(-DEXCLUDE_ETHERNET_WINDOWS)
ENDIF()
@ -250,7 +247,7 @@ include_directories(
../third_party/winpcap/include
)
IF(WITH_WPCAP)
IF(WITH_WPCAP OR CONFIG_IEC61850_R_GOOSE OR CONFIG_IEC61850_R_SMV)
set (library_SRCS
${lib_common_SRCS}
${lib_asn1c_SRCS}
@ -266,11 +263,10 @@ set (library_SRCS
${lib_common_SRCS}
${lib_asn1c_SRCS}
${lib_windows_SRCS}
${lib_rsession_SRCS}
${lib_sntp_SRCS}
)
ENDIF(WITH_WPCAP)
ENDIF(WITH_WPCAP OR CONFIG_IEC61850_R_GOOSE OR CONFIG_IEC61850_R_SMV)
ELSEIF(UNIX)
IF(APPLE)

@ -40,7 +40,8 @@
static bool
prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID, bool useVlanTags);
struct sGoosePublisher {
struct sGoosePublisher
{
uint8_t* buffer;
#if (CONFIG_IEC61850_R_GOOSE == 1)
@ -49,8 +50,10 @@ struct sGoosePublisher {
uint16_t appId;
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
#if (CONFIG_IEC61850_L2_GOOSE == 1)
/* only for Ethernet based GOOSE */
EthernetSocket ethernetSocket;
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
int lengthField;
int payloadStart;
@ -99,6 +102,7 @@ GoosePublisher_createRemote(RSession session, uint16_t appId)
}
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
#if (CONFIG_IEC61850_L2_GOOSE == 1)
GoosePublisher
GoosePublisher_createEx(CommParameters* parameters, const char* interfaceID, bool useVlanTag)
{
@ -127,15 +131,18 @@ GoosePublisher_create(CommParameters* parameters, const char* interfaceID)
{
return GoosePublisher_createEx(parameters, interfaceID, true);
}
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
void
GoosePublisher_destroy(GoosePublisher self)
{
if (self)
{
#if (CONFIG_IEC61850_L2_GOOSE == 1)
if (self->ethernetSocket) {
Ethernet_destroySocket(self->ethernetSocket);
}
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
MmsValue_delete(self->timestamp);
@ -242,6 +249,7 @@ GoosePublisher_setTimeAllowedToLive(GoosePublisher self, uint32_t timeAllowedToL
self->timeAllowedToLive = timeAllowedToLive;
}
#if (CONFIG_IEC61850_L2_GOOSE == 1)
static bool
prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID, bool useVlanTags)
{
@ -342,6 +350,7 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char*
return false;
}
}
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
static int32_t
createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffer, size_t maxPayloadSize)
@ -460,7 +469,8 @@ createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffe
{
MmsValue* dataSetEntry = (MmsValue*) element->data;
if (dataSetEntry) {
if (dataSetEntry)
{
bufPos = MmsValue_encodeMmsData(dataSetEntry, buffer, bufPos, true);
}
else {
@ -490,7 +500,9 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet)
if (self->sqNum == 0)
self->sqNum = 1;
if (self->ethernetSocket) {
#if (CONFIG_IEC61850_L2_GOOSE == 1)
if (self->ethernetSocket)
{
int lengthIndex = self->lengthField;
size_t gooseLength = self->payloadLength + 8;
@ -503,9 +515,11 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet)
if (DEBUG_GOOSE_PUBLISHER)
printf("GOOSE_PUBLISHER: send GOOSE message\n");
}
#if (CONFIG_IEC61850_R_GOOSE == 1)
else if (self->remoteSession) {
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
#if (CONFIG_IEC61850_R_GOOSE == 1)
if (self->remoteSession)
{
RSession_sendMessage(self->remoteSession, RSESSION_SPDU_ID_GOOSE, self->simulation, self->appId, buffer, self->payloadLength);
if (DEBUG_GOOSE_PUBLISHER)

@ -73,7 +73,7 @@ GooseReceiver_createEx(uint8_t* buffer)
{
GooseReceiver self = (GooseReceiver) GLOBAL_MALLOC(sizeof(struct sGooseReceiver));
if (self != NULL)
if (self)
{
self->running = false;
self->stop = false;
@ -94,7 +94,8 @@ GooseReceiver_create()
{
GooseReceiver self = GooseReceiver_createEx(NULL);
if (self) {
if (self)
{
self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
}
@ -107,7 +108,8 @@ GooseReceiver_createRemote(RSession session)
{
GooseReceiver self = GooseReceiver_create();
if (self) {
if (self)
{
self->session = session;
}
@ -1116,7 +1118,8 @@ parseGooseMessage(GooseReceiver self, uint8_t* buffer, int numbytes)
if (subscriberFound)
parseGoosePayload(self, buffer + bufPos, apduLength);
else {
else
{
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: GOOSE message ignored due to unknown DST-MAC or APPID value\n");
}
@ -1128,6 +1131,7 @@ gooseReceiverLoop(void *threadParameter)
{
GooseReceiver self = (GooseReceiver) threadParameter;
#if (CONFIG_IEC61850_L2_GOOSE == 1)
if (self->ethSocket)
{
EthernetHandleSet handleSet = EthernetHandleSet_new();
@ -1159,8 +1163,10 @@ gooseReceiverLoop(void *threadParameter)
EthernetHandleSet_destroy(handleSet);
}
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
#if (CONFIG_IEC61850_R_GOOSE == 1)
else if (self->session)
if (self->session)
{
HandleSet handleSet = Handleset_new();
@ -1207,29 +1213,38 @@ GooseReceiver_start(GooseReceiver self)
{
self->thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, false);
if (self->thread != NULL) {
if (self->ethSocket) {
if (self->thread)
{
#if (CONFIG_IEC61850_L2_GOOSE == 1)
if (self->ethSocket)
{
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: GOOSE receiver started for interface %s\n", self->interfaceId);
Thread_start(self->thread);
return;
}
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
#if (CONFIG_IEC61850_R_GOOSE == 1)
else if (self->session) {
if (self->session)
{
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: R-GOOSE receiver started\n");
Thread_start(self->thread);
return;
}
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
else {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: ERROR - No link/transport layer specified -> cannot start!\n");
Thread_destroy(self->thread);
self->thread = NULL;
}
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: ERROR - No link/transport layer specified -> cannot start!\n");
Thread_destroy(self->thread);
self->thread = NULL;
}
else {
if (DEBUG_GOOSE_SUBSCRIBER)
@ -1287,7 +1302,8 @@ EthernetSocket
GooseReceiver_startThreadless(GooseReceiver self)
{
#if (CONFIG_IEC61850_R_GOOSE == 1)
if (self->session) {
if (self->session)
{
if (RSession_start(self->session) == R_SESSION_ERROR_OK)
{
self->running = true;
@ -1304,6 +1320,7 @@ GooseReceiver_startThreadless(GooseReceiver self)
else {
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
#if (CONFIG_IEC61850_L2_GOOSE == 1)
if (self->interfaceId == NULL)
self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL);
else
@ -1340,6 +1357,7 @@ GooseReceiver_startThreadless(GooseReceiver self)
else {
self->running = false;
}
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
#if (CONFIG_IEC61850_R_GOOSE == 1)
}
@ -1351,8 +1369,10 @@ GooseReceiver_startThreadless(GooseReceiver self)
void
GooseReceiver_stopThreadless(GooseReceiver self)
{
#if (CONFIG_IEC61850_L2_GOOSE == 1)
if (self->ethSocket)
Ethernet_destroySocket(self->ethSocket);
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
self->running = false;
}
@ -1368,7 +1388,6 @@ handleSessionPayloadElement(void* parameter, uint16_t appId, uint8_t* payloadDat
}
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
/* call after reception of ethernet frame */
bool
GooseReceiver_tick(GooseReceiver self)
@ -1384,6 +1403,8 @@ GooseReceiver_tick(GooseReceiver self)
else
{
#endif /* (CONFIG_IEC61850_R_GOOSE == 1) */
#if (CONFIG_IEC61850_L2_GOOSE == 1)
int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH);
if (packetSize > 0)
@ -1393,6 +1414,7 @@ GooseReceiver_tick(GooseReceiver self)
}
else
return false;
#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */
#if (CONFIG_IEC61850_R_GOOSE == 1)
}

@ -1,7 +1,7 @@
/*
* sv_publisher.c
*
* Copyright 2016-2022 Michael Zillgith
* Copyright 2016-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -76,8 +76,10 @@ struct sSVPublisher {
uint16_t appId;
bool simulation;
#if (CONFIG_IEC61850_L2_SMV == 1)
/* only for Ethernet based SV */
EthernetSocket ethernetSocket;
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
#if (CONFIG_IEC61850_R_SMV == 1)
/* only for R-SV */
@ -93,7 +95,7 @@ struct sSVPublisher {
SVPublisher_ASDU asduList;
};
#if (CONFIG_IEC61850_L2_SMV == 1)
static bool
preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* interfaceId, bool useVlanTags)
{
@ -194,7 +196,7 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in
return true;
}
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
static int
encodeUInt16FixedSize(uint16_t value, uint8_t* buffer, int bufPos)
@ -303,6 +305,7 @@ SVPublisher_createRemote(RSession session, uint16_t appId)
}
#endif /* (CONFIG_IEC61850_R_SMV == 1) */
#if (CONFIG_IEC61850_L2_SMV == 1)
SVPublisher
SVPublisher_createEx(CommParameters* parameters, const char* interfaceId, bool useVlanTag)
{
@ -329,6 +332,7 @@ SVPublisher_create(CommParameters* parameters, const char* interfaceId)
{
return SVPublisher_createEx(parameters, interfaceId, true);
}
#endif /* (CONFIG_IEC61850_R_SMV == 1) */
SVPublisher_ASDU
SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint32_t confRev)
@ -527,21 +531,25 @@ SVPublisher_setupComplete(SVPublisher self)
void
SVPublisher_publish(SVPublisher self)
{
if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: send SV message\n");
#if (CONFIG_IEC61850_L2_SMV == 1)
if (self->ethernetSocket)
{
if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: send L2 SV message\n");
if (self->ethernetSocket) {
Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + self->payloadLength);
}
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
#if (CONFIG_IEC61850_R_SMV == 1)
else if (self->remoteSession) {
if (self->remoteSession)
{
if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: send R-SV message\n");
RSession_sendMessage(self->remoteSession, RSESSION_SPDU_ID_SV, self->simulation, self->appId, self->buffer, self->payloadLength);
}
#endif /* (CONFIG_IEC61850_R_SMV == 1) */
else {
if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: no network layer!\n");
}
}
void
@ -549,8 +557,10 @@ SVPublisher_destroy(SVPublisher self)
{
if (self)
{
#if (CONFIG_IEC61850_L2_SMV == 1)
if (self->ethernetSocket)
Ethernet_destroySocket(self->ethernetSocket);
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
if (self->buffer)
GLOBAL_FREEMEM(self->buffer);
@ -808,139 +818,3 @@ SVPublisher_ASDU_setSmpSynch(SVPublisher_ASDU self, uint16_t smpSynch)
self->smpSynch = smpSynch;
*(self->smpSynchBuf) = self->smpSynch;
}
/*******************************************************************
* Wrapper functions to support old API (remove in future versions)
*******************************************************************/
SVPublisher
SampledValuesPublisher_create(CommParameters* parameters, const char* interfaceId)
{
return SVPublisher_create(parameters, interfaceId);
}
SVPublisher_ASDU
SampledValuesPublisher_addASDU(SVPublisher self, char* svID, char* datset, uint32_t confRev)
{
return SVPublisher_addASDU(self, svID, datset, confRev);
}
void
SampledValuesPublisher_setupComplete(SVPublisher self)
{
SVPublisher_setupComplete(self);
}
void
SampledValuesPublisher_publish(SVPublisher self)
{
SVPublisher_publish(self);
}
void
SampledValuesPublisher_destroy(SVPublisher self)
{
SVPublisher_destroy(self);
}
void
SV_ASDU_resetBuffer(SVPublisher_ASDU self)
{
SVPublisher_ASDU_resetBuffer(self);
}
int
SV_ASDU_addINT8(SVPublisher_ASDU self)
{
return SVPublisher_ASDU_addINT8(self);
}
void
SV_ASDU_setINT8(SVPublisher_ASDU self, int index, int8_t value)
{
SVPublisher_ASDU_setINT8(self, index, value);
}
int
SV_ASDU_addINT32(SVPublisher_ASDU self)
{
return SVPublisher_ASDU_addINT32(self);
}
void
SV_ASDU_setINT32(SVPublisher_ASDU self, int index, int32_t value)
{
SVPublisher_ASDU_setINT32(self, index, value);
}
int
SV_ASDU_addINT64(SVPublisher_ASDU self)
{
return SVPublisher_ASDU_addINT64(self);
}
void
SV_ASDU_setINT64(SVPublisher_ASDU self, int index, int64_t value)
{
SVPublisher_ASDU_setINT64(self, index, value);
}
int
SV_ASDU_addFLOAT(SVPublisher_ASDU self)
{
return SVPublisher_ASDU_addFLOAT(self);
}
void
SV_ASDU_setFLOAT(SVPublisher_ASDU self, int index, float value)
{
SVPublisher_ASDU_setFLOAT(self, index, value);
}
int
SV_ASDU_addFLOAT64(SVPublisher_ASDU self)
{
return SVPublisher_ASDU_addFLOAT64(self);
}
void
SV_ASDU_setFLOAT64(SVPublisher_ASDU self, int index, double value)
{
SVPublisher_ASDU_setFLOAT64(self, index, value);
}
void
SV_ASDU_setSmpCnt(SVPublisher_ASDU self, uint16_t value)
{
SVPublisher_ASDU_setSmpCnt(self, value);
}
uint16_t
SV_ASDU_getSmpCnt(SVPublisher_ASDU self)
{
return SVPublisher_ASDU_getSmpCnt(self);
}
void
SV_ASDU_increaseSmpCnt(SVPublisher_ASDU self)
{
SVPublisher_ASDU_increaseSmpCnt(self);
}
void
SV_ASDU_setRefrTm(SVPublisher_ASDU self, uint64_t refrTm)
{
SVPublisher_ASDU_setRefrTm(self, refrTm);
}
void
SV_ASDU_setSmpMod(SVPublisher_ASDU self, uint8_t smpMod)
{
SVPublisher_ASDU_setSmpMod(self, smpMod);
}
void
SV_ASDU_setSmpRate(SVPublisher_ASDU self, uint16_t smpRate)
{
SVPublisher_ASDU_setSmpRate(self, smpRate);
}

@ -1,7 +1,7 @@
/*
* sv_receiver.c
*
* Copyright 2015-2022 Michael Zillgith
* Copyright 2015-2024 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -67,7 +67,6 @@ struct sSVReceiver
Semaphore subscriberListLock;
Thread thread;
#endif
};
struct sSVSubscriber
@ -101,7 +100,8 @@ SVReceiver_create(void)
{
SVReceiver self = (SVReceiver) GLOBAL_CALLOC(1, sizeof(struct sSVReceiver));
if (self != NULL) {
if (self)
{
self->subscriberList = LinkedList_create();
self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
@ -122,7 +122,8 @@ SVReceiver_createRemote(RSession session)
{
SVReceiver self = (SVReceiver) GLOBAL_CALLOC(1, sizeof(struct sSVReceiver));
if (self != NULL) {
if (self != NULL)
{
self->subscriberList = LinkedList_create();
self->buffer = NULL;
@ -193,6 +194,7 @@ svReceiverLoop(void* threadParameter)
{
SVReceiver self = (SVReceiver) threadParameter;
#if (CONFIG_IEC61850_L2_SMV == 1)
if (self->ethSocket)
{
EthernetHandleSet handleSet = EthernetHandleSet_new();
@ -217,8 +219,10 @@ svReceiverLoop(void* threadParameter)
EthernetHandleSet_destroy(handleSet);
}
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
#if (CONFIG_IEC61850_R_SMV == 1)
else if (self->session)
if (self->session)
{
self->stopped = false;
@ -349,14 +353,12 @@ SVReceiver_startThreadless(SVReceiver self)
return true;
}
else
{
return false;
}
}
else
{
#endif /* (CONFIG_IEC61850_R_SMV == 1) */
#if (CONFIG_IEC61850_L2_SMV == 1)
if (self->interfaceId == NULL)
self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL);
else
@ -367,22 +369,25 @@ SVReceiver_startThreadless(SVReceiver self)
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV);
self->running = true;
}
if (self->ethSocket)
return true;
else
return false;
}
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
#if (CONFIG_IEC61850_R_SMV == 1)
}
#endif /* (CONFIG_IEC61850_R_SMV == 1) */
return false;
}
void
SVReceiver_stopThreadless(SVReceiver self)
{
#if (CONFIG_IEC61850_L2_SMV == 1)
if (self->ethSocket)
Ethernet_destroySocket(self->ethSocket);
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
#if (CONFIG_IEC61850_R_SMV == 1)
if (self->session) {
@ -611,35 +616,37 @@ handleSVApdu(SVReceiver self, uint16_t appId, uint8_t* apdu, int apduLength, uin
bool subscriberFound = false;
while (element != NULL) {
while (element)
{
subscriber = (SVSubscriber) LinkedList_getData(element);
if (subscriber->appId == appId) {
if (self->checkDestAddr) {
if (self->ethSocket) {
if (memcmp(dstAddr, subscriber->ethAddr, 6) == 0) {
if (subscriber->appId == appId)
{
if (self->checkDestAddr)
{
if (self->ethSocket)
{
if (memcmp(dstAddr, subscriber->ethAddr, 6) == 0)
{
subscriberFound = true;
break;
}
else
{
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Checking ethernet dest address failed!\n");
}
}
else {
else
{
//TODO check destination IP address for R-SV
}
}
else {
else
{
subscriberFound = true;
break;
}
}
element = LinkedList_getNext(element);
@ -650,8 +657,11 @@ handleSVApdu(SVReceiver self, uint16_t appId, uint8_t* apdu, int apduLength, uin
#endif
if (subscriberFound)
{
parseSVPayload(self, subscriber, apdu, apduLength);
else {
}
else
{
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: SV message ignored due to unknown APPID value or dest address mismatch\n");
}
@ -724,6 +734,7 @@ handleSessionPayloadElement(void* parameter, uint16_t appId, uint8_t* payloadDat
bool
SVReceiver_tick(SVReceiver self)
{
#if (CONFIG_IEC61850_L2_SMV == 1)
if (self->ethSocket)
{
int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH);
@ -734,8 +745,10 @@ SVReceiver_tick(SVReceiver self)
return true;
}
}
#endif /* (CONFIG_IEC61850_L2_SMV == 1) */
#if (CONFIG_IEC61850_R_SMV == 1)
else if (self->session)
if (self->session)
{
if (RSession_receiveMessage(self->session, handleSessionPayloadElement, (void*) self) == R_SESSION_ERROR_OK)
return true;
@ -750,7 +763,7 @@ SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID)
{
SVSubscriber self = (SVSubscriber) GLOBAL_CALLOC(1, sizeof(struct sSVSubscriber));
if (self != NULL)
if (self)
{
self->appId = appID;
@ -764,7 +777,7 @@ SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID)
void
SVSubscriber_destroy(SVSubscriber self)
{
if (self != NULL)
if (self)
GLOBAL_FREEMEM(self);
}
@ -819,7 +832,7 @@ decodeUtcTimeToNsTime(uint8_t* buffer, uint8_t* timeQuality)
nsVal = nsVal * 1000000000UL;
nsVal = nsVal >> 24;
if (timeQuality != NULL)
if (timeQuality)
*timeQuality = buffer[7];
uint64_t timeval64 = (uint64_t) timeval32 * 1000000000ULL + nsVal;
@ -832,7 +845,7 @@ SVSubscriber_ASDU_getRefrTmAsMs(SVSubscriber_ASDU self)
{
msSinceEpoch msTime = 0;
if (self->refrTm != NULL)
if (self->refrTm)
msTime = decodeUtcTimeToNsTime(self->refrTm, NULL);
return (msTime / 1000000ULL);
@ -843,7 +856,7 @@ SVSubscriber_ASDU_getRefrTmAsNs(SVSubscriber_ASDU self)
{
nsSinceEpoch nsTime = 0;
if (self->refrTm != NULL)
if (self->refrTm)
nsTime = decodeUtcTimeToNsTime(self->refrTm, NULL);
return nsTime;
@ -1086,99 +1099,3 @@ SVSubscriber_ASDU_getDataSize(SVSubscriber_ASDU self)
{
return self->dataBufferLength;
}
uint16_t
SVClientASDU_getSmpCnt(SVSubscriber_ASDU self)
{
return SVSubscriber_ASDU_getSmpCnt(self);
}
const char*
SVClientASDU_getSvId(SVSubscriber_ASDU self)
{
return SVSubscriber_ASDU_getSvId(self);
}
uint32_t
SVClientASDU_getConfRev(SVSubscriber_ASDU self)
{
return SVSubscriber_ASDU_getConfRev(self);
}
bool
SVClientASDU_hasRefrTm(SVSubscriber_ASDU self)
{
return SVSubscriber_ASDU_hasRefrTm(self);
}
uint64_t
SVClientASDU_getRefrTmAsMs(SVSubscriber_ASDU self)
{
return SVSubscriber_ASDU_getRefrTmAsMs(self);
}
int8_t
SVClientASDU_getINT8(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT8(self, index);
}
int16_t
SVClientASDU_getINT16(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT16(self, index);
}
int32_t
SVClientASDU_getINT32(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT32(self, index);
}
int64_t
SVClientASDU_getINT64(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT64(self, index);
}
uint8_t
SVClientASDU_getINT8U(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT8U(self, index);
}
uint16_t
SVClientASDU_getINT16U(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT16U(self, index);
}
uint32_t
SVClientASDU_getINT32U(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT32U(self, index);
}
uint64_t
SVClientASDU_getINT64U(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getINT64U(self, index);
}
float
SVClientASDU_getFLOAT32(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getFLOAT32(self, index);
}
double
SVClientASDU_getFLOAT64(SVSubscriber_ASDU self, int index)
{
return SVSubscriber_ASDU_getFLOAT64(self, index);
}
int
SVClientASDU_getDataSize(SVSubscriber_ASDU self)
{
return SVSubscriber_ASDU_getDataSize(self);
}

@ -560,72 +560,7 @@ SVSubscriber_ASDU_getDataSize(SVSubscriber_ASDU self);
uint8_t
SVSubscriber_ASDU_getSmpSynch(SVSubscriber_ASDU self);
#ifndef DEPRECATED
#if defined(__GNUC__) || defined(__clang__)
#define DEPRECATED __attribute__((deprecated))
#else
#define DEPRECATED
#endif
#endif
/**
* \addtogroup sv_subscriber_deprecated_api_group Deprecated API
* \ingroup sv_subscriber_api_group IEC 61850 Sampled Values (SV) publisher API
* \deprecated
* @{
*/
typedef struct sSVSubscriberASDU* SVClientASDU;
LIB61850_API DEPRECATED uint16_t
SVClientASDU_getSmpCnt(SVSubscriber_ASDU self);
LIB61850_API DEPRECATED const char*
SVClientASDU_getSvId(SVSubscriber_ASDU self);
LIB61850_API DEPRECATED uint32_t
SVClientASDU_getConfRev(SVSubscriber_ASDU self);
LIB61850_API DEPRECATED bool
SVClientASDU_hasRefrTm(SVSubscriber_ASDU self);
LIB61850_API DEPRECATED uint64_t
SVClientASDU_getRefrTmAsMs(SVSubscriber_ASDU self);
LIB61850_API DEPRECATED int8_t
SVClientASDU_getINT8(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED int16_t
SVClientASDU_getINT16(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED int32_t
SVClientASDU_getINT32(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED int64_t
SVClientASDU_getINT64(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED uint8_t
SVClientASDU_getINT8U(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED uint16_t
SVClientASDU_getINT16U(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED uint32_t
SVClientASDU_getINT32U(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED uint64_t
SVClientASDU_getINT64U(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED float
SVClientASDU_getFLOAT32(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED double
SVClientASDU_getFLOAT64(SVSubscriber_ASDU self, int index);
LIB61850_API DEPRECATED int
SVClientASDU_getDataSize(SVSubscriber_ASDU self);
/**@} @}*/
/** @}*/
#ifdef __cplusplus
}

Loading…
Cancel
Save