/// <summary> /// Initializes the object when it is created by the WCF framework. /// </summary> protected EndpointBase() { SupportedServices = new SortedList<ExpandedNodeId,ServiceDefinition>(); try { m_host = GetHostForContext(); m_server = GetServerForContext(); MessageContext = m_server.MessageContext; // update the message context for the channel. ChannelBase channel = OperationContext.Current.Channel.InputSession as ChannelBase; if (channel != null) { TcpChannelQuotas quotas = channel.GetProperty<TcpChannelQuotas>(); if (quotas != null) { quotas.MessageContext = m_server.MessageContext; } } EndpointDescription = GetEndpointDescription(); } catch (Exception e) { ServerError = new ServiceResult(e); EndpointDescription = null; m_host = null; m_server = null; } }
/// <summary> /// Constructs a object by specifying each property. /// </summary> public ServiceResult( StatusCode code, ServiceResult innerResult) : this(code, null, null, null, null, innerResult) { }
/// <summary> /// Initializes object with default values. /// </summary> public ServerBase() { m_messageContext = new ServiceMessageContext(); m_serverError = new ServiceResult(StatusCodes.BadServerHalted); m_hosts = new List<ServiceHost>(); m_listeners = new List<ITransportListener>(); m_endpoints = null; m_requestQueue = new RequestQueue(this, 10, 100, 1000); }
/// <summary> /// Initializes the exception with a status code. /// </summary> public ServiceResultException(uint statusCode) : base(GetMessage(statusCode)) { m_status = new ServiceResult(statusCode); if ((Utils.TraceMask & Utils.TraceMasks.StackTrace) != 0) { Utils.Trace(Utils.TraceMasks.StackTrace, "***EXCEPTION*** {0}", m_status); } }
/// <summary> /// Initializes the object with a ServiceResult. /// </summary> public StatusResult(ServiceResult result) { Initialize(); m_result = result; if (result != null) { m_statusCode = result.StatusCode; } }
/// <summary> /// Constructs a object by specifying each property. /// </summary> public ServiceResult( StatusCode code, string symbolicId, string namespaceUri, LocalizedText localizedText, string additionalInfo, ServiceResult innerResult) { StatusCode = code; SymbolicId = symbolicId; NamespaceUri = namespaceUri; LocalizedText = localizedText; AdditionalInfo = additionalInfo; InnerResult = innerResult; }
/// <summary> /// Initializes the object when it is created by the WCF framework. /// </summary> protected EndpointBase() { SupportedServices = new Dictionary<ExpandedNodeId,ServiceDefinition>(); try { m_host = GetHostForContext(); m_server = GetServerForContext(); MessageContext = m_server.MessageContext; EndpointDescription = GetEndpointDescription(); } catch (Exception e) { ServerError = new ServiceResult(e); EndpointDescription = null; m_host = null; m_server = null; } }
/// <summary> /// Updates an audit event after the method is invoked. /// </summary> protected override void UpdateAuditEvent( ISystemContext context, MethodState causeMethod, uint causeId, AuditUpdateStateEventState e, ServiceResult result) { base.UpdateAuditEvent( context, causeMethod, causeId, e, result); // update program specific event fields. if (ServiceResult.IsGood(result)) { ProgramTransitionAuditEventState e2 = e as ProgramTransitionAuditEventState; if (e2 != null) { e2.SetChildValue(context, BrowseNames.Transition, LastTransition, false); } } }
/// <summary> /// Called when the Respond method is called. /// </summary> /// <param name="context">The system context.</param> /// <param name="method">The method being called.</param> /// <param name="objectId">The id of the object.</param> /// <param name="selectedResponse">The selected response.</param> /// <returns>Any error.</returns> protected virtual ServiceResult OnRespondCalled( ISystemContext context, MethodState method, NodeId objectId, int selectedResponse) { ServiceResult error = null; try { if (!this.EnabledState.Id.Value) { return(error = StatusCodes.BadConditionDisabled); } if (!this.DialogState.Id.Value) { return(error = StatusCodes.BadDialogNotActive); } if (selectedResponse < 0 || selectedResponse >= this.ResponseOptionSet.Value.Length) { return(error = StatusCodes.BadDialogResponseInvalid); } if (OnRespond == null) { return(error = StatusCodes.BadNotSupported); } error = OnRespond(context, this, selectedResponse); // report a state change event. if (ServiceResult.IsGood(error)) { ReportStateChange(context, false); } } finally { if (this.AreEventsMonitored) { AuditConditionRespondEventState e = new AuditConditionRespondEventState(null); TranslationInfo info = new TranslationInfo( "AuditConditionDialogResponse", "en-US", "The Respond method was called."); e.Initialize( context, this, EventSeverity.Low, new LocalizedText(info), ServiceResult.IsGood(error), DateTime.UtcNow); e.SourceName.Value = "Attribute/Call"; e.MethodId = new PropertyState <NodeId>(e); e.MethodId.Value = method.NodeId; e.InputArguments = new PropertyState <object[]>(e); e.InputArguments.Value = new object[] { selectedResponse }; ReportEvent(context, e); } } return(error); }
/// <summary> /// Causes the specified transition to occur. /// </summary> public ServiceResult DoTransition( ISystemContext context, uint transitionId, uint causeId, IList <object> inputArguments, IList <object> outputArguments) { // check for valid transition. uint newState = GetNewStateForTransition(context, transitionId); if (newState == 0) { return(StatusCodes.BadNotSupported); } // check the cause permissions. if (causeId != 0) { if (!IsCausePermitted(context, causeId, true)) { return(StatusCodes.BadUserAccessDenied); } } // do any pre-transition processing. ServiceResult result = InvokeCallback( OnBeforeTransition, context, this, transitionId, causeId, inputArguments, outputArguments); if (ServiceResult.IsBad(result)) { return(result); } // save the last state. if (m_lastState == null) { m_lastState = new FiniteStateVariableState(this); } m_lastState.SetChildValue(context, null, CurrentState, false); // update state and transition variables. UpdateStateVariable(context, newState, CurrentState); UpdateTransitionVariable(context, transitionId, LastTransition); // do any post-transition processing. InvokeCallback( OnAfterTransition, context, this, transitionId, causeId, inputArguments, outputArguments); // report the event. if (this.AreEventsMonitored && !m_suppressTransitionEvents) { TransitionEventState e = CreateTransitionEvent(context, transitionId, causeId); if (e != null) { UpdateTransitionEvent(context, transitionId, causeId, e); ReportEvent(context, e); } } return(ServiceResult.Good); }
/// <summary> /// Returns the node ids for a set of relative paths. /// </summary> /// <param name="session">An open session with the server to use.</param> /// <param name="startNodeId">The starting node for the relative paths.</param> /// <param name="relativePaths">The relative paths.</param> /// <returns>A collection of local nodes.</returns> static List<NodeOfInterest> GetNodeIds( Session session, NodeId startNodeId, params string[] relativePaths) { // build the list of browse paths to follow by parsing the relative paths. BrowsePathCollection browsePaths = new BrowsePathCollection(); if (relativePaths != null) { for (int ii = 0; ii < relativePaths.Length; ii++) { BrowsePath browsePath = new BrowsePath(); // The relative paths used indexes in the namespacesUris table. These must be // converted to indexes used by the server. An error occurs if the relative path // refers to a namespaceUri that the server does not recognize. // The relative paths may refer to ReferenceType by their BrowseName. The TypeTree object // allows the parser to look up the server's NodeId for the ReferenceType. browsePath.RelativePath = RelativePath.Parse( relativePaths[ii], session.TypeTree, session.NamespaceUris, session.NamespaceUris); browsePath.StartingNode = startNodeId; browsePaths.Add(browsePath); } } // make the call to the server. BrowsePathResultCollection results; DiagnosticInfoCollection diagnosticInfos; ResponseHeader responseHeader = session.TranslateBrowsePathsToNodeIds( null, browsePaths, out results, out diagnosticInfos); // ensure that the server returned valid results. Session.ValidateResponse(results, browsePaths); Session.ValidateDiagnosticInfos(diagnosticInfos, browsePaths); Console.WriteLine("Translated {0} browse paths.", relativePaths.Length); // collect the list of node ids found. List<NodeOfInterest> nodes = new List<NodeOfInterest>(); for (int ii = 0; ii < results.Count; ii++) { // check if the start node actually exists. if (StatusCode.IsBad(results[ii].StatusCode)) { ServiceResult error = new ServiceResult( results[ii].StatusCode, diagnosticInfos[ii], responseHeader.StringTable); Console.WriteLine("Path '{0}' is not valid. Error = {1}", relativePaths[ii], error); continue; } // an empty list is returned if no node was found. if (results[ii].Targets.Count == 0) { Console.WriteLine("Path '{0}' does not exist.", relativePaths[ii]); continue; } // Multiple matches are possible, however, the node that matches the type model is the // one we are interested in here. The rest can be ignored. BrowsePathTarget target = results[ii].Targets[0]; if (target.RemainingPathIndex != UInt32.MaxValue) { Console.WriteLine("Path '{0}' refers to a node in another server.", relativePaths[ii]); continue; } // The targetId is an ExpandedNodeId because it could be node in another server. // The ToNodeId function is used to convert a local NodeId stored in a ExpandedNodeId to a NodeId. NodeOfInterest node = new NodeOfInterest(); node.NodeId = ExpandedNodeId.ToNodeId(target.TargetId, session.NamespaceUris); nodes.Add(node); } Console.WriteLine("Translate found {0} local nodes.", nodes.Count); // return whatever was found. return nodes; }
/// <summary> /// The delegate used to receive data change notifications via a direct function call instead of a .NET Event. /// </summary> public void OnDataChangeNotification(Opc.Ua.Client.Subscription subscription, DataChangeNotification notification, IList<string> stringTable) { for (int ii = 0; ii < notification.MonitoredItems.Count; ii++) { MonitoredItem localItem = null; DataValue value = null; ServiceResult error = null; lock (subscription.Session) { Opc.Ua.Client.MonitoredItem monitoredItem = subscription.FindItemByClientHandle(notification.MonitoredItems[ii].ClientHandle); if (monitoredItem != null) { MonitoredItemNotification value2 = notification.MonitoredItems[ii]; if (value2.Value.StatusCode != StatusCodes.Good) { error = new ServiceResult(value2.Value.StatusCode, value2.DiagnosticInfo, stringTable); } value = value2.Value; value.WrappedValue = m_mapper.ToLocalVariant(value2.Value.WrappedValue); value.ServerTimestamp = DateTime.UtcNow; localItem = (MonitoredItem)monitoredItem.Handle; } } localItem.QueueValue(value, error); } }
/// <summary> /// Handles a write operation. /// </summary> protected override void Write( ServerSystemContext context, IList<WriteValue> nodesToWrite, IList<ServiceResult> errors, List<NodeHandle> nodesToValidate, IDictionary<NodeId, NodeState> cache) { WriteValueCollection requests = new WriteValueCollection(); List<int> indexes = new List<int>(); // validates the nodes and constructs requests for external nodes. for (int ii = 0; ii < nodesToValidate.Count; ii++) { WriteValue nodeToWrite = nodesToWrite[ii]; NodeHandle handle = nodesToValidate[ii]; lock (Lock) { // validate node. NodeState source = ValidateNode(context, handle, cache); if (source == null) { continue; } // determine if a local node. if (PredefinedNodes.ContainsKey(source.NodeId)) { // write the attribute value. errors[handle.Index] = source.WriteAttribute( context, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. source.ClearChangeMasks(context, false); } WriteValue request = (WriteValue)nodeToWrite.Clone(); request.NodeId = m_mapper.ToRemoteId(nodeToWrite.NodeId); request.Value.WrappedValue = m_mapper.ToRemoteVariant(nodeToWrite.Value.WrappedValue); requests.Add(request); indexes.Add(ii); } } // send request to external system. try { Opc.Ua.Client.Session client = GetClientSession(context); StatusCodeCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = client.Write( null, requests, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, requests); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, requests); // set results. for (int ii = 0; ii < requests.Count; ii++) { errors[indexes[ii]] = ServiceResult.Good; if (results[ii] != StatusCodes.Good) { errors[indexes[ii]] = new ServiceResult(results[ii], ii, diagnosticInfos, responseHeader.StringTable); } } } catch (Exception e) { // handle unexpected communication error. ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system."); for (int ii = 0; ii < requests.Count; ii++) { errors[indexes[ii]] = error; } } }
/// <summary> /// Parses a string representing a numeric range. /// </summary> /// <param name="textToParse">The text to parse, prior to checking it is within the allowed range</param> /// <param name="range">The parsed range.</param> /// <returns>The reason for any error.</returns> public static ServiceResult Validate(string textToParse, out NumericRange range) { range = NumericRange.Empty; if (String.IsNullOrEmpty(textToParse)) { return(ServiceResult.Good); } // check for multidimensional ranges. int index = textToParse.IndexOf(','); if (index >= 0) { int start = 0; List <NumericRange> subranges = new List <NumericRange>(); for (int ii = 0; ii < textToParse.Length; ii++) { char ch = textToParse[ii]; if (ch == ',' || ii == textToParse.Length - 1) { NumericRange subrange = new NumericRange(); string subtext = (ch == ',') ? textToParse.Substring(start, ii - start) : textToParse.Substring(start); ServiceResult result = Validate(subtext, out subrange); if (ServiceResult.IsBad(result)) { return(result); } subranges.Add(subrange); start = ii + 1; } } // must have at least two entries. if (subranges.Count < 2) { return(StatusCodes.BadIndexRangeInvalid); } range.m_begin = subranges[0].Begin; range.m_end = subranges[0].End; range.m_subranges = subranges.ToArray(); return(ServiceResult.Good); } try { index = textToParse.IndexOf(':'); if (index != -1) { range.Begin = Convert.ToInt32(textToParse.Substring(0, index), CultureInfo.InvariantCulture); range.End = Convert.ToInt32(textToParse.Substring(index + 1), CultureInfo.InvariantCulture); if (range.End < 0) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a valid end index ({0}).", range.End)); } if (range.Begin >= range.End) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a start index that is less than the end index ({0}).", range)); } } else { range.Begin = Convert.ToInt32(textToParse, CultureInfo.InvariantCulture); range.End = -1; } if (range.Begin < 0) { return(ServiceResult.Create( StatusCodes.BadIndexRangeInvalid, "NumericRange does not have a valid start index ({0}).", range.Begin)); } } catch (Exception e) { return(ServiceResult.Create( e, StatusCodes.BadIndexRangeInvalid, "NumericRange cannot be parsed ({0}).", textToParse)); } return(ServiceResult.Good); }
/// <summary> /// Validates the object. /// </summary> public Result Validate(FilterContext context) { Result result = new Result(); // check for top level error. if (m_selectClauses == null || m_selectClauses.Count == 0) { result.Status = ServiceResult.Create( StatusCodes.BadStructureMissing, "EventFilter does not specify any Select Clauses."); return(result); } if (m_whereClause == null) { result.Status = ServiceResult.Create( StatusCodes.BadStructureMissing, "EventFilter does not specify any Where Clauses."); return(result); } result.Status = ServiceResult.Good; // validate select clause. bool error = false; foreach (SimpleAttributeOperand clause in m_selectClauses) { ServiceResult clauseResult = null; // check for null. if (clause == null) { clauseResult = ServiceResult.Create( StatusCodes.BadStructureMissing, "EventFilterSelectClause cannot be null in EventFilter SelectClause."); result.SelectClauseResults.Add(clauseResult); error = true; continue; } // validate clause. clauseResult = clause.Validate(context, 0); if (ServiceResult.IsBad(clauseResult)) { result.SelectClauseResults.Add(clauseResult); error = true; continue; } // clause ok. result.SelectClauseResults.Add(null); } if (error) { result.Status = StatusCodes.BadEventFilterInvalid; } else { result.SelectClauseResults.Clear(); } // validate where clause. result.WhereClauseResult = m_whereClause.Validate(context); if (ServiceResult.IsBad(result.WhereClauseResult.Status)) { result.Status = StatusCodes.BadEventFilterInvalid; } return(result); }
/// <summary> /// Throws an exception if validation fails. /// </summary> /// <param name="certificates">The certificates to be checked.</param> /// <exception cref="ServiceResultException">If certificate[0] cannot be accepted</exception> protected virtual async Task InternalValidate(X509Certificate2Collection certificates) { X509Certificate2 certificate = certificates[0]; // check for previously validated certificate. X509Certificate2 certificate2 = null; if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2)) { if (Utils.IsEqual(certificate2.RawData, certificate.RawData)) { return; } } CertificateIdentifier trustedCertificate = await GetTrustedCertificate(certificate); // get the issuers (checks the revocation lists if using directory stores). List <CertificateIdentifier> issuers = new List <CertificateIdentifier>(); bool isIssuerTrusted = await GetIssuers(certificates, issuers); // setup policy chain X509ChainPolicy policy = new X509ChainPolicy(); policy.RevocationFlag = X509RevocationFlag.EntireChain; policy.RevocationMode = X509RevocationMode.NoCheck; policy.VerificationFlags = X509VerificationFlags.NoFlag; foreach (CertificateIdentifier issuer in issuers) { if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0) { policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown; policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown; policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown; policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown; } // we did the revocation check in the GetIssuers call. No need here. policy.RevocationMode = X509RevocationMode.NoCheck; policy.ExtraStore.Add(issuer.Certificate); } // build chain. bool chainStatusChecked = false; X509Chain chain = new X509Chain(); chain.ChainPolicy = policy; chain.Build(certificate); // check the chain results. CertificateIdentifier target = trustedCertificate; if (target == null) { target = new CertificateIdentifier(certificate); } for (int ii = 0; ii < chain.ChainElements.Count; ii++) { X509ChainElement element = chain.ChainElements[ii]; CertificateIdentifier issuer = null; if (ii < issuers.Count) { issuer = issuers[ii]; } // check for chain status errors. foreach (X509ChainStatus status in element.ChainElementStatus) { ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0)); if (ServiceResult.IsBad(result)) { // check untrusted certificates. if (trustedCertificate == null) { ServiceResult errorResult = new ServiceResult( result.StatusCode, result.SymbolicId, result.NamespaceUri, result.LocalizedText, result.AdditionalInfo, StatusCodes.BadCertificateUntrusted); throw new ServiceResultException(errorResult); } throw new ServiceResultException(result); } chainStatusChecked = true; } if (issuer != null) { target = issuer; } } // check whether the chain is complete (if there is a chain) bool issuedByCA = !Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer); bool chainIncomplete = false; if (issuers.Count > 0) { var rootCertificate = issuers[issuers.Count - 1].Certificate; if (!Utils.CompareDistinguishedName(rootCertificate.Subject, rootCertificate.Issuer)) { chainIncomplete = true; } } else { if (issuedByCA) { // no issuer found at all chainIncomplete = true; } } if (issuedByCA && (!chainStatusChecked || chainIncomplete)) { throw ServiceResultException.Create( StatusCodes.BadCertificateChainIncomplete, "Certificate chain validation incomplete.\r\nSubjectName: {0}\r\nIssuerName: {1}", certificate.SubjectName.Name, certificate.IssuerName.Name); } // check if certificate issuer is trusted. if (issuedByCA && !isIssuerTrusted && trustedCertificate == null) { if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData)) { throw ServiceResultException.Create( StatusCodes.BadCertificateUntrusted, "Certificate issuer is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}", certificate.SubjectName.Name, certificate.IssuerName.Name); } } // check if certificate is trusted. if (trustedCertificate == null && !isIssuerTrusted) { if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData)) { throw ServiceResultException.Create( StatusCodes.BadCertificateUntrusted, "Certificate is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}", certificate.SubjectName.Name, certificate.IssuerName.Name); } } // check if certificate is valid for use as app/sw or user cert X509KeyUsageFlags certificateKeyUsage = CertificateFactory.GetKeyUsage(certificate); if ((certificateKeyUsage & X509KeyUsageFlags.DataEncipherment) == 0) { throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed, "Usage of certificate is not allowed."); } // check if minimum requirements are met if (m_rejectSHA1SignedCertificates && IsSHA1SignatureAlgorithm(certificate.SignatureAlgorithm)) { throw new ServiceResultException(StatusCodes.BadCertificatePolicyCheckFailed, "SHA1 signed certificates are not trusted"); } if (certificate.GetRSAPublicKey().KeySize < m_minimumCertificateKeySize) { throw new ServiceResultException(StatusCodes.BadCertificatePolicyCheckFailed, "Certificate doesn't meet minimum key length requirement"); } }
private static ServiceResult CheckChainStatus(X509ChainStatus status, CertificateIdentifier id, CertificateIdentifier issuer, bool isIssuer) { switch (status.Status) { case X509ChainStatusFlags.NotValidForUsage: { return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateUseNotAllowed : StatusCodes.BadCertificateIssuerUseNotAllowed, "Certificate may not be used as an application instance certificate. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NoError: case X509ChainStatusFlags.OfflineRevocation: case X509ChainStatusFlags.InvalidBasicConstraints: case X509ChainStatusFlags.PartialChain: { break; } case X509ChainStatusFlags.UntrustedRoot: { // self signed cert signature validation // .Net Core ChainStatus returns NotSignatureValid only on Windows, // so we have to do the extra cert signature check on all platforms if (issuer == null && !isIssuer && id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Issuer)) { if (!IsSignatureValid(id.Certificate)) { goto case X509ChainStatusFlags.NotSignatureValid; } } // ignore this error because the root check is done // by looking the certificate up in the trusted issuer stores passed to the validator. // the ChainStatus uses the trusted issuer stores. break; } case X509ChainStatusFlags.RevocationStatusUnknown: { if (issuer != null) { if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0) { break; } } // check for meaning less errors for self-signed certificates. if (id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Subject)) { break; } return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateIssuerRevocationUnknown : StatusCodes.BadCertificateRevocationUnknown, "Certificate revocation status cannot be verified. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.Revoked: { return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateIssuerRevoked : StatusCodes.BadCertificateRevoked, "Certificate has been revoked. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NotTimeNested: { if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0)) { break; } return(ServiceResult.Create( StatusCodes.BadCertificateIssuerTimeInvalid, "Certificate issuer validatity time does not overhas is expired or not yet valid. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NotTimeValid: { if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0)) { break; } return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateIssuerTimeInvalid : StatusCodes.BadCertificateTimeInvalid, "Certificate has is expired or not yet valid. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NotSignatureValid: { return(ServiceResult.Create( StatusCodes.BadCertificateUntrusted, status.StatusInformation)); } default: { return(ServiceResult.Create( StatusCodes.BadCertificateInvalid, "Certificate validation failed. {0}: {1}", status.Status, status.StatusInformation)); } } return(null); }
/// <summary> /// Creates a new instance. /// </summary> internal CertificateValidationEventArgs(ServiceResult error, X509Certificate2 certificate) { m_error = error; m_certificate = certificate; }
/// <summary> /// Handles the Unshelve method. /// </summary> protected virtual ServiceResult OnUnshelve( ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { ServiceResult error = null; try { if (!this.EnabledState.Id.Value) { return(error = StatusCodes.BadConditionDisabled); } if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_Unshelve, false)) { return(error = StatusCodes.BadConditionNotShelved); } if (OnShelve == null) { return(error = StatusCodes.BadNotSupported); } error = OnShelve(context, this, false, false, 0); // report a state change event. if (ServiceResult.IsGood(error)) { ReportStateChange(context, false); } } finally { // raise the audit event. if (this.AreEventsMonitored) { AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null); TranslationInfo info = new TranslationInfo( "AuditConditionUnshelve", "en-US", "The Unshelve method was called."); e.Initialize( context, this, EventSeverity.Low, new LocalizedText(info), ServiceResult.IsGood(error), DateTime.UtcNow); e.SourceName.Value = "Attribute/Call"; e.MethodId = new PropertyState <NodeId>(e); e.MethodId.Value = method.NodeId; ReportEvent(context, e); } } return(error); }
/// <summary> /// Handles the TimedShelve method. /// </summary> protected virtual ServiceResult OnTimedShelve( ISystemContext context, MethodState method, NodeId objectId, double shelvingTime) { ServiceResult error = null; try { if (!this.EnabledState.Id.Value) { return(error = StatusCodes.BadConditionDisabled); } if (shelvingTime <= 0 || (this.MaxTimeShelved != null && shelvingTime > this.MaxTimeShelved.Value)) { return(error = StatusCodes.BadShelvingTimeOutOfRange); } if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_TimedShelve, false)) { return(error = StatusCodes.BadConditionAlreadyShelved); } if (OnShelve == null) { return(error = StatusCodes.BadNotSupported); } error = OnShelve(context, this, true, false, shelvingTime); // report a state change event. if (ServiceResult.IsGood(error)) { ReportStateChange(context, false); } } finally { if (this.AreEventsMonitored) { AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null); TranslationInfo info = new TranslationInfo( "AuditConditionTimedShelve", "en-US", "The TimedShelve method was called."); e.Initialize( context, this, EventSeverity.Low, new LocalizedText(info), ServiceResult.IsGood(error), DateTime.UtcNow); e.SourceName.Value = "Attribute/Call"; e.MethodId = new PropertyState <NodeId>(e); e.MethodId.Value = method.NodeId; e.InputArguments = new PropertyState <object[]>(e); e.InputArguments.Value = new object[] { shelvingTime }; ReportEvent(context, e); } } return(error); }
/// <summary> /// Validates the content filter element. /// </summary> /// <param name="context">The context.</param> /// <param name="index">The index.</param> /// <returns>The results of the validation.</returns> public virtual ContentFilter.ElementResult Validate(FilterContext context, int index) { ContentFilter.ElementResult result = new ContentFilter.ElementResult(null); // check the number of operands. int operandCount = -1; switch (m_filterOperator) { case FilterOperator.Not: case FilterOperator.IsNull: case FilterOperator.InView: case FilterOperator.OfType: { operandCount = 1; break; } case FilterOperator.And: case FilterOperator.Or: case FilterOperator.Equals: case FilterOperator.GreaterThan: case FilterOperator.GreaterThanOrEqual: case FilterOperator.LessThan: case FilterOperator.LessThanOrEqual: case FilterOperator.Like: case FilterOperator.Cast: { operandCount = 2; break; } case FilterOperator.Between: { operandCount = 3; break; } case FilterOperator.RelatedTo: { operandCount = 6; break; } case FilterOperator.InList: { operandCount = -1; break; } default: { break; } } if (operandCount != -1) { if (operandCount != m_filterOperands.Count) { result.Status = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "ContentFilterElement does not have the correct number of operands (Operator={0} OperandCount={1}).", m_filterOperator, operandCount); return(result); } } else { if (m_filterOperands.Count < 2) { result.Status = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "ContentFilterElement does not have the correct number of operands (Operator={0} OperandCount={1}).", m_filterOperator, m_filterOperands.Count); return(result); } } // validate the operands. bool error = false; for (int ii = 0; ii < m_filterOperands.Count; ii++) { ServiceResult operandResult = null; ExtensionObject operand = m_filterOperands[ii]; // check for null. if (ExtensionObject.IsNull(operand)) { operandResult = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "The FilterOperand cannot be Null."); result.OperandResults.Add(operandResult); error = true; continue; } // check that the extension object contains a filter operand. FilterOperand filterOperand = operand.Body as FilterOperand; if (filterOperand == null) { operandResult = ServiceResult.Create( StatusCodes.BadEventFilterInvalid, "The FilterOperand is not a supported type ({0}).", filterOperand.GetType()); result.OperandResults.Add(operandResult); error = true; continue; } // validate the operand. filterOperand.Parent = this; operandResult = filterOperand.Validate(context, index); if (ServiceResult.IsBad(operandResult)) { result.OperandResults.Add(operandResult); error = true; continue; } result.OperandResults.Add(null); } // ensure the global error code. if (error) { result.Status = StatusCodes.BadContentFilterInvalid; } else { result.OperandResults.Clear(); } return(result); }
/// <summary> /// Write the value for any non-value attribute. /// </summary> protected override ServiceResult WriteNonValueAttribute( ISystemContext context, uint attributeId, object value) { ServiceResult result = null; switch (attributeId) { case Attributes.EventNotifier: { byte?eventNotifierRef = value as byte?; if (eventNotifierRef == null) { return(StatusCodes.BadTypeMismatch); } if ((WriteMask & AttributeWriteMask.EventNotifier) == 0) { return(StatusCodes.BadNotWritable); } byte eventNotifier = eventNotifierRef.Value; if (OnWriteEventNotifier != null) { result = OnWriteEventNotifier(context, this, ref eventNotifier); } if (ServiceResult.IsGood(result)) { EventNotifier = eventNotifier; } return(result); } case Attributes.ContainsNoLoops: { bool?containsNoLoopsRef = value as bool?; if (containsNoLoopsRef == null) { return(StatusCodes.BadTypeMismatch); } if ((WriteMask & AttributeWriteMask.ContainsNoLoops) == 0) { return(StatusCodes.BadNotWritable); } bool containsNoLoops = containsNoLoopsRef.Value; if (OnWriteContainsNoLoops != null) { result = OnWriteContainsNoLoops(context, this, ref containsNoLoops); } if (ServiceResult.IsGood(result)) { ContainsNoLoops = containsNoLoops; } return(result); } } return(base.WriteNonValueAttribute(context, attributeId, value)); }
/// <summary> /// Used to indicate that the asynchronous operation has completed. /// </summary> /// <param name="response">The response. May be null if an error is provided.</param> /// <param name="error"></param> public void OperationCompleted(IServiceResponse response, ServiceResult error) { // save response and/or error. m_error = null; m_response = response; if (ServiceResult.IsBad(error)) { m_error = new ServiceResultException(error); m_response = SaveExceptionAsResponse(m_error); } // operation completed. OperationCompleted(); }
/// <summary> /// Write the value for any non-value attribute. /// </summary> protected override ServiceResult WriteNonValueAttribute( ISystemContext context, uint attributeId, object value) { ServiceResult result = null; switch (attributeId) { case Attributes.Executable: { bool?executableRef = value as bool?; if (executableRef == null) { return(StatusCodes.BadTypeMismatch); } if ((WriteMask & AttributeWriteMask.Executable) == 0) { return(StatusCodes.BadNotWritable); } bool executable = executableRef.Value; if (OnWriteExecutable != null) { result = OnWriteExecutable(context, this, ref executable); } if (ServiceResult.IsGood(result)) { Executable = executable; } return(result); } case Attributes.UserExecutable: { bool?userExecutableRef = value as bool?; if (userExecutableRef == null) { return(StatusCodes.BadTypeMismatch); } if ((WriteMask & AttributeWriteMask.UserExecutable) == 0) { return(StatusCodes.BadNotWritable); } bool userExecutable = userExecutableRef.Value; if (OnWriteUserExecutable != null) { result = OnWriteUserExecutable(context, this, ref userExecutable); } if (ServiceResult.IsGood(result)) { UserExecutable = userExecutable; } return(result); } } return(base.WriteNonValueAttribute(context, attributeId, value)); }
/// <summary> /// Serializes the service result. /// </summary> /// <param name="info">The info.</param> /// <param name="serviceResult">The service result.</param> /// <param name="prefix">The prefix.</param> private static void SerializeServiceResult(SerializationInfo info, ServiceResult serviceResult, string prefix) { info.AddValue(prefix + "StatusCode", serviceResult.Code); info.AddValue(prefix + "NamespaceUri", serviceResult.NamespaceUri); info.AddValue(prefix + "SymbolicId", serviceResult.SymbolicId); info.AddValue(prefix + "AdditionalInfo", serviceResult.AdditionalInfo); if (serviceResult.LocalizedText != null) { info.AddValue(prefix + "LocalizedTextText", serviceResult.LocalizedText.Text); info.AddValue(prefix + "LocalizedTextKey", serviceResult.LocalizedText.Key); info.AddValue(prefix + "LocalizedTextLocale", serviceResult.LocalizedText.Locale); } if (serviceResult.InnerResult != null) { SerializeServiceResult(info, serviceResult.InnerResult, "InnerResult"); } }
/// <summary> /// Invokes the methods and returns the output parameters. /// </summary> /// <param name="context">The context to use.</param> /// <param name="objectId">The object being called.</param> /// <param name="inputArguments">The input arguments.</param> /// <param name="argumentErrors">Any errors for the input arguments.</param> /// <param name="outputArguments">The output arguments.</param> /// <returns>The result of the method call.</returns> public virtual ServiceResult Call( ISystemContext context, NodeId objectId, IList <Variant> inputArguments, IList <ServiceResult> argumentErrors, IList <Variant> outputArguments) { // validate input arguments. List <object> inputs = new List <object>(); // check for too few or too many arguments. int expectedCount = 0; if (InputArguments != null && InputArguments.Value != null) { expectedCount = InputArguments.Value.Length; } if (expectedCount != inputArguments.Count) { return(StatusCodes.BadArgumentsMissing); } // validate individual arguements. bool error = false; for (int ii = 0; ii < inputArguments.Count; ii++) { ServiceResult argumentError = ValidateInputArgument(context, inputArguments[ii], ii); if (ServiceResult.IsBad(argumentError)) { error = true; } inputs.Add(inputArguments[ii].Value); argumentErrors.Add(argumentError); } // return good - caller must check argument errors. if (error) { return(ServiceResult.Good); } // set output arguments to default values. List <object> outputs = new List <object>(); if (OutputArguments != null) { IList <Argument> arguments = OutputArguments.Value; if (arguments != null && arguments.Count > 0) { for (int ii = 0; ii < arguments.Count; ii++) { outputs.Add(GetArgumentDefaultValue(context, arguments[ii])); } } } // invoke method. ServiceResult result = null; try { result = Call(context, objectId, inputs, outputs); } catch (Exception e) { result = new ServiceResult(e); } // copy out arguments. if (ServiceResult.IsGood(result)) { for (int ii = 0; ii < outputs.Count; ii++) { outputArguments.Add(new Variant(outputs[ii])); } } return(result); }
/// <summary> /// Handles a read operations that fetch data from an external source. /// </summary> protected override void Read( ServerSystemContext context, IList<ReadValueId> nodesToRead, IList<DataValue> values, IList<ServiceResult> errors, List<NodeHandle> nodesToValidate, IDictionary<NodeId, NodeState> cache) { ReadValueIdCollection requests = new ReadValueIdCollection(); List<int> indexes = new List<int>(); for (int ii = 0; ii < nodesToValidate.Count; ii++) { NodeHandle handle = nodesToValidate[ii]; ReadValueId nodeToRead = nodesToRead[ii]; DataValue value = values[ii]; lock (Lock) { // validate node. NodeState source = ValidateNode(context, handle, cache); if (source == null) { continue; } // determine if a local node. if (PredefinedNodes.ContainsKey(source.NodeId)) { errors[handle.Index] = source.ReadAttribute( context, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); continue; } ReadValueId request = (ReadValueId)nodeToRead.Clone(); request.NodeId = m_mapper.ToRemoteId(nodeToRead.NodeId); request.DataEncoding = m_mapper.ToRemoteName(nodeToRead.DataEncoding); requests.Add(request); indexes.Add(ii); } } // send request to external system. try { Opc.Ua.Client.Session client = GetClientSession(context); DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = client.Read( null, 0, TimestampsToReturn.Both, requests, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, requests); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, requests); // set results. for (int ii = 0; ii < requests.Count; ii++) { values[indexes[ii]] = results[ii]; values[indexes[ii]].WrappedValue = m_mapper.ToLocalVariant(results[ii].WrappedValue); errors[indexes[ii]] = ServiceResult.Good; if (results[ii].StatusCode != StatusCodes.Good) { errors[indexes[ii]] = new ServiceResult(results[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable); } } } catch (Exception e) { // handle unexpected communication error. ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system."); for (int ii = 0; ii < requests.Count; ii++) { errors[indexes[ii]] = error; } } }
/// <summary> /// Initializes the object with a result code. /// </summary> /// <param name="status">The status.</param> public Result(ServiceResult status) { m_status = status; }
/// <summary> /// Handles a cal operation. /// </summary> public override void Call( OperationContext context, IList<CallMethodRequest> methodsToCall, IList<CallMethodResult> results, IList<ServiceResult> errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary<NodeId, NodeState> operationCache = new NodeIdDictionary<NodeState>(); CallMethodRequestCollection requests = new CallMethodRequestCollection(); List<int> indexes = new List<int>(); // validates the nodes and constructs requests for external nodes. for (int ii = 0; ii < methodsToCall.Count; ii++) { CallMethodRequest methodToCall = methodsToCall[ii]; // skip items that have already been processed. if (methodToCall.Processed) { continue; } MethodState method = null; lock (Lock) { // check for valid handle. NodeHandle handle = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache); if (handle == null) { continue; } // owned by this node manager. methodToCall.Processed = true; // validate the source node. NodeState source = ValidateNode(systemContext, handle, operationCache); if (source == null) { errors[ii] = StatusCodes.BadNodeIdUnknown; continue; } // determine if a local node. if (PredefinedNodes.ContainsKey(handle.NodeId)) { // find the method. method = source.FindMethod(systemContext, methodToCall.MethodId); if (method == null) { // check for loose coupling. if (source.ReferenceExists(ReferenceTypeIds.HasComponent, false, methodToCall.MethodId)) { method = (MethodState)FindPredefinedNode(methodToCall.MethodId, typeof(MethodState)); } if (method == null) { errors[ii] = StatusCodes.BadMethodInvalid; continue; } } } } if (method != null) { // call the method. CallMethodResult result = results[ii] = new CallMethodResult(); errors[ii] = Call( systemContext, methodToCall, method, result); continue; } CallMethodRequest request = (CallMethodRequest)methodToCall.Clone(); request.ObjectId = m_mapper.ToRemoteId(methodToCall.ObjectId); request.MethodId = m_mapper.ToRemoteId(methodToCall.MethodId); for (int jj = 0; jj < request.InputArguments.Count; jj++) { request.InputArguments[jj] = m_mapper.ToRemoteVariant(methodToCall.InputArguments[jj]); } requests.Add(request); indexes.Add(ii); } // send request to external system. try { Opc.Ua.Client.Session client = GetClientSession(systemContext); CallMethodResultCollection results2 = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = client.Call( null, requests, out results2, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results2, requests); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, requests); // set results. for (int ii = 0; ii < requests.Count; ii++) { results[indexes[ii]] = results2[ii]; errors[indexes[ii]] = ServiceResult.Good; if (results2[ii].StatusCode != StatusCodes.Good) { errors[indexes[ii]] = new ServiceResult(results[ii].StatusCode, ii, diagnosticInfos, responseHeader.StringTable); } else { for (int jj = 0; jj < results2[ii].OutputArguments.Count; jj++) { results2[ii].OutputArguments[jj] = m_mapper.ToLocalVariant(results2[ii].OutputArguments[jj]); } } } } catch (Exception e) { // handle unexpected communication error. ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system."); for (int ii = 0; ii < requests.Count; ii++) { errors[indexes[ii]] = error; } } }
/// <summary> /// Handles the OneShotShelve method. /// </summary> protected virtual ServiceResult OnOneShotShelve( ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { ServiceResult error = null; try { if (!this.EnabledState.Id.Value) { return(error = StatusCodes.BadConditionDisabled); } if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_OneShotShelve, false)) { return(error = StatusCodes.BadConditionAlreadyShelved); } if (OnShelve == null) { return(error = StatusCodes.BadNotSupported); } error = OnShelve(context, this, true, true, 0); // report a state change event. if (ServiceResult.IsGood(error)) { ReportStateChange(context, false); } } finally { if (this.AreEventsMonitored) { AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null); TranslationInfo info = new TranslationInfo( "AuditConditionOneShotShelve", "en-US", "The OneShotShelve method was called."); e.Initialize( context, this, EventSeverity.Low, new LocalizedText(info), ServiceResult.IsGood(error), DateTime.UtcNow); e.SetChildValue(context, BrowseNames.SourceNode, NodeId, false); e.SetChildValue(context, BrowseNames.SourceName, "Method/OneShotShelve", false); e.SetChildValue(context, BrowseNames.MethodId, method.NodeId, false); e.SetChildValue(context, BrowseNames.ShelvingTime, null, false); ReportEvent(context, e); } } return(error); }
public virtual void Stop() { // do any pre-stop processing. try { OnServerStopping(); } catch (Exception e) { m_serverError = new ServiceResult(e); } // close any listeners. List<ITransportListener> listeners = m_listeners; if (listeners != null) { for (int ii = 0; ii < listeners.Count; ii++) { try { listeners[ii].Close(); } catch (Exception e) { Utils.Trace(e, "Unexpected error closing a listener. {0}", listeners[ii].GetType().FullName); } } listeners.Clear(); } // close the hosts. lock (m_hosts) { foreach (ServiceHost host in m_hosts) { if (host.State == CommunicationState.Opened) { host.Abort(); } } m_hosts.Clear(); } }
/// <summary> /// Constructs a object by specifying each property. /// </summary> /// <remarks> /// The innerException is used to construct the inner result. /// </remarks> public ServiceResult( StatusCode code, string symbolicId, string namespaceUri, LocalizedText localizedText, string additionalInfo, Exception innerException) { ServiceResult innerResult = new ServiceResult(innerException); // check if no new information provided. if (code.Code == innerResult.Code && symbolicId == null && localizedText == null && additionalInfo == null) { m_code = innerResult.Code; m_symbolicId = innerResult.SymbolicId; m_namespaceUri = innerResult.NamespaceUri; m_localizedText = innerResult.LocalizedText; m_additionalInfo = innerResult.AdditionalInfo; m_innerResult = innerResult.InnerResult; } // make the exception the inner result. else { m_code = code.Code; m_symbolicId = symbolicId; m_namespaceUri = namespaceUri; m_localizedText = localizedText; m_additionalInfo = additionalInfo; m_innerResult = innerResult; } }
void RunTest(AggregateType aggregate) { try { AggregateTestResultSet myResults = AggregateTestResultSet.LoadFromXMLFile( String.Format(@"{0}TestResult.xml", Enum.GetName(typeof(AggregateType), aggregate))); for (int i = 0; i < myResults.Count; i++) { AggregateTestResult testResult = myResults[i] as AggregateTestResult; Debug.WriteLine(String.Format("Test Data: {0}", testResult.TestDataName)); Debug.WriteLine(String.Format("Start time: {0}\tEnd time: {1}\tInterval: {2}", testResult.Details.StartTime.TimeOfDay, testResult.Details.EndTime.TimeOfDay, testResult.Details.ProcessingInterval)); // get expected values List<DataValue> expected = new List<DataValue>(testResult.DataValues.Count); for (int ii = 0; ii < testResult.DataValues.Count; ii++) expected.Add(testResult.DataValues[ii].GetDataValue()); // configure the aggregate calculator NewAggregateFilter filter = new NewAggregateFilter() { StartTime = testResult.Details.StartTime, EndTime = testResult.Details.EndTime, AggregateType = AggregateLookup[aggregate], AggregateConfiguration = TestData[myResults[i].TestDataName].Configuration.AggregateConfiguration, ProcessingInterval = testResult.Details.ProcessingInterval }; TestData testData = TestData[testResult.TestDataName]; AggregateCalculatorImpl calculator = Aggregators.CreateAggregator(filter, testData.Configuration.Stepped); /* calculator.Configuration = new AggregateConfiguration() { PercentDataBad = 0, PercentDataGood = 100, SteppedSlopedExtrapolation = false, TreatUncertainAsBad = true }; */ HistoryData rawHistoryData = new HistoryData(); for (int ii = 0; ii < testData.DataValues.Count; ii++) { DataValue dv = testData.DataValues[ii].GetDataValue(); rawHistoryData.DataValues.Add(dv); } HistoryData historyData = new HistoryData(); var sr = new ServiceResult(StatusCodes.Good); foreach (DataValue raw in rawHistoryData.DataValues) { IList<DataValue> released = calculator.ProcessValue(raw, sr); if (StatusCode.IsGood(sr.StatusCode) && released.Count > 0) { historyData.DataValues.AddRange(released); } } var lsr = new ServiceResult(StatusCodes.Good); historyData.DataValues.AddRange(calculator.ProcessTermination(lsr)); // obtain the actual values List<DataValue> actual = new List<DataValue>(historyData.DataValues); // compare the two value sets bool assertion = true; HelperMethods.CompareResults(expected, actual, testResult.TestDataName, assertion); Console.WriteLine("Test {0} passed", i); } } catch (Exception ex) { Debug.WriteLine(ex.StackTrace); throw; } }
/// <summary> /// Validates the operand. /// </summary> /// <param name="context">The context.</param> /// <param name="index">The index.</param> /// <returns>the result of the validation</returns> public virtual ServiceResult Validate(FilterContext context, int index) { return(ServiceResult.Create(StatusCodes.BadEventFilterInvalid, "A sub-class of FilterOperand must be specified.")); }
/// <summary> /// Initializes the object with a result code. /// </summary> /// <param name="status">The status.</param> public ElementResult(ServiceResult status) { m_status = status; }
/// <summary> /// Returns true if the status is good or uncertain. /// </summary> public static bool IsNotBad(ServiceResult status) { if (status != null) { return StatusCode.IsNotBad(status.m_code); } return true; }
/// <summary> /// Initializes the object with a status code and a diagnostic info structure. /// </summary> public ServiceResult(StatusCode code, int index, DiagnosticInfoCollection diagnosticInfos, IList<string> stringTable) { m_code = (uint)code; if (index >= 0 && diagnosticInfos != null && index < diagnosticInfos.Count) { DiagnosticInfo diagnosticInfo = diagnosticInfos[index]; if (diagnosticInfo != null) { m_namespaceUri = LookupString(stringTable, diagnosticInfo.NamespaceUri); m_symbolicId = LookupString(stringTable, diagnosticInfo.SymbolicId); string locale = LookupString(stringTable, diagnosticInfo.Locale); string localizedText = LookupString(stringTable, diagnosticInfo.LocalizedText); m_localizedText = new LocalizedText(locale, localizedText); m_additionalInfo = diagnosticInfo.AdditionalInfo; if (!StatusCode.IsGood(diagnosticInfo.InnerStatusCode)) { m_innerResult = new ServiceResult(diagnosticInfo.InnerStatusCode, diagnosticInfo.InnerDiagnosticInfo, stringTable); } } } }
/// <summary> /// Returns true if the status code is uncertain. /// </summary> public static bool IsUncertain(ServiceResult status) { if (status != null) { return StatusCode.IsUncertain(status.m_code); } return false; }
/// <summary> /// Initializes the exception with a status code, a message and an inner exception. /// </summary> public ServiceResultException(uint statusCode, string message, Exception e) : base(message, e) { m_status = new ServiceResult(statusCode, message, e); if ((Utils.TraceMask & Utils.TraceMasks.StackTrace) != 0) { Utils.Trace(Utils.TraceMasks.StackTrace, "***EXCEPTION*** {0} {1} {2}", m_status, e.GetType().Name, message); } }
/// <summary> /// Initializes the exception with a Result object. /// </summary> public ServiceResultException(ServiceResult status) : base(GetMessage(status)) { if (status != null) { m_status = status; } else { m_status = new ServiceResult(StatusCodes.Bad); } if ((Utils.TraceMask & Utils.TraceMasks.StackTrace) != 0) { Utils.Trace(Utils.TraceMasks.StackTrace, "***EXCEPTION*** {0}", m_status); } }
/// <summary> /// Extracts an exception message from a Result object. /// </summary> private static string GetMessage(ServiceResult status) { if (status == null) { return Strings.DefaultMessage; } if (!LocalizedText.IsNullOrEmpty(status.LocalizedText)) { return status.LocalizedText.Text; } return status.ToString(); }
/// <summary> /// Creates a fault message. /// </summary> /// <param name="request">The request.</param> /// <param name="exception">The exception.</param> /// <returns>A fault message.</returns> protected static ServiceFault CreateFault(IServiceRequest request, Exception exception) { DiagnosticsMasks diagnosticsMask = DiagnosticsMasks.ServiceNoInnerStatus; ServiceFault fault = new ServiceFault(); if (request != null) { fault.ResponseHeader.Timestamp = DateTime.UtcNow; fault.ResponseHeader.RequestHandle = request.RequestHeader.RequestHandle; if (request.RequestHeader != null) { diagnosticsMask = (DiagnosticsMasks)request.RequestHeader.ReturnDiagnostics; } } ServiceResult result = null; ServiceResultException sre = exception as ServiceResultException; if (sre != null) { result = new ServiceResult(sre); Utils.Trace( Utils.TraceMasks.Service, "Service Fault Occured. Reason={0}", result); } else { result = new ServiceResult(exception, StatusCodes.BadUnexpectedError); Utils.Trace(exception, "SERVER - Unexpected Service Fault: {0}", exception.Message); } fault.ResponseHeader.ServiceResult = result.Code; StringTable stringTable = new StringTable(); fault.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo( result, diagnosticsMask, true, stringTable); fault.ResponseHeader.StringTable = stringTable.ToArray(); return fault; }
/// <summary> /// Initializes the object from a stream. /// </summary> protected ServiceResultException(SerializationInfo info, StreamingContext context) : base(info, context) { if (info == null) { throw new System.ArgumentNullException("info - ServiceResultException"); } m_status = DeserializeServiceResult(info, string.Empty); }
/// <summary> /// Invokes the methods and returns the output parameters. /// </summary> /// <param name="context">The context to use.</param> /// <param name="objectId">The object being called.</param> /// <param name="inputArguments">The input arguments.</param> /// <param name="argumentErrors">Any errors for the input arguments.</param> /// <param name="outputArguments">The output arguments.</param> /// <returns>The result of the method call.</returns> public virtual ServiceResult Call( ISystemContext context, NodeId objectId, IList<Variant> inputArguments, IList<ServiceResult> argumentErrors, IList<Variant> outputArguments) { // validate input arguments. List<object> inputs = new List<object>(); // check for too few or too many arguments. int expectedCount = 0; if (InputArguments != null && InputArguments.Value != null) { expectedCount = InputArguments.Value.Length; } if (expectedCount != inputArguments.Count) { return StatusCodes.BadArgumentsMissing; } // validate individual arguements. bool error = false; for (int ii = 0; ii < inputArguments.Count; ii++) { ServiceResult argumentError = ValidateInputArgument(context, inputArguments[ii], ii); if (ServiceResult.IsBad(argumentError)) { error = true; } inputs.Add(inputArguments[ii].Value); argumentErrors.Add(argumentError); } // return good - caller must check argument errors. if (error) { return ServiceResult.Good; } // set output arguments to default values. List<object> outputs = new List<object>(); if (OutputArguments != null) { IList<Argument> arguments = OutputArguments.Value; if (arguments != null && arguments.Count > 0) { for (int ii = 0; ii < arguments.Count; ii++) { outputs.Add(GetArgumentDefaultValue(context, arguments[ii])); } } } // invoke method. ServiceResult result = null; try { result = Call(context, objectId, inputs, outputs); } catch (Exception e) { result = new ServiceResult(e); } // copy out arguments. if (ServiceResult.IsGood(result)) { for (int ii = 0; ii < outputs.Count; ii++) { outputArguments.Add(new Variant(outputs[ii])); } } return result; }
/// <summary> /// Throws an exception if validation fails. /// </summary> /// <param name="certificate">The certificate to be checked.</param> /// <exception cref="ServiceResultException">If certificate cannot be accepted</exception> protected virtual void InternalValidate(IList <X509Certificate2> certificates) { lock (m_lock) { X509Certificate2 certificate = certificates[0]; // check for previously validated certificate. X509Certificate2 certificate2 = null; if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2)) { if (Utils.IsEqual(certificate2.RawData, certificate.RawData)) { return; } } CertificateIdentifier trustedCertificate = GetTrustedCertificate(certificate); // get the issuers (checks the revocation lists if using directory stores). List <CertificateIdentifier> issuers = new List <CertificateIdentifier>(); bool isIssuerTrusted = GetIssuers(certificates, issuers); // setup policy chain X509ChainPolicy policy = new X509ChainPolicy(); policy.RevocationFlag = X509RevocationFlag.EntireChain; policy.RevocationMode = X509RevocationMode.NoCheck; policy.VerificationFlags = X509VerificationFlags.NoFlag; foreach (CertificateIdentifier issuer in issuers) { if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0) { policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown; policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown; policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown; policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown; } // we did the revocation check in the GetIssuers call. No need here. policy.RevocationMode = X509RevocationMode.NoCheck; policy.ExtraStore.Add(issuer.Certificate); } // build chain. X509Chain chain = new X509Chain(); chain.ChainPolicy = policy; chain.Build(certificate); // check the chain results. CertificateIdentifier target = trustedCertificate; if (target == null) { target = new CertificateIdentifier(certificate); } for (int ii = 0; ii < chain.ChainElements.Count; ii++) { X509ChainElement element = chain.ChainElements[ii]; CertificateIdentifier issuer = null; if (ii < issuers.Count) { issuer = issuers[ii]; } // check for chain status errors. foreach (X509ChainStatus status in element.ChainElementStatus) { ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0)); if (ServiceResult.IsBad(result)) { throw new ServiceResultException(result); } } if (issuer != null) { target = issuer; } } // check if certificate is trusted. if (trustedCertificate == null && !isIssuerTrusted) { if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData)) { throw ServiceResultException.Create( StatusCodes.BadCertificateUntrusted, "Certificate is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}", certificate.SubjectName.Name, certificate.IssuerName.Name); } } } }