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]); }
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; }
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; }