void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *request, UA_ReadResponse *response) { if(request->nodesToReadSize <= 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; return; } if(request->timestampsToReturn > 3){ response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID; return; } size_t size = request->nodesToReadSize; response->results = UA_Array_new(&UA_TYPES[UA_TYPES_DATAVALUE], size); if(!response->results) { response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; return; } response->resultsSize = size; if(request->maxAge < 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADMAXAGEINVALID; return; } /* ### Begin External Namespaces */ UA_Boolean *isExternal = UA_alloca(sizeof(UA_Boolean) * size); UA_memset(isExternal, UA_FALSE, sizeof(UA_Boolean) * size); UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32) * size); for(UA_Int32 j = 0;j<server->externalNamespacesSize;j++) { size_t indexSize = 0; for(size_t i = 0;i < size;i++) { if(request->nodesToRead[i].nodeId.namespaceIndex != server->externalNamespaces[j].index) continue; isExternal[i] = UA_TRUE; indices[indexSize] = i; indexSize++; } if(indexSize == 0) continue; UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore; ens->readNodes(ens->ensHandle, &request->requestHeader, request->nodesToRead, indices, indexSize, response->results, UA_FALSE, response->diagnosticInfos); } /* ### End External Namespaces */ for(size_t i = 0;i < size;i++) { if(!isExternal[i]) readValue(server, request->timestampsToReturn, &request->nodesToRead[i], &response->results[i]); } #ifdef EXTENSION_STATELESS if(session==&anonymousSession){ /* expiry header */ UA_ExtensionObject additionalHeader; UA_ExtensionObject_init(&additionalHeader); additionalHeader.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING; UA_Variant variant; UA_Variant_init(&variant); variant.type = &UA_TYPES[UA_TYPES_DATETIME]; variant.arrayLength = request->nodesToReadSize; UA_DateTime* expireArray = UA_NULL; expireArray = UA_Array_new(&UA_TYPES[UA_TYPES_DATETIME], request->nodesToReadSize); variant.data = expireArray; UA_ByteString str; UA_ByteString_init(&str); /*expires in 20 seconds*/ for(UA_Int32 i = 0;i < response->resultsSize;i++) { expireArray[i] = UA_DateTime_now() + 20 * 100 * 1000 * 1000; } size_t offset = 0; str.data = UA_malloc(UA_Variant_calcSizeBinary(&variant)); str.length = UA_Variant_calcSizeBinary(&variant); UA_Variant_encodeBinary(&variant, &str, &offset); additionalHeader.body = str; response->responseHeader.additionalHeader = additionalHeader; } #endif }
void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *request, UA_ReadResponse *response) { UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION, "Processing ReadRequest for Session (ns=%i,i=%i)", session->sessionId.namespaceIndex, session->sessionId.identifier.numeric); if(request->nodesToReadSize <= 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; return; } if(request->timestampsToReturn > 3){ response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID; return; } size_t size = request->nodesToReadSize; response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_DATAVALUE]); if(!response->results) { response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; return; } response->resultsSize = size; if(request->maxAge < 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADMAXAGEINVALID; return; } #ifdef UA_ENABLE_EXTERNAL_NAMESPACES UA_Boolean isExternal[size]; UA_UInt32 indices[size]; memset(isExternal, UA_FALSE, sizeof(UA_Boolean) * size); for(size_t j = 0;j<server->externalNamespacesSize;j++) { size_t indexSize = 0; for(size_t i = 0;i < size;i++) { if(request->nodesToRead[i].nodeId.namespaceIndex != server->externalNamespaces[j].index) continue; isExternal[i] = UA_TRUE; indices[indexSize] = i; indexSize++; } if(indexSize == 0) continue; UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore; ens->readNodes(ens->ensHandle, &request->requestHeader, request->nodesToRead, indices, indexSize, response->results, UA_FALSE, response->diagnosticInfos); } #endif for(size_t i = 0;i < size;i++) { #ifdef UA_ENABLE_EXTERNAL_NAMESPACES if(!isExternal[i]) #endif Service_Read_single(server, session, request->timestampsToReturn, &request->nodesToRead[i], &response->results[i]); } #ifdef UA_ENABLE_NONSTANDARD_STATELESS /* Add an expiry header for caching */ if(session==&anonymousSession){ UA_ExtensionObject additionalHeader; UA_ExtensionObject_init(&additionalHeader); additionalHeader.typeId = UA_TYPES[UA_TYPES_VARIANT].typeId; additionalHeader.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING; UA_Variant variant; UA_Variant_init(&variant); UA_DateTime* expireArray = NULL; expireArray = UA_Array_new(&UA_TYPES[UA_TYPES_DATETIME], request->nodesToReadSize); variant.data = expireArray; /*expires in 20 seconds*/ for(UA_Int32 i = 0;i < response->resultsSize;i++) { expireArray[i] = UA_DateTime_now() + 20 * 100 * 1000 * 1000; } UA_Variant_setArray(&variant, expireArray, request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]); size_t offset = 0; UA_ByteString str; UA_ByteString_newMembers(&str, 65536); UA_Variant_encodeBinary(&variant, &str, &offset); UA_Array_delete(expireArray, &UA_TYPES[UA_TYPES_DATETIME], request->nodesToReadSize); additionalHeader.body = str; additionalHeader.body.length = offset; response->responseHeader.additionalHeader = additionalHeader; } #endif }