浏览代码

compile methods

Julius Pfrommer 9 年之前
父节点
当前提交
7f08e21937

+ 1 - 1
examples/client.c

@@ -149,7 +149,7 @@ int main(int argc, char *argv[]) {
                             UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);
     if(retval == UA_STATUSCODE_GOOD) {
         printf("Method call was successfull, and %i returned values available.\n", outputSize);
-        UA_Array_delete(output, &UA_TYPES[UA_TYPES_VARIANT], outputSize);
+        UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
     } else {
         printf("Method call was unsuccessfull, and %x returned values available.\n", retval);
     }

+ 1 - 1
examples/server_method.c

@@ -38,7 +38,7 @@ static UA_StatusCode
 IncInt32ArrayValuesMethod(const UA_NodeId objectId, const UA_Variant *input,
                           UA_Variant *output, void *handle) {
 	UA_Variant_setArrayCopy(output, input->data, 5, &UA_TYPES[UA_TYPES_INT32]);
-	for(int i = 0; i< input->arrayLength; i++)
+	for(size_t i = 0; i< input->arrayLength; i++)
 		((UA_Int32*)output->data)[i] = ((UA_Int32*)input->data)[i] + 1;
 	return UA_STATUSCODE_GOOD;
 }

+ 33 - 40
src/client/ua_client_highlevel_subscriptions.c

