/// <summary>
        /// Updates the session diagnostics summary structure.
        /// </summary>
        private bool UpdateSessionDiagnostics(
            SessionDiagnosticsData diagnostics, 
            SessionDiagnosticsDataType[] sessionArray, 
            int index)
        {  
            // get the latest snapshot.
            object value = null;
            
            ServiceResult result = diagnostics.UpdateCallback(
                SystemContext, 
                diagnostics.Value.Variable, 
                ref value);

            SessionDiagnosticsDataType newValue = value as SessionDiagnosticsDataType;
            sessionArray[index] = newValue;

            // check for changes.
            if (Utils.IsEqual(newValue, diagnostics.Value.Value))
            {
                return false;
            }
            
            diagnostics.Value.Error = null;
            
            // check for bad value.
            if (ServiceResult.IsNotBad(result) && newValue == null)
            {
                result = StatusCodes.BadOutOfService;
            }

            // check for bad result.
            if (ServiceResult.IsBad(result))
            {
                diagnostics.Value.Error = result;
                newValue = null;
            }
            
            // update the value.
            diagnostics.Value.Value = newValue;
            diagnostics.Value.Timestamp = DateTime.UtcNow;

            // notify any monitored items.
            diagnostics.Value.ChangesComplete(SystemContext);

            return true;
        }
        /// <summary>
        /// Creates the diagnostics node for a subscription.
        /// </summary>
        public NodeId CreateSessionDiagnostics(
            ServerSystemContext systemContext, 
            SessionDiagnosticsDataType diagnostics,
            NodeValueSimpleEventHandler updateCallback,
            SessionSecurityDiagnosticsDataType securityDiagnostics,
            NodeValueSimpleEventHandler updateSecurityCallback)
        {
            NodeId nodeId = null;

            lock (Lock)
            {
                SessionDiagnosticsObjectState sessionNode = new SessionDiagnosticsObjectState(null);
                
                // create a new instance and assign ids.
                nodeId = CreateNode(
                    systemContext,
                    null,
                    ReferenceTypeIds.HasComponent,
                    new QualifiedName(diagnostics.SessionName),
                    sessionNode);

                diagnostics.SessionId = nodeId;
                securityDiagnostics.SessionId = nodeId;
                
                // check if diagnostics have been enabled.
                if (!m_diagnosticsEnabled)
                {
                    return nodeId;
                }

                // add reference to session summary object.
                sessionNode.AddReference(
                    ReferenceTypeIds.HasComponent,
                    true,
                    ObjectIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary);
                
                // add reference from session summary object.
                SessionsDiagnosticsSummaryState summary = (SessionsDiagnosticsSummaryState)FindPredefinedNode(
                    ObjectIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary,
                    typeof(SessionsDiagnosticsSummaryState));
                                            
                if (summary != null)
                {
                    summary.AddReference(ReferenceTypeIds.HasComponent, false, sessionNode.NodeId);
                }

                // initialize diagnostics node.
                SessionDiagnosticsVariableState diagnosticsNode = sessionNode.CreateChild(
                   systemContext,
                   BrowseNames.SessionDiagnostics) as SessionDiagnosticsVariableState;
                
                // wrap diagnostics in a thread safe object.
                SessionDiagnosticsVariableValue diagnosticsValue = new SessionDiagnosticsVariableValue(
                    diagnosticsNode, 
                    diagnostics, 
                    Lock);
                
                // must ensure the first update gets sent.
                diagnosticsValue.Value = null;
                diagnosticsValue.Error = StatusCodes.BadWaitingForInitialData;
                diagnosticsValue.CopyPolicy = Opc.Ua.VariableCopyPolicy.Never;
                diagnosticsValue.OnBeforeRead = OnBeforeReadDiagnostics;
                
                // initialize security diagnostics node.
                SessionSecurityDiagnosticsState securityDiagnosticsNode = sessionNode.CreateChild(
                   systemContext,
                   BrowseNames.SessionSecurityDiagnostics) as SessionSecurityDiagnosticsState;
                
                // wrap diagnostics in a thread safe object.
                SessionSecurityDiagnosticsValue securityDiagnosticsValue = new SessionSecurityDiagnosticsValue(
                    securityDiagnosticsNode, 
                    securityDiagnostics, 
                    Lock);
                
                // must ensure the first update gets sent.
                securityDiagnosticsValue.Value = null;
                securityDiagnosticsValue.Error = StatusCodes.BadWaitingForInitialData;
                securityDiagnosticsValue.CopyPolicy = Opc.Ua.VariableCopyPolicy.Never;
                securityDiagnosticsValue.OnBeforeRead = OnBeforeReadDiagnostics;
                
                // save the session.
                SessionDiagnosticsData sessionData = new SessionDiagnosticsData(
                    sessionNode,
                    diagnosticsValue, 
                    updateCallback, 
                    securityDiagnosticsValue, 
                    updateSecurityCallback);

                m_sessions.Add(sessionData);

                // send initial update.
                DoScan(true);
            }

            return nodeId;
        }
        /// <summary>
        /// Reports notifications for any monitored diagnostic nodes.
        /// </summary>
        private void DoScan(object alwaysUpdateArrays)
        {
            try
            {
                lock (Lock)
                {
                    if (!m_diagnosticsEnabled)
                    {
                        return;
                    }

                    m_lastDiagnosticsScanTime = DateTime.UtcNow;
                
                    // update server diagnostics.
                    UpdateServerDiagnosticsSummary();
                   
                    // update session diagnostics.
                    bool sessionsChanged = alwaysUpdateArrays != null;
                    SessionDiagnosticsDataType[] sessionArray = new SessionDiagnosticsDataType[m_sessions.Count];

                    for (int ii = 0; ii < m_sessions.Count; ii++)
                    {
                        SessionDiagnosticsData diagnostics = m_sessions[ii];

                        if (UpdateSessionDiagnostics(diagnostics, sessionArray, ii))
                        {
                            sessionsChanged = true;
                        }
                    }

                    // check of the session diagnostics array node needs to be updated.
                    SessionDiagnosticsArrayState sessionsNode = (SessionDiagnosticsArrayState)FindPredefinedNode(
                        VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionDiagnosticsArray,
                        typeof(SessionDiagnosticsArrayState));
                                                
                    if (sessionsNode != null && (sessionsNode.Value == null || StatusCode.IsBad(sessionsNode.StatusCode) || sessionsChanged))
                    {
                        sessionsNode.Value = sessionArray;
                        sessionsNode.ClearChangeMasks(SystemContext, false);
                    }
                      
                    bool sessionsSecurityChanged = alwaysUpdateArrays != null;
                    SessionSecurityDiagnosticsDataType[] sessionSecurityArray = new SessionSecurityDiagnosticsDataType[m_sessions.Count];

                    for (int ii = 0; ii < m_sessions.Count; ii++)
                    {                        
                        SessionDiagnosticsData diagnostics = m_sessions[ii];

                        if (UpdateSessionSecurityDiagnostics(diagnostics, sessionSecurityArray, ii))
                        {
                            sessionsChanged = true;
                        }
                    }

                    // check of the array node needs to be updated.
                    SessionSecurityDiagnosticsArrayState sessionsSecurityNode = (SessionSecurityDiagnosticsArrayState)FindPredefinedNode(
                        VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionSecurityDiagnosticsArray,
                        typeof(SessionSecurityDiagnosticsArrayState));
                                                
                    if (sessionsSecurityNode != null && (sessionsSecurityNode.Value == null || StatusCode.IsBad(sessionsSecurityNode.StatusCode) || sessionsSecurityChanged))
                    {
                        sessionsSecurityNode.Value = sessionSecurityArray;
                        sessionsSecurityNode.ClearChangeMasks(SystemContext, false);
                    }

                    bool subscriptionsChanged = alwaysUpdateArrays != null;
                    SubscriptionDiagnosticsDataType[] subscriptionArray = new SubscriptionDiagnosticsDataType[m_subscriptions.Count];

                    for (int ii = 0; ii < m_subscriptions.Count; ii++)
                    {
                        SubscriptionDiagnosticsData diagnostics = m_subscriptions[ii];
                        
                        if (UpdateSubscriptionDiagnostics(diagnostics, subscriptionArray, ii))
                        {
                            sessionsChanged = true;
                        }
                    }

                    // check of the subscription node needs to be updated.
                    SubscriptionDiagnosticsArrayState subscriptionsNode = (SubscriptionDiagnosticsArrayState)FindPredefinedNode(
                        VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray,
                        typeof(SubscriptionDiagnosticsArrayState));
                                                   
                    if (subscriptionsNode != null && (subscriptionsNode.Value == null || StatusCode.IsBad(subscriptionsNode.StatusCode) || subscriptionsChanged)) 
                    {
                        subscriptionsNode.Value = subscriptionArray;
                        subscriptionsNode.ClearChangeMasks(SystemContext, false);
                    }

                    for (int ii = 0; ii < m_sessions.Count; ii++)
                    {
                        SessionDiagnosticsData diagnostics = m_sessions[ii];
                        List<SubscriptionDiagnosticsDataType> subscriptionDiagnosticsArray = new List<SubscriptionDiagnosticsDataType>();

                        NodeId sessionId = diagnostics.Summary.NodeId;

                        for (int jj = 0; jj < m_subscriptions.Count; jj++)
                        {
                            SubscriptionDiagnosticsData subscriptionDiagnostics = m_subscriptions[jj];

                            if (subscriptionDiagnostics.Value.Value == null)
                            {
                                continue;
                            }

                            if (subscriptionDiagnostics.Value.Value.SessionId != sessionId)
                            {
                                continue;
                            }

                            subscriptionDiagnosticsArray.Add(subscriptionDiagnostics.Value.Value);
                        }

                        // update session subscription array.
                        subscriptionsNode = (SubscriptionDiagnosticsArrayState)diagnostics.Summary.CreateChild(
                            SystemContext,
                            BrowseNames.SubscriptionDiagnosticsArray);
                                    
                        if (subscriptionsNode != null && (subscriptionsNode.Value == null || StatusCode.IsBad(subscriptionsNode.StatusCode) || subscriptionsChanged))
                        {
                            subscriptionsNode.Value = subscriptionDiagnosticsArray.ToArray();
                            subscriptionsNode.ClearChangeMasks(SystemContext, false);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error during diagnostics scan.");
            }
        }
示例#4
0
        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");
        }
        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>
        /// Updates the current monitored item count for the session.
        /// </summary>
        private void UpdateCurrentMonitoredItemsCount(SessionDiagnosticsDataType diagnostics, int change)
        {
            long monitoredItemsCount = (long)diagnostics.CurrentMonitoredItemsCount;
            monitoredItemsCount += change;

            if (monitoredItemsCount > 0)
            {
                diagnostics.CurrentMonitoredItemsCount = (uint)monitoredItemsCount;
            }
            else
            {
                diagnostics.CurrentMonitoredItemsCount = 0;
            }
        }