Browse Source

writing a bytestring into a byte array

Julius Pfrommer 10 years ago
parent
commit
9d2c1865a4

+ 18 - 18
src/server/ua_services_attribute.c

@@ -59,38 +59,31 @@ static void readValue(UA_Server *server, UA_TimestampsToReturn timestamps,
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &node->nodeId, &UA_TYPES[UA_TYPES_NODEID]);
         break;
-
     case UA_ATTRIBUTEID_NODECLASS:
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &node->nodeClass, &UA_TYPES[UA_TYPES_INT32]);
         break;
-
     case UA_ATTRIBUTEID_BROWSENAME:
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &node->browseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
         break;
-
     case UA_ATTRIBUTEID_DISPLAYNAME:
         retval |= UA_Variant_copySetValue(&v->value, &node->displayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
         if(retval == UA_STATUSCODE_GOOD)
             v->hasVariant = UA_TRUE;
         break;
-
     case UA_ATTRIBUTEID_DESCRIPTION:
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &node->description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
         break;
-
     case UA_ATTRIBUTEID_WRITEMASK:
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &node->writeMask, &UA_TYPES[UA_TYPES_UINT32]);
         break;
-
     case UA_ATTRIBUTEID_USERWRITEMASK:
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &node->userWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
         break;
-
     case UA_ATTRIBUTEID_ISABSTRACT:
         CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE | UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE |
                         UA_NODECLASS_DATATYPE);
@@ -98,28 +91,24 @@ static void readValue(UA_Server *server, UA_TimestampsToReturn timestamps,
         retval |= UA_Variant_copySetValue(&v->value, &((const UA_ReferenceTypeNode *)node)->isAbstract,
                                           &UA_TYPES[UA_TYPES_BOOLEAN]);
         break;
-
     case UA_ATTRIBUTEID_SYMMETRIC:
         CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &((const UA_ReferenceTypeNode *)node)->symmetric,
                                           &UA_TYPES[UA_TYPES_BOOLEAN]);
         break;
-
     case UA_ATTRIBUTEID_INVERSENAME:
         CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &((const UA_ReferenceTypeNode *)node)->inverseName,
                                           &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
         break;
-
     case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
         CHECK_NODECLASS(UA_NODECLASS_VIEW);
         v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copySetValue(&v->value, &((const UA_ViewNode *)node)->containsNoLoops,
                                           &UA_TYPES[UA_TYPES_BOOLEAN]);
         break;
-
     case UA_ATTRIBUTEID_EVENTNOTIFIER:
         CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
         v->hasVariant = UA_TRUE;
@@ -128,7 +117,7 @@ static void readValue(UA_Server *server, UA_TimestampsToReturn timestamps,
                                           	  &UA_TYPES[UA_TYPES_BYTE]);
         } else {
         	retval |= UA_Variant_copySetValue(&v->value, &((const UA_ObjectNode *)node)->eventNotifier,
-        	                                          	  &UA_TYPES[UA_TYPES_BYTE]);
+                                              &UA_TYPES[UA_TYPES_BYTE]);
         }
         break;
 
@@ -156,7 +145,7 @@ static void readValue(UA_Server *server, UA_TimestampsToReturn timestamps,
 					if(retval != UA_STATUSCODE_GOOD)
 						break;
 				}
-        	}else{
+        	} else {
     			v->hasVariant = UA_FALSE;
     			handleSourceTimestamps(timestamps, v);
         	}
@@ -419,15 +408,26 @@ static UA_StatusCode writeValue(UA_Server *server, UA_WriteValue *wvalue) {
                     retval = UA_STATUSCODE_BADTYPEMISMATCH;
                     break;
                 }
