Skip to content

Commit f533339

Browse files
committed
MINIFICPP-2745 Upgrade OPC UA library to v1.5.2
1 parent b1137d2 commit f533339

9 files changed

Lines changed: 100 additions & 46 deletions

File tree

cmake/BundledOpen62541.cmake

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function(use_bundled_open62541 SOURCE_DIR BINARY_DIR)
3434

3535
set(OPEN62541_CMAKE_ARGS ${PASSTHROUGH_CMAKE_ARGS}
3636
"-DCMAKE_INSTALL_PREFIX=${OPEN62541_BYPRODUCT_DIR}"
37-
-DOPEN62541_VERSION=v1.3.3
37+
-DOPEN62541_VERSION=v1.5.2
3838
-DUA_ENABLE_ENCRYPTION=ON
3939
-DUA_FORCE_WERROR=OFF
4040
-DUA_ENABLE_DEBUG_SANITIZER=OFF)
@@ -44,8 +44,8 @@ function(use_bundled_open62541 SOURCE_DIR BINARY_DIR)
4444
# Build project
4545
ExternalProject_Add(
4646
open62541-external
47-
URL "https://github.com/open62541/open62541/archive/refs/tags/v1.4.10.tar.gz"
48-
URL_HASH "SHA256=1a2e762e50bb6dae8d80029dfb66fdbc432876a004e62d618f7cf1bb5b4f495f"
47+
URL "https://github.com/open62541/open62541/archive/refs/tags/v1.5.2.tar.gz"
48+
URL_HASH "SHA256=61110a51c4f00a70a6e47882ea92550b667eede62e66c64431fdc37ff660361c"
4949
SOURCE_DIR "${BINARY_DIR}/thirdparty/open62541-src"
5050
PATCH_COMMAND ${PC}
5151
LIST_SEPARATOR % # This is needed for passing semicolon-separated lists

extensions/opc/src/opc.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "open62541/client_highlevel.h"
3434
#include "open62541/client_config_default.h"
3535

36+
extern "C" int mp_vsnprintf(char* s, size_t count, const char* format, va_list arg);
37+
3638
namespace org::apache::nifi::minifi::opc {
3739

3840
/*
@@ -586,7 +588,7 @@ std::string OPCDateTime2String(UA_DateTime raw_date) {
586588

587589
void logFunc(void *context, UA_LogLevel level, UA_LogCategory /*category*/, const char *msg, va_list args) {
588590
std::array<char, 1024> buffer{};
589-
(void)vsnprintf(buffer.data(), buffer.size(), msg, args);
591+
(void)mp_vsnprintf(buffer.data(), buffer.size(), msg, args);
590592
auto loggerPtr = reinterpret_cast<core::logging::Logger*>(context);
591593
loggerPtr->log_string(MapOPCLogLevel(level), buffer.data());
592594
}

extensions/opc/tests/OpcUaTestServer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "unit/TestUtils.h"
2525
#include "unit/Catch.h"
2626

27+
extern "C" int mp_vsnprintf(char* s, size_t count, const char* format, va_list arg);
28+
2729
using namespace std::literals::chrono_literals;
2830

2931
namespace org::apache::nifi::minifi::test {
@@ -37,7 +39,7 @@ class OpcUaTestServer {
3739
UA_ServerConfig_setMinimal(config, port, nullptr);
3840
config->logging->log = [] (void *log_context, UA_LogLevel level, UA_LogCategory /*category*/, const char *msg, va_list args) {
3941
char buffer[1024];
40-
vsnprintf(buffer, sizeof(buffer), msg, args);
42+
mp_vsnprintf(buffer, sizeof(buffer), msg, args);
4143

4244
std::string level_str;
4345
switch (level) {

extensions/opc/tests/features/opcua.feature

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,8 @@ Feature: Putting and fetching data to OPC UA server
115115
And a PutFile processor with the "Directory" property set to "/tmp/output" in the "fetch-opc-ua-node" flow
116116
And PutFile's success relationship is auto-terminated in the "fetch-opc-ua-node" flow
117117
And PutFile is EVENT_DRIVEN in the "fetch-opc-ua-node" flow
118-
And a host resource file "opcua_client_cert.der" is bound to the "/tmp/resources/opcua/opcua_client_cert.der" path in the MiNiFi container "create-opc-ua-node"
119-
And a host resource file "opcua_client_key.der" is bound to the "/tmp/resources/opcua/opcua_client_key.der" path in the MiNiFi container "create-opc-ua-node"
120-
And a host resource file "opcua_client_cert.der" is bound to the "/tmp/resources/opcua/opcua_client_cert.der" path in the MiNiFi container "fetch-opc-ua-node"
121-
And a host resource file "opcua_client_key.der" is bound to the "/tmp/resources/opcua/opcua_client_key.der" path in the MiNiFi container "fetch-opc-ua-node"
118+
And the OPC UA server certificate files are placed in the "/tmp/resources/opcua/" directory in the MiNiFi container "create-opc-ua-node"
119+
And the OPC UA server certificate files are placed in the "/tmp/resources/opcua/" directory in the MiNiFi container "fetch-opc-ua-node"
122120
And these processor properties are set in the "create-opc-ua-node" flow
123121
| processor name | property name | property value |
124122
| PutOPCProcessor | Parent node ID | 85 |
@@ -132,7 +130,7 @@ Feature: Putting and fetching data to OPC UA server
132130
| PutOPCProcessor | Certificate path | /tmp/resources/opcua/opcua_client_cert.der |
133131
| PutOPCProcessor | Key path | /tmp/resources/opcua/opcua_client_key.der |
134132
| PutOPCProcessor | Trusted server certificate path | /tmp/resources/opcua/opcua_client_cert.der |
135-
| PutOPCProcessor | Application URI | urn:open62541.server.application |
133+
| PutOPCProcessor | Application URI | urn:open62541.unconfigured.application |
136134
And these processor properties are set in the "fetch-opc-ua-node" flow
137135
| processor name | property name | property value |
138136
| FetchOPCProcessor | Node ID | 9999 |
@@ -143,7 +141,7 @@ Feature: Putting and fetching data to OPC UA server
143141
| FetchOPCProcessor | Certificate path | /tmp/resources/opcua/opcua_client_cert.der |
144142
| FetchOPCProcessor | Key path | /tmp/resources/opcua/opcua_client_key.der |
145143
| FetchOPCProcessor | Trusted server certificate path | /tmp/resources/opcua/opcua_client_cert.der |
146-
| FetchOPCProcessor | Application URI | urn:open62541.server.application |
144+
| FetchOPCProcessor | Application URI | urn:open62541.unconfigured.application |
147145

148146
And in the "create-opc-ua-node" flow the "success" relationship of the GetFile processor is connected to the PutOPCProcessor
149147
And in the "fetch-opc-ua-node" flow the "success" relationship of the FetchOPCProcessor processor is connected to the PutFile
@@ -153,7 +151,7 @@ Feature: Putting and fetching data to OPC UA server
153151
When all instances start up
154152

155153
Then in the "fetch-opc-ua-node" container at least one file with the content "Test" is placed in the "/tmp/output" directory in less than 60 seconds
156-
And the OPC UA server logs contain the following message: "SecureChannel opened with SecurityPolicy http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep" in less than 5 seconds
154+
And the OPC UA server logs contain the following message: "Channel opened with SecurityMode SignAndEncrypt for SecurityPolicy http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss" in less than 5 seconds
157155

158156
Scenario: Create and fetch data from an OPC UA node through username and password authenticated connection
159157
Given a GetFile processor with the "Input Directory" property set to "/tmp/input" in the "create-opc-ua-node" flow
-1.02 KB
Binary file not shown.
-1.16 KB
Binary file not shown.

extensions/opc/tests/features/steps/opc_ua_server_container.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020

2121

2222
class OPCUAServerContainer(Container):
23+
OPC_SERVER_IMAGE = "lordgamez/open62541:1.5.2"
24+
2325
def __init__(self, test_context: MinifiTestContext, command: Optional[List[str]] = None):
24-
super().__init__("lordgamez/open62541:1.4.10", f"opcua-server-{test_context.scenario_id}", test_context.network, command=command)
26+
super().__init__(self.OPC_SERVER_IMAGE, f"opcua-server-{test_context.scenario_id}", test_context.network, command=command)
2527

2628
def deploy(self):
2729
super().deploy()

extensions/opc/tests/features/steps/steps.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
import logging
17+
import os
18+
import tempfile
19+
import docker
20+
import io
21+
import tarfile
1622
import humanfriendly
17-
from behave import step, then
1823

24+
from behave import given, step, then
1925
from minifi_test_framework.steps import checking_steps # noqa: F401
2026
from minifi_test_framework.steps import configuration_steps # noqa: F401
2127
from minifi_test_framework.steps import core_steps # noqa: F401
@@ -45,3 +51,36 @@ def step_impl(context, log_message, duration):
4551
timeout_seconds=timeout_seconds,
4652
bail_condition=lambda: opcua_container.exited,
4753
context=context)
54+
55+
56+
def _copy_file_from_docker_image(image_name: str, file_path: str, output_path: str):
57+
docker_client: docker.DockerClient = docker.from_env()
58+
container = docker_client.containers.create(image_name)
59+
60+
try:
61+
bits, _ = container.get_archive(file_path)
62+
tar_stream = io.BytesIO(b"".join(bits))
63+
with tarfile.open(fileobj=tar_stream) as tar:
64+
member = tar.getmembers()[0]
65+
file_content = tar.extractfile(member).read()
66+
67+
with open(output_path, "wb") as f:
68+
f.write(file_content)
69+
70+
return True
71+
except Exception as e:
72+
logging.error(f"Error copying file {file_path} from Docker image {image_name}: {e}")
73+
return False
74+
finally:
75+
container.remove(force=True)
76+
77+
78+
@given('the OPC UA server certificate files are placed in the "{directory}" directory in the MiNiFi container "{container_name}"')
79+
def step_impl(context: MinifiTestContext, directory: str, container_name: str):
80+
if not hasattr(context, "opcua_cert_temp_dir"):
81+
context.opcua_cert_temp_dir = tempfile.TemporaryDirectory()
82+
_copy_file_from_docker_image(OPCUAServerContainer.OPC_SERVER_IMAGE, "/opt/open62541/pki/created/server_cert.der", os.path.join(context.opcua_cert_temp_dir.name, "server_cert.der"))
83+
_copy_file_from_docker_image(OPCUAServerContainer.OPC_SERVER_IMAGE, "/opt/open62541/pki/created/server_key.der", os.path.join(context.opcua_cert_temp_dir.name, "server_key.der"))
84+
85+
context.get_or_create_minifi_container(container_name).add_host_file(os.path.join(context.opcua_cert_temp_dir.name, "server_cert.der"), os.path.join(directory, "opcua_client_cert.der"))
86+
context.get_or_create_minifi_container(container_name).add_host_file(os.path.join(context.opcua_cert_temp_dir.name, "server_key.der"), os.path.join(directory, "opcua_client_key.der"))
Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,53 @@
11
diff --git a/CMakeLists.txt b/CMakeLists.txt
2-
index d0e9d75e2..bbf1b4c9a 100644
2+
index e9baae1ec..954909854 100644
33
--- a/CMakeLists.txt
44
+++ b/CMakeLists.txt
5-
@@ -11,7 +11,7 @@ endif()
5+
@@ -18,7 +18,7 @@ endif()
66

7-
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER_CASE)
7+
# set(CMAKE_VERBOSE_MAKEFILE ON)
88

99
-set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/tools/cmake")
1010
+list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/tools/cmake")
11-
if(${CMAKE_VERSION} VERSION_LESS 3.12)
12-
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/tools/cmake3.12")
13-
endif()
14-
@@ -642,17 +642,17 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
1511

16-
# IPO requires too much memory for unit tests
17-
# GCC docu recommends to compile all files with the same options, therefore ignore it completely
18-
- if(NOT UA_BUILD_UNIT_TESTS AND NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
19-
- # needed to check if IPO is supported (check needs cmake > 3.9)
20-
- if("${CMAKE_VERSION}" VERSION_GREATER 3.9)
21-
- cmake_policy(SET CMP0069 NEW) # needed as long as required cmake < 3.9
22-
- include(CheckIPOSupported)
23-
- check_ipo_supported(RESULT CC_HAS_IPO) # Inter Procedural Optimization / Link Time Optimization (should be same as -flto)
24-
- if(CC_HAS_IPO)
25-
- set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
26-
- endif()
27-
- endif()
28-
- endif()
29-
+ # if(NOT UA_BUILD_UNIT_TESTS AND NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
30-
+ # # needed to check if IPO is supported (check needs cmake > 3.9)
31-
+ # if("${CMAKE_VERSION}" VERSION_GREATER 3.9)
32-
+ # cmake_policy(SET CMP0069 NEW) # needed as long as required cmake < 3.9
33-
+ # include(CheckIPOSupported)
34-
+ # check_ipo_supported(RESULT CC_HAS_IPO) # Inter Procedural Optimization / Link Time Optimization (should be same as -flto)
35-
+ # if(CC_HAS_IPO)
36-
+ # set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
37-
+ # endif()
38-
+ # endif()
39-
+ # endif()
12+
find_package(Python3 REQUIRED)
13+
find_package(Git)
14+
@@ -669,7 +669,6 @@ if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") AND
15+
# Threading support
16+
if(UA_MULTITHREADING GREATER_EQUAL 100 AND NOT WIN32)
17+
check_add_cc_flag("-pthread")
18+
- check_add_cc_flag("-ftls-model=initial-exec") # Enable thread-local variables in the .so shared object
19+
endif()
20+
21+
# Force 32bit build
22+
@@ -691,17 +690,6 @@ if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") AND
23+
endif()
4024
endif()
4125

42-
if(UA_ENABLE_AMALGAMATION)
26+
- # Inter Procedural Optimization / Link Time Optimization (should be same as -flto)
27+
- # IPO requires too much memory for unit tests
28+
- # GCC docu recommends to compile all files with the same options, therefore ignore it completely
29+
- if(NOT UA_BUILD_UNIT_TESTS AND NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
30+
- include(CheckIPOSupported)
31+
- check_ipo_supported(RESULT CC_HAS_IPO)
32+
- if(CC_HAS_IPO)
33+
- set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
34+
- endif()
35+
- endif()
36+
-
37+
# Linker
38+
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") # cmake sets -rdynamic by default
39+
if(APPLE)
40+
diff --git a/arch/posix/eventloop_posix.h b/arch/posix/eventloop_posix.h
41+
index a5f51383e..0d8b78418 100644
42+
--- a/arch/posix/eventloop_posix.h
43+
+++ b/arch/posix/eventloop_posix.h
44+
@@ -277,7 +277,9 @@ typedef int SOCKET;
45+
46+
#ifndef __ANDROID__
47+
#ifndef __APPLE__
48+
+#ifdef __GLIBC__
49+
#include <bits/stdio_lim.h>
50+
+#endif
51+
#endif /* !__APPLE__ */
52+
#endif /* !__ANDROID__ */
53+

0 commit comments

Comments
 (0)