High Performance OPC UA Server SDK  1.3.1.248
provider_minimal.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/ *
* *
*****************************************************************************/
#include <platform/memory.h>
#include <uaserver/addressspace/addressspace.h>
#include <uaserver/addressspace/management.h>
#include <uaserver/provider/provider.h>
#include <trace/trace.h>
#include <timer/timer.h>
#include <uabase/accesslevel.h>
#include <uabase/valuerank.h>
#include <uabase/qualifiedname.h>
#include <uabase/identifiers.h>
#include <uabase/structure/nodeclass.h>
#include <uaserver/addressspace/variable.h>
#include <uaserver/addressspace/object.h>
#include <uaserver/valuestore/memorystore.h>
#include <uaserver/valuestore/valuestore.h>
#if UA_AUTHENTICATION_BACKEND == UA_AUTHENTICATION_BACKEND_INTERNAL
#include <uaserver/session/authentication/internal/internal_authentication.h>
#endif
#include "provider_minimal.h"
static struct ua_variant g_values[2];
static struct ua_memorystore g_store;
static uint32_t g_timer_id;
#ifdef HAVE_TRACE
static unsigned int g_session_cnt = 0;
static unsigned int g_session_max = 0;
static unsigned int g_securechannel_cnt = 0;
static unsigned int g_securechannel_max = 0;
#endif /* HAVE_TRACE */
static int provider_minimal_sample_data(uint64_t elapsed, void *data)
{
static uint32_t var1 = 1000;
static uint32_t var2 = 5000;
UA_UNUSED(elapsed);
UA_UNUSED(data);
/* simulation */
var1++;
var2 += 2;
/* fill cache */
ua_variant_set_uint32(&g_values[0], var1);
ua_variant_set_uint32(&g_values[1], var2);
return 0;
}
static void provider_minimal_cleanup(struct uaprovider *ctx)
{
UA_UNUSED(ctx);
timer_remove(NULL, g_timer_id, NULL);
TRACE_INFO(TRACE_FAC_PROVIDER, "max_securechannel_cnt = %u\n", g_securechannel_max);
TRACE_INFO(TRACE_FAC_PROVIDER, "max_session_cnt = %u\n", g_session_max);
}
static int provider_minimal_create_nodes(uint16_t nsidx)
{
int ret;
ua_node_t node, folder;
struct ua_nodeid id;
struct ua_nodeid datatypeid;
struct ua_variant v;
ua_nodeid_set_numeric(&datatypeid, 0, UA_ID_UINT32);
/* Create folder for variables */
ua_nodeid_set_numeric(&id, nsidx, 1001);
folder = ua_object_create_folder(&id, UA_NODE_OBJECTSFOLDER, "Variables");
if (folder == UA_NODE_INVALID) return -1;
/* Variable1 */
ua_nodeid_set_numeric(&id, nsidx, 1002);
node = ua_node_create_with_attributes(&id, UA_NODECLASS_VARIABLE, id.nsindex, "Variable1", NULL, UA_NODE_INVALID, folder, UA_NODE_ORGANIZES);
if (node == UA_NODE_INVALID) return -1;
if (ret != 0) return ret;
/* set value */
ret = ua_memorystore_attach_new_value(&g_store, &v, node);
if (ret != 0) return ret;
/* Variable2 */
ua_nodeid_set_numeric(&id, nsidx, 1003);
node = ua_node_create_with_attributes(&id, UA_NODECLASS_VARIABLE, id.nsindex, "Variable2", NULL, UA_NODE_INVALID, folder, UA_NODE_ORGANIZES);
if (node == UA_NODE_INVALID) return -1;
if (ret != 0) return ret;
/* set value */
ua_variant_set_uint32(&v, 298463);
ret = ua_memorystore_attach_new_value(&g_store, &v, node);
if (ret != 0) return ret;
return 0;
}
static int provider_minimal_users(void)
{
int ret = 0;
#if UA_AUTHORIZATION_BACKEND == UA_AUTHORIZATION_BACKEND_INODE
ret = ua_inode_add_user("anonymous", 0);
if (ret != 0) return ret;
ret = ua_inode_add_user("root", 1);
if (ret != 0) return ret;
ret = ua_inode_add_user("joe", 2);
if (ret != 0) return ret;
ret = ua_inode_add_user("john", 3);
if (ret != 0) return ret;
ret = ua_inode_add_user("sue", 4);
if (ret != 0) return ret;
#endif
#if UA_AUTHENTICATION_BACKEND == UA_AUTHENTICATION_BACKEND_INTERNAL
/* add passwords for the users ("anonymous" has no password) */
ret = ua_authentication_add_user(UA_AUTH_HASH_NONE, "root", NULL, "secret");
if (ret != 0) return ret;
ret = ua_authentication_add_user(UA_AUTH_HASH_NONE, "joe", NULL, "god");
if (ret != 0) return ret;
ret = ua_authentication_add_user(UA_AUTH_HASH_NONE, "john", NULL, "master");
if (ret != 0) return ret;
ret = ua_authentication_add_user(UA_AUTH_HASH_NONE, "sue", NULL, "curly");
if (ret != 0) return ret;
#endif
return ret;
}
/* Demo hook for monitoring session events. */
static void provider_minimal_session_hook(enum uasession_event_type type, uint32_t channel_id, struct uasession_session *session)
{
#ifdef HAVE_TRACE
switch (type) {
case UASESSION_EVENT_OPENSECURECHANNEL:
TRACE_INFO(TRACE_FAC_PROVIDER, "Secure channel with channel_id=%u was created.\n", channel_id);
g_securechannel_cnt++;
if (g_securechannel_cnt > g_securechannel_max) g_securechannel_max = g_securechannel_cnt;
break;
case UASESSION_EVENT_RENEWSECURECHANNEL:
if (session)
TRACE_INFO(TRACE_FAC_PROVIDER, "Secure channel with channel_id=%u was renewed, session_id=%u.\n", channel_id, session->session_id);
else
TRACE_INFO(TRACE_FAC_PROVIDER, "Secure channel with channel_id=%u was renewed. No associated session.\n", channel_id);
break;
case UASESSION_EVENT_CLOSESECURECHANNEL:
g_securechannel_cnt--;
if (session)
TRACE_INFO(TRACE_FAC_PROVIDER, "Secure channel with channel_id=%u was closed, session_id=%u.\n", channel_id, session->session_id);
else
TRACE_INFO(TRACE_FAC_PROVIDER, "Secure channel with channel_id=%u was closed. No associated session.\n", channel_id);
break;
case UASESSION_EVENT_CONNECTIONLOST:
if (session)
TRACE_INFO(TRACE_FAC_PROVIDER, "TCP connection lost for channel_id=%u, session_id=%u.\n", channel_id, session->session_id);
else
TRACE_INFO(TRACE_FAC_PROVIDER, "TCP connection lost for channel_id=%u. No associated session.\n", channel_id);
break;
case UASESSION_EVENT_CREATESESSION:
TRACE_INFO(TRACE_FAC_PROVIDER, "A session with session_id=%u was created on channel with chanel_id=%u.\n", session->session_id, channel_id);
g_session_cnt++;
if (g_session_cnt > g_session_max) g_session_max = g_session_cnt;
break;
case UASESSION_EVENT_ACTIVATESESSION:
TRACE_INFO(TRACE_FAC_PROVIDER, "A session with session_id=%u was activated on channel with chanel_id=%u.\n", session->session_id, channel_id);
break;
case UASESSION_EVENT_CLOSESESSION:
TRACE_INFO(TRACE_FAC_PROVIDER, "A session with session_id=%u was closed on channel with chanel_id=%u.\n", session->session_id, channel_id);
g_session_cnt--;
break;
}
#else
UA_UNUSED(type);
UA_UNUSED(channel_id);
UA_UNUSED(session);
#endif /* HAVE_TRACE */
}
int provider_minimal_init(struct uaprovider *ctx)
{
uint16_t uaprovider_minimal_nsidx;
struct ua_addressspace_config config;
int ret;
ua_memset(&config, 0, sizeof(config));
config.max_variables = 3;
config.max_references = 5;
config.max_strings = 3;
config.nsidx = UA_NSIDX_INVALID; /* auto assign */
"http://www.unifiedautomation.com/MinimalServer/",
&config,
if (ret < 0) return ret;
uaprovider_minimal_nsidx = (uint16_t) ret;
ret = uaprovider_register_nsindex(ctx, uaprovider_minimal_nsidx);
if (ret < 0) return ret;
/* register the in-memory store */
ret = ua_memorystore_init(&g_store, 0, g_values, countof(g_values));
if (ret != 0) return ret;
/* create nodes */
ret = provider_minimal_create_nodes(uaprovider_minimal_nsidx);
if (ret < 0) return ret;
ret = provider_minimal_users();
if (ret < 0) return ret;
/* print statistics */
TRACE_DEBUG(TRACE_FAC_SESSION, "Statistics for namespace %i (http://www.unifiedautomation.com/DemoServer/):\n", uaprovider_minimal_nsidx);
ua_addressspace_print_stat(uaprovider_minimal_nsidx);
}
ctx->cleanup = provider_minimal_cleanup;
ctx->session_event = provider_minimal_session_hook;
/* add a timer to for sampling the data */
ret = timer_add(NULL,
&g_timer_id,
100, /* ms */
provider_minimal_sample_data,
NULL, /* user data */
if (ret != 0) {
TRACE_ERROR(TRACE_FAC_APPLICATION, "%s: Creating the sampling timer failed.\n", __func__);
}
return ret;
}