+
                 if(!UA_NodeId_equal(&vn->variable.variant.type->typeId, &wvalue->value.value.type->typeId)) {
-                    // when the nodeids differ, it is possible that an enum was sent as an int, or
-                    // an opaque type as a bytestring
-                    if(!vn->variable.variant.type->namespaceZero || wvalue->value.value.type->namespaceZero ||
-                       vn->variable.variant.type->typeIndex != wvalue->value.value.type->typeIndex) {
+                    if(vn->variable.variant.type->namespaceZero && wvalue->value.value.type->namespaceZero &&
+                       vn->variable.variant.type->typeIndex == wvalue->value.value.type->typeIndex)
+                        // an enum was sent as an int32, or an opaque type as a bytestring
+                        wvalue->value.value.type = vn->variable.variant.type;
+                    else if(vn->variable.variant.type == &UA_TYPES[UA_TYPES_BYTE] &&
+                            (!vn->variable.variant.dataPtr || vn->variable.variant.arrayLength > -1) /* isArray */ &&
+                            wvalue->value.value.type == &UA_TYPES[UA_TYPES_BYTESTRING] &&
+                            wvalue->value.value.dataPtr && wvalue->value.value.arrayLength == -1 /* isScalar */) {
+                        // a string is written to a byte array
+                        UA_ByteString *str = (UA_ByteString*) wvalue->value.value.dataPtr;
+                        wvalue->value.value.arrayLength = str->length;
+                        wvalue->value.value.dataPtr = str->data;
+                        wvalue->value.value.type = &UA_TYPES[UA_TYPES_BYTE];
+                        UA_free(str);
+                    } else {
                         retval = UA_STATUSCODE_BADTYPEMISMATCH;
                         break;
                     }
-                    wvalue->value.value.type = vn->variable.variant.type;
                 }
 
                 UA_VariableNode *newVn = UA_VariableNode_new();

+ 2 - 6
src/server/ua_services_nodemanagement.c

@@ -39,19 +39,14 @@ static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node *
 
     // now copy all the attributes. This potentially removes them from the decoded attributes.
     COPY_STANDARDATTRIBUTES;
-
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
         vnode->accessLevel = attr.accessLevel;
-
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
         vnode->userAccessLevel = attr.userAccessLevel;
-
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
         vnode->historizing = attr.historizing;
-
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
         vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
-
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
         vnode->valueRank = attr.valueRank;
 
@@ -83,8 +78,9 @@ static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node *
 
 static UA_StatusCode parseObjectNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
     if(attributes->typeId.identifier.numeric !=
-       UA_TYPES[UA_TYPES_OBJECTATTRIBUTES].typeId.identifier.numeric + UA_ENCODINGOFFSET_BINARY)  // VariableAttributes_Encoding_DefaultBinary
+       UA_TYPES[UA_TYPES_OBJECTATTRIBUTES].typeId.identifier.numeric + UA_ENCODINGOFFSET_BINARY)
         return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+
     UA_ObjectAttributes attr;
     size_t pos = 0;
     // todo return more informative error codes from decodeBinary

+ 6 - 9
src/server/ua_services_view.c

@@ -4,8 +4,9 @@
 #include "ua_nodestore.h"
 #include "ua_util.h"
 
-static UA_StatusCode fillrefdescr(UA_NodeStore *ns, const UA_Node *curr, UA_ReferenceNode *ref,
-                                  UA_UInt32 mask, UA_ReferenceDescription *descr)
+static UA_StatusCode
+fillrefdescr(UA_NodeStore *ns, const UA_Node *curr, UA_ReferenceNode *ref, UA_UInt32 mask,
+             UA_ReferenceDescription *descr)
 {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_ReferenceDescription_init(descr);
@@ -98,26 +99,22 @@ findsubtypes(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **reftypes, size
                 continue;
 
             if(++last >= results_size) { // is the array big enough?
-                UA_NodeId *new_results = UA_malloc(sizeof(UA_NodeId) * results_size * 2);
+                UA_NodeId *new_results = UA_realloc(results, sizeof(UA_NodeId) * results_size * 2);
                 if(!new_results) {
                     retval = UA_STATUSCODE_BADOUTOFMEMORY;
                     break;
                 }
-                UA_memcpy(new_results, results, sizeof(UA_NodeId) * results_size);
                 results_size *= 2;
-                UA_free(results);
-                results = new_results;
             }
 
             retval = UA_NodeId_copy(&node->references[i].targetId.nodeId, &results[last]);
             if(retval != UA_STATUSCODE_GOOD) {
-                last--;
+                last--; // for array_delete
                 break;
             }
         }
         UA_NodeStore_release(node);
-        index++;
-    } while(index <= last && retval == UA_STATUSCODE_GOOD);
+    } while(++index <= last && retval == UA_STATUSCODE_GOOD);
 
     if(retval) {
         UA_Array_delete(results, &UA_TYPES[UA_TYPES_NODEID], last);