void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
                           const UA_CreateSessionRequest *request,
                           UA_CreateSessionResponse *response) {
    response->responseHeader.serviceResult =
        UA_Array_copy(server->endpointDescriptions, (void**)&response->serverEndpoints,
                      &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], server->endpointDescriptionsSize);
    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
        return;
    response->serverEndpointsSize = server->endpointDescriptionsSize;

	UA_Session *newSession;
    response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager,
                                                                             channel, request, &newSession);
	if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
		return;

    //TODO get maxResponseMessageSize internally
    newSession->maxResponseMessageSize = request->maxResponseMessageSize;
    response->sessionId = newSession->sessionId;
    response->revisedSessionTimeout = newSession->timeout;
    response->authenticationToken = newSession->authenticationToken;
    response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName);
    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, server, &newSession->authenticationToken);
         return;
    }
}
END_TEST

START_TEST(arrayCopyShallMakeADeepCopy) {
	// given
	UA_String a1[3];
	a1[0] = (UA_String){1, (UA_Byte*)"a"};
	a1[1] = (UA_String){2, (UA_Byte*)"bb"};
	a1[2] = (UA_String){3, (UA_Byte*)"ccc"};
	// when
	UA_String *a2;
	UA_Int32   retval = UA_Array_copy((const void *)a1, 3, &UA_TYPES[UA_STRING], (void **)&a2);
	// then
	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
	ck_assert_int_eq(a1[0].length, 1);
	ck_assert_int_eq(a1[1].length, 2);
	ck_assert_int_eq(a1[2].length, 3);
	ck_assert_int_eq(a1[0].length, a2[0].length);
	ck_assert_int_eq(a1[1].length, a2[1].length);
	ck_assert_int_eq(a1[2].length, a2[2].length);
	ck_assert_ptr_ne(a1[0].data, a2[0].data);
	ck_assert_ptr_ne(a1[1].data, a2[1].data);
	ck_assert_ptr_ne(a1[2].data, a2[2].data);
	ck_assert_int_eq(a1[0].data[0], a2[0].data[0]);
	ck_assert_int_eq(a1[1].data[0], a2[1].data[0]);
	ck_assert_int_eq(a1[2].data[0], a2[2].data[0]);
	// finally
	UA_Array_delete((void *)a2, 3, &UA_TYPES[UA_STRING]);
}
Exemple #3
0
UA_StatusCode UA_Node_copyAnyNodeClass(const UA_Node *src, UA_Node *dst) {
    if(src->nodeClass != dst->nodeClass)
        return UA_STATUSCODE_BADINTERNALERROR;
    
    /* copy standard content */
	UA_StatusCode retval = UA_NodeId_copy(&src->nodeId, &dst->nodeId);
	dst->nodeClass = src->nodeClass;
	retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName);
	retval |= UA_LocalizedText_copy(&src->displayName, &dst->displayName);
	retval |= UA_LocalizedText_copy(&src->description, &dst->description);
	dst->writeMask = src->writeMask;
	dst->userWriteMask = src->userWriteMask;
	if(retval != UA_STATUSCODE_GOOD) {
    	UA_Node_deleteMembersAnyNodeClass(dst);
        return retval;
    }
	retval |= UA_Array_copy(src->references, src->referencesSize, (void**)&dst->references,
                            &UA_TYPES[UA_TYPES_REFERENCENODE]);
	if(retval != UA_STATUSCODE_GOOD) {
    	UA_Node_deleteMembersAnyNodeClass(dst);
        return retval;
    }
    dst->referencesSize = src->referencesSize;

    /* copy unique content of the nodeclass */
    switch(src->nodeClass) {
    case UA_NODECLASS_OBJECT:
        retval = UA_ObjectNode_copy((const UA_ObjectNode*)src, (UA_ObjectNode*)dst);
        break;
    case UA_NODECLASS_VARIABLE:
        retval = UA_VariableNode_copy((const UA_VariableNode*)src, (UA_VariableNode*)dst);
        break;
    case UA_NODECLASS_METHOD:
        retval = UA_MethodNode_copy((const UA_MethodNode*)src, (UA_MethodNode*)dst);
        break;
    case UA_NODECLASS_OBJECTTYPE:
        retval = UA_ObjectTypeNode_copy((const UA_ObjectTypeNode*)src, (UA_ObjectTypeNode*)dst);
        break;
    case UA_NODECLASS_VARIABLETYPE:
        retval = UA_VariableTypeNode_copy((const UA_VariableTypeNode*)src, (UA_VariableTypeNode*)dst);
        break;
    case UA_NODECLASS_REFERENCETYPE:
        retval = UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode*)src, (UA_ReferenceTypeNode*)dst);
        break;
    case UA_NODECLASS_DATATYPE:
        retval = UA_DataTypeNode_copy((const UA_DataTypeNode*)src, (UA_DataTypeNode*)dst);
        break;
    case UA_NODECLASS_VIEW:
        retval = UA_ViewNode_copy((const UA_ViewNode*)src, (UA_ViewNode*)dst);
        break;
    default:
        break;
    }
	if(retval != UA_STATUSCODE_GOOD)
    	UA_Node_deleteMembersAnyNodeClass(dst);
    return retval;
}
Exemple #4
0
static UA_StatusCode UA_Node_copy(const UA_Node *src, UA_Node *dst) {
	UA_StatusCode retval = UA_STATUSCODE_GOOD;
	UA_Node_init(dst);
	retval |= UA_NodeId_copy(&src->nodeId, &dst->nodeId);
	dst->nodeClass = src->nodeClass;
	retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName);
	retval |= UA_LocalizedText_copy(&src->displayName, &dst->displayName);
	retval |= UA_LocalizedText_copy(&src->description, &dst->description);
	dst->writeMask = src->writeMask;
	dst->userWriteMask = src->userWriteMask;
	dst->referencesSize = src->referencesSize;
	retval |= UA_Array_copy(src->references, (void**)&dst->references, &UA_TYPES[UA_TYPES_REFERENCENODE],
                            src->referencesSize);
	if(retval)
    	UA_Node_deleteMembers(dst);
	return retval;
}
static UA_DateTime* sortDateTimes(UA_DateTime *data) {
    size_t count = 0;
    while(data[count++]);
    UA_DateTime* ret;
    if (UA_Array_copy(data, count, (void**)&ret, &UA_TYPES[UA_TYPES_DATETIME]) != UA_STATUSCODE_GOOD)
        return NULL;
    --count;
    // sort it
    for (size_t i = 1; i < count; i++) {
       for (size_t j = 0; j < count - i; j++) {
           if (ret[j] > ret[j+1]) {
               UA_DateTime tmp = ret[j];
               ret[j] = ret[j+1];
               ret[j+1] = tmp;
           }
       }
    }
    return ret;
}
void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
                           const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
    if(channel->securityToken.channelId == 0) {
        response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
        return;
    }
    response->responseHeader.serviceResult =
        UA_Array_copy(server->endpointDescriptions, server->endpointDescriptionsSize,
                      (void**)&response->serverEndpoints, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
        return;
    response->serverEndpointsSize = server->endpointDescriptionsSize;

    UA_Session *newSession;
    response->responseHeader.serviceResult =
        UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession);
    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
        UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Processing CreateSessionRequest failed");
        return;
    }

    newSession->maxResponseMessageSize = request->maxResponseMessageSize;
    newSession->maxRequestMessageSize = channel->connection->localConf.maxMessageSize;
    response->sessionId = newSession->sessionId;
    response->revisedSessionTimeout = (UA_Double)newSession->timeout;
    response->authenticationToken = newSession->authenticationToken;
    response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName);
    if(server->endpointDescriptionsSize > 0)
        response->responseHeader.serviceResult |= UA_ByteString_copy(&server->endpointDescriptions->serverCertificate,
                               &response->serverCertificate);
    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
        UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken);
         return;
    }
    UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Session " PRINTF_GUID_FORMAT " created",
                         PRINTF_GUID_DATA(newSession->sessionId));
}
static UA_StatusCode
updateHistory(UA_PerformUpdateType updateType, UA_DateTime *updateData, UA_StatusCode ** operationResults, size_t *operationResultsSize)
{
    UA_UpdateDataDetails *details = UA_UpdateDataDetails_new();
    details->performInsertReplace = updateType;
    UA_NodeId_copy(&outNodeId, &details->nodeId);
    int updateDataSize = -1;
    while(updateData[++updateDataSize]);
    fprintf(stderr, "updateHistory for %d values.\n", updateDataSize);
    details->updateValuesSize = (size_t)updateDataSize;
    details->updateValues = (UA_DataValue*)UA_Array_new(details->updateValuesSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
    for (size_t i = 0; i < details->updateValuesSize; ++i) {
        UA_DataValue_init(&details->updateValues[i]);
        details->updateValues[i].hasValue = true;
        UA_Int64 d = updateType;
        UA_Variant_setScalarCopy(&details->updateValues[i].value, &d, &UA_TYPES[UA_TYPES_INT64]);
        details->updateValues[i].hasSourceTimestamp = true;
        details->updateValues[i].sourceTimestamp = updateData[i];
        details->updateValues[i].hasServerTimestamp = true;
        details->updateValues[i].serverTimestamp = updateData[i];
        details->updateValues[i].hasStatus = true;
        details->updateValues[i].status = UA_STATUSCODE_GOOD;
    }

    UA_HistoryUpdateRequest request;
    UA_HistoryUpdateRequest_init(&request);
    request.historyUpdateDetailsSize = 1;
    request.historyUpdateDetails = UA_ExtensionObject_new();
    UA_ExtensionObject_init(request.historyUpdateDetails);

    request.historyUpdateDetails[0].encoding = UA_EXTENSIONOBJECT_DECODED;
    request.historyUpdateDetails[0].content.decoded.type = &UA_TYPES[UA_TYPES_UPDATEDATADETAILS];
    request.historyUpdateDetails[0].content.decoded.data = details;

    UA_HistoryUpdateResponse response;
    UA_HistoryUpdateResponse_init(&response);
    Service_HistoryUpdate(server, &server->adminSession, &request, &response);
    UA_HistoryUpdateRequest_deleteMembers(&request);
    UA_StatusCode ret = UA_STATUSCODE_GOOD;
    if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
        ret = response.responseHeader.serviceResult;
    else if (response.resultsSize != 1)
        ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
    else if (response.results[0].statusCode != UA_STATUSCODE_GOOD)
        ret = response.results[0].statusCode;
    else if (response.results[0].operationResultsSize != (size_t)updateDataSize)
        ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
    else {
        if (operationResults) {
            *operationResultsSize = response.results[0].operationResultsSize;
            ret = UA_Array_copy(response.results[0].operationResults, *operationResultsSize, (void**)operationResults, &UA_TYPES[UA_TYPES_STATUSCODE]);
        } else {
            for (size_t i = 0; i < response.results[0].operationResultsSize; ++i) {
                if (response.results[0].operationResults[i] != UA_STATUSCODE_GOOD) {
                    ret = response.results[0].operationResults[i];
                    break;
                }
            }
        }
    }
    UA_HistoryUpdateResponse_deleteMembers(&response);
    return ret;
}
/* Stack layout: ... | node | type */
static UA_StatusCode
writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
                              UA_VariableNode *node, const UA_VariableTypeNode *type,
                              size_t arrayDimensionsSize, UA_UInt32 *arrayDimensions) {
    UA_assert(node != NULL);
    UA_assert(type != NULL);

    /* If this is a variabletype, there must be no instances or subtypes of it
     * when we do the change */
    if(node->nodeClass == UA_NODECLASS_VARIABLETYPE &&
       UA_Node_hasSubTypeOrInstances((UA_Node*)node)) {
        UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
                    "Cannot change a variable type with existing instances");
        return UA_STATUSCODE_BADINTERNALERROR;
    }

    /* Check that the array dimensions match with the valuerank */
    if(!compatibleValueRankArrayDimensions(node->valueRank, arrayDimensionsSize)) {
        UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
                     "The current value rank does not match the new array dimensions");
        return UA_STATUSCODE_BADTYPEMISMATCH;
    }

    /* Check if the array dimensions match with the wildcards in the
     * variabletype (dimension length 0) */
    if(type->arrayDimensions &&
       !compatibleArrayDimensions(type->arrayDimensionsSize, type->arrayDimensions,
                                  arrayDimensionsSize, arrayDimensions)) {
       UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
                    "Array dimensions in the variable type do not match");
       return UA_STATUSCODE_BADTYPEMISMATCH;
    }

    /* Check if the current value is compatible with the array dimensions */
    UA_DataValue value;
    UA_DataValue_init(&value);
    UA_StatusCode retval = readValueAttribute(server, session, node, &value);
    if(retval != UA_STATUSCODE_GOOD)
        return retval;
    if(value.hasValue) {
        if(!compatibleValueArrayDimensions(&value.value, arrayDimensionsSize, arrayDimensions))
            retval = UA_STATUSCODE_BADTYPEMISMATCH;
        UA_DataValue_deleteMembers(&value);
        if(retval != UA_STATUSCODE_GOOD) {
            UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
                         "Array dimensions in the current value do not match");
            return retval;
        }
    }

    /* Ok, apply */
    UA_UInt32 *oldArrayDimensions = node->arrayDimensions;
    retval = UA_Array_copy(arrayDimensions, arrayDimensionsSize,
                           (void**)&node->arrayDimensions,
                           &UA_TYPES[UA_TYPES_UINT32]);
    if(retval != UA_STATUSCODE_GOOD)
        return retval;
    UA_free(oldArrayDimensions);
    node->arrayDimensionsSize = arrayDimensionsSize;
    return UA_STATUSCODE_GOOD;
}