Explorar o código

Merge branch '1.0' into master

Stefan Profanter %!s(int64=5) %!d(string=hai) anos
pai
achega
40d9e588cd

+ 1 - 1
.travis.yml

@@ -368,4 +368,4 @@ deploy:
   on:
     repo: open62541/open62541
     tags: true
-    condition: $CC = gcc-4.8 && $ANALYZE = false
+    condition: $MINGW=true

+ 2 - 2
debian/open62541-dev.install

@@ -1,5 +1,5 @@
-usr/include/*
-usr/lib/*/lib{*.a,*.so,*.so.*}
+usr/include
+usr/lib/*/{*.a,*.so}
 usr/lib/*/cmake/open62541/*
 usr/lib/*/pkgconfig/open62541.pc
 usr/share/open62541/*

+ 1 - 1
debian/open62541.install

@@ -1 +1 @@
-usr/lib/*/lib{*.a,*.so,*.so.*}
+usr/lib/*/*.so.*

+ 1 - 1
examples/pubsub/tutorial_pubsub_subscribe.c

@@ -38,7 +38,7 @@ static void fillTestDataSetMetaData(UA_DataSetMetaDataType *pMetaData);
 static void
 addPubSubConnection(UA_Server *server, UA_String *transportProfile,
                     UA_NetworkAddressUrlDataType *networkAddressUrl) {
-    if((server == NULL) && (transportProfile == NULL) &&
+    if((server == NULL) || (transportProfile == NULL) ||
         (networkAddressUrl == NULL)) {
         return;
     }

+ 5 - 5
examples/server_ctt.c

@@ -121,7 +121,7 @@ readRandomInt32Data(UA_Server *server,
     }
     return UA_STATUSCODE_GOOD;
 }
-    
+
 static UA_StatusCode
 readRandomInt64Data(UA_Server *server,
              const UA_NodeId *sessionId, void *sessionContext,
@@ -142,7 +142,7 @@ readRandomInt64Data(UA_Server *server,
     }
     return UA_STATUSCODE_GOOD;
 }
-    
+
 static UA_StatusCode
 readRandomUInt16Data(UA_Server *server,
              const UA_NodeId *sessionId, void *sessionContext,
@@ -184,7 +184,7 @@ readRandomUInt32Data(UA_Server *server,
     }
     return UA_STATUSCODE_GOOD;
 }
-    
+
 static UA_StatusCode
 readRandomUInt64Data(UA_Server *server,
              const UA_NodeId *sessionId, void *sessionContext,
@@ -292,7 +292,7 @@ readByteString (UA_Server *server,
     }
    return UA_STATUSCODE_GOOD;
 }
-    
+
 /* Method Node Example */
 #ifdef UA_ENABLE_METHODCALLS
 
@@ -1043,7 +1043,7 @@ int main(int argc, char **argv) {
         if(strcmp(argv[pos], "--disableBasic256Sha256") == 0) {
             disableBasic256Sha256 = true;
             continue;
-        }        
+        }
 
         if(strcmp(argv[pos], "--trustlist") == 0) {
             filetype = 't';

+ 4 - 4
open62541.pc.in

@@ -3,10 +3,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=@CMAKE_INSTALL_PREFIX@
-libdir=@CMAKE_INSTALL_PREFIX@/lib
-sharedlibdir=@CMAKE_INSTALL_PREFIX@/share
-includedir=@CMAKE_INSTALL_PREFIX@/include
+exec_prefix=${prefix}
+libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
+sharedlibdir=${libdir}
+includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
 
 Name: open62541
 Description: open62541 is an open source C (C99) implementation of OPC UA

+ 15 - 0
src/client/ua_client_subscriptions.c

@@ -366,7 +366,14 @@ UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId
     UA_CreateMonitoredItemsResponse response = 
        UA_Client_MonitoredItems_createEvents(client, request, &context,
                                              &callback, &deleteCallback);
+    UA_StatusCode retval = response.responseHeader.serviceResult;
     UA_MonitoredItemCreateResult result;
+    UA_MonitoredItemCreateResult_init(&result);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+        result.statusCode = retval;
+        return result;
+    }
     UA_MonitoredItemCreateResult_copy(response.results , &result);
     UA_CreateMonitoredItemsResponse_deleteMembers(&response);
     return result;
@@ -673,6 +680,14 @@ UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequ
         return;
     }
 
+    if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
+        if (client->config.inactivityCallback)
+            client->config.inactivityCallback(client);
+        UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
+                       "Received Timeout for Publish Response");
+        return;
+    }
+
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
         UA_LOG_WARNING(&client->config.logger, UA_LOGCATEGORY_CLIENT,
                        "Received Publish Response with code %s",

+ 9 - 4
src/server/ua_services_nodemanagement.c

@@ -743,11 +743,16 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
                 }
 
                 /* Object node created of an abstract ObjectType. Only allowed
-                 * if within BaseObjectType folder */
+                 * if within BaseObjectType folder or if it's an event (subType of BaseEventType) */
                 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
