setServerConfig(ServerConfig* pServerConfig) how to use?

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
richng01
Full Member
Full Member
Posts: 6
Joined: 25 May 2017, 09:11

setServerConfig(ServerConfig* pServerConfig) how to use?

Post by richng01 »

Dear all,

I need to use my own configuration from database.
I call pServer->setServerConfig(ServerConfig* pServerConfig);
However, pServer->start() always failed to start opc ua server.
How should i initialize pServerConfig with minimum settings?
Is there any example how to use pServer->setServerConfig(ServerConfig* pServerConfig);

Thanks in advance,
Richie

User avatar
Support Team
Hero Member
Hero Member
Posts: 3071
Joined: 18 Mar 2011, 15:09

Re: setServerConfig(ServerConfig* pServerConfig) how to use?

Post by Support Team »

Hello richng01,

I can provide a sample implementation for a ServerConfig class that works without configuration file:

serverconfigbase.h:

Code: Select all

#ifndef SERVERCONFIGBASE_H
#define SERVERCONFIGBASE_H

#include "serverconfigdata.h"

class UaCoreServerApplication;
class UaServerApplicationCallback;
class UaEndpointBase;

class ServerConfigBase : public ServerConfigData
{
    UA_DISABLE_COPY(ServerConfigBase);
public:
    ServerConfigBase(
        const UaString&              sApplicationPath,
        const UaString&              sConfigurationPath,
        const UaString&              sTracePath,
        const UaString&              sProductUri,
        const UaString&              sManufacturerName,
        const UaString&              sProductName,
        const UaString&              sSoftwareVersion,
        const UaString&              sBuildNumber,
        const UaString&              sServerInstanceUri,
        const UaString&              sServerInstanceName,
        UaCoreServerApplication*     pUaCoreServerApplication,
        UaServerApplicationCallback* pUaServerApplicationCallback);
    virtual ~ServerConfigBase();

    void addEndpoint(UaEndpointBase* pEndpoint);

    // Implement ServerConfigData
    virtual UaStatus afterLoadConfiguration();

    // Implement ServerConfig
    virtual UaStatus loadConfiguration();
    virtual UaStatus startUp(ServerManager* pServerManager);
    virtual UaStatus shutDown();
    virtual UaStatus saveConfiguration();
    virtual Session* createSession(OpcUa_Int32 sessionID, const UaNodeId &authenticationToken);
    virtual UaStatus logonSessionUser(Session* pSession, UaUserIdentityToken* pUserIdentityToken);

    // Additional Setter
    UaStatus setStackTraceSettings(
        OpcUa_Boolean bTraceEnabled,
        OpcUa_UInt32  uTraceLevel);

    UaStatus setServerTraceSettings(
        OpcUa_Boolean   bTraceEnabled,       //!< [in] Globally enable/disable trace output from the SDK
        OpcUa_UInt32    uTraceLevel,         /**< [in] Configures the level of messages traced
                                             - (0) NoTrace - No Trace
                                             - (1) Errors - Unexpected errors
                                             - (2) Warning - Unexpected behaviour that is not an error
                                             - (3) Info - Information about important activities like connection establishment
                                             - (4) InterfaceCall - Calls to module interfaces
                                             - (5) CtorDtor - Creation and destruction of objects
                                             - (6) ProgramFlow - Internal program flow
                                             - (7) Data - Data */
        OpcUa_UInt32    uMaxTraceEntries,    //!< [in] Maximum number of trace entries in one trace file
        OpcUa_UInt32    uMaxBackupFiles,     //!< [in] Maximum number of backup files
        const UaString& sTraceFile,          //!< [in] Name and path of the trace file
        OpcUa_Boolean   bDisableFlush        //!< [in] Disable flushing the trace file after each trace entry
    );

protected:
    UaCoreServerApplication*        m_pUaCoreServerApplication;
    UaServerApplicationCallback*    m_pUaServerApplicationCallback;
};

class UaEndpointBase : public UaEndpoint
{
    UA_DISABLE_COPY(UaEndpointBase);
public:
    UaEndpointBase();
    UaEndpointBase(const UaString& sPort, bool isSecure = true);
    void setCertificateStore(OpcUa_UInt32 endpointCertificateStoreIndex, CertificateStoreConfiguration* pEndpointCertificateStore);
    virtual ~UaEndpointBase();
};

#endif // SERVERCONFIGBASE_H
serverconfigbase.cpp:

Code: Select all

#include "serverconfigbase.h"
#include "uacoreserverapplication.h"