@@ -197,16 +197,15 @@ UA_Client_processPublishRx(UA_Client *client, UA_PublishResponse response) {
     // Check if the server has acknowledged any of our ACKS
     // Note that a list of serverside status codes may be send without valid publish data, i.e. 
     // during keepalives or no data availability
-    UA_Client_NotificationsAckNumber *tmpAck = client->pendingNotificationsAcks.lh_first;
-    UA_Client_NotificationsAckNumber *nxtAck = tmpAck;
-    for(int i=0; i<response.resultsSize && nxtAck != NULL; i++) {
-        tmpAck = nxtAck;
-        nxtAck = tmpAck->listEntry.le_next;
+    UA_Client_NotificationsAckNumber *ack, *tmpAck;
+    size_t i = 0;
+    LIST_FOREACH_SAFE(ack, &client->pendingNotificationsAcks, listEntry, tmpAck) {
         if(response.results[i] == UA_STATUSCODE_GOOD ||
-            response.results[i] == UA_STATUSCODE_BADSEQUENCENUMBERINVALID) {
-            LIST_REMOVE(tmpAck, listEntry);
-            UA_free(tmpAck);
+           response.results[i] == UA_STATUSCODE_BADSEQUENCENUMBERINVALID) {
+            LIST_REMOVE(ack, listEntry);
+            UA_free(ack);
         }
+        i++;
     }
     
     if(response.subscriptionId == 0)
@@ -221,44 +220,38 @@ UA_Client_processPublishRx(UA_Client *client, UA_PublishResponse response) {
         return UA_FALSE;
     
     UA_NotificationMessage msg = response.notificationMessage;
-    UA_DataChangeNotification dataChangeNotification;
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_Client_MonitoredItem *mon;
-    size_t decodingOffset = 0;
-    for(int k = 0; k < msg.notificationDataSize; k++) {
-        if(msg.notificationData[k].encoding == UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING) {
-            if(msg.notificationData[k].typeId.namespaceIndex == 0 &&
-                msg.notificationData[k].typeId.identifier.numeric == 811 ) {
-                // This is a dataChangeNotification
-                retval |= UA_DataChangeNotification_decodeBinary(&msg.notificationData[k].body,
-                                                                 &decodingOffset, &dataChangeNotification);
-                UA_MonitoredItemNotification *mitemNot;
-                for(int i = 0; i < dataChangeNotification.monitoredItemsSize; i++) {
-                    mitemNot = &dataChangeNotification.monitoredItems[i];
-                    // find this client handle
-                    LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
-                        if(mon->ClientHandle == mitemNot->clientHandle) {
-                            mon->handler(mitemNot->clientHandle, &mitemNot->value);
-                            break;
-                        }
+    for(size_t k = 0; k < msg.notificationDataSize; k++) {
+        if(msg.notificationData[k].encoding != UA_EXTENSIONOBJECT_DECODED)
+            continue;
+        
+        if(msg.notificationData[k].content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]) {
+            // This is a dataChangeNotification
+            UA_DataChangeNotification *dataChangeNotification = msg.notificationData[k].content.decoded.data;
+            for(size_t i = 0; i < dataChangeNotification->monitoredItemsSize; i++) {
+            UA_MonitoredItemNotification *mitemNot = &dataChangeNotification->monitoredItems[i];
+                // find this client handle
+                LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
+                    if(mon->ClientHandle == mitemNot->clientHandle) {
+                        mon->handler(mitemNot->clientHandle, &mitemNot->value);
+                        break;
                     }
                 }
-                UA_DataChangeNotification_deleteMembers(&dataChangeNotification);
-                continue;
             }
+            continue;
+        }
 
-            if(msg.notificationData[k].typeId.namespaceIndex == 0 &&
-               msg.notificationData[k].typeId.identifier.numeric == 820 ) {
-                //FIXME: This is a statusChangeNotification (not supported yet)
-                continue;
-            }
+        /* if(msg.notificationData[k].typeId.namespaceIndex == 0 && */
+        /*    msg.notificationData[k].typeId.identifier.numeric == 820 ) { */
+        /*     //FIXME: This is a statusChangeNotification (not supported yet) */
+        /*     continue; */
+        /* } */
 
-            if(msg.notificationData[k].typeId.namespaceIndex == 0 &&
-               msg.notificationData[k].typeId.identifier.numeric == 916 ) {
-                //FIXME: This is an EventNotification
-                continue;
-            }
-        }
+        /* if(msg.notificationData[k].typeId.namespaceIndex == 0 && */
+        /*    msg.notificationData[k].typeId.identifier.numeric == 916 ) { */
+        /*     //FIXME: This is an EventNotification */
+        /*     continue; */
+        /* } */
     }
     
     /* We processed this message, add it to the list of pending acks (but make

+ 41 - 55
src/server/ua_services_call.c

@@ -5,16 +5,15 @@
 #include "ua_nodestore.h"
 #include "ua_nodes.h"
 
-static const UA_VariableNode
-*getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
-                          UA_String withBrowseName) {
-    const UA_Node *refTarget;
+static const UA_VariableNode *
+getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
+                         UA_String withBrowseName) {
     UA_NodeId hasProperty = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
-    
-    for(UA_Int32 i = 0; i < ofMethod->referencesSize; i++) {
+    for(size_t i = 0; i < ofMethod->referencesSize; i++) {
         if(ofMethod->references[i].isInverse == UA_FALSE && 
             UA_NodeId_equal(&hasProperty, &ofMethod->references[i].referenceTypeId)) {
-            refTarget = UA_NodeStore_get(server->nodestore, &ofMethod->references[i].targetId.nodeId);
+            const UA_Node *refTarget =
+                UA_NodeStore_get(server->nodestore, &ofMethod->references[i].targetId.nodeId);
             if(!refTarget)
                 continue;
             if(refTarget->nodeClass == UA_NODECLASS_VARIABLE && 
@@ -29,16 +28,16 @@ static const UA_VariableNode
 }
 
 static UA_StatusCode
-statisfySignature(UA_Variant *var, UA_Argument arg) {
-    if(!UA_NodeId_equal(&var->type->typeId, &arg.dataType) )
+satisfySignature(const UA_Variant *var, const UA_Argument *arg) {
+    if(!UA_NodeId_equal(&var->type->typeId, &arg->dataType) )
         return UA_STATUSCODE_BADINVALIDARGUMENT;
     
     // Note: The namespace compiler will compile nodes with their actual array dimensions, never -1
-    if(arg.arrayDimensionsSize > 0 && var->arrayDimensionsSize > 0)
-        if(var->arrayDimensionsSize != arg.arrayDimensionsSize) 
+    if(arg->arrayDimensionsSize > 0 && var->arrayDimensionsSize > 0)
+        if(var->arrayDimensionsSize != arg->arrayDimensionsSize) 
             return UA_STATUSCODE_BADINVALIDARGUMENT;
         
-        // Continue with jpfr's statisfySignature from here on
+        // Continue with jpfr's satisfySignature from here on
         /* ValueRank Semantics
          *  n >= 1: the value is an array with the specified number of dimens*ions.
          *  n = 0: the value is an array with one or more dimensions.
@@ -46,27 +45,27 @@ statisfySignature(UA_Variant *var, UA_Argument arg) {
          *  n = -2: the value can be a scalar or an array with any number of dimensions.
          *  n = -3:  the value can be a scalar or a one dimensional array. */
         UA_Boolean scalar = UA_Variant_isScalar(var);
-        if(arg.valueRank == 0 && scalar)
+        if(arg->valueRank == 0 && scalar)
             return UA_STATUSCODE_BADINVALIDARGUMENT;
-        if(arg.valueRank == -1 && !scalar)
+        if(arg->valueRank == -1 && !scalar)
             return UA_STATUSCODE_BADINVALIDARGUMENT;
-        if(arg.valueRank == -3 && var->arrayDimensionsSize > 1)
+        if(arg->valueRank == -3 && var->arrayDimensionsSize > 1)
             return UA_STATUSCODE_BADINVALIDARGUMENT;
-        if(arg.valueRank > 1 && var->arrayDimensionsSize != arg.arrayDimensionsSize)
+        if(arg->valueRank > 1 && var->arrayDimensionsSize != arg->arrayDimensionsSize)
             return UA_STATUSCODE_BADINVALIDARGUMENT;
         
         //variants do not always encode the dimension flag (e.g. 1d array)
-       if(!var->arrayDimensions && arg.arrayDimensionsSize == 1 &&
-          arg.arrayDimensions[0] == var->arrayLength) {
+       if(!var->arrayDimensions && arg->arrayDimensionsSize == 1 &&
+          arg->arrayDimensions[0] == var->arrayLength) {
     	   return UA_STATUSCODE_GOOD;
        } else {
-         if(arg.valueRank >= 1 && var->arrayDimensionsSize != arg.arrayDimensionsSize)
+         if(arg->valueRank >= 1 && var->arrayDimensionsSize != arg->arrayDimensionsSize)
             return UA_STATUSCODE_BADINVALIDARGUMENT;
-         if(arg.arrayDimensionsSize >= 1) {
-            if(arg.arrayDimensionsSize != var->arrayDimensionsSize)
+         if(arg->arrayDimensionsSize >= 1) {
+            if(arg->arrayDimensionsSize != var->arrayDimensionsSize)
                 return UA_STATUSCODE_BADINVALIDARGUMENT;
-            for(size_t i = 0; i < arg.arrayDimensionsSize; i++) {
-                if(arg.arrayDimensions[i] != var->arrayDimensions[i])
+            for(size_t i = 0; i < arg->arrayDimensionsSize; i++) {
+                if(arg->arrayDimensions[i] != var->arrayDimensions[i])
                     return UA_STATUSCODE_BADINVALIDARGUMENT;
             }
          }
@@ -86,25 +85,14 @@ argConformsToDefinition(UA_CallMethodRequest *rs, const UA_VariableNode *argDefi
        rs->inputArgumentsSize > argDefinition->value.variant.value.arrayLength)
         return UA_STATUSCODE_BADINVALIDARGUMENT;
     
-    const UA_ExtensionObject *thisArgDefExtObj;
-    UA_Variant *var;
-    UA_Argument arg;
-    size_t decodingOffset = 0;
+    if(argDefinition->value.variant.value.type != &UA_TYPES[UA_TYPES_ARGUMENT])
+        return UA_STATUSCODE_BADINTERNALERROR;
+
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    UA_NodeId ArgumentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ARGUMENT + UA_ENCODINGOFFSET_BINARY);
-    for(int i = 0; i<rs->inputArgumentsSize; i++) {
-        var = &rs->inputArguments[i];
-        if(argDefinition->value.variant.value.type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]) {
-            thisArgDefExtObj = &((const UA_ExtensionObject *) (argDefinition->value.variant.value.data))[i];
-            decodingOffset = 0;
-            
-            if(!UA_NodeId_equal(&ArgumentNodeId, &thisArgDefExtObj->typeId))
-                return UA_STATUSCODE_BADINTERNALERROR;
-                
-            retval |= UA_decodeBinary(&thisArgDefExtObj->body, &decodingOffset, &arg, &UA_TYPES[UA_TYPES_ARGUMENT]);
-        } else if(argDefinition->value.variant.value.type == &UA_TYPES[UA_TYPES_ARGUMENT])
-            arg = ((UA_Argument *) argDefinition->value.variant.value.data)[i];
-        retval |= statisfySignature(var, arg);
+    for(size_t i = 0; i < argDefinition->value.variant.value.arrayLength; i++) {
+        UA_Variant *var = &rs->inputArguments[i];
+        UA_Argument *arg = &((UA_Argument*)argDefinition->value.variant.value.data)[i];
+        retval |= satisfySignature(var, arg);
     }
     return retval;
 }
@@ -138,7 +126,7 @@ callMethod(UA_Server *server, UA_Session *session, UA_CallMethodRequest *request
     // Object must have a hasComponent reference (or any inherited referenceType from sayd reference) 
     // to be valid for a methodCall...
     result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
-    for(UA_Int32 i = 0; i < withObject->referencesSize; i++) {
+    for(size_t i = 0; i < withObject->referencesSize; i++) {
         if(withObject->references[i].referenceTypeId.identifier.numeric == UA_NS0ID_HASCOMPONENT) {
             // FIXME: Not checking any subtypes of HasComponent at the moment
             if(UA_NodeId_equal(&withObject->references[i].targetId.nodeId, &methodCalled->nodeId)) {
@@ -157,32 +145,30 @@ callMethod(UA_Server *server, UA_Session *session, UA_CallMethodRequest *request
     }
 
     /* Verify Input Argument count, types and sizes */
-    const UA_VariableNode *inputArguments = getArgumentsVariableNode(server, methodCalled,
-                                                                     UA_STRING("InputArguments"));
+    const UA_VariableNode *inputArguments =
+        getArgumentsVariableNode(server, methodCalled, UA_STRING("InputArguments"));
     if(inputArguments) {
-        // Expects arguments
         result->statusCode = argConformsToDefinition(request, inputArguments);
         UA_NodeStore_release((const UA_Node*)inputArguments);
         if(result->statusCode != UA_STATUSCODE_GOOD)
             goto releaseBothReturn;
     } else if(request->inputArgumentsSize > 0) {
-        // Expects no arguments, but got some
         result->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT;
         goto releaseBothReturn;
     }
 
-    const UA_VariableNode *outputArguments = getArgumentsVariableNode(server, methodCalled,
-                                                                      UA_STRING("OutputArguments"));
+    const UA_VariableNode *outputArguments =
+        getArgumentsVariableNode(server, methodCalled, UA_STRING("OutputArguments"));
     if(!outputArguments) {
         // A MethodNode must have an OutputArguments variable (which may be empty)
         result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
         goto releaseBothReturn;
     }
     
-    // Call method if available
+    /* Call method if available */
     if(methodCalled->attachedMethod) {
-        result->outputArguments = UA_Array_new(&UA_TYPES[UA_TYPES_VARIANT],
-                                               outputArguments->value.variant.value.arrayLength);
+        result->outputArguments = UA_Array_new(outputArguments->value.variant.value.arrayLength,
+                                               &UA_TYPES[UA_TYPES_VARIANT]);
         result->outputArgumentsSize = outputArguments->value.variant.value.arrayLength;
         result->statusCode = methodCalled->attachedMethod(withObject->nodeId, request->inputArguments,
                                                           result->outputArguments, methodCalled->methodHandle);
@@ -190,7 +176,7 @@ callMethod(UA_Server *server, UA_Session *session, UA_CallMethodRequest *request
     else
         result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
     
-    /* FIXME: Verify Output Argument count, types and sizes */
+    /* TODO: Verify Output Argument count, types and sizes */
     if(outputArguments)
         UA_NodeStore_release((const UA_Node*)outputArguments);
 
@@ -207,14 +193,14 @@ void Service_Call(UA_Server *server, UA_Session *session, const UA_CallRequest *
         return;
     }
 
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_CALLMETHODRESULT],
-                                     request->methodsToCallSize);
+    response->results = UA_Array_new(request->methodsToCallSize,
+                                     &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
     }
     response->resultsSize = request->methodsToCallSize;
     
-    for(UA_Int32 i = 0; i < request->methodsToCallSize;i++)
+    for(size_t i = 0; i < request->methodsToCallSize;i++)
         callMethod(server, session, &request->methodsToCall[i], &response->results[i]);
 }

+ 11 - 9
src/server/ua_services_subscription.c

@@ -119,14 +119,14 @@ void Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
         return;
     }
 
-    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], request->itemsToCreateSize);
+    response->results = UA_Array_new(request->itemsToCreateSize, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
     }
     response->resultsSize = request->itemsToCreateSize;
 
-    for(UA_Int32 i = 0; i<request->itemsToCreateSize; i++)
+    for(size_t i = 0; i < request->itemsToCreateSize; i++)
         createMonitoredItems(server, session, sub, &request->itemsToCreate[i], &response->results[i]);
 }
 
@@ -139,7 +139,7 @@ void Service_Publish(UA_Server *server, UA_Session *session, const UA_PublishReq
     // Delete Acknowledged Subscription Messages
     response->resultsSize = request->subscriptionAcknowledgementsSize;
     response->results     = UA_malloc(sizeof(UA_StatusCode)*(response->resultsSize));
-    for(UA_Int32 i = 0; i < request->subscriptionAcknowledgementsSize; i++) {
+    for(size_t i = 0; i < request->subscriptionAcknowledgementsSize; i++) {
         response->results[i] = UA_STATUSCODE_GOOD;
         UA_Subscription *sub =
             SubscriptionManager_getSubscriptionByID(&session->subscriptionManager,
@@ -248,9 +248,10 @@ void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
     }
     response->resultsSize = request->subscriptionIdsSize;
 
-    for(UA_Int32 i = 0; i < request->subscriptionIdsSize; i++)
-        response->results[i] = SubscriptionManager_deleteSubscription(server, &session->subscriptionManager,
-                                                                      request->subscriptionIds[i]);
+    for(size_t i = 0; i < request->subscriptionIdsSize; i++)
+        response->results[i] =
+            SubscriptionManager_deleteSubscription(server, &session->subscriptionManager,
+                                                   request->subscriptionIds[i]);
 } 
 
 void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
@@ -270,7 +271,8 @@ void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
     }
     response->resultsSize = request->monitoredItemIdsSize;
 
-    for(UA_Int32 i = 0; i < request->monitoredItemIdsSize; i++)
-        response->results[i] = SubscriptionManager_deleteMonitoredItem(manager, sub->subscriptionID,
-                                                                       request->monitoredItemIds[i]);
+    for(size_t i = 0; i < request->monitoredItemIdsSize; i++)
+        response->results[i] =
+            SubscriptionManager_deleteMonitoredItem(manager, sub->subscriptionID,
+                                                    request->monitoredItemIds[i]);
 }

+ 20 - 57
src/server/ua_subscription.c

@@ -22,13 +22,12 @@ UA_Subscription *UA_Subscription_new(UA_Int32 subscriptionID) {
 }
 
 void UA_Subscription_deleteMembers(UA_Subscription *subscription, UA_Server *server) {
-    UA_MonitoredItem *mon, *tmp_mon;
-    
     // Just in case any parallel process attempts to access this subscription
     // while we are deleting it... make it vanish.
     subscription->subscriptionID = 0;
     
     // Delete monitored Items
+    UA_MonitoredItem *mon, *tmp_mon;
     LIST_FOREACH_SAFE(mon, &subscription->MonitoredItems, listEntry, tmp_mon) {
         LIST_REMOVE(mon, listEntry);
         MonitoredItem_delete(mon);
@@ -38,7 +37,7 @@ void UA_Subscription_deleteMembers(UA_Subscription *subscription, UA_Server *ser
     Subscription_deleteUnpublishedNotification(0, true, subscription);
     
     // Unhook/Unregister any timed work assiociated with this subscription
-    if(subscription->timedUpdateJob != NULL){
+    if(subscription->timedUpdateJob) {
         Subscription_unregisterUpdateJob(server, subscription);
         UA_free(subscription->timedUpdateJob);
     }
@@ -79,8 +78,6 @@ void Subscription_updateNotifications(UA_Subscription *subscription) {
     //MonitoredItem_queuedValue *queuedValue;
     UA_unpublishedNotification *msg;
     UA_UInt32 monItemsChangeT = 0, monItemsStatusT = 0, monItemsEventT = 0;
-    UA_DataChangeNotification *changeNotification;
-    size_t notificationOffset;
     
     if(!subscription || subscription->lastPublished + subscription->publishingInterval > UA_DateTime_now())
         return;
@@ -115,9 +112,8 @@ void Subscription_updateNotifications(UA_Subscription *subscription) {
         return;
     }
     
-    msg = (UA_unpublishedNotification *) UA_malloc(sizeof(UA_unpublishedNotification));
-    msg->notification = UA_malloc(sizeof(UA_NotificationMessage));
-    INITPOINTER(msg->notification->notificationData);
+    msg = UA_malloc(sizeof(UA_unpublishedNotification));
+    msg->notification = UA_NotificationMessage_new();
     msg->notification->sequenceNumber = subscription->sequenceNumber++;
     msg->notification->publishTime    = UA_DateTime_now();
     
@@ -125,22 +121,18 @@ void Subscription_updateNotifications(UA_Subscription *subscription) {
     // list of Queued values from all monitoredItems of that type
     msg->notification->notificationDataSize = ISNOTZERO(monItemsChangeT);
     // + ISNOTZERO(monItemsEventT) + ISNOTZERO(monItemsStatusT);
-    msg->notification->notificationData = UA_Array_new(&UA_TYPES[UA_TYPES_EXTENSIONOBJECT], 
-                                                       msg->notification->notificationDataSize);
+    msg->notification->notificationData =
+        UA_Array_new(msg->notification->notificationDataSize, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
     
-    for(int notmsgn=0; notmsgn < msg->notification->notificationDataSize; notmsgn++) {
+    for(size_t notmsgn = 0; notmsgn < msg->notification->notificationDataSize; notmsgn++) {
         // Set the notification message type and encoding for each of 
         //   the three possible NotificationData Types
-        msg->notification->notificationData[notmsgn].encoding = 1; // Encoding is always binary
-        msg->notification->notificationData[notmsgn].typeId = UA_NODEID_NUMERIC(0, 811);
+        /* msg->notification->notificationData[notmsgn].encoding = 1; // Encoding is always binary */
+        /* msg->notification->notificationData[notmsgn].typeId = UA_NODEID_NUMERIC(0, 811); */
       
         if(notmsgn == 0) {
-            // Construct a DataChangeNotification
-            changeNotification = UA_malloc(sizeof(UA_DataChangeNotification));
-	
-            // Create one DataChangeNotification for each queue item held in each monitoredItems queue:
-            changeNotification->monitoredItems = UA_Array_new(&UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION],
-                                                              monItemsChangeT);
+            UA_DataChangeNotification *changeNotification = UA_DataChangeNotification_new();
+            changeNotification->monitoredItems = UA_Array_new(monItemsChangeT, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
 	
             // Scan all monitoredItems in this subscription and have their queue transformed into an Array of
             // the propper NotificationMessageType (Status, Change, Event)
@@ -152,29 +144,10 @@ void Subscription_updateNotifications(UA_Subscription *subscription) {
                 monItemsChangeT += MonitoredItem_QueueToDataChangeNotifications(&changeNotification->monitoredItems[monItemsChangeT], mon);
                 MonitoredItem_ClearQueue(mon);
             }
-            
-            changeNotification->monitoredItemsSize  = monItemsChangeT;
-            changeNotification->diagnosticInfosSize = 0;
-            changeNotification->diagnosticInfos     = NULL;
-        
-            msg->notification->notificationData[notmsgn].body.length =
-                UA_calcSizeBinary(changeNotification, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
-            msg->notification->notificationData[notmsgn].body.data   =
-                UA_calloc(msg->notification->notificationData[notmsgn].body.length, sizeof(UA_Byte));
-        
-            notificationOffset = 0;
-            UA_StatusCode retval = UA_encodeBinary(changeNotification, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION],
-                                                   &msg->notification->notificationData[notmsgn].body, &notificationOffset);
-            if(retval != UA_STATUSCODE_GOOD)
-                UA_ByteString_deleteMembers(&msg->notification->notificationData[notmsgn].body);
-	
-            // FIXME: Not properly freed!
-            for(unsigned int i=0; i<monItemsChangeT; i++) {
-                UA_MonitoredItemNotification *thisNotification = &(changeNotification->monitoredItems[i]);
-                UA_DataValue_deleteMembers(&(thisNotification->value));
-            }
-            UA_free(changeNotification->monitoredItems);
-            UA_free(changeNotification);
+            changeNotification->monitoredItemsSize = monItemsChangeT;
+            msg->notification->notificationData[notmsgn].encoding = UA_EXTENSIONOBJECT_DECODED;
+            msg->notification->notificationData[notmsgn].content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION];
+            msg->notification->notificationData[notmsgn].content.decoded.data = changeNotification;
         } else if(notmsgn == 1) {
             // FIXME: Constructing a StatusChangeNotification is not implemented
         } else if(notmsgn == 2) {
@@ -216,12 +189,8 @@ void Subscription_copyTopNotificationMessage(UA_NotificationMessage *dst, UA_Sub
     
     if(latest->notificationDataSize == 0)
         return;
-    
-    dst->notificationData = (UA_ExtensionObject *) UA_malloc(sizeof(UA_ExtensionObject));
-    dst->notificationData->encoding = latest->notificationData->encoding;
-    dst->notificationData->typeId   = latest->notificationData->typeId;
-    UA_ByteString_copy(&latest->notificationData->body,
-                       &dst->notificationData->body);
+    dst->notificationData = UA_ExtensionObject_new();
+    UA_ExtensionObject_copy(latest->notificationData, dst->notificationData);
 }
 
 UA_UInt32 Subscription_deleteUnpublishedNotification(UA_UInt32 seqNo, UA_Boolean bDeleteAll, UA_Subscription *sub) {
@@ -231,14 +200,8 @@ UA_UInt32 Subscription_deleteUnpublishedNotification(UA_UInt32 seqNo, UA_Boolean
         if (!bDeleteAll && not->notification->sequenceNumber != seqNo)
             continue;
         LIST_REMOVE(not, listEntry);
-        if(not->notification) {
-            if(not->notification->notificationData) {
-                if(not->notification->notificationData->body.data)
-                    UA_free(not->notification->notificationData->body.data);
-                UA_free(not->notification->notificationData);
-            }
-            UA_free(not->notification);
-        }
+        if(not->notification)
+            UA_NotificationMessage_delete(not->notification);
         UA_free(not);
         deletedItems++;
     }
@@ -519,7 +482,7 @@ void MonitoredItem_QueuePushDataValue(UA_Server *server, UA_MonitoredItem *monit
     }
   
     // encode the data to find if its different to the previous
-    newValueAsByteString.length = UA_calcSizeBinary(&newvalue->value, &UA_TYPES[UA_TYPES_DATAVALUE]);
+    newValueAsByteString.length = 512; // Todo: Hack! We should make a copy of the value, not encode it. UA_calcSizeBinary(&newvalue->value, &UA_TYPES[UA_TYPES_DATAVALUE]);
     newValueAsByteString.data   = UA_malloc(newValueAsByteString.length);
     UA_StatusCode retval = UA_encodeBinary(&newvalue->value, &UA_TYPES[UA_TYPES_DATAVALUE], &newValueAsByteString, &encodingOffset);
     if(retval != UA_STATUSCODE_GOOD)