예제 #1
0
void Service_Call(UA_Server *server, UA_Session *session, const UA_CallRequest *request,
                  UA_CallResponse *response) {
    if(request->methodsToCallSize <= 0) {
        response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
        return;
    }

    response->results = UA_Array_new(&UA_TYPES[UA_TYPES_CALLMETHODRESULT], request->methodsToCallSize);
    if(!response->results) {
        response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
        return;
    }
    response->resultsSize = request->methodsToCallSize;
    
    for(UA_Int32 i = 0; i < request->methodsToCallSize;i++) {
        UA_CallMethodRequest *rq = &request->methodsToCall[i];
        UA_CallMethodResult  *rs = &response->results[i];
        
        /* Get/Check Nodes */
        const UA_MethodNode *methodCalled =
            (const UA_MethodNode*) UA_NodeStore_get(server->nodestore, &rq->methodId);
        if(methodCalled == UA_NULL) {
            rs->statusCode = UA_STATUSCODE_BADMETHODINVALID;
            continue;
        }
        const UA_ObjectNode *withObject =
            (const UA_ObjectNode *) UA_NodeStore_get(server->nodestore, &rq->objectId);
        if(withObject == UA_NULL) {
            rs->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
            printf("Obj not found\n");
            continue;
        }
        
        if(methodCalled->nodeClass != UA_NODECLASS_METHOD) {
            rs->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
            continue;
        }
        if(withObject->nodeClass != UA_NODECLASS_OBJECT && withObject->nodeClass != UA_NODECLASS_OBJECTTYPE) {
            rs->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
            printf("Obj not found 1\n");
            continue;
        }
        
        /* Verify method/object relations */
        // Object must have a hasComponent reference (or any inherited referenceType from sayd reference) 
        // to be valid for a methodCall...
        for(UA_Int32 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)) {
                    rs->statusCode = UA_STATUSCODE_GOOD;
                    break;
                }
                
            }
        }
        if(rs->statusCode != UA_STATUSCODE_GOOD)
            continue;
        
        /* Verify method executable */
        if(((const UA_MethodNode *) methodCalled)->executable == UA_FALSE ||
           ((const UA_MethodNode *) methodCalled)->userExecutable == UA_FALSE ) {
            rs->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
            continue;
        }

        /* Verify Input Argument count, types and sizes */
        const UA_VariableNode *inputArguments = getArgumentsVariableNode(server, methodCalled,
                                                                         UA_STRING("InputArguments"));
        if(inputArguments) {
            // Expects arguments
            rs->statusCode = argConformsToDefinition(rq, inputArguments);
            UA_NodeStore_release((const UA_Node*)inputArguments);
            if(rs->statusCode != UA_STATUSCODE_GOOD)
                continue;
        } else if(rq->inputArgumentsSize > 0) {
            // Expects no arguments, but got some
            rs->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT;
            UA_NodeStore_release((const UA_Node*)inputArguments);
            continue;
        }

        const UA_VariableNode *outputArguments = getArgumentsVariableNode(server, methodCalled,
                                                                          UA_STRING("OutputArguments"));
        if(!outputArguments) {
            // A MethodNode must have an OutputArguments variable (which may be empty)
            rs->statusCode = UA_STATUSCODE_BADINTERNALERROR;
            continue;
        }
        
        // Call method if available
        if(methodCalled->attachedMethod) {
            rs->outputArguments = UA_Array_new(&UA_TYPES[UA_TYPES_VARIANT],
                                               outputArguments->value.variant.arrayLength);
            rs->outputArgumentsSize = outputArguments->value.variant.arrayLength;
            rs->statusCode = methodCalled->attachedMethod(withObject->nodeId, rq->inputArguments,
                                                          rs->outputArguments);
        }
        else
            rs->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
            
        /* FIXME: Verify Output Argument count, types and sizes */
        if(outputArguments) {
            UA_NodeStore_release((const UA_Node*)outputArguments);
        }
        UA_NodeStore_release((const UA_Node *)withObject);
        UA_NodeStore_release((const UA_Node *)methodCalled);
    }
}
예제 #2
0
void
Service_Call_single(UA_Server *server, UA_Session *session, const UA_CallMethodRequest *request,
                    UA_CallMethodResult *result) {
    /* Verify method/object relations. Object must have a hasComponent reference to the method node. */
    UA_Boolean found = false;
    UA_NodeId hasComponentNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_HASCOMPONENT);
    result->statusCode = isNodeInTree(server->nodestore, &request->methodId, &request->objectId,
                                      &hasComponentNodeId, 1, 1, &found);
    if(!found)
        result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
    if(result->statusCode != UA_STATUSCODE_GOOD)
        return;

    /* Get/verify the method node */
    const UA_MethodNode *methodCalled =
        (const UA_MethodNode*)UA_NodeStore_get(server->nodestore, &request->methodId);
    if(!methodCalled) {
        result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
        return;
    }
    if(methodCalled->nodeClass != UA_NODECLASS_METHOD) {
        result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
        return;
    }
    if(!methodCalled->executable || !methodCalled->userExecutable || !methodCalled->attachedMethod) {
        result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
        return;
    }

    /* Get/verify the object node */
    const UA_ObjectNode *withObject =
        (const UA_ObjectNode*)UA_NodeStore_get(server->nodestore, &request->objectId);
    if(!withObject) {
        result->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
        return;
    }
    if(withObject->nodeClass != UA_NODECLASS_OBJECT && withObject->nodeClass != UA_NODECLASS_OBJECTTYPE) {
        result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
        return;
    }

    /* Verify Input Argument count, types and sizes */
    const UA_VariableNode *inputArguments = getArgumentsVariableNode(server, methodCalled, UA_STRING("InputArguments"));
    if(!inputArguments) {
        result->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT;
        return;
    }
    result->statusCode = argConformsToDefinition(server, inputArguments, request->inputArgumentsSize,
                                                 request->inputArguments);
    if(result->statusCode != UA_STATUSCODE_GOOD)
        return;

    /* Allocate the output arguments */
    const UA_VariableNode *outputArguments = getArgumentsVariableNode(server, methodCalled, UA_STRING("OutputArguments"));
    if(!outputArguments) {
        result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
        return;
    }
    result->outputArguments = UA_Array_new(outputArguments->value.variant.value.arrayLength, &UA_TYPES[UA_TYPES_VARIANT]);
    if(!result->outputArguments) {
        result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
        return;
    }
    result->outputArgumentsSize = outputArguments->value.variant.value.arrayLength;

    /* Call the method */
    result->statusCode = methodCalled->attachedMethod(methodCalled->methodHandle, withObject->nodeId,
                                                      request->inputArgumentsSize, request->inputArguments,
                                                      result->outputArgumentsSize, result->outputArguments);
    /* TODO: Verify Output Argument count, types and sizes */
}
예제 #3
0
static void
callMethod(UA_Server *server, UA_Session *session, UA_CallMethodRequest *request,
           UA_CallMethodResult *result) {
    const UA_MethodNode *methodCalled = (const UA_MethodNode*)UA_NodeStore_get(server->nodestore, &request->methodId);
    if(!methodCalled) {
        result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
        return;
    }
    
    const UA_ObjectNode *withObject = (const UA_ObjectNode*)UA_NodeStore_get(server->nodestore, &request->objectId);
    if(!withObject) {
        result->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
        goto releaseMethodReturn;
    }
    
    if(methodCalled->nodeClass != UA_NODECLASS_METHOD) {
        result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
        goto releaseBothReturn;
    }
    
    if(withObject->nodeClass != UA_NODECLASS_OBJECT && withObject->nodeClass != UA_NODECLASS_OBJECTTYPE) {
        result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
        goto releaseBothReturn;
    }
    
    /* Verify method/object relations */
    // 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++) {
        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)) {
                result->statusCode = UA_STATUSCODE_GOOD;
                break;
            }
        }
    }
    if(result->statusCode != UA_STATUSCODE_GOOD)
        goto releaseBothReturn;
        
    /* Verify method executable */
    if(methodCalled->executable == UA_FALSE || methodCalled->userExecutable == UA_FALSE) {
        result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
        goto releaseBothReturn;
    }

    /* Verify Input Argument count, types and sizes */
    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"));
    if(!outputArguments) {
        // A MethodNode must have an OutputArguments variable (which may be empty)
        result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
        goto releaseBothReturn;
    }
    
    // Call method if available
    if(methodCalled->attachedMethod) {
        result->outputArguments = UA_Array_new(&UA_TYPES[UA_TYPES_VARIANT],
                                               outputArguments->value.variant.value.arrayLength);
        result->outputArgumentsSize = outputArguments->value.variant.value.arrayLength;
        result->statusCode = methodCalled->attachedMethod(withObject->nodeId, request->inputArguments,
                                                          result->outputArguments, methodCalled->methodHandle);
    }
    else
        result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
    
    /* FIXME: Verify Output Argument count, types and sizes */
    if(outputArguments)
        UA_NodeStore_release((const UA_Node*)outputArguments);

 releaseBothReturn:
    UA_NodeStore_release((const UA_Node*)withObject);
 releaseMethodReturn:
    UA_NodeStore_release((const UA_Node*)methodCalled);
}