/* ----------------------------------------------------------------------------
Begin Class    ServerConfigBase
-----------------------------------------------------------------------------*/
ServerConfigBase::ServerConfigBase(
    const UaString&  sApplicationPath,   //!< The path to the server executable.
    const UaString&  sConfigurationPath, //!< The path to the configuration files.
    const UaString&  sTracePath,         //!< The path to the log files.
    const UaString&  sProductUri,        //!< The product URI of the server.
    const UaString&  sManufacturerName,  //!< The manufacturer name of the server.
    const UaString&  sProductName,       //!< The product name of the server.
    const UaString&  sSoftwareVersion,   //!< The software version of the server.
    const UaString&  sBuildNumber,       //!< The build number of the server.
    const UaString&  sServerInstanceUri, //!< The application instance URI of the server. The placeholder [NodeName] can be used to automatically insert the host name.
    const UaString&  sServerInstanceName, //!< The application instance name of the server. The placeholder [NodeName] can be used to automatically insert the host name.
    UaCoreServerApplication*     pUaCoreServerApplication, //!< The main server application object.
    UaServerApplicationCallback* pUaServerApplicationCallback) //!< The user application callback interface.
    : ServerConfigData(sApplicationPath, sConfigurationPath, sTracePath),
    m_pUaCoreServerApplication(pUaCoreServerApplication),
    m_pUaServerApplicationCallback(pUaServerApplicationCallback)
{
    setProductUri(sProductUri);
    setManufacturerName(sManufacturerName);
    setProductName(sProductName);
    setSoftwareVersion(sSoftwareVersion);
    setBuildNumber(sBuildNumber);

    char szHostname[256];
    UA_GetHostname(szHostname, sizeof(szHostname));
    UaString sHostName(szHostname);
    UaString sReplacedServerInstanceUri(sServerInstanceUri);
    replaceNodeName(sReplacedServerInstanceUri, sHostName);
    setServerUri(sReplacedServerInstanceUri);
    UaString sReplacedServerInstanceName(sServerInstanceName);
    replaceNodeName(sReplacedServerInstanceName, sHostName);
    setServerName(sReplacedServerInstanceName);

    m_sTraceFile = "[TracePath]/UaServerCPP.log";
    replaceTracePath(m_sTracePath, m_sTracePath);
    replaceTracePath(m_sTraceFile, m_sTracePath);

    // Create default certificat store
    CertificateStoreConfiguration* pDefaultCertificateStore = new CertificateStoreConfiguration;
    pDefaultCertificateStore->m_maxTrustListSize = 100;
    pDefaultCertificateStore->m_sCertificateTrustListLocation = UaString("%1/pkiserver/trusted/certs/").arg(sConfigurationPath);
    pDefaultCertificateStore->m_sCertificateRevocationListLocation = UaString("%1/pkiserver/trusted/crl/").arg(sConfigurationPath);
    pDefaultCertificateStore->m_sIssuersCertificatesLocation = UaString("%1/pkiserver/issuers/certs/").arg(sConfigurationPath);
    pDefaultCertificateStore->m_sIssuersRevocationListLocation = UaString("%1/pkiserver/issuers/crl/").arg(sConfigurationPath);

    // Create default certificat configuration
    CertificateConfiguration* pNewCertificate = new CertificateConfiguration;
    pNewCertificate->m_sCertificateLocation = UaString("%1/pkiserver/own/certs/uaservercpp.der").arg(sConfigurationPath);
    pNewCertificate->m_sPrivateKeyLocation = UaString("%1/pkiserver/own/private/uaservercpp.pem").arg(sConfigurationPath);
    pNewCertificate->m_createCertificate = true;
    pNewCertificate->m_autoCompleteCertificateChain = true;
    pNewCertificate->m_certificateCreateSetting.m_sCommonName = sReplacedServerInstanceName;
    pNewCertificate->m_certificateCreateSetting.m_sDomainComponent = sHostName;
    pNewCertificate->m_certificateCreateSetting.m_sOrganization = "Organization";
    pNewCertificate->m_certificateCreateSetting.m_sOrganizationUnit = "Unit";
    pNewCertificate->m_certificateCreateSetting.m_sLocality = "LocationName";
    pNewCertificate->m_certificateCreateSetting.m_sState = "";
    pNewCertificate->m_certificateCreateSetting.m_sCountry = "DE";
    pNewCertificate->m_certificateCreateSetting.m_certificateType = CertificateCreateSettings::CertificateType_RsaSha256;
    pNewCertificate->m_certificateCreateSetting.m_arrDNSNames.create(1);
    sHostName.copyTo(&pNewCertificate->m_certificateCreateSetting.m_arrDNSNames[0]);

    // Add certificate to store
    pDefaultCertificateStore->addCertificate(pNewCertificate);
    pNewCertificate->releaseReference();
    // Add certificate store to configuration
    addCertificateStoreConfiguration(pDefaultCertificateStore);
    pDefaultCertificateStore->releaseReference();
}

