forked from eclipse-4diac/4diac-forte
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix and move ldsMe to its own class (eclipse-4diac#239)
* fix and move ldsMe to its own class * add documentation * update for v1.4.5 * remove not needed include
- Loading branch information
Showing
6 changed files
with
220 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
if(FORTE_COM_OPC_UA_MULTICAST) | ||
forte_add_sourcefile_hcpp(lds_me_handler) | ||
endif(FORTE_COM_OPC_UA_MULTICAST) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
|
||
#include "lds_me_handler.h" | ||
|
||
#include "devlog.h" | ||
|
||
using namespace forte::com::opc_ua::detail; | ||
|
||
LdsMeHandler::LdsMeHandler(UA_Server& paUaServer) : mUaServer{paUaServer} { | ||
UA_Server_setServerOnNetworkCallback(&mUaServer, serverOnNetworkCallback, this); | ||
} | ||
|
||
LdsMeHandler::~LdsMeHandler() { | ||
for(const auto& registeredServer : mRegisteredServers){ | ||
deregisterDiscoveryServer(registeredServer.mString); | ||
} | ||
UA_Server_setServerOnNetworkCallback(&mUaServer, nullptr, nullptr); | ||
} | ||
|
||
void LdsMeHandler::configureServer(UA_ServerConfig& paUaServerConfig, const std::string& paServerName) { | ||
UA_String_clear(&paUaServerConfig.mdnsConfig.mdnsServerName); | ||
paUaServerConfig.mdnsConfig.mdnsServerName = UA_String_fromChars(paServerName.c_str()); | ||
// Enable the mDNS announce and response functionality | ||
paUaServerConfig.mdnsEnabled = true; | ||
} | ||
|
||
void LdsMeHandler::serverOnNetworkCallback(const UA_ServerOnNetwork* paServerOnNetwork, UA_Boolean paIsServerAnnounce, UA_Boolean paIsTxtReceived, void* paData) { | ||
|
||
if(!paIsTxtReceived) { | ||
return; // we wait until the corresponding TXT record is announced. | ||
} | ||
|
||
DEVLOG_DEBUG("[OPC UA LDS ME]: mDNS %s '%.*s' with url '%.*s'\n", paIsServerAnnounce ? "announce" : "remove", paServerOnNetwork->serverName.length, | ||
paServerOnNetwork->serverName.data, paServerOnNetwork->discoveryUrl.length, paServerOnNetwork->discoveryUrl.data); | ||
|
||
// check if server is LDS | ||
bool isServerLDS = false; | ||
|
||
UA_StringRAII ldsStr("LDS"); | ||
for(unsigned int i = 0; i < paServerOnNetwork->serverCapabilitiesSize; i++) { | ||
if(UA_String_equal(&paServerOnNetwork->serverCapabilities[i], &ldsStr.mString)) { | ||
isServerLDS = true; | ||
break; | ||
} | ||
} | ||
|
||
// skip non-LDS servers | ||
if(!isServerLDS) { | ||
return; | ||
} | ||
|
||
auto handler = static_cast<LdsMeHandler*>(paData); | ||
|
||
auto foundDiscoveryUrl = handler->mRegisteredServers.end(); | ||
for(auto iter = handler->mRegisteredServers.begin(); iter != handler->mRegisteredServers.end(); iter++) { | ||
if(UA_String_equal(&paServerOnNetwork->discoveryUrl, &iter->mString)) { | ||
foundDiscoveryUrl = iter; | ||
break; | ||
} | ||
} | ||
|
||
// if a new server is being announced | ||
if(paIsServerAnnounce && foundDiscoveryUrl == handler->mRegisteredServers.end()) { | ||
if(handler->registerDiscoveryServer(paServerOnNetwork->discoveryUrl)){ | ||
handler->mRegisteredServers.emplace_back(paServerOnNetwork->discoveryUrl); | ||
} | ||
// if a known server is being un-announced | ||
} else if(!paIsServerAnnounce && foundDiscoveryUrl != handler->mRegisteredServers.end()) { | ||
handler->deregisterDiscoveryServer(foundDiscoveryUrl->mString); | ||
handler->mRegisteredServers.erase(foundDiscoveryUrl); | ||
} | ||
} | ||
|
||
bool LdsMeHandler::registerDiscoveryServer(const UA_String& paDiscoveryUrl) { | ||
|
||
UA_ClientConfig clientConfig; | ||
memset(&clientConfig, 0, sizeof(UA_ClientConfig)); | ||
UA_ClientConfig_setDefault(&clientConfig); | ||
auto retVal = UA_Server_registerDiscovery(&mUaServer, &clientConfig, paDiscoveryUrl, UA_STRING_NULL); | ||
if( UA_STATUSCODE_GOOD != retVal) { | ||
DEVLOG_ERROR("[OPC UA LDSME]: Could not register with LDS. Error: %s\n", UA_StatusCode_name(retVal)); | ||
return false; | ||
} | ||
DEVLOG_INFO("[OPC UA LDSME]: Registered to LDS '%.*s'\n", paDiscoveryUrl.length, paDiscoveryUrl.data); | ||
return true; | ||
} | ||
|
||
void LdsMeHandler::deregisterDiscoveryServer(const UA_String& paDiscoveryUrl) { | ||
UA_ClientConfig clientConfig; | ||
memset(&clientConfig, 0, sizeof(UA_ClientConfig)); | ||
UA_ClientConfig_setDefault(&clientConfig); | ||
|
||
auto retVal = UA_Server_deregisterDiscovery(&mUaServer, &clientConfig, paDiscoveryUrl); | ||
// if unregister fails, we don't do anything else | ||
if( UA_STATUSCODE_GOOD != retVal) { | ||
DEVLOG_ERROR("[OPC UA LDSME]: Could not deregister with LDS. Error: %s\n", UA_StatusCode_name(retVal)); | ||
return; | ||
} | ||
|
||
DEVLOG_INFO("[OPC UA LDSME]: Unregistered from LDS '%.*s'\n", paDiscoveryUrl.length, paDiscoveryUrl.data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 Jose Cabral | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Jose Cabral | ||
* - initial integration of the OPC-UA protocol | ||
*******************************************************************************/ | ||
|
||
#ifndef SRC_COM_OPC_UA_DETAIL_LDSMEHANDLER_H_ | ||
#define SRC_COM_OPC_UA_DETAIL_LDSMEHANDLER_H_ | ||
|
||
#include <open62541.h> | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
namespace forte::com::opc_ua::detail { | ||
|
||
/** | ||
* @brief Handles all things related to LDS-ME | ||
* | ||
* Configures the server to accept LDS-ME messages and handles them accordingly. | ||
*/ | ||
class LdsMeHandler { | ||
public: | ||
|
||
/** | ||
* @brief Register this instance as handler for incoming discovery message | ||
* | ||
* @param paUaServer OpcUa server to handle | ||
*/ | ||
LdsMeHandler(UA_Server& paUaServer); | ||
|
||
/** | ||
* @brief Un-register this instance as handler incoming discovery message | ||
* | ||
*/ | ||
~LdsMeHandler(); | ||
|
||
|
||
/** | ||
* @brief Sets the proper values to the server configuration so it accepts LDS-ME messages | ||
* | ||
* @param paUaServerConfig configuration to be set | ||
* @param paServerName server name to be used when registering to the discovery server | ||
*/ | ||
static void configureServer(UA_ServerConfig& paUaServerConfig, const std::string& paServerName); | ||
|
||
private: | ||
|
||
bool registerDiscoveryServer(const UA_String& paDiscoveryUrl); | ||
void deregisterDiscoveryServer(const UA_String& paDiscoveryUrl); | ||
|
||
static void serverOnNetworkCallback(const UA_ServerOnNetwork* paServerOnNetwork, UA_Boolean paIsServerAnnounce, UA_Boolean paIsTxtReceived, void* paData); | ||
|
||
UA_Server& mUaServer; | ||
|
||
// Handle the lifetime of a UA_String nicely | ||
class UA_StringRAII { | ||
public: | ||
UA_StringRAII(const UA_String& paString) { | ||
UA_String_copy(&paString, &mString); | ||
} | ||
|
||
UA_StringRAII(const char* paString) { | ||
mString = UA_String_fromChars(paString); | ||
} | ||
|
||
~UA_StringRAII() { | ||
UA_String_clear(&mString); | ||
} | ||
|
||
UA_StringRAII(UA_StringRAII&& paOther) { | ||
*this = std::move(paOther); | ||
} | ||
|
||
UA_StringRAII& operator=(UA_StringRAII&& paOther) { | ||
mString = paOther.mString; | ||
UA_String_init(&paOther.mString); | ||
return *this; | ||
}; | ||
|
||
|
||
UA_StringRAII(const UA_StringRAII&) = delete; | ||
UA_StringRAII& operator=(const UA_StringRAII&) = delete; | ||
|
||
UA_String mString; | ||
}; | ||
|
||
/// List of discovery servers where this instance is already registered | ||
std::vector<UA_StringRAII> mRegisteredServers; | ||
}; | ||
} | ||
|
||
#endif // SRC_COM_OPC_UA_DETAIL_LDSMEHANDLER_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2015, 2023 Florian Froschermeier <[email protected]>, | ||
* Copyright (c) 2015, 2024 Florian Froschermeier <[email protected]>, | ||
* fortiss GmbH, Primetals Technologies Austria GmbH | ||
* | ||
* This program and the accompanying materials are made available under the | ||
|
@@ -30,6 +30,9 @@ | |
#include "forte_printer.h" | ||
#include "../../arch/utils/mainparam_utils.h" | ||
#include "opcua_local_handler.h" | ||
#ifdef FORTE_COM_OPC_UA_MULTICAST | ||
#include "detail/lds_me_handler.h" | ||
#endif //FORTE_COM_OPC_UA_MULTICAST | ||
#include <string> | ||
|
||
#ifndef FORTE_COM_OPC_UA_CUSTOM_HOSTNAME | ||
|
@@ -57,12 +60,6 @@ COPC_UA_Local_Handler::~COPC_UA_Local_Handler() { | |
UA_NodeId_delete(const_cast<UA_NodeId*>(iter->mNodeId)); | ||
} | ||
mNodesReferences.clear(); | ||
|
||
#ifdef FORTE_COM_OPC_UA_MULTICAST | ||
for(CSinglyLinkedList<UA_String*>::Iterator iter = mRegisteredWithLds.begin(); iter != mRegisteredWithLds.end(); ++iter) { | ||
UA_String_delete(*iter); | ||
} | ||
#endif //FORTE_COM_OPC_UA_MULTICAST | ||
} | ||
|
||
void COPC_UA_Local_Handler::enableHandler() { | ||
|
@@ -91,12 +88,15 @@ void COPC_UA_Local_Handler::run() { | |
configureUAServer(serverStrings, *uaServerConfig); | ||
|
||
if(initializeNodesets(*mUaServer)) { | ||
#ifdef FORTE_COM_OPC_UA_MULTICAST | ||
UA_Server_setServerOnNetworkCallback(mUaServer, serverOnNetworkCallback, this); | ||
#endif //FORTE_COM_OPC_UA_MULTICAST | ||
|
||
UA_StatusCode retVal = UA_Server_run_startup(mUaServer); | ||
if(UA_STATUSCODE_GOOD == retVal) { | ||
{ | ||
#ifdef FORTE_COM_OPC_UA_MULTICAST | ||
// the extra curly brace on top is to limit the lifetime of this object. | ||
// it was avoided to have inside this ifdef to also avoid the closing brace | ||
// with the exta ifdef making it cleaner this way | ||
auto mLdsMeHandler = forte::com::opc_ua::detail::LdsMeHandler(*mUaServer); | ||
#endif //FORTE_COM_OPC_UA_MULTICAST | ||
mServerStarted.inc(); | ||
while(isAlive()) { | ||
UA_UInt16 timeToSleepMs; | ||
|
@@ -110,6 +110,7 @@ void COPC_UA_Local_Handler::run() { | |
|
||
mServerNeedsIteration.timedWait(static_cast<TForteUInt64>(timeToSleepMs) * 1000000ULL); | ||
} | ||
} | ||
retVal = UA_Server_run_shutdown(mUaServer); | ||
if(UA_STATUSCODE_GOOD == retVal) { | ||
DEVLOG_INFO("[OPC UA LOCAL]: Server successfully stopped\n"); | ||
|
@@ -166,10 +167,7 @@ void COPC_UA_Local_Handler::generateServerStrings(TForteUInt16 paUAServerPort, U | |
|
||
void COPC_UA_Local_Handler::configureUAServer(UA_ServerStrings &paServerStrings, UA_ServerConfig &paUaServerConfig) const { | ||
#ifdef FORTE_COM_OPC_UA_MULTICAST | ||
paUaServerConfig.applicationDescription.applicationType = UA_APPLICATIONTYPE_DISCOVERYSERVER; | ||
// hostname will be added by mdns library | ||
UA_String_clear(&paUaServerConfig.mdnsConfig.mdnsServerName); | ||
paUaServerConfig.mdnsConfig.mdnsServerName = UA_String_fromChars(paServerStrings.mMdnsServerName.c_str()); | ||
forte::com::opc_ua::detail::LdsMeHandler::configureServer(paUaServerConfig, paServerStrings.mMdnsServerName); | ||
#endif //FORTE_COM_OPC_UA_MULTICAST | ||
|
||
UA_Array_delete(paUaServerConfig.serverUrls, paUaServerConfig.serverUrlsSize, &UA_TYPES[UA_TYPES_STRING]); | ||
|
@@ -280,85 +278,7 @@ void COPC_UA_Local_Handler::getNodesReferencedByAction(const CActionInfo &paActi | |
} | ||
} | ||
|
||
#ifdef FORTE_COM_OPC_UA_MULTICAST | ||
|
||
const UA_String* COPC_UA_Local_Handler::getDiscoveryUrl() const { | ||
|
||
UA_ServerConfig *mServerConfig = UA_Server_getConfig(mUaServer); //change mServerConfig to serverConfig when only master branch is present | ||
if(0 == mServerConfig->networkLayersSize) { | ||
return 0; | ||
} | ||
return &mServerConfig->networkLayers[0].discoveryUrl; | ||
} | ||
|
||
void COPC_UA_Local_Handler::serverOnNetworkCallback(const UA_ServerOnNetwork *paServerOnNetwork, UA_Boolean paIsServerAnnounce, UA_Boolean paIsTxtReceived, | ||
void *paData) { //NOSONAR | ||
COPC_UA_Local_Handler *handler = static_cast<COPC_UA_Local_Handler*>(paData); | ||
|
||
const UA_String *ownDiscoverUrl = handler->getDiscoveryUrl(); | ||
|
||
if(!ownDiscoverUrl || UA_String_equal(&paServerOnNetwork->discoveryUrl, ownDiscoverUrl)) { | ||
// skip self | ||
return; | ||
} | ||
|
||
if(!paIsTxtReceived) { | ||
return; // we wait until the corresponding TXT record is announced. | ||
} | ||
|
||
DEVLOG_DEBUG("[OPC UA LOCAL]: mDNS %s '%.*s' with url '%.*s'\n", paIsServerAnnounce ? "announce" : "remove", paServerOnNetwork->serverName.length, | ||
paServerOnNetwork->serverName.data, paServerOnNetwork->discoveryUrl.length, paServerOnNetwork->discoveryUrl.data); | ||
|
||
// check if server is LDS, and then register | ||
UA_String ldsStr = UA_String_fromChars("LDS"); | ||
for(unsigned int i = 0; i < paServerOnNetwork->serverCapabilitiesSize; i++) { | ||
if(UA_String_equal(&paServerOnNetwork->serverCapabilities[i], &ldsStr)) { | ||
if(paIsServerAnnounce) { | ||
handler->registerWithLds(&paServerOnNetwork->discoveryUrl); | ||
} else { | ||
handler->removeLdsRegister(&paServerOnNetwork->discoveryUrl); | ||
} | ||
break; | ||
} | ||
} | ||
UA_String_clear(&ldsStr); | ||
} | ||
|
||
void COPC_UA_Local_Handler::registerWithLds(const UA_String *paDiscoveryUrl) { | ||
// check if already registered with the given LDS | ||
for(CSinglyLinkedList<UA_String*>::Iterator iter = mRegisteredWithLds.begin(); iter != mRegisteredWithLds.end(); ++iter) { | ||
if(UA_String_equal(paDiscoveryUrl, *iter)) { | ||
return; | ||
} | ||
} | ||
|
||
// will be freed when removed from list | ||
UA_String *discoveryUrlChar = 0; | ||
UA_String_copy(paDiscoveryUrl, discoveryUrlChar); | ||
|
||
mRegisteredWithLds.pushFront(discoveryUrlChar); | ||
DEVLOG_INFO("[OPC UA LOCAL]: Registering with LDS '%.*s'\n", paDiscoveryUrl->length, paDiscoveryUrl->data); | ||
UA_StatusCode retVal = UA_Server_addPeriodicServerRegisterCallback(mUaServer, 0, reinterpret_cast<const char*>(discoveryUrlChar->data), 10 * 60 * 1000, 500, 0); | ||
if( UA_STATUSCODE_GOOD != retVal) { | ||
DEVLOG_ERROR("[OPC UA LOCAL]: Could not register with LDS. Error: %s\n", UA_StatusCode_name(retVal)); | ||
} | ||
} | ||
|
||
void COPC_UA_Local_Handler::removeLdsRegister(const UA_String *paDiscoveryUrl) { | ||
UA_String *toDelete = 0; | ||
for(CSinglyLinkedList<UA_String*>::Iterator iter = mRegisteredWithLds.begin(); iter != mRegisteredWithLds.end(); ++iter) { | ||
if(UA_String_equal(paDiscoveryUrl, *iter)) { | ||
toDelete = *iter; | ||
break; | ||
} | ||
} | ||
if(toDelete) { | ||
mRegisteredWithLds.erase(toDelete); | ||
UA_String_delete(toDelete); | ||
} | ||
} | ||
|
||
#endif //FORTE_COM_OPC_UA_MULTICAST | ||
|
||
UA_StatusCode COPC_UA_Local_Handler::initializeAction(CActionInfo &paActionInfo) { | ||
enableHandler(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters