ANSI C Based OPC UA Client/Server SDK  1.9.0.430
servermain.c
/*****************************************************************************
* *
* Copyright (c) 2006-2019 Unified Automation GmbH. All rights reserved. *
* *
* Software License Agreement ("SLA") Version 2.7 *
* *
* Unless explicitly acquired and licensed from Licensor under another *
* license, the contents of this file are subject to the Software License *
* Agreement ("SLA") Version 2.7, or subsequent versions as allowed by the *
* SLA, and You may not copy or use this file in either source code or *
* executable form, except in compliance with the terms and conditions of *
* the SLA. *
* *
* All software distributed under the SLA is provided strictly on an "AS *
* IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, *
* AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT *
* LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR *
* PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the SLA for specific *
* language governing rights and limitations under the SLA. *
* *
* The complete license agreement can be found here: *
* http://unifiedautomation.com/License/SLA/2.7/ *
* *
* Project: Unified Automation ANSI C based OPC UA Server SDK *
* *
*****************************************************************************/
/*============================================================================
* Includes
*===========================================================================*/
#include <uaserver_config.h>
#include <stdlib.h>
#if defined(_WIN32) || defined(_WIN32_WCE)
# include <winsock2.h>
#else
# include <unistd.h>
# include <netdb.h>
# ifdef VXWORKS
# include <hostLib.h>
# endif /* VXWORKS */
#endif
#include <uaserver_module.h>
#include <uaserver_utilities.h>
#include "custom_provider.h"
/*============================================================================
* Application Defines
*===========================================================================*/
/* Server/application URLs, URIs and names */
#define UASERVER_PORT 48020
#define UASERVER_APPLICATIONNAME "UaSdkC - Lesson05"
#define UASERVER_APPLICATIONURI "UnifiedAutomation:UaSdkC:Lesson05"
#define UASERVER_PRODUCTNAME "UaSdkC - Lesson05"
#define UASERVER_PRODUCTURI "urn:UnifiedAutomation:UaSdkC:Lesson05"
#define UASERVER_MANUFACTURERNAME "Unified Automation GmbH"
/*============================================================================
* Main helper functions
*===========================================================================*/
/* Initializes OPC UA Stack.
* Here you can configure trace settings and other stack configuration options.
*/
OpcUa_StatusCode InitializeOpcUaStack(OpcUa_Handle *a_phProxyStubPlatformLayer,
OpcUa_ProxyStubConfiguration *a_pProxyStubConfiguration)
{
OpcUa_InitializeStatus(OpcUa_Module_Server, "InitializeOpcUaStack");
/* Initialize Stack */
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Server: Initializing Stack...\n");
/* Default values can be changed here */
a_pProxyStubConfiguration->bProxyStub_Trace_Enabled = OpcUa_True;
a_pProxyStubConfiguration->uProxyStub_Trace_Level = OPCUA_TRACE_OUTPUT_LEVEL_WARNING;
uStatus = UaBase_Module_InitializeUaStack(a_phProxyStubPlatformLayer, a_pProxyStubConfiguration);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/* Cleanup counterpart to InitializeOpcUaStack. */
OpcUa_StatusCode CleanupOpcUaStack(OpcUa_Handle *a_phProxyStubPlatformLayer)
{
OpcUa_InitializeStatus(OpcUa_Module_Server, "CleanupOpcUaStack");
/* Clean Up UA Stack */
uStatus = UaBase_Module_ClearUaStack(a_phProxyStubPlatformLayer);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
int GetFQHostname( char *szHostname, int len )
{
struct hostent *pEnt = 0;
int ret = gethostname( szHostname, len );
if ( ret != 0 ) return ret;
pEnt = gethostbyname( szHostname );
if ( pEnt == 0 ) return -1;
OpcUa_StrlCpyA( szHostname, pEnt->h_name, len );
szHostname[len - 1] = 0;
return 0;
}
/* Main OPC UA Server Loop. */
OpcUa_StatusCode ServerMain()
{
UaServer uaServer;
OpcUa_CharA szHostname[256];
OpcUa_CharA szEndpointURL[300];
OpcUa_CharA szApplicationUri[300];
UaServer_Endpoint *pEndpoint = OpcUa_Null;
UaServer_Provider customProvider;
UaServer_Configuration *pServerConfig = OpcUa_Null;
OpcUa_InitializeStatus(OpcUa_Module_Server, "ServerMain");
OpcUa_MemSet(szEndpointURL, 0, sizeof(szEndpointURL));
OpcUa_MemSet(szApplicationUri, 0, sizeof(szApplicationUri));
/* Create EndpointURL and ApplicationURI strings */
GetFQHostname(szHostname, sizeof(szHostname));
OpcUa_SnPrintfA(szEndpointURL, sizeof(szEndpointURL)-1, "opc.tcp://%s:%u", szHostname, UASERVER_PORT);
OpcUa_SnPrintfA(szApplicationUri, sizeof(szApplicationUri)-1, "urn:%s:%s", szHostname, UASERVER_APPLICATIONURI);
/* Initialize Server */
uStatus = UaServer_Initialize(&uaServer);
OpcUa_GotoErrorIfBad(uStatus);
/* Get configuration structure of the server */
pServerConfig = UaServer_GetConfiguration(&uaServer);
/* Configure ApplicationDescription of the server */
OpcUa_String_AttachCopy(&pServerConfig->ApplicationDescription.ApplicationUri, szApplicationUri);
OpcUa_String_AttachReadOnly(&pServerConfig->ApplicationDescription.ProductUri, UASERVER_PRODUCTURI);
OpcUa_String_AttachReadOnly(&pServerConfig->ApplicationDescription.ApplicationName.Text, UASERVER_APPLICATIONNAME);
pServerConfig->ApplicationDescription.DiscoveryUrls = OpcUa_Alloc(sizeof(OpcUa_String));
OpcUa_GotoErrorIfAllocFailed(pServerConfig->ApplicationDescription.DiscoveryUrls);
pServerConfig->ApplicationDescription.NoOfDiscoveryUrls = 1;
OpcUa_String_Initialize(&pServerConfig->ApplicationDescription.DiscoveryUrls[0]);
OpcUa_String_AttachCopy(&pServerConfig->ApplicationDescription.DiscoveryUrls[0], szEndpointURL);
/* Configure BuildInfo of the server */
OpcUa_String_AttachReadOnly(&pServerConfig->BuildInfo.ManufacturerName, UASERVER_MANUFACTURERNAME);
OpcUa_String_AttachReadOnly(&pServerConfig->BuildInfo.ProductName, UASERVER_PRODUCTNAME);
OpcUa_String_AttachReadOnly(&pServerConfig->BuildInfo.SoftwareVersion, UASDK_VERSION);
OpcUa_String_AttachReadOnly(&pServerConfig->BuildInfo.BuildNumber, UASDK_BUILD_VERSION_STR);
OpcUa_String_AttachReadOnly(&pServerConfig->BuildInfo.ProductUri, UASERVER_APPLICATIONURI);
pServerConfig->BuildInfo.BuildDate = UaServer_GetBuildDate();
/* Create one endpoint */
pServerConfig->pEndpoints = OpcUa_Alloc(sizeof(UaServer_Endpoint));
OpcUa_GotoErrorIfAllocFailed(pServerConfig->pEndpoints);
pServerConfig->uNoOfEndpoints = 1;
UaServer_Endpoint_Initialize(&pServerConfig->pEndpoints[0]);
pEndpoint = &pServerConfig->pEndpoints[0];
/* Set the endpoint URL */
OpcUa_String_AttachCopy(&pEndpoint->sEndpointUrl, szEndpointURL);
/* This example does not use security, disable PKI */
OpcUa_String_AttachReadOnly(&pEndpoint->PkiConfigName, "PkiStoreNone");
pEndpoint->PkiConfig.strPkiType = (char*)OPCUA_PKI_TYPE_NONE;
/* Set the endpoint configuration to use no security */
pEndpoint->pSecurityPolicyConfigurations = OpcUa_Alloc(sizeof(OpcUa_Endpoint_SecurityPolicyConfiguration));
OpcUa_GotoErrorIfAllocFailed(pEndpoint->pSecurityPolicyConfigurations);
OpcUa_MemSet(pEndpoint->pSecurityPolicyConfigurations, 0, sizeof(OpcUa_Endpoint_SecurityPolicyConfiguration));
OpcUa_String_AttachReadOnly(&pEndpoint->pSecurityPolicyConfigurations[0].sSecurityPolicy, OpcUa_SecurityPolicy_None);
pEndpoint->pSecurityPolicyConfigurations[0].uMessageSecurityModes = OPCUA_ENDPOINT_MESSAGESECURITYMODE_NONE;
/* Set the endpoint configuration to use anonymous logon */
pEndpoint->pUserTokenPolicy = OpcUa_Alloc(sizeof(OpcUa_UserTokenPolicy));
OpcUa_GotoErrorIfAllocFailed(pEndpoint->pUserTokenPolicy);
pEndpoint->uNoOfUserTokenPolicy = 1;
OpcUa_UserTokenPolicy_Initialize(&pEndpoint->pUserTokenPolicy[0]);
OpcUa_String_AttachReadOnly(&pEndpoint->pUserTokenPolicy[0].PolicyId, "Anonymous");
/* Initialize the provider list, the server provider is added automatically */
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Server: Building Provider List...\n");
uStatus = UaServer_ProviderList_Create(&uaServer);
OpcUa_GotoErrorIfBad(uStatus);
/* Add custom provider */
OpcUa_MemSet(&customProvider, 0, sizeof(customProvider));
customProvider.pfInit = CustomProvider_Initialize;
uStatus = UaServer_ProviderList_AddProvider(&uaServer, &customProvider);
OpcUa_GotoErrorIfBad(uStatus);
/* Load providers */
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Server: Loading Provider Modules...\n");
uStatus = UaServer_Providers_Initialize(&uaServer);
OpcUa_GotoErrorIfBad(uStatus);
/* Start up server */
uStatus = UaServer_StartUp(&uaServer);
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "#############################################\n");
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "# Server started! Press %s to stop!\n", UABASE_P_SHUTDOWN_SEQUENCE);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "#############################################\n");
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Endpoint URL: %s\n", szEndpointURL);
/* Initialize the check for shutdown keystrokes. On Linux, default signal handlers
are added in UaBase_P_RegisterShutdownHandler. */
/******************************************************************************/
/* Serve! */
while (OpcUa_IsGood(uStatus))
{
uStatus = UaBase_DoCom();
}
/******************************************************************************/
/* Clean up the check for shutdown keystrokes */
/* UaServer_Clear clears the PkiConfig of the endpoint and attempts to free the strings
set there. As we have set literal string constants, we don't want those to be freed, so
we set them to NULL by initializing the structure. */
OpcUa_CertificateStoreConfiguration_Initialize(&pEndpoint->PkiConfig);
/* Clean up server */
UaServer_Clear(&uaServer);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Server: Main stopped successfully.\n");
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
/* Clean up the check for shutdown keystrokes */
/* UaServer_Clear clears the PkiConfig of the endpoint and attempts to free the strings
set there. As we have set literal string constants, we don't want those to be freed, so
we set them to NULL by initializing the structure. */
if (pEndpoint != OpcUa_Null)
{
OpcUa_CertificateStoreConfiguration_Initialize(&pEndpoint->PkiConfig);
}
/* Clean up server */
UaServer_Clear(&uaServer);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Server: Main stopped due to error 0x%08X\n", uStatus);
OpcUa_FinishErrorHandling;
}
/*============================================================================
* Main entry point for the application
*===========================================================================*/
int main(int argc, char *argv[])
{
int ret = EXIT_SUCCESS;
OpcUa_StatusCode uStatus = OpcUa_Good;
OpcUa_Handle hProxyStubPlatformLayer = OpcUa_Null;
OpcUa_ProxyStubConfiguration proxyStubConfiguration;
/* The main method parameters are unused */
OpcUa_ReferenceParameter(argc);
OpcUa_ReferenceParameter(argv);
/* Set up OPC UA */
uStatus = InitializeOpcUaStack(&hProxyStubPlatformLayer, &proxyStubConfiguration);
if ( OpcUa_IsNotGood(uStatus) )
{
return EXIT_FAILURE;
}
/* Start the main server loop */
uStatus = ServerMain();
if ( OpcUa_IsNotGood(uStatus) )
{
ret = EXIT_FAILURE;
}
/* Clean up OPC UA */
uStatus = CleanupOpcUaStack(&hProxyStubPlatformLayer);
if ( OpcUa_IsNotGood(uStatus) )
{
ret = EXIT_FAILURE;
}
return ret;
}
#ifdef _WIN32_WCE
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nShowCmd)
{
OpcUa_ReferenceParameter(hInstance);
OpcUa_ReferenceParameter(hPrevInstance);
OpcUa_ReferenceParameter(lpCmdLine);
OpcUa_ReferenceParameter(nShowCmd);
return main(0, OpcUa_Null);
}
#endif