/** Destroys the ServerConfigBase object */
ServerConfigBase::~ServerConfigBase()
{
}

/** Adds an endpoint to the server configuration.
*
*  It sets also the default certificate store if no certificate store is configured for the endpoint.
*/
void ServerConfigBase::addEndpoint(UaEndpointBase* pEndpoint)
{
    if ((pEndpoint->pEndpointCertificateStore() == NULL) && (m_certificateStores.length() > 0))
    {
        pEndpoint->setCertificateStore(0, m_certificateStores[0]);
    }
    m_uaEndpointArray.addObject(pEndpoint);
}

UaStatus ServerConfigBase::afterLoadConfiguration()
{
    return OpcUa_Good;
}
UaStatus ServerConfigBase::loadConfiguration()
{
    return OpcUa_Good;
}
UaStatus ServerConfigBase::startUp(ServerManager* pServerManager)
{
    OpcUa_ReferenceParameter(pServerManager);
    if (m_uaEndpointArray.length() == 0)
    {
        return OpcUa_BadInvalidState;
    }
    return OpcUa_Good;
}
UaStatus ServerConfigBase::shutDown()
{
    return OpcUa_Good;
}
UaStatus ServerConfigBase::saveConfiguration()
{
    return OpcUa_BadNotImplemented;
}

Session* ServerConfigBase::createSession(OpcUa_Int32 sessionID, const UaNodeId &authenticationToken)
{
    if (m_pUaServerApplicationCallback)
    {
        return m_pUaServerApplicationCallback->createSession(sessionID, authenticationToken);
    }
    else
    {
        return m_pUaCoreServerApplication->createDefaultSession(sessionID, authenticationToken);
    }
}

UaStatus ServerConfigBase::logonSessionUser(Session* pSession, UaUserIdentityToken* pUserIdentityToken)
{
    OpcUa_Boolean  bEnableAnonymous;
    OpcUa_Boolean  bEnableUserPw;
    OpcUa_Boolean  bEnableCertificate;
    OpcUa_Boolean  bEnableKerberosTicket;

    // Get the settings for user identity tokens to support
    getUserIdentityTokenConfig(bEnableAnonymous, bEnableUserPw, bEnableCertificate, bEnableKerberosTicket);

    if (pUserIdentityToken->getTokenType() == OpcUa_UserTokenType_Anonymous)
    {
        if (bEnableAnonymous == OpcUa_False)
        {
            return OpcUa_BadIdentityTokenRejected;
        }
        else
        {
            if (m_pUaServerApplicationCallback)
            {
                return m_pUaServerApplicationCallback->logonSessionUser(pSession, pUserIdentityToken, this);
            }
            else
            {
                return OpcUa_Good;
            }
        }
    }
    else if (pUserIdentityToken->getTokenType() == OpcUa_UserTokenType_UserName)
    {
        if (bEnableUserPw == OpcUa_False)
        {
            return OpcUa_BadIdentityTokenRejected;
        }
        else
        {
            if (m_pUaServerApplicationCallback)
            {
                return m_pUaServerApplicationCallback->logonSessionUser(pSession, pUserIdentityToken, this);
            }
            else
            {
                return OpcUa_BadIdentityTokenRejected;
            }
        }
    }
    else if (pUserIdentityToken->getTokenType() == OpcUa_UserTokenType_Certificate)
    {
        if (bEnableCertificate == OpcUa_False)
        {
            return OpcUa_BadIdentityTokenRejected;
        }
        else
        {
            if (m_pUaServerApplicationCallback)
            {
                return m_pUaServerApplicationCallback->logonSessionUser(pSession, pUserIdentityToken, this);
            }
            else
            {
                return OpcUa_BadIdentityTokenRejected;
            }
        }
    }
    else if (pUserIdentityToken->getTokenType() == 4/*OpcUa_UserTokenType_KerberosToken*/)
    {
        if (bEnableKerberosTicket == OpcUa_False)
        {
            return OpcUa_BadIdentityTokenRejected;
        }
        else
        {
            if (m_pUaServerApplicationCallback)
            {
                return m_pUaServerApplicationCallback->logonSessionUser(pSession, pUserIdentityToken, this);
            }
            else
            {
                return OpcUa_BadIdentityTokenRejected;
            }
        }
    }

    return OpcUa_Bad;
}


