Skip to content

Commit

Permalink
Merge pull request open62541#5985 from jpfr/merge_13_14_3
Browse files Browse the repository at this point in the history
Merge 1.3 to 1.4
  • Loading branch information
jpfr authored Sep 6, 2023
2 parents 8465181 + cef0680 commit 0e2cbab
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 42 deletions.
26 changes: 10 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -612,10 +612,10 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang")

# Force 32bit build
if(UA_FORCE_32BIT)
if(MSVC)
message(FATAL_ERROR "Select the 32bit (cross-) compiler instead of forcing compiler options")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") # GCC and Clang, possibly more
if(MSVC)
message(FATAL_ERROR "Select the 32bit (cross-) compiler instead of forcing compiler options")
endif()
check_add_cc_flag("-m32") # GCC and Clang, possibly more
endif()

if(NOT MINGW AND NOT UA_BUILD_OSS_FUZZ)
Expand Down Expand Up @@ -1233,17 +1233,6 @@ ua_generate_nodeset(NAME "ns0" FILE ${UA_FILE_NODESETS} ${UA_NODESET_FILE_DA}
IGNORE "${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/NodeID_NS0_Base.txt"
DEPENDS_TARGET "open62541-generator-types")

# stack protector and optimization needs to be disabled for the huge ns0 file, otherwise debian packaging fails due to long build times.
# We also disable optimization on Appveyor builds, since they take almost an hour otherwise
if(UA_PACK_DEBIAN OR (NOT "$ENV{APPVEYOR}" STREQUAL "") OR (
(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" OR CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") AND (
# List of compilers which have problems with the huge ns0 optimization
(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0))
)
))
set_source_files_properties(${PROJECT_BINARY_DIR}/src_generated/open62541/namespace0_generated.c PROPERTIES COMPILE_FLAGS "-fno-stack-protector -O0")
endif()

if(UA_ENABLE_NODESET_INJECTOR)
message(STATUS "Nodesetinjector feature enabled")
cmake_minimum_required(VERSION 3.20)
Expand Down Expand Up @@ -1306,6 +1295,7 @@ if(UA_ENABLE_AMALGAMATION)
add_dependencies(open62541-amalgamation-header open62541-generator-namespace)
else()
add_library(open62541-object OBJECT ${lib_sources} ${lib_headers} ${exported_headers})
target_include_directories(open62541-object PRIVATE ${PROJECT_SOURCE_DIR}/src)

