/// <summary> /// Selects the DA COM client to use for the current context. /// </summary> /// <param name="context">The context.</param> /// <returns>A DA COM client instance.</returns> public ComDaClient SelectClient(ServerSystemContext context) { // This method can be used to select different COM server instances // depending on the user credentials or locales used by the the session. // For now all it does is return the default instance. return DefaultClient; }
/// <summary> /// Saves a history data reader. /// </summary> protected virtual void SaveDataReader(Opc.Ua.Server.ServerSystemContext context, HistoryDataReader reader) { if (context == null || context.OperationContext == null || context.OperationContext.Session == null) { return; } context.OperationContext.Session.SaveHistoryContinuationPoint(reader.Id, reader); }
/// <summary> /// Creates a copy of the context that can be used with the specified operation context. /// </summary> /// <param name="context">The operation context to use.</param> /// <returns> /// A copy of the system context that references the new operation context. /// </returns> public ServerSystemContext Copy(OperationContext context) { ServerSystemContext copy = (ServerSystemContext)MemberwiseClone(); if (context != null) { copy.OperationContext = context; } return(copy); }
/// <summary> /// Returns the history data source for a node. /// </summary> protected virtual ServiceResult GetHistoryDataSource( Opc.Ua.Server.ServerSystemContext context, BaseVariableState variable, out IHistoryDataSource datasource) { datasource = m_system.GetHistoryFile(variable); if (datasource == null) { return StatusCodes.BadNotReadable; } return ServiceResult.Good; }
/// <summary> /// Restores a previously cached history reader. /// </summary> protected virtual HistoryDataReader RestoreDataReader(Opc.Ua.Server.ServerSystemContext context, byte[] continuationPoint) { if (context == null || context.OperationContext == null || context.OperationContext.Session == null) { return(null); } HistoryDataReader reader = context.OperationContext.Session.RestoreHistoryContinuationPoint(continuationPoint) as HistoryDataReader; if (reader == null) { return(null); } return(reader); }
/// <summary> /// Creates the configuration node for the server. /// </summary> public void CreateServerConfiguration( ServerSystemContext systemContext, ApplicationConfiguration configuration) { // setup server configuration node m_serverConfigurationNode.ServerCapabilities.Value = configuration.ServerConfiguration.ServerCapabilities.ToArray(); m_serverConfigurationNode.ServerCapabilities.ValueRank = ValueRanks.OneDimension; m_serverConfigurationNode.ServerCapabilities.ArrayDimensions = new ReadOnlyList <uint>(new List <uint> { 0 }); m_serverConfigurationNode.SupportedPrivateKeyFormats.Value = configuration.ServerConfiguration.SupportedPrivateKeyFormats.ToArray(); m_serverConfigurationNode.SupportedPrivateKeyFormats.ValueRank = ValueRanks.OneDimension; m_serverConfigurationNode.SupportedPrivateKeyFormats.ArrayDimensions = new ReadOnlyList <uint>(new List <uint> { 0 }); m_serverConfigurationNode.MaxTrustListSize.Value = (uint)configuration.ServerConfiguration.MaxTrustListSize; m_serverConfigurationNode.MulticastDnsEnabled.Value = configuration.ServerConfiguration.MultiCastDnsEnabled; m_serverConfigurationNode.UpdateCertificate.OnCall = new UpdateCertificateMethodStateMethodCallHandler(UpdateCertificate); m_serverConfigurationNode.CreateSigningRequest.OnCall = new CreateSigningRequestMethodStateMethodCallHandler(CreateSigningRequest); m_serverConfigurationNode.ApplyChanges.OnCallMethod = new GenericMethodCalledEventHandler(ApplyChanges); m_serverConfigurationNode.GetRejectedList.OnCall = new GetRejectedListMethodStateMethodCallHandler(GetRejectedList); m_serverConfigurationNode.ClearChangeMasks(systemContext, true); // setup certificate group trust list handlers foreach (var certGroup in m_certificateGroups) { certGroup.Node.CertificateTypes.Value = certGroup.CertificateTypes; certGroup.Node.TrustList.Handle = new TrustList( certGroup.Node.TrustList, certGroup.TrustedStorePath, certGroup.IssuerStorePath, new TrustList.SecureAccess(HasApplicationSecureAdminAccess), new TrustList.SecureAccess(HasApplicationSecureAdminAccess) ); certGroup.Node.ClearChangeMasks(systemContext, true); } // find ServerNamespaces node and subscribe to StateChanged NamespacesState serverNamespacesNode = FindPredefinedNode(ObjectIds.Server_Namespaces, typeof(NamespacesState)) as NamespacesState; if (serverNamespacesNode != null) { serverNamespacesNode.StateChanged += ServerNamespacesChanged; } }
/// <summary> /// Initializes a session audit event. /// </summary> private void InitializeSessionAuditEvent(ServerSystemContext systemContext, AuditEventState e, TranslationInfo message) { e.Initialize( systemContext, null, EventSeverity.MediumLow, new LocalizedText(message), true, DateTime.UtcNow); e.SetChildValue(systemContext, BrowseNames.SourceNode, m_sessionId, false); e.SetChildValue(systemContext, BrowseNames.SourceName, m_sessionName, false); e.SetChildValue(systemContext, BrowseNames.SessionId, m_sessionId, false); e.SetChildValue(systemContext, BrowseNames.ServerId, m_server.ServerUris.GetString(0), false); e.SetChildValue(systemContext, BrowseNames.ClientUserId, m_identity.DisplayName, false); e.SetChildValue(systemContext, BrowseNames.ClientAuditEntryId, systemContext.OperationContext.AuditEntryId, false); }
/// <summary> /// Reports an audit create session event. /// </summary> private void ReportAuditCreateSessionEvent(ServerSystemContext context) { // raise an audit event. AuditCreateSessionEventState e = new AuditCreateSessionEventState(null); TranslationInfo message = new TranslationInfo( "AuditCreateSessionEvent", "en-US", "Session {0} created.", m_sessionName); InitializeSessionAuditEvent(context, e, message); e.SetChildValue(context, BrowseNames.ClientCertificate, m_securityDiagnostics.ClientCertificate, false); e.SetChildValue(context, BrowseNames.SecureChannelId, m_secureChannelId, false); m_server.ReportEvent(context, e); }
/// <summary> /// Creates a copy of the context that can be used with the specified session. /// </summary> /// <param name="context">The session to use.</param> /// <returns> /// A copy of the system context that references the new operation context. /// </returns> public ServerSystemContext Copy(ServerSystemContext context) { ServerSystemContext copy = (ServerSystemContext)MemberwiseClone(); if (context != null) { OperationContext = context.OperationContext; SessionId = context.SessionId; UserIdentity = context.UserIdentity; PreferredLocales = context.PreferredLocales; NamespaceUris = context.NamespaceUris; ServerUris = context.ServerUris; TypeTable = context.TypeTable; EncodeableFactory = context.EncodeableFactory; } return(copy); }
/// <summary> /// Creates a copy of the context that can be used with the specified session. /// </summary> /// <param name="session">The session to use.</param> /// <returns> /// A copy of the system context that references the new operation context. /// </returns> public ServerSystemContext Copy(Session session) { ServerSystemContext copy = (ServerSystemContext)MemberwiseClone(); OperationContext = null; if (session != null) { SessionId = session.Id; UserIdentity = session.Identity; PreferredLocales = session.PreferredLocales; } else { SessionId = null; UserIdentity = null; PreferredLocales = null; } return(copy); }
/// <summary> /// Initializes the datastore with the server configuration. /// </summary> /// <param name="serverDescription">The server description.</param> /// <param name="configuration">The configuration.</param> /// <param name="messageContext">The message context.</param> /// <param name="certificateValidator">The certificate validator.</param> /// <param name="instanceCertificate">The instance certificate.</param> public ServerInternalData( ServerProperties serverDescription, ApplicationConfiguration configuration, ServiceMessageContext messageContext, CertificateValidator certificateValidator, X509Certificate2 instanceCertificate) { m_serverDescription = serverDescription; m_configuration = configuration; m_messageContext = messageContext; m_endpointAddresses = new List <Uri>(); foreach (string baseAddresses in m_configuration.ServerConfiguration.BaseAddresses) { Uri url = Utils.ParseUri(baseAddresses); if (url != null) { m_endpointAddresses.Add(url); } } m_namespaceUris = m_messageContext.NamespaceUris; m_factory = m_messageContext.Factory; m_serverUris = new StringTable(); m_typeTree = new TypeTable(m_namespaceUris); #if LEGACY_CORENODEMANAGER m_typeSources = new TypeSourceTable(); #endif // add the server uri to the server table. m_serverUris.Append(m_configuration.ApplicationUri); // create the default system context. m_defaultSystemContext = new ServerSystemContext(this); }
/// <summary> /// Initializes a new instance of the <see cref="ComAeSubscriptionClient"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="configuration">The configuration.</param> /// <param name="cache">The cache for known types.</param> /// <param name="namespaceIndex">The namespace index for the event types.</param> /// <param name="manager">The manager.</param> /// <param name="monitoredItem">The monitored item.</param> public ComAeSubscriptionClient( ServerSystemContext context, ComAeClientConfiguration configuration, AeTypeCache cache, ushort namespaceIndex, ComAeClientManager manager, MonitoredItem monitoredItem) { m_defaultContext = context; m_separators = configuration.SeperatorChars; m_cache = cache; m_namespaceIndex = namespaceIndex; m_manager = manager; m_refreshComplete = new ManualResetEvent(false); m_monitoredItems = new List<MonitoredItem>(); m_monitoredItems.Add(monitoredItem); m_qualifiedName = null; m_isSource = false; NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; AeAreaState area = handle.Node as AeAreaState; if (area != null) { m_qualifiedName = area.QualifiedName; m_isSource = false; } else { AeSourceState source = handle.Node as AeSourceState; if (source != null) { m_qualifiedName = source.QualifiedName; m_isSource = true; } } }
/// <summary> /// Returns the node for the event type mapping identified by the node id. /// </summary> public AeEventTypeMappingState GetMappingNode(ServerSystemContext context, NodeId nodeId) { BaseObjectTypeState objectType = null; if (!EventTypeNodes.TryGetValue(nodeId, out objectType)) { return null; } AeEventTypeMappingState mappingNode = objectType as AeEventTypeMappingState; if (mappingNode == null) { return null; } if (context.TypeTable.FindSubTypes(mappingNode.NodeId).Count == 0) { return null; } return mappingNode; }
/// <summary> /// Reports an audit activate session event. /// </summary> private void ReportAuditActivateSessionEvent(ServerSystemContext context) { AuditActivateSessionEventState e = new AuditActivateSessionEventState(null); TranslationInfo message = new TranslationInfo( "AuditActivateSessionEvent", "en-US", "Session {0} activated.", m_sessionName); InitializeSessionAuditEvent(context, e, message); if (m_softwareCertificates != null) { e.SetChildValue(context, BrowseNames.ClientSoftwareCertificates, m_softwareCertificates.ToArray(), false); } if (m_identityToken != null) { e.SetChildValue(context, BrowseNames.UserIdentityToken, Utils.Clone(m_identityToken), false); } m_server.ReportEvent(context, e); }
/// <summary> /// Reads raw history data. /// </summary> protected override void HistoryReadRawModified( ServerSystemContext context, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, IList<HistoryReadValueId> nodesToRead, IList<HistoryReadResult> results, IList<ServiceResult> errors, List<NodeHandle> nodesToProcess, IDictionary<NodeId, NodeState> cache) { ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); for (int ii = 0; ii < nodesToProcess.Count; ii++) { NodeHandle handle = nodesToProcess[ii]; HistoryReadValueId nodeToRead = nodesToRead[handle.Index]; HistoryReadResult result = results[handle.Index]; // check if the node id has been parsed. HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; if (parsedNodeId == null) { errors[handle.Index] = StatusCodes.BadNodeIdInvalid; continue; } // read the history of an item. if (parsedNodeId.RootType == HdaModelUtils.HdaItem) { errors[handle.Index] = HistoryReadItem( context, client, details, timestampsToReturn, nodeToRead, parsedNodeId, result); continue; } // read the history of an attribute. if (parsedNodeId.RootType == HdaModelUtils.HdaItemAttribute) { errors[handle.Index] = HistoryReadAttribute( context, client, details, timestampsToReturn, nodeToRead, parsedNodeId, result); continue; } // read the annotations of an item. if (parsedNodeId.RootType == HdaModelUtils.HdaItemAnnotations) { errors[handle.Index] = HistoryReadAnnotations( context, client, details, timestampsToReturn, nodeToRead, parsedNodeId, result); continue; } errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; } }
/// <summary> /// Checks if the node is in the view. /// </summary> protected override bool IsNodeInView(ServerSystemContext context, ContinuationPoint continuationPoint, NodeState node) { if (continuationPoint.View != null) { if (continuationPoint.View.ViewId == new NodeId(Quickstarts.Views.Views.Engineering, NamespaceIndex)) { // suppress operations properties. if (node != null && node.BrowseName.NamespaceIndex == NamespaceIndexes[2]) { return false; } } if (continuationPoint.View.ViewId == new NodeId(Quickstarts.Views.Views.Operations, NamespaceIndex)) { // suppress engineering properties. if (node != null && node.BrowseName.NamespaceIndex == NamespaceIndexes[1]) { return false; } } } return true; }
/// <summary> /// Reads the history of an HDA item. /// </summary> private ServiceResult HistoryReadItem( ServerSystemContext context, ComHdaClient client, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, HistoryReadValueId nodeToRead, HdaParsedNodeId parsedNodeId, HistoryReadResult result) { // create the request or load it from a continuation point. HdaHistoryReadRawModifiedRequest request = null; if (nodeToRead.ContinuationPoint == null) { request = new HdaHistoryReadRawModifiedRequest(parsedNodeId.RootId, details, nodeToRead); } else { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadRawModifiedRequest; if (request == null) { return StatusCodes.BadContinuationPointInvalid; } } // fetch the data. result.StatusCode = client.ReadHistory(request); // fill in the results. if (request.Results != null) { HistoryData data = (request.IsReadModified)?new HistoryModifiedData():new HistoryData(); if (request.IsReadModified) { ((HistoryModifiedData)data).ModificationInfos = request.ModificationInfos; } data.DataValues = request.Results; result.HistoryData = new ExtensionObject(data); } // create a new continuation point. if (!request.Completed) { result.ContinuationPoint = SaveContinuationPoint(context, request); } return result.StatusCode; }
/// <summary> /// Reads the history of an HDA item annotations. /// </summary> private ServiceResult HistoryReadAnnotations( ServerSystemContext context, ComHdaClient client, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, HistoryReadValueId nodeToRead, HdaParsedNodeId parsedNodeId, HistoryReadResult result) { // create the request or load it from a continuation point. HdaHistoryReadAnnotationRequest request = null; if (nodeToRead.ContinuationPoint == null) { // create a new request. request = new HdaHistoryReadAnnotationRequest(parsedNodeId.RootId, details, nodeToRead); // fetch all of the data at once. result.StatusCode = client.ReadAnnotationHistory(request); } else { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadAnnotationRequest; if (request == null) { return StatusCodes.BadContinuationPointInvalid; } } // select a subset of the results. if (StatusCode.IsGood(result.StatusCode)) { request.Results = new DataValueCollection(); request.GetHistoryResults(context, nodeToRead, request.Results); } // fill in the results. if (request.Results != null) { HistoryData data = new HistoryData(); data.DataValues = request.Results; result.HistoryData = new ExtensionObject(data); } // create a new continuation point. if (!request.Completed) { result.ContinuationPoint = SaveContinuationPoint(context, request); } return result.StatusCode; }
/// <summary> /// Initializes the datastore with the server configuration. /// </summary> /// <param name="serverDescription">The server description.</param> /// <param name="configuration">The configuration.</param> /// <param name="messageContext">The message context.</param> /// <param name="certificateValidator">The certificate validator.</param> /// <param name="instanceCertificate">The instance certificate.</param> public ServerInternalData( ServerProperties serverDescription, ApplicationConfiguration configuration, ServiceMessageContext messageContext, CertificateValidator certificateValidator, X509Certificate2 instanceCertificate) { m_serverDescription = serverDescription; m_configuration = configuration; m_messageContext = messageContext; m_endpointAddresses = new List<Uri>(); foreach (string baseAddresses in m_configuration.ServerConfiguration.BaseAddresses) { Uri url = Utils.ParseUri(baseAddresses); if (url != null) { m_endpointAddresses.Add(url); } } m_namespaceUris = m_messageContext.NamespaceUris; m_factory = m_messageContext.Factory; m_serverUris = new StringTable(); m_typeTree = new TypeTable(m_namespaceUris); #if LEGACY_CORENODEMANAGER m_typeSources = new TypeSourceTable(); #endif // add the server uri to the server table. m_serverUris.Append(m_configuration.ApplicationUri); // create the default system context. m_defaultSystemContext = new ServerSystemContext(this); }
/// <summary> /// Returns the type identified by the category id and condition name. /// </summary> public AeEventTypeState FindType(ServerSystemContext context, NodeId nodeId) { if (NodeId.IsNull(nodeId)) { return null; } BaseObjectTypeState eventType = null; if (!EventTypeNodes.TryGetValue(nodeId, out eventType)) { return null; } return eventType as AeEventTypeState; }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected override NodeState ValidateNode( ServerSystemContext context, Opc.Ua.Server.NodeHandle handle, IDictionary<NodeId, NodeState> cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // lookup in operation cache. NodeState target = FindNodeInCache(context, handle, cache); if (target == null) { // TBD return null; } return ValidationComplete(context, handle, target, cache); }
/// <summary> /// Called when a batch of monitored items has been created. /// </summary> protected override void OnCreateMonitoredItemsComplete(ServerSystemContext context, IList<IMonitoredItem> monitoredItems) { ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; ComHdaClient client = (ComHdaClient)system.SelectClient(context, false); // use locale for session to find a subscription manager. HdaSubscribeRequestManager manager = null; if (!m_subscriptionManagers.TryGetValue(client.LocaleId, out manager)) { m_subscriptionManagers[client.LocaleId] = manager = new HdaSubscribeRequestManager(context, client.LocaleId, m_configuration); } manager.CreateItems(context, monitoredItems); for (int ii = 0; ii < monitoredItems.Count; ii++) { m_monitoredItems[monitoredItems[ii].Id] = manager; } }
/// <summary> /// Selects the COM client to use for the current context. /// </summary> /// <param name="context">The context.</param> /// <param name="useDefault">The whether to use the default context.</param> /// <returns>A COM client instance.</returns> public virtual ComClient SelectClient(ServerSystemContext context, bool useDefault) { if (useDefault) { return DefaultClient; } return GetLocalizedClient(context.UserIdentity, context.PreferredLocales); }
/// <summary> /// Activates the session and binds it to the current secure channel. /// </summary> public bool Activate( OperationContext context, List <SoftwareCertificate> clientSoftwareCertificates, UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity, StringCollection localeIds, byte[] serverNonce) { lock (m_lock) { // update user identity. bool changed = false; if (identityToken != null) { if (UpdateUserIdentity(identityToken, identity, effectiveIdentity)) { changed = true; } } // update local ids. if (UpdateLocaleIds(localeIds)) { changed = true; } if (!m_activated) { // toggle the activated flag. m_activated = true; // save the software certificates. m_softwareCertificates = clientSoftwareCertificates; TraceState("FIRST ACTIVATION"); } else { // bind to the new secure channel. m_secureChannelId = context.ChannelContext.SecureChannelId; TraceState("RE-ACTIVATION"); } // update server nonce. m_serverNonce = serverNonce; // build list of signed certificates for audit event. List <SignedSoftwareCertificate> signedSoftwareCertificates = new List <SignedSoftwareCertificate>(); if (clientSoftwareCertificates != null) { foreach (SoftwareCertificate softwareCertificate in clientSoftwareCertificates) { SignedSoftwareCertificate item = new SignedSoftwareCertificate(); item.CertificateData = softwareCertificate.SignedCertificate.GetRawCertData(); signedSoftwareCertificates.Add(item); } } // raise an audit event. ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(context); ReportAuditActivateSessionEvent(systemContext); // update the contact time. lock (m_diagnostics) { m_diagnostics.ClientLastContactTime = DateTime.UtcNow; } // indicate whether the user context has changed. return(changed); } }
/// <summary> /// Returns a unique handle for the node. /// </summary> protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary<NodeId, NodeState> cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } NodeState node = null; if (!PredefinedNodes.TryGetValue(nodeId, out node)) { return null; } NodeHandle handle = new NodeHandle(); handle.NodeId = nodeId; handle.Node = node; handle.Validated = true; return handle; } }
/// <summary> /// Called when a batch of monitored items has their monitoring mode changed. /// </summary> protected override void OnSetMonitoringModeComplete(ServerSystemContext context, IList<IMonitoredItem> monitoredItems) { OnModifyMonitoredItemsComplete(context, monitoredItems); }
/// <summary> /// Called when a batch of monitored items has been deleted. /// </summary> protected override void OnDeleteMonitoredItemsComplete(ServerSystemContext context, IList<IMonitoredItem> monitoredItems) { ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; ComHdaClient client = (ComHdaClient)system.SelectClient(context, false); // sort monitored items by the locale id used to create them. Dictionary<int, List<IMonitoredItem>> monitoredItemsByLocaleId = new Dictionary<int, List<IMonitoredItem>>(); for (int ii = 0; ii < monitoredItems.Count; ii++) { // look up the manager that was previously used to create the monitor item. HdaSubscribeRequestManager manager = null; if (!m_monitoredItems.TryGetValue(monitoredItems[ii].Id, out manager)) { manager = m_subscriptionManagers[client.LocaleId]; } // add monitored item to a list of items for the locale of the manager. List<IMonitoredItem> subset = null; if (!monitoredItemsByLocaleId.TryGetValue(manager.LocaleId, out subset)) { monitoredItemsByLocaleId[manager.LocaleId] = subset = new List<IMonitoredItem>(); } subset.Add(monitoredItems[ii]); } // delete the items. foreach (KeyValuePair<int, List<IMonitoredItem>> entry in monitoredItemsByLocaleId) { HdaSubscribeRequestManager manager = null; if (m_subscriptionManagers.TryGetValue(entry.Key, out manager)) { manager.DeleteItems(context, entry.Value); } } }
/// <summary> /// Checks if the reference is in the view. /// </summary> protected override bool IsReferenceInView(ServerSystemContext context, ContinuationPoint continuationPoint, IReference reference) { if (continuationPoint.View != null) { // guard against absolute node ids. if (reference.TargetId.IsAbsolute) { return true; } // find the node. NodeState node = FindPredefinedNode((NodeId)reference.TargetId, typeof(NodeState)); if (node != null) { return IsNodeInView(context, continuationPoint, node); } } return true; }
/// <summary> /// Creates a new instance and assigns unique identifiers to all children. /// </summary> /// <param name="context">The operation context.</param> /// <param name="parentId">An optional parent identifier.</param> /// <param name="referenceTypeId">The reference type from the parent.</param> /// <param name="browseName">The browse name.</param> /// <param name="instance">The instance to create.</param> /// <returns>The new node id.</returns> public NodeId CreateNode( ServerSystemContext context, NodeId parentId, NodeId referenceTypeId, QualifiedName browseName, BaseInstanceState instance) { ServerSystemContext contextToUse = (ServerSystemContext)m_systemContext.Copy(context); lock (Lock) { instance.ReferenceTypeId = referenceTypeId; NodeState parent = null; if (parentId != null) { if (!PredefinedNodes.TryGetValue(parentId, out parent)) { throw ServiceResultException.Create( StatusCodes.BadNodeIdUnknown, "Cannot find parent with id: {0}", parentId); } parent.AddChild(instance); } instance.Create(contextToUse, null, browseName, null, true); AddPredefinedNode(contextToUse, instance); return instance.NodeId; } }
/// <summary> /// Returns a unique handle for the node. /// </summary> protected override Opc.Ua.Server.NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary<NodeId, NodeState> cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } NodeState node = null; // check cache (the cache is used because the same node id can appear many times in a single request). if (cache != null) { if (cache.TryGetValue(nodeId, out node)) { return new Opc.Ua.Server.NodeHandle(nodeId, node); } } // look up predefined node. if (PredefinedNodes.TryGetValue(nodeId, out node)) { Opc.Ua.Server.NodeHandle handle = new Opc.Ua.Server.NodeHandle(nodeId, node); if (cache != null) { cache.Add(nodeId, node); } return handle; } return null; } }
public Session( OperationContext context, IServerInternal server, X509Certificate2 serverCertificate, NodeId authenticationToken, byte[] serverNonce, string sessionName, ApplicationDescription clientDescription, string endpointUrl, X509Certificate2 clientCertificate, double sessionTimeout, uint maxResponseMessageSize, double maxRequestAge, int maxBrowseContinuationPoints, int maxHistoryContinuationPoints) { if (context == null) { throw new ArgumentNullException("context"); } if (server == null) { throw new ArgumentNullException("server"); } // verify that a secure channel was specified. if (context.ChannelContext == null) { throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } m_server = server; m_authenticationToken = authenticationToken; m_serverNonce = serverNonce; m_sessionName = sessionName; m_serverCertificate = serverCertificate; m_clientCertificate = clientCertificate; m_secureChannelId = context.ChannelContext.SecureChannelId; m_maxResponseMessageSize = maxResponseMessageSize; m_maxRequestAge = maxRequestAge; m_maxBrowseContinuationPoints = maxBrowseContinuationPoints; m_maxHistoryContinuationPoints = maxHistoryContinuationPoints; m_endpoint = context.ChannelContext.EndpointDescription; // use anonymous the default identity. m_identity = new UserIdentity(); // initialize diagnostics. m_diagnostics = new SessionDiagnosticsDataType(); m_diagnostics.SessionId = null; m_diagnostics.SessionName = sessionName; m_diagnostics.ClientDescription = clientDescription; m_diagnostics.ServerUri = null; m_diagnostics.EndpointUrl = endpointUrl; m_diagnostics.LocaleIds = new StringCollection(); m_diagnostics.ActualSessionTimeout = sessionTimeout; m_diagnostics.ClientConnectionTime = DateTime.UtcNow; m_diagnostics.ClientLastContactTime = DateTime.UtcNow; m_diagnostics.CurrentSubscriptionsCount = 0; m_diagnostics.CurrentMonitoredItemsCount = 0; m_diagnostics.CurrentPublishRequestsInQueue = 0; m_diagnostics.TotalRequestCount = new ServiceCounterDataType(); m_diagnostics.UnauthorizedRequestCount = 0; m_diagnostics.ReadCount = new ServiceCounterDataType(); m_diagnostics.HistoryReadCount = new ServiceCounterDataType(); m_diagnostics.WriteCount = new ServiceCounterDataType(); m_diagnostics.HistoryUpdateCount = new ServiceCounterDataType(); m_diagnostics.CallCount = new ServiceCounterDataType(); m_diagnostics.CreateMonitoredItemsCount = new ServiceCounterDataType(); m_diagnostics.ModifyMonitoredItemsCount = new ServiceCounterDataType(); m_diagnostics.SetMonitoringModeCount = new ServiceCounterDataType(); m_diagnostics.SetTriggeringCount = new ServiceCounterDataType(); m_diagnostics.DeleteMonitoredItemsCount = new ServiceCounterDataType(); m_diagnostics.CreateSubscriptionCount = new ServiceCounterDataType(); m_diagnostics.ModifySubscriptionCount = new ServiceCounterDataType(); m_diagnostics.SetPublishingModeCount = new ServiceCounterDataType(); m_diagnostics.PublishCount = new ServiceCounterDataType(); m_diagnostics.RepublishCount = new ServiceCounterDataType(); m_diagnostics.TransferSubscriptionsCount = new ServiceCounterDataType(); m_diagnostics.DeleteSubscriptionsCount = new ServiceCounterDataType(); m_diagnostics.AddNodesCount = new ServiceCounterDataType(); m_diagnostics.AddReferencesCount = new ServiceCounterDataType(); m_diagnostics.DeleteNodesCount = new ServiceCounterDataType(); m_diagnostics.DeleteReferencesCount = new ServiceCounterDataType(); m_diagnostics.BrowseCount = new ServiceCounterDataType(); m_diagnostics.BrowseNextCount = new ServiceCounterDataType(); m_diagnostics.TranslateBrowsePathsToNodeIdsCount = new ServiceCounterDataType(); m_diagnostics.QueryFirstCount = new ServiceCounterDataType(); m_diagnostics.QueryNextCount = new ServiceCounterDataType(); m_diagnostics.RegisterNodesCount = new ServiceCounterDataType(); m_diagnostics.UnregisterNodesCount = new ServiceCounterDataType(); // initialize security diagnostics. m_securityDiagnostics = new SessionSecurityDiagnosticsDataType(); m_securityDiagnostics.SessionId = m_sessionId; m_securityDiagnostics.ClientUserIdOfSession = m_identity.DisplayName; m_securityDiagnostics.AuthenticationMechanism = m_identity.TokenType.ToString(); m_securityDiagnostics.Encoding = context.ChannelContext.MessageEncoding.ToString(); m_securityDiagnostics.ClientUserIdHistory = new StringCollection(); m_securityDiagnostics.ClientUserIdHistory.Add(m_identity.DisplayName); EndpointDescription description = context.ChannelContext.EndpointDescription; if (description != null) { m_securityDiagnostics.TransportProtocol = new Uri(description.EndpointUrl).Scheme; m_securityDiagnostics.SecurityMode = m_endpoint.SecurityMode; m_securityDiagnostics.SecurityPolicyUri = m_endpoint.SecurityPolicyUri; } if (clientCertificate != null) { m_securityDiagnostics.ClientCertificate = clientCertificate.RawData; } ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(context); // create diagnostics object. m_sessionId = server.DiagnosticsNodeManager.CreateSessionDiagnostics( systemContext, m_diagnostics, OnUpdateDiagnostics, m_securityDiagnostics, OnUpdateSecurityDiagnostics); // report the audit event. ReportAuditCreateSessionEvent(systemContext); TraceState("CREATED"); }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected virtual bool ValidateNode(ServerSystemContext context, NodeState node) { // validate node only if required. if (node.ValidationRequired) { return node.Validate(context); } return true; }
/// <summary> /// Deletes the data history for one or more nodes. /// </summary> protected override void HistoryDeleteAtTime( ServerSystemContext context, IList<DeleteAtTimeDetails> nodesToUpdate, IList<HistoryUpdateResult> results, IList<ServiceResult> errors, List<NodeHandle> nodesToProcess, IDictionary<NodeId, NodeState> cache) { ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); for (int ii = 0; ii < nodesToProcess.Count; ii++) { NodeHandle handle = nodesToProcess[ii]; DeleteAtTimeDetails nodeToUpdate = nodesToUpdate[handle.Index]; HistoryUpdateResult result = results[handle.Index]; // check if the node id has been parsed. HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; if (parsedNodeId == null) { errors[handle.Index] = StatusCodes.BadNodeIdInvalid; continue; } if (parsedNodeId.RootType == HdaModelUtils.HdaItem) { errors[handle.Index] = client.DeleteAtTime(parsedNodeId.RootId, nodeToUpdate, results[handle.Index]); continue; } errors[handle.Index] = StatusCodes.BadHistoryOperationUnsupported; } }
/// <summary> /// Deletes a node and all of its children. /// </summary> public bool DeleteNode( ServerSystemContext context, NodeId nodeId) { ServerSystemContext contextToUse = m_systemContext.Copy(context); bool found = false; List<LocalReference> referencesToRemove = new List<LocalReference>(); lock (Lock) { NodeState node = null; if (PredefinedNodes.TryGetValue(nodeId, out node)) { RemovePredefinedNode(contextToUse, node, referencesToRemove); found = true; } RemoveRootNotifier(node); } // must release the lock before removing cross references to other node managers. if (referencesToRemove.Count > 0) { Server.NodeManager.RemoveReferences(referencesToRemove); } return found; }
/// <summary> /// Validates the nodes and reads the values from the underlying source. /// </summary> /// <param name="context">The context.</param> /// <param name="nodesToRead">The nodes to read.</param> /// <param name="values">The values.</param> /// <param name="errors">The errors.</param> /// <param name="nodesToValidate">The nodes to validate.</param> /// <param name="cache">The cache.</param> protected override void Read( ServerSystemContext context, IList<ReadValueId> nodesToRead, IList<DataValue> values, IList<ServiceResult> errors, List<NodeHandle> nodesToValidate, IDictionary<NodeId, NodeState> cache) { ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); HdaReadRequestCollection requests = new HdaReadRequestCollection(); for (int ii = 0; ii < nodesToValidate.Count; ii++) { NodeHandle handle = nodesToValidate[ii]; lock (Lock) { NodeState source = ValidateNode(context, handle, cache); if (source == null) { continue; } DataValue value = values[handle.Index]; ReadValueId nodeToRead = nodesToRead[handle.Index]; // determine if request can be sent to the server. bool queued = false; errors[handle.Index] = requests.Add(source, nodeToRead, out queued); if (queued) { continue; } // read built-in metadata. errors[handle.Index] = source.ReadAttribute( context, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); } } // read the attributes. if (requests.Count > 0) { client.Read(requests, false); } // extract the values from the results. for (int ii = 0; ii < nodesToValidate.Count; ii++) { NodeHandle handle = nodesToValidate[ii]; DataValue value = values[handle.Index]; ReadValueId nodeToRead = nodesToRead[handle.Index]; lock (Lock) { if (!requests.HasResult(nodeToRead)) { continue; } errors[handle.Index] = requests.GetResult(context, handle.Node, nodeToRead, value, context.DiagnosticsMask); } } }
/// <summary> /// Loads a history continuation point. /// </summary> private HdaHistoryReadRequest LoadContinuationPoint( ServerSystemContext context, byte[] continuationPoint) { Session session = context.OperationContext.Session; if (session == null) { return null; } HdaHistoryReadRequest request = session.RestoreHistoryContinuationPoint(continuationPoint) as HdaHistoryReadRequest; if (request == null) { return null; } return request; }
/// <summary> /// Releases the history continuation point. /// </summary> protected override void HistoryReleaseContinuationPoints( ServerSystemContext context, IList<HistoryReadValueId> nodesToRead, IList<ServiceResult> errors, List<NodeHandle> nodesToProcess, IDictionary<NodeId, NodeState> cache) { ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle; ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false); for (int ii = 0; ii < nodesToProcess.Count; ii++) { NodeHandle handle = nodesToProcess[ii]; HistoryReadValueId nodeToRead = nodesToRead[handle.Index]; // check if the node id has been parsed. HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; if (parsedNodeId == null) { errors[handle.Index] = StatusCodes.BadNodeIdInvalid; continue; } // find the continuation point. HdaHistoryReadRequest request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } // all done. errors[handle.Index] = StatusCodes.Good; } }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary<NodeId, NodeState> cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // TBD return null; }
/// <summary> /// Saves a history continuation point. /// </summary> private byte[] SaveContinuationPoint( ServerSystemContext context, HdaHistoryReadRequest request) { Session session = context.OperationContext.Session; if (session == null) { return null; } Guid id = Guid.NewGuid(); session.SaveHistoryContinuationPoint(id, request); request.ContinuationPoint = id.ToByteArray(); return request.ContinuationPoint; }
/// <summary> /// Initializes the manager by creating the default instance. /// </summary> public void Initialize( ServerSystemContext context, ComClientConfiguration configuration, ComServerStatusState statusNode, object statusNodeLock, WaitCallback reconnectCallback) { m_defaultSystemContext = context; m_configuration = configuration; m_statusNode = statusNode; m_statusNodeLock = statusNodeLock; m_statusUpdateInterval = m_configuration.MaxReconnectWait; m_reconnectCallback = reconnectCallback; // limit status updates to once per 10 seconds. if (m_statusUpdateInterval < 10000) { m_statusUpdateInterval = 10000; } StartStatusTimer(OnStatusTimerExpired); }
/// <summary> /// Returns a unique handle for the node. /// </summary> protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary<NodeId, NodeState> cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check cache. if (cache != null) { NodeState node = null; if (cache.TryGetValue(nodeId, out node)) { return new NodeHandle(nodeId, node); } } NodeHandle handle = null; try { // check for predefined nodes. if (PredefinedNodes != null) { NodeState node = null; if (PredefinedNodes.TryGetValue(nodeId, out node)) { return handle = new NodeHandle(nodeId, node); } } // parse the identifier. HdaParsedNodeId parsedNodeId = HdaParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { handle = new NodeHandle(); handle.NodeId = nodeId; handle.Validated = false; handle.Node = null; handle.ParsedNodeId = parsedNodeId; return handle; } } finally { if (handle != null && handle.Node != null && cache != null) { cache.Add(nodeId, handle.Node); } } return null; } }
/// <summary> /// Publishes all available event notifications. /// </summary> public virtual bool Publish(OperationContext context, Queue<EventFieldList> notifications) { if (context == null) throw new ArgumentNullException("context"); if (notifications == null) throw new ArgumentNullException("notifications"); lock (m_lock) { // check if the item reports events. if ((m_typeMask & MonitoredItemTypeMask.Events) == 0) { return false; } // only publish if reporting. if (!IsReadyToPublish) { return false; } // go to the next sampling interval. IncrementSampleTime(); // publish events. if (m_events != null) { Utils.Trace("MONITORED ITEM: Publish(QueueSize={0})", notifications.Count); EventFieldList overflowEvent = null; if (m_overflow) { // construct event. EventQueueOverflowEventState e = new EventQueueOverflowEventState(null); TranslationInfo message = new TranslationInfo( "EventQueueOverflowEventState", "en-US", "Events lost due to queue overflow."); ISystemContext systemContext = new ServerSystemContext(m_server, context); e.Initialize( systemContext, null, EventSeverity.Low, new LocalizedText(message)); e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false); e.SetChildValue(systemContext, BrowseNames.SourceName, "Internal", false); // fetch the event fields. overflowEvent = GetEventFields( new FilterContext(m_server.NamespaceUris, m_server.TypeTree, m_session.PreferredLocales), m_filterToUse as EventFilter, e); } // place event at the beginning of the queue. if (overflowEvent != null && m_discardOldest) { notifications.Enqueue(overflowEvent); } for (int ii = 0; ii < m_events.Count; ii++) { EventFieldList fields = (EventFieldList)m_events[ii]; // apply any diagnostic masks. for (int jj = 0; jj < fields.EventFields.Count; jj++) { object value = fields.EventFields[jj].Value; StatusResult result = value as StatusResult; if (result != null) { result.ApplyDiagnosticMasks(context.DiagnosticsMask, context.StringTable); } } notifications.Enqueue((EventFieldList)m_events[ii]); } m_events.Clear(); // place event at the end of the queue. if (overflowEvent != null && !m_discardOldest) { notifications.Enqueue(overflowEvent); } Utils.Trace("MONITORED ITEM: Publish(QueueSize={0})", notifications.Count); } // reset state variables. m_overflow = false; m_readyToPublish = false; m_readyToTrigger = false; m_triggered = false; return false; } }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary<NodeId, NodeState> cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } NodeState target = null; // check if already in the cache. if (cache != null) { if (cache.TryGetValue(handle.NodeId, out target)) { // nulls mean a NodeId which was previously found to be invalid has been referenced again. if (target == null) { return null; } handle.Node = target; handle.Validated = true; return handle.Node; } target = null; } try { // check if the node id has been parsed. HdaParsedNodeId parsedNodeId = handle.ParsedNodeId as HdaParsedNodeId; if (parsedNodeId == null) { return null; } ComHdaClient client = (ComHdaClient)m_system.SelectClient(context, false); switch (parsedNodeId.RootType) { case HdaModelUtils.HdaBranch: { ComHdaBrowserClient browser = new ComHdaBrowserClient(client, null); target = browser.FindBranch(context, parsedNodeId.RootId, NamespaceIndex); browser.Dispose(); break; } case HdaModelUtils.HdaItem: { HdaItem[] items = client.GetItems(parsedNodeId.RootId); if (items[0].Error < 0) { return null; } try { string browseName = null; if (!m_configuration.ItemIdParser.Parse(client, m_configuration, parsedNodeId.RootId, out browseName)) { HdaAttributeValue[] attributes = client.ReadAttributeValues(items[0].ServerHandle, OpcRcw.Hda.Constants.OPCHDA_ITEMID); browseName = attributes[0].Value as string; } target = new HdaItemState(items[0].ItemId, browseName, NamespaceIndex); } finally { client.ReleaseItemHandles(items); } break; } case HdaModelUtils.HdaItemAttribute: { bool[] results = client.ValidateItemIds(parsedNodeId.RootId); if (!results[0]) { return null; } target = client.FindItemAttribute(parsedNodeId.RootId, parsedNodeId.AttributeId, NamespaceIndex); break; } case HdaModelUtils.HdaItemAnnotations: { bool[] results = client.ValidateItemIds(parsedNodeId.RootId); if (!results[0]) { return null; } target = client.FindItemAnnotations(parsedNodeId.RootId, NamespaceIndex); break; } case HdaModelUtils.HdaItemConfiguration: { bool[] results = client.ValidateItemIds(parsedNodeId.RootId); if (results == null || !results[0]) { return null; } target = HdaModelUtils.GetItemConfigurationNode(parsedNodeId.RootId, NamespaceIndex); target.OnCreateBrowser = OnCreateItemConfigurationBrowser; break; } case HdaModelUtils.HdaAggregate: { target = client.FindAggregate(parsedNodeId.AggregateId, NamespaceIndex); break; } } // check if found. if (target == null) { return null; } // found a valid component. handle.Validated = true; handle.Node = target; return handle.Node; } finally { // store the node in the cache to optimize subsequent lookups. if (cache != null) { cache.Add(handle.NodeId, target); } } }