public ResponseHeader BrowseNext( RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { return(m_session.BrowseNext(requestHeader, releaseContinuationPoints, continuationPoints, out results, out diagnosticInfos)); }
public ResponseHeader Browse( RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { return(m_session.Browse(requestHeader, view, requestedMaxReferencesPerNode, nodesToBrowse, out results, out diagnosticInfos)); }
/// <summary> /// Create the continuation point collection from the browse result /// collection for the BrowseNext service. /// </summary> /// <param name="browseResultCollection">The browse result collection to use.</param> /// <returns>The collection of continuation points for the BrowseNext service.</returns> public static ByteStringCollection PrepareBrowseNext(BrowseResultCollection browseResultCollection) { var continuationPoints = new ByteStringCollection(); foreach (var browseResult in browseResultCollection) { if (browseResult.ContinuationPoint != null) { continuationPoints.Add(browseResult.ContinuationPoint); } } return(continuationPoints); }
/// <summary> /// Invokes the BrowseNext service. /// </summary> public virtual ResponseHeader BrowseNext( RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { results = null; diagnosticInfos = null; ValidateRequest(requestHeader); // Insert implementation. return(CreateResponse(requestHeader, StatusCodes.BadServiceUnsupported)); }
/// <summary> /// Invokes the Browse service. /// </summary> public virtual ResponseHeader Browse( RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { results = null; diagnosticInfos = null; ValidateRequest(requestHeader); // Insert implementation. return(CreateResponse(requestHeader, StatusCodes.BadServiceUnsupported)); }
/// <summary> /// Fetches the next batch of references. /// </summary> private bool BrowseNext() { if (m_continuationPoint != null) { ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(m_continuationPoint); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = m_client.BrowseNext( null, false, continuationPoints, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); m_position = 0; m_references = null; m_continuationPoint = null; // check status. if (StatusCode.IsGood(results[0].StatusCode)) { m_references = results[0].References; m_continuationPoint = results[0].ContinuationPoint; } return(m_references != null || m_references.Count > 0); } return(false); }
private static void BrowseTree2(Session session, BrowseDescriptionCollection bdCollection, string sPre) { BrowseResultCollection br = new BrowseResultCollection(); DiagnosticInfoCollection dc = new DiagnosticInfoCollection(); netCalls++; Console.WriteLine($"Getting: {bdCollection.Count}"); if (bdCollection.Count != 0) { session.Browse(null, null, (uint)1000000, bdCollection, out br, out dc); if (br != null) { if (bdCollection.Count != br.Count) { Console.WriteLine($"NOT EQUAL: DC Count = {dc.Count}"); } int i = 0; BrowseDescriptionCollection bc = new BrowseDescriptionCollection(); foreach (var b in br) { nodeList.Add(b); var inNode = bdCollection[i]; foreach (var n in b.References) { BrowseDescription bd = new BrowseDescription(); bd.NodeId = (NodeId)n.NodeId; bd.BrowseDirection = BrowseDirection.Forward; bd.ReferenceTypeId = ReferenceTypeIds.HasChild; bd.IncludeSubtypes = true; bd.NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method; bc.Add(bd); } } BrowseTree2(session, bc, "KN"); } } }
/// <summary> /// Browses the children of the node and updates the tree. /// </summary> private bool BrowseChildren(TreeNode parent) { ReferenceDescription reference = parent.Tag as ReferenceDescription; if (reference == null) { return(false); } parent.Nodes.Clear(); if (reference.NodeId.IsAbsolute) { return(false); } BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = (NodeId)reference.NodeId; nodeToBrowse.BrowseDirection = m_browseDirection; nodeToBrowse.ReferenceTypeId = m_referenceTypeId; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)(int)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); ViewDescription view = null; if (NodeId.IsNull(m_viewId)) { view = new ViewDescription(); view.ViewId = m_viewId; view.Timestamp = DateTime.MinValue; view.ViewVersion = 0; } BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Browse( null, view, 0, nodesToBrowse, out results, out diagnosticInfos); if (results.Count != 1 || StatusCode.IsBad(results[0].StatusCode)) { return(false); } UpdateNode(parent, results[0].References); while (results[0].ContinuationPoint != null && results[0].ContinuationPoint.Length > 0) { ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); m_session.BrowseNext( null, parent == null, continuationPoints, out results, out diagnosticInfos); if (results.Count != 1 || StatusCode.IsBad(results[0].StatusCode)) { return(false); } UpdateNode(parent, results[0].References); } return(true); }
/// <summary> /// Returns the set of references that meet the filter criteria. /// </summary> public virtual void Browse( OperationContext context, ViewDescription view, uint maxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { if (context == null) throw new ArgumentNullException("context"); if (nodesToBrowse == null) throw new ArgumentNullException("nodesToBrowse"); if (view != null && !NodeId.IsNull(view.ViewId)) { INodeManager viewManager = null; object viewHandle = GetManagerHandle(view.ViewId, out viewManager); if (viewHandle == null) { throw new ServiceResultException(StatusCodes.BadViewIdUnknown); } NodeMetadata metadata = viewManager.GetNodeMetadata(context, viewHandle, BrowseResultMask.NodeClass); if (metadata == null || metadata.NodeClass != NodeClass.View) { throw new ServiceResultException(StatusCodes.BadViewIdUnknown); } view.Handle = viewHandle; } bool diagnosticsExist = false; results = new BrowseResultCollection(nodesToBrowse.Count); diagnosticInfos = new DiagnosticInfoCollection(nodesToBrowse.Count); uint continuationPointsAssigned = 0; for (int ii = 0; ii < nodesToBrowse.Count; ii++) { // check if request has timed out or been cancelled. if (StatusCode.IsBad(context.OperationStatus)) { // release all allocated continuation points. foreach (BrowseResult current in results) { if (current != null && current.ContinuationPoint != null && current.ContinuationPoint.Length > 0) { ContinuationPoint cp = context.Session.RestoreContinuationPoint(current.ContinuationPoint); cp.Dispose(); } } throw new ServiceResultException(context.OperationStatus); } BrowseDescription nodeToBrowse = nodesToBrowse[ii]; // initialize result. BrowseResult result = new BrowseResult(); result.StatusCode = StatusCodes.Good; results.Add(result); ServiceResult error = null; // need to trap unexpected exceptions to handle bugs in the node managers. try { error = Browse( context, view, maxReferencesPerNode, continuationPointsAssigned < m_maxContinuationPointsPerBrowse, nodeToBrowse, result); } catch (Exception e) { error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error browsing node."); } // check for continuation point. if (result.ContinuationPoint != null && result.ContinuationPoint.Length > 0) { continuationPointsAssigned++; } // check for error. result.StatusCode = error.StatusCode; if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) { DiagnosticInfo diagnosticInfo = null; if (error != null && error.Code != StatusCodes.Good) { diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, error); diagnosticsExist = true; } diagnosticInfos.Add(diagnosticInfo); } } // clear the diagnostics array if no diagnostics requested or no errors occurred. UpdateDiagnostics(context, diagnosticsExist, ref diagnosticInfos); }
/// <summary> /// Invokes the Browse service. /// </summary> public virtual ResponseHeader Browse( RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { results = null; diagnosticInfos = null; ValidateRequest(requestHeader); // Insert implementation. return CreateResponse(requestHeader, StatusCodes.BadServiceUnsupported); }
/// <summary> /// /// </summary> /// <param name="session"></param> /// <param name="nodesToBrowse"></param> /// <returns></returns> public static ReferenceDescriptionCollection BrowsePart(this Session session, BrowseDescriptionCollection nodesToBrowse) { try { ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); BrowseDescriptionCollection unprocessedOperations = new BrowseDescriptionCollection(); while (nodesToBrowse.Count > 0) { // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); for (int ii = 0; ii < nodesToBrowse.Count; ii++) { // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { // this error indicates that the server does not have enough simultaneously active // continuation points. This request will need to be resent after the other operations // have been completed and their continuation points released. if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints) { unprocessedOperations.Add(nodesToBrowse[ii]); } continue; } // check if all references have been fetched. if (results[ii].References.Count == 0) { continue; } // save results. references.AddRange(results[ii].References); } // check if unprocessed results exist. nodesToBrowse = unprocessedOperations; } // return complete list. return(references); } catch (Exception) { return(null); } }
/// <summary> /// Browses the address space and returns the references found. /// </summary> public static ReferenceDescriptionCollection Browse(Session session, ViewDescription view, BrowseDescription nodeToBrowse, bool throwOnError) { try { ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); // construct browse request. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, view, 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); do { // check for error. if (StatusCode.IsBad(results[0].StatusCode)) { throw new ServiceResultException(results[0].StatusCode); } // process results. for (int ii = 0; ii < results[0].References.Count; ii++) { references.Add(results[0].References[ii]); } // check if all references have been fetched. if (results[0].References.Count == 0 || results[0].ContinuationPoint == null) { break; } // continue browse operation. ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); session.BrowseNext( null, false, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); }while (true); //return complete list. return(references); } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return(null); } }
/// <summary> /// Invokes the Browse service. /// </summary> /// <param name="requestHeader">The request header.</param> /// <param name="view">The view.</param> /// <param name="requestedMaxReferencesPerNode">The maximum number of references to return for each node.</param> /// <param name="nodesToBrowse">The list of nodes to browse.</param> /// <param name="results">The list of results for the passed starting nodes and filters.</param> /// <param name="diagnosticInfos">The diagnostic information for the results.</param> /// <returns> /// Returns a <see cref="ResponseHeader"/> object /// </returns> public override ResponseHeader Browse( RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { results = null; diagnosticInfos = null; OperationContext context = ValidateRequest(requestHeader, RequestType.Browse); try { if (nodesToBrowse == null || nodesToBrowse.Count == 0) { throw new ServiceResultException(StatusCodes.BadNothingToDo); } m_serverInternal.NodeManager.Browse( context, view, requestedMaxReferencesPerNode, nodesToBrowse, out results, out diagnosticInfos); return CreateResponse(requestHeader, context.StringTable); } catch (ServiceResultException e) { lock (ServerInternal.DiagnosticsLock) { ServerInternal.ServerDiagnostics.RejectedRequestsCount++; if (IsSecurityError(e.StatusCode)) { ServerInternal.ServerDiagnostics.SecurityRejectedRequestsCount++; } } throw TranslateException(context, e); } finally { OnRequestComplete(context); } }
public static void BrowseNode(String currentNode, String browseName) { BrowseResultCollection browseResultCollection = null; DiagnosticInfoCollection diagnosticInfos; BrowseDescriptionCollection browseDescriptionCollection = null; List <NodeClass> nodeClasses = new List <NodeClass>() { NodeClass.Unspecified }; foreach (NodeClass nodeClass in nodeClasses) { browseDescriptionCollection = PrepareBrowseDescriptionCollection(currentNode, (uint)nodeClass); clientSession.Browse( null, null, 100, browseDescriptionCollection, out browseResultCollection, out diagnosticInfos); if (browseResultCollection.Where(br => br.References.Count > 0).FirstOrDefault() == null) { continue; } int browseResultCounter = browseResultCollection.FindIndex(br => br.References.Count > 0); String referenceType = String.Empty; foreach (BrowseResult browseResult in browseResultCollection) { switch (browseResultCounter) { case 0: referenceType = "Organizes"; break; case 1: referenceType = "HasComponent"; break; case 2: referenceType = "HasChild"; break; case 3: referenceType = "HasDescription"; break; case 4: referenceType = "HasProperty"; break; default: referenceType = "HasProperty"; break; } if (browseResult.References.Count > 0) { foreach (ReferenceDescription referenceDescription in browseResult.References) { if (referenceDescription.BrowseName.NamespaceIndex != UaDefaultNamespaceIndex) { BrowseNode(referenceDescription.NodeId.ToString(), referenceDescription.BrowseName.ToString()); } //TBD - If a node id has different relations with its parent node, the additional "relation" should be added //OpcuaNodeList opcuaNodeSubStructure = new OpcuaNodeList(); //opcuaNodeSubStructure.nodeId = referenceDescription.NodeId.ToString(); //opcuaNodeSubStructure.browseName = referenceDescription.BrowseName.ToString(); OpcuaNodeLink opcuaNodeLink = new OpcuaNodeLink(); opcuaNodeLink.nodeID = referenceDescription.NodeId.ToString(); opcuaNodeLink.browseName = referenceDescription.BrowseName.ToString(); opcuaNodeLink.parentNodeId = currentNode; opcuaNodeLink.parentNodebrowseName = browseName; opcuaNodeLink.referenceType = referenceType; if (referenceDescription.IsForward) { opcuaNodeLink.BrowseDirection = BrowseDirection.Forward.ToString("G"); } opcuaNodeLink.NodeClassMask = nodeClass.ToString("G"); opcuaNodeLink.browseResultMask = BrowseResultMask.All.ToString("G"); //if (!opcuaNodeStructure.IsChildPresent(referenceDescription.NodeId.ToString())) if (opcuaNodeStructure.ChildrenNodes == null) { opcuaNodeStructure.ChildrenNodes = new List <OpcuaNodeLink>(); } addNode(opcuaNodeLink); if (referenceDescription.NodeClass == NodeClass.Method) { Node methodNode = clientSession.ReadNode((NodeId)(referenceDescription.NodeId.ToString())); browseDescriptionCollection = PrepareBrowseDescriptionCollection(referenceDescription.NodeId.ToString(), (uint)nodeClass); clientSession.Browse( null, null, 100, browseDescriptionCollection, out browseResultCollection, out diagnosticInfos); if (browseResultCollection.Where(br => br.References.Count > 0).FirstOrDefault() == null) { continue; } String inputArgumentsNodeId = String.Empty, outputArgumentsNodeId = String.Empty; foreach (BrowseResult br in browseResultCollection) { foreach (ReferenceDescription rd in br.References) { OpcuaNodeLink nodeLink = new OpcuaNodeLink(); nodeLink.nodeID = rd.NodeId.ToString(); nodeLink.browseName = rd.BrowseName.ToString(); if (nodeLink.browseName == "InputArguments") { inputArgumentsNodeId = nodeLink.nodeID; } else if (nodeLink.browseName == "OutputArguments") { outputArgumentsNodeId = nodeLink.nodeID; } nodeLink.parentNodeId = referenceDescription.NodeId.ToString(); nodeLink.parentNodebrowseName = referenceDescription.BrowseName.ToString(); nodeLink.referenceType = referenceType; if (rd.IsForward) { opcuaNodeLink.BrowseDirection = BrowseDirection.Forward.ToString("G"); } nodeLink.NodeClassMask = nodeClass.ToString("G"); nodeLink.browseResultMask = BrowseResultMask.All.ToString("G"); //if (!opcuaNodeStructure.IsChildPresent(referenceDescription.NodeId.ToString())) if (opcuaNodeStructure.ChildrenNodes == null) { opcuaNodeStructure.ChildrenNodes = new List <OpcuaNodeLink>(); } addNode(nodeLink); } } opcuaNodeLink.isMethod = true; BrowsePathCollection pathsToArgs = new BrowsePathCollection(); BrowsePath pathToInputArgs = new BrowsePath(); pathToInputArgs.StartingNode = methodNode.NodeId; pathToInputArgs.RelativePath = new RelativePath(ReferenceTypeIds.HasProperty, false, true, new QualifiedName("InputArguments")); pathsToArgs.Add(pathToInputArgs); BrowsePath pathToOutputArgs = new BrowsePath(); pathToOutputArgs.StartingNode = methodNode.NodeId; pathToOutputArgs.RelativePath = new RelativePath(ReferenceTypeIds.HasProperty, false, true, new QualifiedName("OutputArguments")); pathsToArgs.Add(pathToOutputArgs); BrowsePathResultCollection results = null; // Get the nodeId of the input argument ResponseHeader responseHeader = clientSession.TranslateBrowsePathsToNodeIds( null, pathsToArgs, out results, out diagnosticInfos ); ArgumentCollection[] arguments = new ArgumentCollection[2]; for (int i = 0; i < 2; i++) { arguments[i] = new ArgumentCollection(); foreach (BrowsePathTarget bptarget in results[i].Targets) { DataValueCollection readResults = null; ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)bptarget.TargetId; nodeToRead.AttributeId = Attributes.Value; ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); nodesToRead.Add(nodeToRead); DiagnosticInfoCollection readDiagnoistcInfos = null; clientSession.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out readResults, out readDiagnoistcInfos ); ExtensionObject[] exts = (ExtensionObject[])readResults[0].Value; for (int j = 0; j < exts.Length; ++j) { ExtensionObject ext = exts[j]; arguments[i].Add((Argument)ext.Body); OpcuaNodeLink nl = new OpcuaNodeLink(); nl.nodeID = ((Opc.Ua.Argument)ext.Body).BinaryEncodingId.ToString(); nl.browseName = ((Opc.Ua.Argument)ext.Body).Name; if (((Opc.Ua.Argument)ext.Body).Description.Text.Equals("Input argument")) { nl.parentNodeId = inputArgumentsNodeId; } else if (((Opc.Ua.Argument)ext.Body).Description.Text.Equals("Output argument")) { nl.parentNodeId = outputArgumentsNodeId; } nl.parentNodebrowseName = referenceDescription.BrowseName.ToString(); nl.referenceType = referenceType; if (referenceDescription.IsForward) { opcuaNodeLink.BrowseDirection = BrowseDirection.Forward.ToString("G"); } nl.NodeClassMask = NodeClass.Variable.ToString("G"); nl.browseResultMask = BrowseResultMask.All.ToString("G"); nl.isArgument = true; //if (!opcuaNodeStructure.IsChildPresent(referenceDescription.NodeId.ToString())) if (opcuaNodeStructure.ChildrenNodes == null) { opcuaNodeStructure.ChildrenNodes = new List <OpcuaNodeLink>(); } addNode(nl); } } } } } } } } }
/// <summary> /// Updates the browse element with the children returned in the browse results. /// </summary> /// <param name="element">The element.</param> /// <param name="nodesToBrowse">The nodes to browse.</param> /// <param name="results">The results.</param> /// <param name="first">The index of the first browse result associated with the element.</param> /// <returns></returns> private bool UpdateBrowseElement( BrowseElement element, BrowseDescriptionCollection nodesToBrowse, BrowseResultCollection results, int first) { // check for a valid range within the collection. if (first < 0 || first >= nodesToBrowse.Count) { return false; } bool missingReferences = false; // process all references. Dictionary<string,ReferenceDescription> referencesByName = new Dictionary<string, ReferenceDescription>(); Dictionary<string,ReferenceDescription> duplicateNames = new Dictionary<string, ReferenceDescription>(); for (int ii = first; ii < first+2; ii++) { BrowseResult result = results[ii]; // check for errors - rejected node id are fatal; others can be ignored. if (StatusCode.IsBad(result.StatusCode)) { if (result.StatusCode == StatusCodes.BadNodeIdInvalid || result.StatusCode == StatusCodes.BadNodeIdInvalid || result.StatusCode == StatusCodes.BadNodeNotInView) { return false; } missingReferences = true; continue; } // eliminate duplicates and index references by browse name. for (int jj = 0; jj < result.References.Count; jj++) { ReferenceDescription reference = result.References[jj]; // ignore off server references. if (reference.NodeId == null || reference.NodeId.IsAbsolute) { continue; } // construct the browse name. string browseName = m_mapper.GetLocalBrowseName(reference.BrowseName); if (reference.DisplayName != null) { browseName = reference.DisplayName.Text; } // check for duplicates. ReferenceDescription duplicate = null; if (referencesByName.TryGetValue(browseName, out duplicate)) { if (reference.NodeId != duplicate.NodeId) { duplicateNames[browseName] = duplicate; } continue; } // add to table. referencesByName.Add(browseName, reference); } } // remove duplicates. foreach (string duplicateName in duplicateNames.Keys) { referencesByName.Remove(duplicateName); } // save child lookup table. element.ReferencesByName = referencesByName; element.MissingReferences = missingReferences; // update the masks. SetElementMasks(element); return true; }
/// <summary> /// Sends the browse request to the server. /// </summary> /// <param name="session">The session.</param> /// <param name="nodesToBrowse">The nodes to browse.</param> /// <returns></returns> private BrowseResultCollection BrowseBlock(Session session, BrowseDescriptionCollection nodesToBrowse) { try { // Utils.Trace("Browsing {0} Nodes", nodesToBrowse.Count); ViewDescription view = new ViewDescription(); Dictionary<int,BrowseResult> combinedResults = new Dictionary<int, BrowseResult>(); // initialize the table of indexes used to correlate results. BrowseDescriptionCollection browseOperations = nodesToBrowse; List<int> browseIndexes = new List<int>(); for (int ii = 0; ii < nodesToBrowse.Count; ii++) { browseIndexes.Add(ii); } BrowseDescriptionCollection unprocessedOperations = new BrowseDescriptionCollection(); List<int> unprocessedBrowseIndexes = new List<int>(); while (browseOperations.Count > 0) { // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, view, 0, browseOperations, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, browseOperations); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browseOperations); unprocessedOperations.Clear(); unprocessedBrowseIndexes.Clear(); ByteStringCollection continuationPoints = new ByteStringCollection(); List<int> continuationPointIndexes = new List<int>(); for (int ii = 0; ii < browseOperations.Count; ii++) { int index = browseIndexes[ii]; // Utils.Trace("{0}/{1}/{2}", browseOperations[ii].NodeId, browseOperations[ii].ReferenceTypeId, results[ii].References.Count); // look up results. BrowseResult combinedResult = null; if (!combinedResults.TryGetValue(index, out combinedResult)) { combinedResults[index] = combinedResult = new BrowseResult(); } // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { // this error indicates that the server does not have enough simultaneously active // continuation points. This request will need to be resent after the other operations // have been completed and their continuation points released. if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints) { unprocessedOperations.Add(browseOperations[ii]); unprocessedBrowseIndexes.Add(index); continue; } // save error. if (StatusCode.IsGood(combinedResult.StatusCode)) { combinedResult.StatusCode = results[ii].StatusCode; } continue; } // check if all references have been fetched. if (results[ii].References.Count == 0) { continue; } // save results. combinedResult.References.AddRange(results[ii].References); // check for continuation point. if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) { continuationPoints.Add(results[ii].ContinuationPoint); continuationPointIndexes.Add(index); } } // process continuation points. ByteStringCollection revisedContinuationPoints = new ByteStringCollection(); List<int> revisedContinuationPointIndexes = new List<int>(); while (continuationPoints.Count > 0) { bool releaseContinuationPoints = false; // continue browse operation. session.BrowseNext( null, releaseContinuationPoints, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); revisedContinuationPoints.Clear(); revisedContinuationPointIndexes.Clear(); for (int ii = 0; ii < continuationPoints.Count; ii++) { int index = continuationPointIndexes[ii]; // look up results. BrowseResult combinedResult = null; if (!combinedResults.TryGetValue(index, out combinedResult)) { combinedResults[index] = new BrowseResult(); } // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { // save error. if (StatusCode.IsGood(combinedResult.StatusCode)) { combinedResult.StatusCode = results[ii].StatusCode; } continue; } // check if all references have been fetched. if (results[ii].References.Count == 0) { continue; } // save results. combinedResult.References.AddRange(results[ii].References); // check for continuation point. if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) { revisedContinuationPoints.Add(results[ii].ContinuationPoint); revisedContinuationPointIndexes.Add(index); } } // check if browsing must continue; continuationPoints = revisedContinuationPoints; continuationPointIndexes = revisedContinuationPointIndexes; } // check if unprocessed results exist. browseOperations = unprocessedOperations; browseIndexes = unprocessedBrowseIndexes; } // reconstruct list of combined results. BrowseResultCollection finalResults = new BrowseResultCollection(); for (int ii = 0; ii < nodesToBrowse.Count; ii++) { BrowseResult combinedResult = null; if (!combinedResults.TryGetValue(ii, out combinedResult)) { combinedResult = new BrowseResult(); } finalResults.Add(combinedResult); } // return complete list. return finalResults; } catch (Exception e) { throw ComUtils.CreateComException(e, ResultIds.E_FAIL); } }
/// <summary> /// Sends the browse request to the server. /// </summary> /// <param name="session">The session.</param> /// <param name="nodesToBrowse">The nodes to browse.</param> /// <returns></returns> private BrowseResultCollection Browse(Session session, BrowseDescriptionCollection nodesToBrowse) { BrowseResultCollection results = null; // break the request into smaller blocks. if (m_browseBlockSize > 0 && nodesToBrowse.Count > m_browseBlockSize) { results = new BrowseResultCollection(); for (int ii = 0; ii < nodesToBrowse.Count; ii += m_browseBlockSize) { BrowseDescriptionCollection x = new BrowseDescriptionCollection(); for (int jj = ii; jj < ii + m_browseBlockSize && jj < nodesToBrowse.Count; jj++) { x.Add(nodesToBrowse[jj]); } BrowseResultCollection y = BrowseBlock(session, x); results.AddRange(y); } return results; } // small enough to do directly. return BrowseBlock(session, nodesToBrowse); }
/// <summary> /// Invokes the BrowseNext service. /// </summary> /// <param name="requestHeader">The request header.</param> /// <param name="releaseContinuationPoints">if set to <c>true</c> the continuation points are released.</param> /// <param name="continuationPoints">A list of continuation points returned in a previous Browse or BrewseNext call.</param> /// <param name="results">The list of resulted references for browse.</param> /// <param name="diagnosticInfos">The diagnostic information for the results.</param> /// <returns> /// Returns a <see cref="ResponseHeader"/> object /// </returns> public override ResponseHeader BrowseNext( RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { results = null; diagnosticInfos = null; OperationContext context = ValidateRequest(requestHeader, RequestType.BrowseNext); try { if (continuationPoints == null || continuationPoints.Count == 0) { throw new ServiceResultException(StatusCodes.BadNothingToDo); } m_serverInternal.NodeManager.BrowseNext( context, releaseContinuationPoints, continuationPoints, out results, out diagnosticInfos); return CreateResponse(requestHeader, context.StringTable); } catch (ServiceResultException e) { lock (ServerInternal.DiagnosticsLock) { ServerInternal.ServerDiagnostics.RejectedRequestsCount++; if (IsSecurityError(e.StatusCode)) { ServerInternal.ServerDiagnostics.SecurityRejectedRequestsCount++; } } throw TranslateException(context, e); } finally { OnRequestComplete(context); } }
/// <summary> /// Invokes the Browse service. /// </summary> public virtual ResponseHeader Browse( RequestHeader requestHeader, ViewDescription view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { BrowseRequest request = new BrowseRequest(); BrowseResponse response = null; request.RequestHeader = requestHeader; request.View = view; request.RequestedMaxReferencesPerNode = requestedMaxReferencesPerNode; request.NodesToBrowse = nodesToBrowse; UpdateRequestHeader(request, requestHeader == null, "Browse"); try { if (UseTransportChannel) { IServiceResponse genericResponse = TransportChannel.SendRequest(request); if (genericResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } ValidateResponse(genericResponse.ResponseHeader); response = (BrowseResponse)genericResponse; } else { BrowseResponseMessage responseMessage = InnerChannel.Browse(new BrowseMessage(request)); if (responseMessage == null || responseMessage.BrowseResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } response = responseMessage.BrowseResponse; ValidateResponse(response.ResponseHeader); } results = response.Results; diagnosticInfos = response.DiagnosticInfos; } finally { RequestCompleted(request, response, "Browse"); } return response.ResponseHeader; }
/// <summary> /// Browses the address space and returns the references found. /// </summary> public static ReferenceDescriptionCollection Browse(Session session, ViewDescription view, BrowseDescriptionCollection nodesToBrowse, bool throwOnError) { try { ReferenceDescriptionCollection references = new ReferenceDescriptionCollection(); BrowseDescriptionCollection unprocessedOperations = new BrowseDescriptionCollection(); while (nodesToBrowse.Count > 0) { // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, view, 0, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); ByteStringCollection continuationPoints = new ByteStringCollection(); for (int ii = 0; ii < nodesToBrowse.Count; ii++) { // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { // this error indicates that the server does not have enough simultaneously active // continuation points. This request will need to be resent after the other operations // have been completed and their continuation points released. if (results[ii].StatusCode == StatusCodes.BadNoContinuationPoints) { unprocessedOperations.Add(nodesToBrowse[ii]); } continue; } // check if all references have been fetched. if (results[ii].References.Count == 0) { continue; } // save results. references.AddRange(results[ii].References); // check for continuation point. if (results[ii].ContinuationPoint != null) { continuationPoints.Add(results[ii].ContinuationPoint); } } // process continuation points. ByteStringCollection revisedContiuationPoints = new ByteStringCollection(); while (continuationPoints.Count > 0) { // continue browse operation. session.BrowseNext( null, false, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); for (int ii = 0; ii < continuationPoints.Count; ii++) { // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { continue; } // check if all references have been fetched. if (results[ii].References.Count == 0) { continue; } // save results. references.AddRange(results[ii].References); // check for continuation point. if (results[ii].ContinuationPoint != null) { revisedContiuationPoints.Add(results[ii].ContinuationPoint); } } // check if browsing must continue; revisedContiuationPoints = continuationPoints; } // check if unprocessed results exist. nodesToBrowse = unprocessedOperations; } // return complete list. return(references); } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return(null); } }
/// <summary> /// Invokes the BrowseNext service. /// </summary> public virtual ResponseHeader BrowseNext( RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { BrowseNextRequest request = new BrowseNextRequest(); BrowseNextResponse response = null; request.RequestHeader = requestHeader; request.ReleaseContinuationPoints = releaseContinuationPoints; request.ContinuationPoints = continuationPoints; UpdateRequestHeader(request, requestHeader == null, "BrowseNext"); try { if (UseTransportChannel) { IServiceResponse genericResponse = TransportChannel.SendRequest(request); if (genericResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } ValidateResponse(genericResponse.ResponseHeader); response = (BrowseNextResponse)genericResponse; } else { BrowseNextResponseMessage responseMessage = InnerChannel.BrowseNext(new BrowseNextMessage(request)); if (responseMessage == null || responseMessage.BrowseNextResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } response = responseMessage.BrowseNextResponse; ValidateResponse(response.ResponseHeader); } results = response.Results; diagnosticInfos = response.DiagnosticInfos; } finally { RequestCompleted(request, response, "BrowseNext"); } return response.ResponseHeader; }
/// <summary> /// Finds the targets for the specified reference. /// </summary> private static List <NodeId> FindTargetOfReference(Session session, List <NodeId> nodeIds, NodeId referenceTypeId, bool throwOnError) { try { // construct browse request. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); for (int ii = 0; ii < nodeIds.Count; ii++) { BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeIds[ii]; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = referenceTypeId; nodeToBrowse.IncludeSubtypes = false; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.None; nodesToBrowse.Add(nodeToBrowse); } // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; session.Browse( null, null, 1, nodesToBrowse, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); List <NodeId> targetIds = new List <NodeId>(); ByteStringCollection continuationPoints = new ByteStringCollection(); for (int ii = 0; ii < nodeIds.Count; ii++) { targetIds.Add(null); // check for error. if (StatusCode.IsBad(results[ii].StatusCode)) { continue; } // check for continuation point. if (results[ii].ContinuationPoint != null && results[ii].ContinuationPoint.Length > 0) { continuationPoints.Add(results[ii].ContinuationPoint); } // get the node id. if (results[ii].References.Count > 0) { if (NodeId.IsNull(results[ii].References[0].NodeId) || results[ii].References[0].NodeId.IsAbsolute) { continue; } targetIds[ii] = (NodeId)results[ii].References[0].NodeId; } } // release continuation points. if (continuationPoints.Count > 0) { session.BrowseNext( null, true, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); } //return complete list. return(targetIds); } catch (Exception exception) { if (throwOnError) { throw new ServiceResultException(exception, StatusCodes.BadUnexpectedError); } return(null); } }
/// <summary> /// Finishes an asynchronous invocation of the BrowseNext service. /// </summary> public ResponseHeader EndBrowseNext( IAsyncResult result, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { BrowseNextResponse response = null; try { if (UseTransportChannel) { IServiceResponse genericResponse = TransportChannel.EndSendRequest(result); if (genericResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } ValidateResponse(genericResponse.ResponseHeader); response = (BrowseNextResponse)genericResponse; } else { BrowseNextResponseMessage responseMessage = InnerChannel.EndBrowseNext(result); if (responseMessage == null || responseMessage.BrowseNextResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } response = responseMessage.BrowseNextResponse; ValidateResponse(response.ResponseHeader); } results = response.Results; diagnosticInfos = response.DiagnosticInfos; } finally { RequestCompleted(null, response, "BrowseNext"); } return response.ResponseHeader; }
/// <summary> /// Invokes the BrowseNext service. /// </summary> public virtual ResponseHeader BrowseNext( RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { results = null; diagnosticInfos = null; ValidateRequest(requestHeader); // Insert implementation. return CreateResponse(requestHeader, StatusCodes.BadServiceUnsupported); }
/// <summary> /// Worker function to browse the full address space of a server. /// </summary> /// <param name="services">The service interface.</param> /// <param name="operationLimits">The operation limits.</param> public static ReferenceDescriptionCollection BrowseFullAddressSpaceWorker( IServerTestServices services, RequestHeader requestHeader, OperationLimits operationLimits = null, BrowseDescription browseDescription = null) { operationLimits = operationLimits ?? new OperationLimits(); requestHeader.Timestamp = DateTime.UtcNow; // Browse template var startingNode = Objects.RootFolder; var browseTemplate = browseDescription ?? new BrowseDescription { NodeId = startingNode, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, NodeClassMask = 0, ResultMask = (uint)BrowseResultMask.All }; var browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId( new NodeIdCollection(new NodeId[] { Objects.RootFolder }), browseTemplate); // Browse ResponseHeader response = null; uint requestedMaxReferencesPerNode = operationLimits.MaxNodesPerBrowse; bool verifyMaxNodesPerBrowse = operationLimits.MaxNodesPerBrowse > 0; var referenceDescriptions = new ReferenceDescriptionCollection(); // Test if server responds with BadNothingToDo { var sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, browseDescriptionCollection.Take(0).ToArray(), out var results, out var infos)); Assert.AreEqual(StatusCodes.BadNothingToDo, sre.StatusCode); } while (browseDescriptionCollection.Any()) { BrowseResultCollection allResults = new BrowseResultCollection(); if (verifyMaxNodesPerBrowse && browseDescriptionCollection.Count > operationLimits.MaxNodesPerBrowse) { verifyMaxNodesPerBrowse = false; // Test if server responds with BadTooManyOperations var sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, browseDescriptionCollection, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); // Test if server responds with BadTooManyOperations var tempBrowsePath = browseDescriptionCollection.Take((int)operationLimits.MaxNodesPerBrowse + 1).ToArray(); sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, tempBrowsePath, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); } bool repeatBrowse; var maxNodesPerBrowse = operationLimits.MaxNodesPerBrowse; BrowseResultCollection browseResultCollection = new BrowseResultCollection(); DiagnosticInfoCollection diagnosticsInfoCollection; do { var browseCollection = (maxNodesPerBrowse == 0) ? browseDescriptionCollection : browseDescriptionCollection.Take((int)maxNodesPerBrowse).ToArray(); repeatBrowse = false; try { requestHeader.Timestamp = DateTime.UtcNow; response = services.Browse(requestHeader, null, requestedMaxReferencesPerNode, browseCollection, out browseResultCollection, out diagnosticsInfoCollection); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticsInfoCollection, browseCollection); allResults.AddRange(browseResultCollection); } catch (ServiceResultException sre) { if (sre.StatusCode == StatusCodes.BadEncodingLimitsExceeded || sre.StatusCode == StatusCodes.BadResponseTooLarge) { // try to address by overriding operation limit maxNodesPerBrowse = maxNodesPerBrowse == 0 ? (uint)browseCollection.Count / 2 : maxNodesPerBrowse / 2; repeatBrowse = true; } else { throw; } } } while (repeatBrowse); if (maxNodesPerBrowse == 0) { browseDescriptionCollection.Clear(); } else { browseDescriptionCollection = browseDescriptionCollection.Skip((int)maxNodesPerBrowse).ToArray(); } // Browse next var continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseResultCollection); while (continuationPoints.Any()) { requestHeader.Timestamp = DateTime.UtcNow; response = services.BrowseNext(requestHeader, false, continuationPoints, out var browseNextResultCollection, out diagnosticsInfoCollection); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticsInfoCollection, continuationPoints); allResults.AddRange(browseNextResultCollection); continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseNextResultCollection); } // Build browse request for next level var browseTable = new NodeIdCollection(); foreach (var result in allResults) { referenceDescriptions.AddRange(result.References); foreach (var reference in result.References) { browseTable.Add(ExpandedNodeId.ToNodeId(reference.NodeId, null)); } } browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId(browseTable, browseTemplate); } referenceDescriptions.Sort((x, y) => (x.NodeId.CompareTo(y.NodeId))); TestContext.Out.WriteLine("Found {0} references on server.", referenceDescriptions.Count); foreach (var reference in referenceDescriptions) { TestContext.Out.WriteLine("NodeId {0} {1} {2}", reference.NodeId, reference.NodeClass, reference.BrowseName); } return(referenceDescriptions); }
/// <summary> /// Fetches the references for the node. /// </summary> private List <ReferenceDescription> Browse(Session session, NodeId nodeId) { List <ReferenceDescription> references = new List <ReferenceDescription>(); // specify the references to follow and the fields to return. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.References; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.BrowseDirection = BrowseDirection.Both; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = session.Browse( null, null, 2, nodesToBrowse, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); // check status. if (StatusCode.IsBad(results[0].StatusCode)) { // embed the diagnostic information in a exception. throw ServiceResultException.Create(results[0].StatusCode, 0, diagnosticInfos, responseHeader.StringTable); } // add first batch. references.AddRange(results[0].References); // check if server limited the results. while (results[0].ContinuationPoint != null && results[0].ContinuationPoint.Length > 0) { ByteStringCollection continuationPoints = new ByteStringCollection(); continuationPoints.Add(results[0].ContinuationPoint); // continue browse operation. responseHeader = session.BrowseNext( null, false, continuationPoints, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, continuationPoints); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); // check status. if (StatusCode.IsBad(results[0].StatusCode)) { // embed the diagnostic information in a exception. throw ServiceResultException.Create(results[0].StatusCode, 0, diagnosticInfos, responseHeader.StringTable); } // add next batch. references.AddRange(results[0].References); } return(references); }
/// <summary> /// Continues a browse operation that was previously halted. /// </summary> public virtual void BrowseNext( OperationContext context, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { if (context == null) throw new ArgumentNullException("context"); if (continuationPoints == null) throw new ArgumentNullException("continuationPoints"); bool diagnosticsExist = false; results = new BrowseResultCollection(continuationPoints.Count); diagnosticInfos = new DiagnosticInfoCollection(continuationPoints.Count); uint continuationPointsAssigned = 0; for (int ii = 0; ii < continuationPoints.Count; ii++) { ContinuationPoint cp = null; // check if request has timed out or been cancelled. if (StatusCode.IsBad(context.OperationStatus)) { // release all allocated continuation points. foreach (BrowseResult current in results) { if (current != null && current.ContinuationPoint != null && current.ContinuationPoint.Length > 0) { cp = context.Session.RestoreContinuationPoint(current.ContinuationPoint); cp.Dispose(); } } throw new ServiceResultException(context.OperationStatus); } // find the continuation point. cp = context.Session.RestoreContinuationPoint(continuationPoints[ii]); // initialize result. BrowseResult result = new BrowseResult(); result.StatusCode = StatusCodes.Good; results.Add(result); // check if simply releasing the continuation point. if (releaseContinuationPoints) { if (cp != null) { cp.Dispose(); cp = null; } continue; } ServiceResult error = null; // check if continuation point has expired. if (cp == null) { error = StatusCodes.BadContinuationPointInvalid; } if (cp != null) { // need to trap unexpected exceptions to handle bugs in the node managers. try { ReferenceDescriptionCollection references = result.References; error = FetchReferences( context, continuationPointsAssigned < m_maxContinuationPointsPerBrowse, ref cp, ref references); result.References = references; } catch (Exception e) { error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error browsing node."); } // check for continuation point. if (result.ContinuationPoint != null && result.ContinuationPoint.Length > 0) { continuationPointsAssigned++; } } // check for error. result.StatusCode = error.StatusCode; if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) { DiagnosticInfo diagnosticInfo = null; if (error != null && error.Code != StatusCodes.Good) { diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, error); diagnosticsExist = true; } diagnosticInfos.Add(diagnosticInfo); } // check for continuation point. if (cp != null) { result.StatusCode = StatusCodes.Good; result.ContinuationPoint = cp.Id.ToByteArray(); continue; } } // clear the diagnostics array if no diagnostics requested or no errors occurred. UpdateDiagnostics(context, diagnosticsExist, ref diagnosticInfos); }
/// <summary> /// Returns the next reference. /// </summary> /// <returns>The next reference that meets the browse criteria.</returns> public override IReference Next() { lock (DataLock) { IReference reference = null; // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. reference = base.Next(); if (reference != null) { return(reference); } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return(null); } if (m_stage == Stage.Begin) { // construct request. BrowseDescription nodeToBrowse = new BrowseDescription(); NodeId startId = ObjectIds.ObjectsFolder; if (m_source != null) { startId = m_mapper.ToRemoteId(m_source.NodeId); } nodeToBrowse.NodeId = startId; nodeToBrowse.BrowseDirection = this.BrowseDirection; nodeToBrowse.ReferenceTypeId = this.ReferenceType; nodeToBrowse.IncludeSubtypes = this.IncludeSubtypes; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = m_client.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); m_position = 0; m_references = null; m_continuationPoint = null; m_stage = Stage.References; // check status. if (StatusCode.IsGood(results[0].StatusCode)) { m_references = results[0].References; m_continuationPoint = results[0].ContinuationPoint; reference = NextChild(); if (reference != null) { return(reference); } } } if (m_stage == Stage.References) { reference = NextChild(); if (reference != null) { return(reference); } if (m_source == null && IsRequired(ReferenceTypes.HasNotifier, false)) { // construct request. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = ObjectIds.Server; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = ReferenceTypes.HasNotifier; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = m_client.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); m_position = 0; m_references = null; m_continuationPoint = null; m_stage = Stage.Notifiers; // check status. if (StatusCode.IsGood(results[0].StatusCode)) { m_references = results[0].References; m_continuationPoint = results[0].ContinuationPoint; } } m_stage = Stage.Notifiers; } if (m_stage == Stage.Notifiers) { reference = NextChild(); if (reference != null) { return(reference); } m_stage = Stage.Done; } // all done. return(null); } }
public async Task BrowseAsync() { // Browse template var startingNode = Objects.RootFolder; var browseTemplate = new BrowseDescription { NodeId = startingNode, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, NodeClassMask = 0, ResultMask = (uint)BrowseResultMask.All }; var requestHeader = new RequestHeader(); var referenceDescriptions = new ReferenceDescriptionCollection(); var browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId( new NodeIdCollection(new NodeId[] { Objects.RootFolder }), browseTemplate); while (browseDescriptionCollection.Any()) { TestContext.Out.WriteLine("Browse {0} Nodes...", browseDescriptionCollection.Count); BrowseResultCollection allResults = new BrowseResultCollection(); var response = await Session.BrowseAsync( requestHeader, null, 5, browseDescriptionCollection, CancellationToken.None).ConfigureAwait(false); BrowseResultCollection results = response.Results; DiagnosticInfoCollection diagnosticInfos = response.DiagnosticInfos; allResults.AddRange(results); var continuationPoints = ServerFixtureUtils.PrepareBrowseNext(results); while (continuationPoints.Any()) { TestContext.Out.WriteLine("BrowseNext {0} Nodes...", continuationPoints.Count); var nextResponse = await Session.BrowseNextAsync(requestHeader, false, continuationPoints, CancellationToken.None); BrowseResultCollection browseNextResultCollection = nextResponse.Results; diagnosticInfos = nextResponse.DiagnosticInfos; ServerFixtureUtils.ValidateResponse(response.ResponseHeader); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, continuationPoints); allResults.AddRange(browseNextResultCollection); continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseNextResultCollection); } // Build browse request for next level var browseTable = new NodeIdCollection(); foreach (var result in allResults) { referenceDescriptions.AddRange(result.References); foreach (var reference in result.References) { browseTable.Add(ExpandedNodeId.ToNodeId(reference.NodeId, Session.NamespaceUris)); } } browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId(browseTable, browseTemplate); } referenceDescriptions.Sort((x, y) => (x.NodeId.CompareTo(y.NodeId))); // read values var nodesToRead = new ReadValueIdCollection(referenceDescriptions.Select(r => new ReadValueId() { NodeId = ExpandedNodeId.ToNodeId(r.NodeId, Session.NamespaceUris), AttributeId = Attributes.Value })); // test reads TestContext.Out.WriteLine("Test Read Nodes..."); var readResponse = await Session.ReadAsync(requestHeader, 0, TimestampsToReturn.Neither, nodesToRead, CancellationToken.None).ConfigureAwait(false); // test register nodes TestContext.Out.WriteLine("Test Register Nodes..."); var nodesToRegister = new NodeIdCollection(nodesToRead.Select(n => n.NodeId)); var registerResponse = await Session.RegisterNodesAsync(requestHeader, nodesToRegister, CancellationToken.None).ConfigureAwait(false); var unregisterResponse = await Session.UnregisterNodesAsync(requestHeader, registerResponse.RegisteredNodeIds, CancellationToken.None).ConfigureAwait(false); // test writes var nodesToWrite = new WriteValueCollection(); int ii = 0; foreach (var result in readResponse.Results) { if (StatusCode.IsGood(result.StatusCode)) { var writeValue = new WriteValue() { AttributeId = Attributes.Value, NodeId = nodesToRead[ii].NodeId, Value = new DataValue(result.WrappedValue) }; nodesToWrite.Add(writeValue); } ii++; } TestContext.Out.WriteLine("Test Writes..."); var writeResponse = await Session.WriteAsync(requestHeader, nodesToWrite, CancellationToken.None).ConfigureAwait(false); TestContext.Out.WriteLine("Found {0} references on server.", referenceDescriptions.Count); ii = 0; foreach (var reference in referenceDescriptions) { TestContext.Out.WriteLine("NodeId {0} {1} {2} {3}", reference.NodeId, reference.NodeClass, reference.BrowseName, readResponse.Results[ii++].WrappedValue); } }