add_custom_target(open62541-code-generation DEPENDS
open62541-generator-types
Expand All @@ -1321,7 +1311,11 @@ else()
add_coverage(open62541-object)
endif()

target_include_directories(open62541-object PRIVATE ${PROJECT_SOURCE_DIR}/src)
# stack protector and optimization are disabled for the huge ns0 file
if(UA_NAMESPACE_ZERO STREQUAL "FULL" AND NOT MSVC)
set_source_files_properties(${PROJECT_BINARY_DIR}/src_generated/open62541/namespace0_generated.c
PROPERTIES COMPILE_FLAGS "-fno-stack-protector -O0")
endif()

add_library(open62541-plugins OBJECT ${plugin_sources} ${architecture_sources} ${exported_headers})
add_dependencies(open62541-plugins open62541-generator-types open62541-generator-transport open62541-generator-namespace)
Expand Down
2 changes: 1 addition & 1 deletion arch/eventloop_posix_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ ETH_openConnection(UA_ConnectionManager *cm, const UA_KeyValueMap *params,
/* Validate the parameters */
UA_StatusCode res =
UA_KeyValueRestriction_validate(el->eventLoop.logger, "ETH", ETHConfigParameters,
ETH_PARAMETERSSIZE, params);
ethParams, params);
if(res != UA_STATUSCODE_GOOD) {
UA_UNLOCK(&el->elMutex);
return res;
Expand Down
67 changes: 50 additions & 17 deletions src/client/ua_client_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ responseGetEndpoints(UA_Client *client, void *userdata,
client->endpointsHandshake = false;

UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Received FindServersResponse");
"Received GetEndpointsResponse");

UA_GetEndpointsResponse *resp = (UA_GetEndpointsResponse*)response;

Expand Down Expand Up @@ -1063,7 +1063,7 @@ responseFindServers(UA_Client *client, void *userdata,
}
}

/* The current EndpointURL is not usable. Pick the first DiscoveryUrl of a
/* The current EndpointURL is not usable. Pick the first "opc.tcp" DiscoveryUrl of a
* returned server. */
for(size_t i = 0; i < fsr->serversSize; i++) {
UA_ApplicationDescription *server = &fsr->servers[i];
Expand All @@ -1072,32 +1072,42 @@ responseFindServers(UA_Client *client, void *userdata,
server->applicationType != UA_APPLICATIONTYPE_DISCOVERYSERVER
)
continue;
if(server->discoveryUrlsSize == 0)
continue;

/* Filter by the ApplicationURI if defined */
if(client->config.applicationUri.length > 0 &&
!UA_String_equal(&client->config.applicationUri,
&server->applicationUri))
continue;

/* Use this DiscoveryUrl in the client */
UA_String_clear(&client->discoveryUrl);
client->discoveryUrl = server->discoveryUrls[0];
UA_String_init(&server->discoveryUrls[0]);
for(size_t j = 0; j < server->discoveryUrlsSize; j++) {
/* Try to parse the DiscoveryUrl. This weeds out http schemas (etc.)
* and invalid DiscoveryUrls in general. */
UA_String hostname, path;
UA_UInt16 port;
UA_StatusCode res =
UA_parseEndpointUrl(&server->discoveryUrls[j], &hostname,
&port, &path);
if(res != UA_STATUSCODE_GOOD)
continue;

UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Use the EndpointURL %.*s returned from FindServers",
(int)client->discoveryUrl.length,
client->discoveryUrl.data);
/* Use this DiscoveryUrl in the client */
UA_String_clear(&client->discoveryUrl);
client->discoveryUrl = server->discoveryUrls[j];
UA_String_init(&server->discoveryUrls[j]);

/* Close the SecureChannel to build it up new with the correct
* EndpointURL in the HEL/ACK handshake */
closeSecureChannel(client);
return;
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"Use the EndpointURL %.*s returned from FindServers",
(int)client->discoveryUrl.length, client->discoveryUrl.data);

/* Close the SecureChannel to build it up new with the correct
* EndpointURL in the HEL/ACK handshake */
closeSecureChannel(client);
return;
}
}

/* Could not find a suitable server. Try to continue. */
/* Could not find a suitable server. Try to continue with the
* original EndpointURL. */
UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"FindServers did not returned a suitable DiscoveryURL. "
"Continue with the EndpointURL %.*s.",
Expand Down Expand Up @@ -1227,6 +1237,27 @@ createSessionAsync(UA_Client *client) {
return res;
}

/* A workaround if the DiscoveryUrl returned by the FindServers service doesn't work.
* Then default back to the initial EndpointUrl and pretend that was returned
* by FindServers. */
static void
fixBadDiscoveryUrl(UA_Client* client) {
if(client->connectStatus == UA_STATUSCODE_GOOD)
return;
if(client->discoveryUrl.length == 0 ||
UA_String_equal(&client->discoveryUrl, &client->config.endpointUrl))
return;

UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"The DiscoveryUrl returned by the FindServers service (%.*s) could not be "
"connected. Trying with the original EndpointUrl.",
(int)client->discoveryUrl.length, client->discoveryUrl.data);

UA_String_clear(&client->discoveryUrl);
UA_String_copy(&client->config.endpointUrl, &client->discoveryUrl);
client->connectStatus = UA_STATUSCODE_GOOD;
}