UaStatus ServerConfigBase::setStackTraceSettings(OpcUa_Boolean bTraceEnabled, OpcUa_UInt32  uTraceLevel)
{
    m_bTraceEnabled = bTraceEnabled;
    m_uTraceLevel = uTraceLevel;
    return OpcUa_Good;
}

UaStatus ServerConfigBase::setServerTraceSettings(
    OpcUa_Boolean   bTraceEnabled,       //!< [in] Globally enable/disable trace output from the SDK
    OpcUa_UInt32    uTraceLevel,         /**< [in] Configures the level of messages traced
                                         - (0) NoTrace - No Trace
                                         - (1) Errors - Unexpected errors
                                         - (2) Warning - Unexpected behaviour that is not an error
                                         - (3) Info - Information about important activities like connection establishment
                                         - (4) InterfaceCall - Calls to module interfaces
                                         - (5) CtorDtor - Creation and destruction of objects
                                         - (6) ProgramFlow - Internal program flow
                                         - (7) Data - Data */
    OpcUa_UInt32    uMaxTraceEntries,    //!< [in] Maximum number of trace entries in one trace file
    OpcUa_UInt32    uMaxBackupFiles,     //!< [in] Maximum number of backup files
    const UaString& sTraceFile,          //!< [in] Name and path of the trace file
    OpcUa_Boolean   bDisableFlush        //!< [in] Disable flushing the trace file after each trace entry
)
{
    m_bSdkTraceEnabled = bTraceEnabled;
    m_uSdkTraceLevel = uTraceLevel;
    m_uMaxTraceEntries = uMaxTraceEntries;
    m_uMaxBackupFiles = uMaxBackupFiles;
    m_sTraceFile = sTraceFile;
    m_bDisableFlush = bDisableFlush;
    return OpcUa_Good;
}

/** Creates an instance of the UaEndpointBase class with default settings
*
*  The default endpoint is created with the standard OPC UA port 4840 and without security
*/
UaEndpointBase::UaEndpointBase()
{
    // initialize the EndpointUrl with NodeName
    char szHostName[256] = "127.0.0.1";
    UA_GetHostname(szHostName, 256);
    setEndpointUrl(UaString("opc.tcp://%1:4840").arg(szHostName), OpcUa_True);

    setSerializerType(OpcUa_Endpoint_SerializerType_Binary);
    UaEndpointSecuritySetting securitySetting;
    securitySetting.setSecurityPolicy(OpcUa_SecurityPolicy_None);
    securitySetting.addMessageSecurityMode(OPCUA_ENDPOINT_MESSAGESECURITYMODE_NONE);
    addSecuritySetting(securitySetting);
}

/** Creates an instance of the ServerConfigBase class working without file access
* @param sPort the port that is used by the endpoint.
* @param isSecure flag indicating if security is required for the endpoint.
*/
UaEndpointBase::UaEndpointBase(const UaString& sPort, bool isSecure)
{
    // initialize the EndpointUrl with NodeName
    char szHostName[256] = "127.0.0.1";
    UA_GetHostname(szHostName, 256);
    setEndpointUrl(UaString("opc.tcp://%1:%2").arg(szHostName).arg(sPort), OpcUa_True);

    setSerializerType(OpcUa_Endpoint_SerializerType_Binary);
    UaEndpointSecuritySetting securitySetting;
    if (isSecure)
    {
        securitySetting.setSecurityPolicy(OpcUa_SecurityPolicy_Basic256Sha256);
        securitySetting.addMessageSecurityMode(OPCUA_ENDPOINT_MESSAGESECURITYMODE_SIGN);
        securitySetting.addMessageSecurityMode(OPCUA_ENDPOINT_MESSAGESECURITYMODE_SIGNANDENCRYPT);
        addSecuritySetting(securitySetting);
    }
    else
    {
        securitySetting.setSecurityPolicy(OpcUa_SecurityPolicy_None);
        securitySetting.addMessageSecurityMode(OPCUA_ENDPOINT_MESSAGESECURITYMODE_NONE);
        addSecuritySetting(securitySetting);
    }
}

/** Destroys the UaEndpointBase object */
UaEndpointBase::~UaEndpointBase()
{
}

