1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/**
* @file server_lds.c
* @brief Local Discovery Server implementation.
*
* This program runs an OPC UA Local Discovery Server (LDS) with a configurable
* cleanup timeout. Encryption is optional: when certificate, privateKey, and
* trustStore are provided, the server offers all security policies; otherwise
* it runs with SecurityPolicy#None only. Other OPC UA servers register
* with this LDS using the RegisterServer2 service. Clients can query this LDS
* using the FindServers service to discover registered servers.
*/
#include "common.h"
#include "config.h"
#include <open62541/plugin/log_stdout.h>
#include <open62541/server.h>
#include <signal.h>
#include <stdlib.h>
volatile UA_Boolean g_running = true;
static void
_s_stop_handler (int sig)
{
g_running = false;
}
int
main (int argc, char *argv[])
{
signal (SIGINT, _s_stop_handler);
signal (SIGTERM, _s_stop_handler);
if (argc < 2 || argc > 3)
{
UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Usage: %s <config-file> [log-level]", argv[0]);
return EXIT_FAILURE;
}
const char *log_level_str = (argc == 3) ? argv[2] : "info";
int log_level = parse_log_level (log_level_str);
if (log_level < 0)
{
UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Unknown log level: %s "
"(expected trace, debug, info, warning, error, fatal)",
log_level_str);
return EXIT_FAILURE;
}
config cfg;
if (config_load (argv[1], &cfg) != 0)
return EXIT_FAILURE;
int port = config_require_int (&cfg, "port", "ServerLDS");
const char *application_uri
= config_require (&cfg, "applicationUri", "ServerLDS");
int cleanup_timeout
= config_require_int (&cfg, "cleanupTimeout", "ServerLDS");
if (!application_uri || port < 0 || cleanup_timeout < 0)
{
config_free (&cfg);
return EXIT_FAILURE;
}
/* The OPC UA specification requires the cleanup timeout to exceed the
register-server interval. open62541 enforces a floor of 10 seconds. */
if (cleanup_timeout <= 10)
{
UA_LOG_FATAL (UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Cleanup timeout must be > 10 seconds (got %d)",
cleanup_timeout);
config_free (&cfg);
return EXIT_FAILURE;
}
security_config sec;
if (parse_security_config (&cfg, "ServerLDS", false, &sec) != 0)
{
config_free (&cfg);
return EXIT_FAILURE;
}
auth_config auth;
if (parse_auth_config (&cfg, "ServerLDS", &auth) != 0)
{
free_trust_store (sec.trust_paths, sec.trust_size);
config_free (&cfg);
return EXIT_FAILURE;
}
UA_StatusCode retval;
UA_Server *server
= create_server ((UA_UInt16)port, application_uri,
sec.cert_path ? &sec : NULL, true, &retval);
if (!server)
{
free_trust_store (sec.trust_paths, sec.trust_size);
config_free (&cfg);
return EXIT_FAILURE;
}
UA_ServerConfig *server_config = UA_Server_getConfig (server);
server_config->logging->context = (void *)(uintptr_t)log_level;
/* Some OPC UA stacks omit the timestamp in the request header. The
default behaviour rejects these requests with BadInvalidTimestamp.
Downgrade to a warning so third-party servers can still register. */
server_config->verifyRequestTimestamp = UA_RULEHANDLING_WARN;
retval = configure_access_control (server_config, &auth);
if (retval != UA_STATUSCODE_GOOD)
{
UA_Server_delete (server);
free_trust_store (sec.trust_paths, sec.trust_size);
config_free (&cfg);
return EXIT_FAILURE;
}
/* Mark this server as a Discovery Server so clients can identify it. */
server_config->applicationDescription.applicationType
= UA_APPLICATIONTYPE_DISCOVERYSERVER;
/* Time (seconds) after which stale registrations are removed. Must
exceed the registering server's re-register interval. */
server_config->discoveryCleanupTimeout = cleanup_timeout;
retval = UA_Server_run (server, &g_running);
UA_Server_delete (server);
free_trust_store (sec.trust_paths, sec.trust_size);
config_free (&cfg);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
|