static void
initSecurityPolicy(UA_Client *client) {
/* Already initialized */
Expand Down Expand Up @@ -1512,6 +1543,7 @@ __Client_networkCallback(UA_ConnectionManager *cm, uintptr_t connectionId,

/* Trigger the next action from our end to fully open up the connection */
continue_connect:
fixBadDiscoveryUrl(client);
if(!isFullyConnected(client))
connectActivity(client);

Expand All @@ -1522,6 +1554,7 @@ __Client_networkCallback(UA_ConnectionManager *cm, uintptr_t connectionId,

refuse_connection:
client->connectStatus = UA_STATUSCODE_BADCONNECTIONREJECTED;
fixBadDiscoveryUrl(client);
notifyClientState(client);
UA_UNLOCK(&client->clientMutex);
}
Expand Down
6 changes: 3 additions & 3 deletions src/pubsub/ua_pubsub_networkmessage.c
Original file line number Diff line number Diff line change
Expand Up @@ -760,14 +760,14 @@ UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_Net
UA_CHECK_STATUS(rv, return rv);
}

rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst);
UA_CHECK_STATUS(rv, return rv);

if(dst->securityEnabled) {
rv = UA_SecurityHeader_decodeBinary(src, offset, dst);
UA_CHECK_STATUS(rv, return rv);
}

rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst);
UA_CHECK_STATUS(rv, return rv);

return UA_STATUSCODE_GOOD;
}

Expand Down
8 changes: 3 additions & 5 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -394,21 +394,19 @@ ua_add_test(server/check_server_reverseconnect.c)
# Test Client

ua_add_test(client/check_client.c)
ua_add_test(client/check_client_discovery.c)
ua_add_test(client/check_activateSession.c)
if(UA_ENABLE_SUBSCRIPTIONS)
ua_add_test(client/check_subscriptionWithactivateSession.c)
endif()
ua_add_test(client/check_activateSessionAsync.c)
ua_add_test(client/check_client_securechannel.c)
ua_add_test(client/check_client_async.c)
ua_add_test(client/check_client_async_connect.c)
ua_add_test(client/check_client_highlevel.c)

if(UA_ENABLE_SUBSCRIPTIONS)
ua_add_test(client/check_client_subscriptions.c)
ua_add_test(client/check_subscriptionWithactivateSession.c)
endif()

ua_add_test(client/check_client_highlevel.c)

if(UA_ENABLE_HISTORIZING)
ua_add_test(client/check_client_historical_data.c)
endif()
Expand Down
81 changes: 81 additions & 0 deletions tests/client/check_client_discovery.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <open62541/client_config_default.h>
#include <open62541/server_config_default.h>

#include "client/ua_client_internal.h"

#include <check.h>
#include <stdlib.h>

#include "thread_wrapper.h"

UA_Server *server;
UA_Boolean running;
THREAD_HANDLE server_thread;


THREAD_CALLBACK(serverloop) {
while(running)
UA_Server_run_iterate(server, true);
return 0;
}

static void setup(void) {
running = true;
server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_Server_run_startup(server);
THREAD_CREATE(server_thread, serverloop);
}

static void teardown(void) {
running = false;
THREAD_JOIN(server_thread);
UA_Server_run_shutdown(server);
UA_Server_delete(server);
}

START_TEST(Client_connect_badEndpointUrl) {
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));

/* Use the internal API to force a bad DiscoveryUrl */
UA_String_clear(&client->config.endpointUrl);
UA_String_clear(&client->discoveryUrl);
client->config.endpointUrl = UA_STRING_ALLOC("opc.tcp://localhost:4840");
client->discoveryUrl = UA_STRING_ALLOC("abc://xxx:4840");

/* Open a Session when possible */
client->config.noSession = false;

UA_LOCK(&client->clientMutex);
connectSync(client);
UA_UNLOCK(&client->clientMutex);
ck_assert_uint_eq(client->connectStatus, UA_STATUSCODE_GOOD);

UA_Client_disconnect(client);
UA_Client_delete(client);
}
END_TEST

static Suite* testSuite_Client(void) {
Suite *s = suite_create("Client");
TCase *tc_client = tcase_create("Client Discovery");
tcase_add_checked_fixture(tc_client, setup, teardown);
tcase_add_test(tc_client, Client_connect_badEndpointUrl);
suite_add_tcase(s,tc_client);
return s;
}

int main(void) {
Suite *s = testSuite_Client();
SRunner *sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr,CK_NORMAL);
int number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

0 comments on commit 0e2cbab

Please sign in to comment.