-                if(!isNodeInTree(server->nsCtx, parentNodeId, &objectTypes,
-                                 parentTypeHierarchy, parentTypeHierarchySize)) {
-                    UA_LOG_NODEID_WRAP(nodeId, UA_LOG_WARNING_SESSION(&server->config.logger, session,
+                UA_Boolean isInBaseObjectType = isNodeInTree(server->nsCtx, parentNodeId, &objectTypes,
+                                                             parentTypeHierarchy, parentTypeHierarchySize);
+
+                const UA_NodeId eventTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
+                UA_Boolean isInBaseEventType = isNodeInTree(server->nsCtx, &type->nodeId, &eventTypes, &hasSubtype, 1);
+
+                if(!isInBaseObjectType && !(isInBaseEventType && UA_NodeId_isNull(parentNodeId))) {
+                    UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
                                         "AddNodes: Type of object node %.*s must "
                                         "be ObjectType and not be abstract",
                                         (int)nodeIdStr.length, nodeIdStr.data));

+ 27 - 19
src/ua_types.c

@@ -309,34 +309,42 @@ UA_NodeId_order(const UA_NodeId *n1, const UA_NodeId *n2) {
             return UA_ORDER_MORE;
         break;
     case UA_NODEIDTYPE_GUID:
-        if(n1->identifier.guid.data1 < n2->identifier.guid.data1 ||
-           n1->identifier.guid.data2 < n2->identifier.guid.data2 ||
-           n1->identifier.guid.data3 < n2->identifier.guid.data3 ||
-           strncmp((const char*)n1->identifier.guid.data4,
-                   (const char*)n2->identifier.guid.data4, 8) < 0)
+        if(n1->identifier.guid.data1 < n2->identifier.guid.data1) {
             return UA_ORDER_LESS;
-        if(n1->identifier.guid.data1 > n2->identifier.guid.data1 ||
-           n1->identifier.guid.data2 > n2->identifier.guid.data2 ||
-           n1->identifier.guid.data3 > n2->identifier.guid.data3 ||
-           strncmp((const char*)n1->identifier.guid.data4,
-                   (const char*)n2->identifier.guid.data4, 8) > 0)
+        } else if(n1->identifier.guid.data1 > n2->identifier.guid.data1) {
             return UA_ORDER_MORE;
+        } else if(n1->identifier.guid.data2 < n2->identifier.guid.data2) {
+            return UA_ORDER_LESS;
+        } else if(n1->identifier.guid.data2 > n2->identifier.guid.data2) {
+            return UA_ORDER_MORE;
+        } else if(n1->identifier.guid.data3 < n2->identifier.guid.data3) {
+            return UA_ORDER_LESS;
+        } else if(n1->identifier.guid.data3 > n2->identifier.guid.data3) {
+            return UA_ORDER_MORE;
+        } else {
+            int cmp = memcmp(n1->identifier.guid.data4, n2->identifier.guid.data4, 8);
+
+            if(cmp < 0) return UA_ORDER_LESS;
+            if(cmp > 0) return UA_ORDER_MORE;
+
+        }
+
         break;
     case UA_NODEIDTYPE_STRING:
     case UA_NODEIDTYPE_BYTESTRING: {
+        size_t minLength = UA_MIN(n1->identifier.string.length, n2->identifier.string.length);
+        int cmp = strncmp((const char*)n1->identifier.string.data,
+                          (const char*)n2->identifier.string.data,
+                          minLength);
+        if(cmp < 0)
+            return UA_ORDER_LESS;
+        if(cmp > 0)
+            return UA_ORDER_MORE;
+
         if(n1->identifier.string.length < n2->identifier.string.length)
             return UA_ORDER_LESS;
         if(n1->identifier.string.length > n2->identifier.string.length)
             return UA_ORDER_MORE;
-        if(n1->identifier.string.length > 0) {
-            int cmp = strncmp((const char*)n1->identifier.string.data,
-                              (const char*)n2->identifier.string.data,
-                              n1->identifier.string.length);
-            if(cmp < 0)
-                return UA_ORDER_LESS;
-            if(cmp > 0)
-                return UA_ORDER_MORE;
-        }
         break;
     }
     default:

+ 139 - 0
tests/check_utils.c

@@ -393,6 +393,137 @@ START_TEST(idToStringByte) {
 } END_TEST
 
 
+START_TEST(idOrderNs) {
+    UA_NodeId id_ns1 = UA_NODEID_NUMERIC(1, 12345);
+    UA_NodeId id_ns3 = UA_NODEID_NUMERIC(3, 12345);
+
+    ck_assert(UA_NodeId_order(&id_ns1, &id_ns1) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_ns1, &id_ns3) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_ns3, &id_ns1) == UA_ORDER_MORE);
+} END_TEST
+
+START_TEST(idOrderIdentifier) {
+    UA_NodeId id_num = UA_NODEID_NUMERIC(1, 12345);
+    UA_NodeId id_str = UA_NODEID_STRING(1, "asdf");
+
+    ck_assert(UA_NodeId_order(&id_num, &id_num) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_num, &id_str) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_str, &id_num) == UA_ORDER_MORE);
+} END_TEST
+
+START_TEST(idOrderNumeric) {
+    UA_NodeId id_num_12345 = UA_NODEID_NUMERIC(1, 12345);
+    UA_NodeId id_num_23456 = UA_NODEID_NUMERIC(1, 23456);
+
+    ck_assert(UA_NodeId_order(&id_num_12345, &id_num_12345) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_num_12345, &id_num_23456) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_num_23456, &id_num_12345) == UA_ORDER_MORE);
+} END_TEST
+
+START_TEST(idOrderGuid) {
+
+    // See also https://github.com/open62541/open62541/pull/2904#issuecomment-514111395
+
+    // 00000000-FFFF-FFFF-FFFFFFFFFFFF,
+    UA_Guid guid1 = {
+            0,
+            0xffff,
+            0xffff,
+            { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+    };
+    // 00000001-0000-0000-000000000000
+    UA_Guid guid2 = {
+            0x1,
+            0,
+            0,
+            { 0, 0, 0, 0, 0, 0, 0, 0 }
+    };
+    // 00000000-0000-FFFF-FFFFFFFFFFFF
+    UA_Guid guid3 = {
+            0,
+            0,
+            0xffff,
+            { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+    };
+    // 00000000-0001-0000-000000000000
+    UA_Guid guid4 = {
+            0,
+            0x1,
+            0,
+            { 0, 0, 0, 0, 0, 0, 0, 0 }
+    };
+    // 00000000-0000-0000-FFFFFFFFFFFF
+    UA_Guid guid5 = {
+            0,
+            0,
+            0,
+            { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+    };
+    // 00000000-0000-0001-000000000000
+    UA_Guid guid6 = {
+            0,
+            0,
+            0x1,
+            { 0, 0, 0, 0, 0, 0, 0, 0 }
+    };
+    // 00000000-0000-0000-000000000000
+    UA_Guid guid7 = {
+            0,
+            0,
+            0,
+            { 0, 0, 0, 0, 0, 0, 0, 0 }
+    };
+    // 00000000-0000-0000-000000000001
+    UA_Guid guid8 = {
+            0,
+            0,
+            0,
+            { 0, 0, 0, 0, 0, 0, 0, 0x1 }
+    };
+
+
+    UA_NodeId id_guid_1 = UA_NODEID_GUID(1, guid1);
+    UA_NodeId id_guid_2 = UA_NODEID_GUID(1, guid2);
+    ck_assert(UA_NodeId_order(&id_guid_1, &id_guid_1) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_guid_1, &id_guid_2) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_guid_2, &id_guid_1) == UA_ORDER_MORE);
+
+    UA_NodeId id_guid_3 = UA_NODEID_GUID(1, guid3);
+    UA_NodeId id_guid_4 = UA_NODEID_GUID(1, guid4);
+    ck_assert(UA_NodeId_order(&id_guid_3, &id_guid_3) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_guid_3, &id_guid_4) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_guid_4, &id_guid_3) == UA_ORDER_MORE);
+
+    UA_NodeId id_guid_5 = UA_NODEID_GUID(1, guid5);
+    UA_NodeId id_guid_6 = UA_NODEID_GUID(1, guid6);
+    ck_assert(UA_NodeId_order(&id_guid_5, &id_guid_5) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_guid_5, &id_guid_2) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_guid_6, &id_guid_5) == UA_ORDER_MORE);
+
+    UA_NodeId id_guid_7 = UA_NODEID_GUID(1, guid7);
+    UA_NodeId id_guid_8 = UA_NODEID_GUID(1, guid8);
+    ck_assert(UA_NodeId_order(&id_guid_7, &id_guid_7) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_guid_7, &id_guid_8) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_guid_8, &id_guid_7) == UA_ORDER_MORE);
+
+} END_TEST
+
+START_TEST(idOrderString) {
+    UA_NodeId id_str_a = UA_NODEID_STRING(1, "aaaaa");
+    UA_NodeId id_str_b = UA_NODEID_STRING(1, "baa");
+
+    ck_assert(UA_NodeId_order(&id_str_a, &id_str_a) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_str_a, &id_str_b) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_str_b, &id_str_a) == UA_ORDER_MORE);
+
+    UA_NodeId id_str_c = UA_NODEID_STRING(1, "cddd");
+    UA_NodeId id_str_d = UA_NODEID_STRING(1, "dddd");
+
+    ck_assert(UA_NodeId_order(&id_str_c, &id_str_c) == UA_ORDER_EQ);
+    ck_assert(UA_NodeId_order(&id_str_c, &id_str_d) == UA_ORDER_LESS);
+    ck_assert(UA_NodeId_order(&id_str_d, &id_str_c) == UA_ORDER_MORE);
+} END_TEST
+
 
 static Suite* testSuite_Utils(void) {
     Suite *s = suite_create("Utils");
@@ -417,6 +548,14 @@ static Suite* testSuite_Utils(void) {
     tcase_add_test(tc1, idToStringByte);
     suite_add_tcase(s, tc1);
 
+    TCase *tc2 = tcase_create("test nodeid order");
+    tcase_add_test(tc1, idOrderNs);
+    tcase_add_test(tc1, idOrderIdentifier);
+    tcase_add_test(tc1, idOrderNumeric);
+    tcase_add_test(tc1, idOrderGuid);
+    tcase_add_test(tc1, idOrderString);
+    suite_add_tcase(s, tc2);
+
     return s;
 }
 

+ 51 - 0
tests/server/check_subscription_events.c

@@ -384,6 +384,54 @@ START_TEST(generateEvents) {
     UA_DeleteMonitoredItemsResponse_deleteMembers(&deleteResponse);
 } END_TEST
 
+static bool hasBaseModelChangeEventType(void) {
+
+    UA_QualifiedName readBrowsename;
+    UA_QualifiedName_init(&readBrowsename);
+    UA_StatusCode retval = UA_Server_readBrowseName(server, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEMODELCHANGEEVENTTYPE), &readBrowsename);
+    UA_QualifiedName_deleteMembers(&readBrowsename);
+    return !(retval == UA_STATUSCODE_BADNODEIDUNKNOWN);
+}
+
+START_TEST(createAbstractEvent) {
+    if (!hasBaseModelChangeEventType())
+        return;
+
+    UA_NodeId eventNodeId = UA_NODEID_NULL;
+    UA_NodeId abstractEventType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEMODELCHANGEEVENTTYPE);
+    serverMutexLock();
+    UA_StatusCode retval = UA_Server_createEvent(server, abstractEventType, &eventNodeId);
+    serverMutexUnlock();
+    ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
+} END_TEST
+
+START_TEST(createAbstractEventWithParent) {
+    if (!hasBaseModelChangeEventType())
+        return;
+    UA_NodeId eventNodeId = UA_NODEID_NULL;
+    UA_NodeId abstractEventType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEMODELCHANGEEVENTTYPE);
+    serverMutexLock();
+    // createEvent does not use a parent, so we are instead using addObjectNode
+    UA_StatusCode retval = UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
+                                                   UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                                                   UA_QUALIFIEDNAME(0, "Abstract Event"), abstractEventType,
+                                                   UA_ObjectAttributes_default, NULL, &eventNodeId);
+    serverMutexUnlock();
+    ck_assert_uint_eq(retval, UA_STATUSCODE_BADTYPEDEFINITIONINVALID);
+} END_TEST
+
+START_TEST(createNonAbstractEventWithParent) {
+    UA_NodeId eventNodeId = UA_NODEID_NULL;
+    serverMutexLock();
+    // Our SimpleEventType is not abstract
+    UA_StatusCode retval = UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
+                                                   UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                                                   UA_QUALIFIEDNAME(0, "Non-Abstract Event"), eventType,
+                                                   UA_ObjectAttributes_default, NULL, &eventNodeId);
+    serverMutexUnlock();
+    ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
+} END_TEST
+
 static void
 handler_events_propagate(UA_Client *lclient, UA_UInt32 subId, void *subContext,
                          UA_UInt32 monId, void *monContext,
@@ -625,6 +673,9 @@ static Suite *testSuite_Client(void) {
     tcase_add_unchecked_fixture(tc_server, setup, teardown);
     tcase_add_test(tc_server, generateEventEmptyFilter);
     tcase_add_test(tc_server, generateEvents);
+    tcase_add_test(tc_server, createAbstractEvent);
+    tcase_add_test(tc_server, createAbstractEventWithParent);
+    tcase_add_test(tc_server, createNonAbstractEventWithParent);
     tcase_add_test(tc_server, uppropagation);
     tcase_add_test(tc_server, eventOverflow);
     tcase_add_test(tc_server, multipleMonitoredItemsOneNode);