Ver código fonte

fix bugs from conformance testing tool

Julius Pfrommer 10 anos atrás
pai
commit
1b7c84f653

+ 1 - 1
CMakeLists.txt

@@ -208,12 +208,12 @@ endif()
 option(GENERATE_SELFSIGNED "Generate self-signed certificates" OFF)
 if(GENERATE_SELFSIGNED)
     message(STATUS "Enabling self-signed certificates")
-    SET(lib_sources ${lib_sources} ${PROJECT_BINARY_DIR}/localhost.der ${PROJECT_BINARY_DIR}/ca.crt)
     add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/localhost.der
                               ${PROJECT_BINARY_DIR}/ca.crt
                    COMMAND python ${PROJECT_SOURCE_DIR}/tools/certs/create_self-signed.py ${PROJECT_BINARY_DIR}
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/certs/create_self-signed.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/certs/localhost.cnf)
+    add_custom_target(selfsigned ALL DEPENDS ${PROJECT_BINARY_DIR}/localhost.der ${PROJECT_BINARY_DIR}/ca.crt)
 endif()
 
 # build unit tests

+ 10 - 4
examples/server_datasource.c

@@ -21,7 +21,7 @@
 /*************************/
 /* Read-only data source */
 /*************************/
-static UA_StatusCode readTimeData(const void *handle, UA_DataValue *value) {
+static UA_StatusCode readTimeData(const void *handle, UA_Boolean sourceTimeStamp, UA_DataValue *value) {
     UA_DateTime *currentTime = UA_DateTime_new();
     if(!currentTime)
         return UA_STATUSCODE_BADOUTOFMEMORY;
@@ -32,6 +32,10 @@ static UA_StatusCode readTimeData(const void *handle, UA_DataValue *value) {
     value->value.arrayDimensionsSize = -1;
     value->value.arrayDimensions = NULL;
     value->hasVariant = UA_TRUE;
+    if(sourceTimeStamp) {
+        value->hasSourceTimestamp = UA_TRUE;
+        value->sourceTimestamp = *currentTime;
+    }
     return UA_STATUSCODE_GOOD;
 }
 
@@ -49,7 +53,7 @@ static void printDeviceStatus(UA_Server *server, void *data) {
     printf("Device Status: %i\n", deviceStatus);
 }
 
-static UA_StatusCode readDeviceStatus(const void *handle, UA_DataValue *value) {
+static UA_StatusCode readDeviceStatus(const void *handle, UA_Boolean sourceTimeStamp, UA_DataValue *value) {
     /* In order to reduce blocking time, we could alloc memory for every read
        and return a copy of the data. */
     pthread_rwlock_rdlock(&deviceStatusLock);
@@ -59,8 +63,10 @@ static UA_StatusCode readDeviceStatus(const void *handle, UA_DataValue *value) {
     value->value.arrayDimensionsSize = -1;
     value->value.arrayDimensions = NULL;
     value->hasVariant = UA_TRUE;
-    value->sourceTimestamp = UA_DateTime_now();
-    value->hasSourceTimestamp = UA_TRUE;
+    if(sourceTimeStamp) {
+        value->sourceTimestamp = UA_DateTime_now();
+        value->hasSourceTimestamp = UA_TRUE;
+    }
     return UA_STATUSCODE_GOOD;
 }
 

+ 1 - 1
include/ua_server.h

@@ -71,7 +71,7 @@ UA_StatusCode UA_EXPORT UA_Server_run(UA_Server *server, UA_UInt16 nThreads, UA_
  **/
 typedef struct {
     const void *handle;
-    UA_StatusCode (*read)(const void *handle, UA_DataValue *value);
+    UA_StatusCode (*read)(const void *handle, UA_Boolean sourceTimeStamp, UA_DataValue *value);
     void (*release)(const void *handle, UA_DataValue *value);
     UA_StatusCode (*write)(const void *handle, const UA_Variant *data);
 } UA_DataSource;

+ 7 - 3
src/server/ua_server.c

@@ -44,7 +44,8 @@ void UA_Server_addNetworkLayer(UA_Server *server, UA_ServerNetworkLayer networkL
 }
 
 void UA_Server_setServerCertificate(UA_Server *server, UA_ByteString certificate) {
-    UA_ByteString_copy(&certificate, &server->serverCertificate);
+    for(UA_Int32 i=0;i<server->endpointDescriptionsSize;i++)
+        UA_ByteString_copy(&certificate, &server->endpointDescriptions[i].serverCertificate);
 }
 
 void UA_Server_setLogger(UA_Server *server, UA_Logger logger) {
@@ -81,7 +82,7 @@ void UA_Server_delete(UA_Server *server) {
     UA_free(server);
 }
 
-static UA_StatusCode readStatus(const void *handle, UA_DataValue *value) {
+static UA_StatusCode readStatus(const void *handle, UA_Boolean sourceTimeStamp, UA_DataValue *value) {
     UA_ServerStatusDataType *status = UA_ServerStatusDataType_new();
     status->startTime   = ((const UA_Server*)handle)->startTime;
     status->currentTime = UA_DateTime_now();
@@ -95,13 +96,16 @@ static UA_StatusCode readStatus(const void *handle, UA_DataValue *value) {
     UA_String_copycstring("0", &status->buildInfo.buildNumber);
     status->buildInfo.buildDate = ((const UA_Server*)handle)->buildDate;
     status->secondsTillShutdown = 0;
-
     value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
 	value->value.arrayLength = 1;
     value->value.dataPtr = status;
     value->value.arrayDimensionsSize = -1;
     value->value.arrayDimensions = UA_NULL;
     value->hasVariant = UA_TRUE;
+    if(sourceTimeStamp) {
+        value->hasSourceTimestamp = UA_TRUE;
+        value->sourceTimestamp = UA_DateTime_now();
+    }
     return UA_STATUSCODE_GOOD;
 }
 

+ 19 - 12
src/server/ua_services_attribute.c

@@ -13,7 +13,8 @@
     }
 
 /** Reads a single attribute from a node in the nodestore. */
-static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue *v) {
+static void readValue(UA_Server *server, UA_TimestampsToReturn timestamps,
+                      const UA_ReadValueId *id, UA_DataValue *v) {
     UA_Node const *node = UA_NodeStore_get(server->nodestore, &(id->nodeId));
     if(!node) {
         v->hasStatus = UA_TRUE;
@@ -22,7 +23,6 @@ static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue
     }
 
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-
     switch(id->attributeId) {
     case UA_ATTRIBUTEID_NODEID:
         v->hasVariant = UA_TRUE;
@@ -102,23 +102,25 @@ static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue
             const UA_VariableNode *vn = (const UA_VariableNode*)node;
             if(vn->variableType == UA_VARIABLENODETYPE_VARIANT) {
                 retval = UA_Variant_copy(&vn->variable.variant, &v->value);
-                if(retval == UA_STATUSCODE_GOOD){
-                    v->hasVariant = UA_TRUE;
-                    v->hasServerTimestamp = UA_TRUE;
-                    v->serverTimestamp = UA_DateTime_now();
+                if(retval != UA_STATUSCODE_GOOD)
+                    break;
+                v->hasVariant = UA_TRUE;
+                if(timestamps == UA_TIMESTAMPSTORETURN_SOURCE || timestamps == UA_TIMESTAMPSTORETURN_BOTH) {
+                    v->hasSourceTimestamp = UA_TRUE;
+                    v->sourceTimestamp = UA_DateTime_now();
                 }
             } else {
                 UA_DataValue val;
                 UA_DataValue_init(&val);
-                retval |= vn->variable.dataSource.read(vn->variable.dataSource.handle, &val);
+                UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
+                                              timestamps == UA_TIMESTAMPSTORETURN_BOTH);
+                retval |= vn->variable.dataSource.read(vn->variable.dataSource.handle, sourceTimeStamp, &val);
                 if(retval != UA_STATUSCODE_GOOD)
                     break;
                 retval |= UA_DataValue_copy(&val, v);
                 vn->variable.dataSource.release(vn->variable.dataSource.handle, &val);
                 if(retval != UA_STATUSCODE_GOOD)
                     break;
-                v->hasServerTimestamp = UA_TRUE;
-                v->serverTimestamp = UA_DateTime_now();
             }
         }
         break;
@@ -138,7 +140,7 @@ static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue
             else {
                 UA_DataValue val;
                 UA_DataValue_init(&val);
-                retval |= vn->variable.dataSource.read(vn->variable.dataSource.handle, &val);
+                retval |= vn->variable.dataSource.read(vn->variable.dataSource.handle, UA_FALSE, &val);
                 if(retval != UA_STATUSCODE_GOOD)
                     break;
                 retval |= UA_Variant_copySetValue(&v->value, &val.value.type->typeId,
@@ -170,7 +172,7 @@ static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue
             } else {
                 UA_DataValue val;
                 UA_DataValue_init(&val);
-                retval |= vn->variable.dataSource.read(vn->variable.dataSource.handle, &val);
+                retval |= vn->variable.dataSource.read(vn->variable.dataSource.handle, UA_FALSE, &val);
                 if(retval != UA_STATUSCODE_GOOD)
                     break;
                 if(!val.hasVariant) {
@@ -238,6 +240,11 @@ static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue
     if(retval != UA_STATUSCODE_GOOD) {
         v->hasStatus = UA_TRUE;
         v->status = UA_STATUSCODE_BADNOTREADABLE;
+    } else {
+        if(timestamps == UA_TIMESTAMPSTORETURN_SERVER || timestamps == UA_TIMESTAMPSTORETURN_BOTH) {
+            v->hasServerTimestamp = UA_TRUE;
+            v->serverTimestamp = UA_DateTime_now();
+        }
     }
 }
 
@@ -279,7 +286,7 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
     response->resultsSize = size;
     for(size_t i = 0;i < size;i++) {
         if(!isExternal[i])
-            readValue(server, &request->nodesToRead[i], &response->results[i]);
+            readValue(server, request->timestampsToReturn, &request->nodesToRead[i], &response->results[i]);
     }
 
 #ifdef EXTENSION_STATELESS

+ 5 - 2
src/server/ua_services_session.c

@@ -18,7 +18,8 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
     // creates a session and adds a pointer to the channel. Only when the
     // session is activated will the channel point to the session as well
 	UA_Session *newSession;
-    response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager, channel, &newSession);
+    response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager,
+                                                                             channel, &newSession);
 	if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
 		return;
 
@@ -28,7 +29,9 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
     response->revisedSessionTimeout = newSession->timeout;
     response->authenticationToken = newSession->authenticationToken;
     response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName);
-    response->responseHeader.serviceResult |= UA_ByteString_copy(&server->serverCertificate, &response->serverCertificate);
+    if(server->endpointDescriptions)
+        response->responseHeader.serviceResult |=
+            UA_ByteString_copy(&server->endpointDescriptions->serverCertificate, &response->serverCertificate);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
         UA_SessionManager_removeSession(&server->sessionManager, &newSession->sessionId);
          return;