/** Set the certificate store for the endpoint.
*/
void UaEndpointBase::setCertificateStore(
    OpcUa_UInt32 endpointCertificateStoreIndex, //!< The index of the CertificateSore used for the endpoint
    CertificateStoreConfiguration* pEndpointCertificateStore) //!< The CertificateStoreConfiguration object for the endpoint
{
    if (m_pEndpointCertificateStore)
    {
        m_pEndpointCertificateStore->releaseReference();
    }
    if (m_pEndpointCertificateSettings)
    {
        m_pEndpointCertificateSettings->releaseReference();
    }

    m_endpointCertificateStoreIndex = endpointCertificateStoreIndex;
    m_pEndpointCertificateStore = pEndpointCertificateStore;
    if (m_pEndpointCertificateStore)
    {
        m_pEndpointCertificateStore->addReference();
        if (m_pEndpointCertificateStore->certificateCount() > 0)
        {
            m_pEndpointCertificateSettings = m_pEndpointCertificateStore->getCertificate(0);
            if (m_pEndpointCertificateSettings)
            {
                m_pEndpointCertificateSettings->addReference();
            }
        }
    }
}
Best regards
Unified Automation Support Team

User avatar
Support Team
Hero Member
Hero Member
Posts: 3071
Joined: 18 Mar 2011, 15:09

Re: setServerConfig(ServerConfig* pServerConfig) how to use?

Post by Support Team »

In your server implementation you need to create this class and set the configuration:

Code: Select all

    // Create and initialize server object
    OpcServer* pServer = new OpcServer;
    ServerConfigBase* pServerConfig = new ServerConfigBase(
        szAppPath,
        szAppPath,
        szAppPath,
        SERVERCONFIG_PRODUCTURI,
        SERVERCONFIG_MANUFACTURERNAME,
        SERVERCONFIG_PRODUCTNAME,
        SERVERCONFIG_SOFTWAREVERSION,
        SERVERCONFIG_BUILDNUMBER,
        "urn:[NodeName] : UnifiedAutomation : UaServerCpp",
        "UaServerCpp@[NodeName]",
        pServer,
        &serverCallback);

    // add Endpoint with SecurityPolicy None
    UaEndpointBase* pEndpoint = new UaEndpointBase("48010", false);

    // add Endpoint with SecurityPolicy Basic256
    UaEndpointSecuritySetting securitySetting;
    securitySetting.setSecurityPolicy(OpcUa_SecurityPolicy_Basic256);
    securitySetting.addMessageSecurityMode(OPCUA_ENDPOINT_MESSAGESECURITYMODE_SIGNANDENCRYPT);
    pEndpoint->addSecuritySetting(securitySetting);

    // configure rejected directory
    pServerConfig->setRejectedCertificatesDirectory(UaString("%1/pkiserver/rejected").arg(szAppPath));

    // configure available user tokens
    pServerConfig->setEnableUserPw(OpcUa_True);
    pServerConfig->setEnableCertificate(OpcUa_True);
    pServerConfig->setUserIdentityTokenSecurityPolicy(OpcUa_SecurityPolicy_Basic256);
    pServerConfig->setRejectedUserCertificatesCount(123);
    pServerConfig->setRejectedUserCertificatesDirectory(UaString("%1/pkiuser/rejected").arg(szAppPath));

    // configure certificate store for user certificates
    CertificateStoreConfiguration* pCertConfig = NULL;
    UaString sRejected;
    OpcUa_UInt32 nNumRejected = 0;
    OpcUa_Boolean bCertTokenconfigured = OpcUa_False;

    pServerConfig->getDefaultUserCertificateStore(
        &pCertConfig,
        sRejected,
        nNumRejected,
        bCertTokenconfigured);

    pCertConfig->m_sCertificateTrustListLocation = UaString("%1/pkiuser/trusted/certs").arg(szAppPath);
    pCertConfig->m_sCertificateRevocationListLocation = UaString("%1/pkiuser/trusted/crl").arg(szAppPath);
    pCertConfig->m_sIssuersCertificatesLocation = UaString("%1/pkiuser/issuers/certs").arg(szAppPath);
    pCertConfig->m_sIssuersRevocationListLocation = UaString("%1/pkiuser/issuers/crl").arg(szAppPath);

    // add Endpoint
    pServerConfig->addEndpoint(pEndpoint);
    // set ServerConfig
    pServer->setServerConfig(pServerConfig);
Best regards
Unified Automation Support Team

Post Reply