|
@@ -5,16 +5,15 @@
|
|
#include "ua_nodestore.h"
|
|
#include "ua_nodestore.h"
|
|
#include "ua_nodes.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);
|
|
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 &&
|
|
if(ofMethod->references[i].isInverse == UA_FALSE &&
|
|
UA_NodeId_equal(&hasProperty, &ofMethod->references[i].referenceTypeId)) {
|
|
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)
|
|
if(!refTarget)
|
|
continue;
|
|
continue;
|
|
if(refTarget->nodeClass == UA_NODECLASS_VARIABLE &&
|
|
if(refTarget->nodeClass == UA_NODECLASS_VARIABLE &&
|
|
@@ -29,16 +28,16 @@ static const UA_VariableNode
|
|
}
|
|
}
|
|
|
|
|
|
static UA_StatusCode
|
|
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;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
|
|
|
|
// Note: The namespace compiler will compile nodes with their actual array dimensions, never -1
|
|
// 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;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
|
|
|
|
- // Continue with jpfr's statisfySignature from here on
|
|
|
|
|
|
+ // Continue with jpfr's satisfySignature from here on
|
|
/* ValueRank Semantics
|
|
/* ValueRank Semantics
|
|
* n >= 1: the value is an array with the specified number of dimens*ions.
|
|
* 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.
|
|
* 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 = -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. */
|
|
* n = -3: the value can be a scalar or a one dimensional array. */
|
|
UA_Boolean scalar = UA_Variant_isScalar(var);
|
|
UA_Boolean scalar = UA_Variant_isScalar(var);
|
|
- if(arg.valueRank == 0 && scalar)
|
|
|
|
|
|
+ if(arg->valueRank == 0 && scalar)
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
- if(arg.valueRank == -1 && !scalar)
|
|
|
|
|
|
+ if(arg->valueRank == -1 && !scalar)
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
- if(arg.valueRank == -3 && var->arrayDimensionsSize > 1)
|
|
|
|
|
|
+ if(arg->valueRank == -3 && var->arrayDimensionsSize > 1)
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
- if(arg.valueRank > 1 && var->arrayDimensionsSize != arg.arrayDimensionsSize)
|
|
|
|
|
|
+ if(arg->valueRank > 1 && var->arrayDimensionsSize != arg->arrayDimensionsSize)
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
|
|
|
|
//variants do not always encode the dimension flag (e.g. 1d array)
|
|
//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;
|
|
return UA_STATUSCODE_GOOD;
|
|
} else {
|
|
} else {
|
|
- if(arg.valueRank >= 1 && var->arrayDimensionsSize != arg.arrayDimensionsSize)
|
|
|
|
|
|
+ if(arg->valueRank >= 1 && var->arrayDimensionsSize != arg->arrayDimensionsSize)
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
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;
|
|
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;
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -86,25 +85,14 @@ argConformsToDefinition(UA_CallMethodRequest *rs, const UA_VariableNode *argDefi
|
|
rs->inputArgumentsSize > argDefinition->value.variant.value.arrayLength)
|
|
rs->inputArgumentsSize > argDefinition->value.variant.value.arrayLength)
|
|
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
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_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;
|
|
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)
|
|
// Object must have a hasComponent reference (or any inherited referenceType from sayd reference)
|
|
// to be valid for a methodCall...
|
|
// to be valid for a methodCall...
|
|
result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
|
|
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) {
|
|
if(withObject->references[i].referenceTypeId.identifier.numeric == UA_NS0ID_HASCOMPONENT) {
|
|
// FIXME: Not checking any subtypes of HasComponent at the moment
|
|
// FIXME: Not checking any subtypes of HasComponent at the moment
|
|
if(UA_NodeId_equal(&withObject->references[i].targetId.nodeId, &methodCalled->nodeId)) {
|
|
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 */
|
|
/* 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) {
|
|
if(inputArguments) {
|
|
- // Expects arguments
|
|
|
|
result->statusCode = argConformsToDefinition(request, inputArguments);
|
|
result->statusCode = argConformsToDefinition(request, inputArguments);
|
|
UA_NodeStore_release((const UA_Node*)inputArguments);
|
|
UA_NodeStore_release((const UA_Node*)inputArguments);
|
|
if(result->statusCode != UA_STATUSCODE_GOOD)
|
|
if(result->statusCode != UA_STATUSCODE_GOOD)
|
|
goto releaseBothReturn;
|
|
goto releaseBothReturn;
|
|
} else if(request->inputArgumentsSize > 0) {
|
|
} else if(request->inputArgumentsSize > 0) {
|
|
- // Expects no arguments, but got some
|
|
|
|
result->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
result->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT;
|
|
goto releaseBothReturn;
|
|
goto releaseBothReturn;
|
|
}
|
|
}
|
|
|
|
|
|
- const UA_VariableNode *outputArguments = getArgumentsVariableNode(server, methodCalled,
|
|
|
|
- UA_STRING("OutputArguments"));
|
|
|
|
|
|
+ const UA_VariableNode *outputArguments =
|
|
|
|
+ getArgumentsVariableNode(server, methodCalled, UA_STRING("OutputArguments"));
|
|
if(!outputArguments) {
|
|
if(!outputArguments) {
|
|
// A MethodNode must have an OutputArguments variable (which may be empty)
|
|
// A MethodNode must have an OutputArguments variable (which may be empty)
|
|
result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
|
|
result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
|
|
goto releaseBothReturn;
|
|
goto releaseBothReturn;
|
|
}
|
|
}
|
|
|
|
|
|
- // Call method if available
|
|
|
|
|
|
+ /* Call method if available */
|
|
if(methodCalled->attachedMethod) {
|
|
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->outputArgumentsSize = outputArguments->value.variant.value.arrayLength;
|
|
result->statusCode = methodCalled->attachedMethod(withObject->nodeId, request->inputArguments,
|
|
result->statusCode = methodCalled->attachedMethod(withObject->nodeId, request->inputArguments,
|
|
result->outputArguments, methodCalled->methodHandle);
|
|
result->outputArguments, methodCalled->methodHandle);
|
|
@@ -190,7 +176,7 @@ callMethod(UA_Server *server, UA_Session *session, UA_CallMethodRequest *request
|
|
else
|
|
else
|
|
result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
|
|
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)
|
|
if(outputArguments)
|
|
UA_NodeStore_release((const UA_Node*)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;
|
|
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) {
|
|
if(!response->results) {
|
|
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
|
|
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
response->resultsSize = request->methodsToCallSize;
|
|
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]);
|
|
callMethod(server, session, &request->methodsToCall[i], &response->results[i]);
|
|
}
|
|
}
|