public void Execute(MethodDefinition method) { ExecutionEngine engine = new ExecutionEngine(); Thread thread = new Thread(engine); MethodState state = new MethodState(thread, method); thread.Methods.Push(state); thread.Execute(); }
public void Execute(MethodState state, Instruction inst) { // FIXME SECURITY: Verifier should ensure all ldloc access is under the local var max. if (this.m_Parameter == null) state.LocalVariables[(int)inst.Operand] = state.EvaluationStack.Pop(); else state.LocalVariables[(int)this.m_Parameter] = state.EvaluationStack.Pop(); }
public EditedMethodUpdater(Lazy<IMethodAnnotations> methodAnnotations, ModuleDocumentNode modNode, MethodDef originalMethod, Emit.MethodBody newBody, MethodDefOptions methodDefOptions) { this.methodAnnotations = methodAnnotations; ownerNode = modNode.Context.DocumentTreeView.FindNode(originalMethod); if (ownerNode == null) throw new InvalidOperationException(); method = originalMethod; originalMethodState = new MethodState(originalMethod, methodAnnotations.Value.IsBodyModified(method)); newMethodState = new MethodState(newBody, methodDefOptions, true); }
public void Execute(MethodState state, Instruction inst) { if (inst.Operand is MemberReference) { if ((inst.Operand as MemberReference).FullName == "System.Void System.Console::WriteLine(System.String)") Console.WriteLine((string)state.EvaluationStack.Pop()); else throw new NotSupportedException(); } else throw new NotSupportedException(); }
public void VisitMethod(BeginMethod begin) { if (!m_disabled) { Log.DebugLine(this, "{0}", begin.Info.Method); string root = DoGetRootName(begin.Info.Method); MethodState state = new MethodState { Method = begin.Info.Method, IsThreadRoot = root != null, IsThreadSafe = DoIsMarkedThreadSafe(begin.Info.Method), IsExternal = begin.Info.Method.ExternallyVisible(Cache), }; m_methods.Add(begin.Info.Method, state); if (root != null) { m_knownRoots.Add(state, root); } else if (state.IsThreadSafe && state.IsExternal) { m_knownRoots.Add(state, "*"); } else { if (Cache.Assembly.EntryPoint == begin.Info.Method) { m_entryPoints.Add(begin.Info.Method); } else if (state.IsExternal) { Log.TraceLine(this, "Externally visible but not marked as a thread:"); Log.TraceLine(this, " {0}", begin.Info.Method); m_entryPoints.Add(begin.Info.Method); } } if (DoTypeIsMarkedThreadSafe(begin.Info.Type)) if (m_safeTypes.IndexOf(begin.Info.Type) < 0) m_safeTypes.Add(begin.Info.Type); if (DoMethodIsMarkedThreadSafe(begin.Info.Method)) m_safeMethods.Add(state); } }
public void Execute(MethodState state, Instruction inst) { switch (this.m_Type) { case LdcType.i4: if (this.m_Parameter == null) state.EvaluationStack.Push(new Int32Type((Int32)inst.Operand)); else state.EvaluationStack.Push(new Int32Type((Int32)this.m_Parameter)); break; case LdcType.i8: state.EvaluationStack.Push(new Int64Type((Int64)inst.Operand)); break; case LdcType.r4: case LdcType.r8: state.EvaluationStack.Push(new FloatingPointType((float)inst.Operand)); break; } }
/// <summary> /// Finds the child with the specified browse name. /// </summary> protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case ObjectTypeTest.BrowseNames.BrowseName4node66: { if (createOrReplace) { if (BrowseName4node66 == null) { if (replacement == null) { BrowseName4node66 = new PropertyState<LocalizedText>(this); } else { BrowseName4node66 = (PropertyState<LocalizedText>)replacement; } } } instance = BrowseName4node66; break; } case ObjectTypeTest.BrowseNames.NameNotSet1109: { if (createOrReplace) { if (NameNotSet1109 == null) { if (replacement == null) { NameNotSet1109 = new AnalogItemState(this); } else { NameNotSet1109 = (AnalogItemState)replacement; } } } instance = NameNotSet1109; break; } case ObjectTypeTest.BrowseNames.ChildMethod: { if (createOrReplace) { if (ChildMethod == null) { if (replacement == null) { ChildMethod = new ChildMethodComplexObjectMethodState(this); } else { ChildMethod = (ChildMethodComplexObjectMethodState)replacement; } } } instance = ChildMethod; break; } case ObjectTypeTest.BrowseNames.NonExecutableMethod: { if (createOrReplace) { if (NonExecutableMethod == null) { if (replacement == null) { NonExecutableMethod = new MethodState(this); } else { NonExecutableMethod = (MethodState)replacement; } } } instance = NonExecutableMethod; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); }
private ServiceResult CloseAndUpdate( ISystemContext context, MethodState method, NodeId objectId, uint fileHandle, ref bool restartRequired) { HasSecureWriteAccess(context); ServiceResult result = StatusCodes.Good; lock (m_lock) { if (m_sessionId != context.SessionId) { return(StatusCodes.BadUserAccessDenied); } if (m_fileHandle != fileHandle) { return(StatusCodes.BadInvalidArgument); } try { TrustListDataType trustList = DecodeTrustListData(context, m_strm); TrustListMasks masks = (TrustListMasks)trustList.SpecifiedLists; X509Certificate2Collection issuerCertificates = null; List <X509CRL> issuerCrls = null; X509Certificate2Collection trustedCertificates = null; List <X509CRL> trustedCrls = null; // test integrity of all CRLs if ((masks & TrustListMasks.IssuerCertificates) != 0) { issuerCertificates = new X509Certificate2Collection(); foreach (var cert in trustList.IssuerCertificates) { issuerCertificates.Add(new X509Certificate2(cert)); } } if ((masks & TrustListMasks.IssuerCrls) != 0) { issuerCrls = new List <X509CRL>(); foreach (var crl in trustList.IssuerCrls) { issuerCrls.Add(new X509CRL(crl)); } } if ((masks & TrustListMasks.TrustedCertificates) != 0) { trustedCertificates = new X509Certificate2Collection(); foreach (var cert in trustList.TrustedCertificates) { trustedCertificates.Add(new X509Certificate2(cert)); } } if ((masks & TrustListMasks.TrustedCrls) != 0) { trustedCrls = new List <X509CRL>(); foreach (var crl in trustList.TrustedCrls) { trustedCrls.Add(new X509CRL(crl)); } } // update store // test integrity of all CRLs TrustListMasks updateMasks = TrustListMasks.None; if ((masks & TrustListMasks.IssuerCertificates) != 0) { if (UpdateStoreCertificates(m_issuerStorePath, issuerCertificates)) { updateMasks |= TrustListMasks.IssuerCertificates; } } if ((masks & TrustListMasks.IssuerCrls) != 0) { if (UpdateStoreCrls(m_issuerStorePath, issuerCrls)) { updateMasks |= TrustListMasks.IssuerCrls; } } if ((masks & TrustListMasks.TrustedCertificates) != 0) { if (UpdateStoreCertificates(m_trustedStorePath, trustedCertificates)) { updateMasks |= TrustListMasks.TrustedCertificates; } } if ((masks & TrustListMasks.TrustedCrls) != 0) { if (UpdateStoreCrls(m_trustedStorePath, trustedCrls)) { updateMasks |= TrustListMasks.TrustedCrls; } } if (masks != updateMasks) { result = StatusCodes.BadCertificateInvalid; } } catch { result = StatusCodes.BadCertificateInvalid; } finally { m_sessionId = null; m_strm = null; m_node.LastUpdateTime.Value = DateTime.UtcNow; m_node.OpenCount.Value = 0; } } restartRequired = false; return(result); }
private ServiceResult ApplyChanges( ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { HasApplicationSecureAdminAccess(context); bool disconnectSessions = false; foreach (var certificateGroup in m_certificateGroups) { try { var updateCertificate = certificateGroup.UpdateCertificate; if (updateCertificate != null) { if (certificateGroup.UpdateCertificate.SessionId == context.SessionId) { using (ICertificateStore appStore = CertificateStoreIdentifier.OpenStore(certificateGroup.ApplicationCertificate.StorePath)) { appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait(); appStore.Add(updateCertificate.CertificateWithPrivateKey).Wait(); updateCertificate.CertificateWithPrivateKey = null; } using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath)) { foreach (var issuer in updateCertificate.IssuerCollection) { try { issuerStore.Add(issuer).Wait(); } catch (ArgumentException) { // ignore error if issuer cert already exists } } } disconnectSessions = true; } } } finally { certificateGroup.UpdateCertificate = null; } } if (disconnectSessions) { Task.Run(async() => { // give the client some time to receive the response // before the certificate update may disconnect all sessions await Task.Delay(1000); await m_configuration.CertificateValidator.UpdateCertificate(m_configuration.SecurityConfiguration); } ); } return(StatusCodes.Good); }
/// <summary> /// Method to remove the node from the subscription and stop publishing telemetry to IoTHub. Executes synchronously. /// </summary> private ServiceResult OnUnpublishNodeCall(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { if (string.IsNullOrEmpty(inputArguments[0] as string) || string.IsNullOrEmpty(inputArguments[1] as string)) { Trace("UnpublishNode: Invalid arguments!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!")); } bool result = false; NodeId nodeId = null; ExpandedNodeId expandedNodeId = null; Uri endpointUri = null; bool isNodeIdFormat = true; try { string id = inputArguments[0] as string; if (id.Contains("nsu=")) { expandedNodeId = ExpandedNodeId.Parse(id); isNodeIdFormat = false; } else { nodeId = NodeId.Parse(id); isNodeIdFormat = true; } endpointUri = new Uri(inputArguments[1] as string); } catch (UriFormatException) { Trace($"UnpublishNode: The endpointUrl is invalid '{inputArguments[1] as string}'!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!")); } catch (Exception e) { Trace(e, $"UnpublishNode: The NodeId has an invalid format '{inputArguments[0] as string}'!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA NodeId in NodeId or ExpandedNodeId format as first argument!")); } // find the session and stop monitoring the node. try { if (ShutdownTokenSource.IsCancellationRequested) { return(ServiceResult.Create(StatusCodes.BadUnexpectedError, $"Publisher shutdown in progress.")); } // find the session we need to monitor the node OpcSession opcSession = null; try { OpcSessionsListSemaphore.Wait(); opcSession = OpcSessions.FirstOrDefault(s => s.EndpointUri.AbsoluteUri.Equals(endpointUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase)); } catch { opcSession = null; } finally { OpcSessionsListSemaphore.Release(); } if (opcSession == null) { // do nothing if there is no session for this endpoint. Trace($"UnpublishNode: Session for endpoint '{endpointUri.OriginalString}' not found."); return(ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for endpoint of node to unpublished not found!")); } else { if (isNodeIdFormat) { // stop monitoring the node, execute syncronously Trace($"UnpublishNode: Request to stop monitoring item with NodeId '{nodeId.ToString()}' (PublishingInterval: {OpcPublishingInterval}, SamplingInterval: {OpcSamplingInterval})"); result = opcSession.RequestMonitorItemRemovalAsync(nodeId, null, OpcPublishingInterval, OpcSamplingInterval, ShutdownTokenSource.Token).Result; } else { // stop monitoring the node, execute syncronously Trace($"UnpublishNode: Request to stop monitoring item with ExpandedNodeId '{expandedNodeId.ToString()}' (PublishingInterval: {OpcPublishingInterval}, SamplingInterval: {OpcSamplingInterval})"); result = opcSession.RequestMonitorItemRemovalAsync(null, expandedNodeId, OpcPublishingInterval, OpcSamplingInterval, ShutdownTokenSource.Token).Result; } } } catch (Exception e) { Trace(e, $"UnpublishNode: Exception while trying to configure publishing node '{nodeId.ToString()}'"); return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error unpublishing node: {e.Message}")); } return(result ? ServiceResult.Good : ServiceResult.Create(StatusCodes.Bad, "Can not stop monitoring node!")); }
/// <summary> /// Called when a client locks the server. /// </summary> public ServiceResult OnGetMonitoredItems( ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments) { if (inputArguments == null || inputArguments.Count != 1) { return StatusCodes.BadInvalidArgument; } uint? subscriptionId = inputArguments[0] as uint?; if (subscriptionId == null) { return StatusCodes.BadInvalidArgument; } uint[] serverHandles = null; uint[] clientHandles = null; foreach (Subscription subscription in Server.SubscriptionManager.GetSubscriptions()) { if (subscription.Id == subscriptionId) { subscription.GetMonitoredItems(out serverHandles, out clientHandles); outputArguments[0] = serverHandles; outputArguments[1] = clientHandles; return ServiceResult.Good; } } return StatusCodes.BadSubscriptionIdInvalid; }
/// <summary> /// Method exposed as a node in the server to stop monitoring it and no longer publish telemetry of it. /// </summary> private ServiceResult UnPublishNodeMethod(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { if (inputArguments[0] == null || inputArguments[1] == null) { Trace("UnPublishNodeMethod: Invalid arguments!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!")); } string nodeId = inputArguments[0] as string; string endpointUrl = inputArguments[1] as string; if (string.IsNullOrEmpty(nodeId) || string.IsNullOrEmpty(endpointUrl)) { Trace($"UnPublishNodeMethod: Arguments (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}') are not valid strings!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!")); } NodeToPublish nodeToUnpublish = new NodeToPublish(); try { nodeToUnpublish = new NodeToPublish(nodeId, endpointUrl); } catch (UriFormatException) { Trace($"UnPublishNodeMethod: The endpointUrl is invalid (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}')!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!")); } // Find the session and stop monitoring the node. try { // find the session we need to monitor the node OpcSession opcSession = OpcSessions.First(s => s.EndpointUri == nodeToUnpublish.EndPointUri); if (opcSession == null) { // do nothing if there is no session for this endpoint. Trace($"UnPublishNodeMethod: Session for endpoint '{nodeToUnpublish.EndPointUri.AbsolutePath}' not found."); return(ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for endpoint of published node not found!")); } else { Trace($"UnPublishNodeMethod: Session found for endpoint '{nodeToUnpublish.EndPointUri.AbsolutePath}'"); } // remove the node from the sessions monitored items list. opcSession.TagNodeForMonitoringStop(nodeToUnpublish.NodeId); Trace("UnPublishNodeMethod: Requested to stop monitoring of node."); // stop monitoring the node Task monitorTask = Task.Run(async() => await opcSession.ConnectAndMonitor()); monitorTask.Wait(); Trace("UnPublishNodeMethod: Session processing completed."); // remove node from our persisted data set. var itemToRemove = NodesToPublish.Find(l => l.NodeId == nodeToUnpublish.NodeId && l.EndPointUri == nodeToUnpublish.EndPointUri); NodesToPublish.Remove(itemToRemove); // persist data File.WriteAllText(NodesToPublishAbsFilename, JsonConvert.SerializeObject(NodesToPublish)); } catch (Exception e) { Trace(e, $"DoPublish: Exception while trying to configure publishing node '{nodeToUnpublish.ToString()}'"); return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error publishing node: {e.Message}")); } return(ServiceResult.Good); }
public abstract void SetNode(MethodState node);
/// <summary> /// Imports a node from the set. /// </summary> private NodeState Import(ISystemContext context, UANode node) { NodeState importedNode = null; NodeClass nodeClass = NodeClass.Unspecified; if (node is UAObject) nodeClass = NodeClass.Object; else if (node is UAVariable) nodeClass = NodeClass.Variable; else if (node is UAMethod) nodeClass = NodeClass.Method; else if (node is UAObjectType) nodeClass = NodeClass.ObjectType; else if (node is UAVariableType) nodeClass = NodeClass.VariableType; else if (node is UADataType) nodeClass = NodeClass.DataType; else if (node is UAReferenceType) nodeClass = NodeClass.ReferenceType; else if (node is UAView) nodeClass = NodeClass.View; switch (nodeClass) { case NodeClass.Object: { UAObject o = (UAObject)node; BaseObjectState value = new BaseObjectState(null); value.EventNotifier = o.EventNotifier; importedNode = value; break; } case NodeClass.Variable: { UAVariable o = (UAVariable)node; NodeId typeDefinitionId = null; if (node.References != null) { for (int ii = 0; ii < node.References.Length; ii++) { Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true); bool isInverse = !node.References[ii].IsForward; Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris); if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { typeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); break; } } } BaseVariableState value = null; if (typeDefinitionId == Opc.Ua.VariableTypeIds.PropertyType) { value = new PropertyState(null); } else { value = new BaseDataVariableState(null); } value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true); value.ValueRank = o.ValueRank; value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions); value.AccessLevel = o.AccessLevel; value.UserAccessLevel = o.UserAccessLevel; value.MinimumSamplingInterval = o.MinimumSamplingInterval; value.Historizing = o.Historizing; if (o.Value != null) { XmlDecoder decoder = CreateDecoder(context, o.Value); TypeInfo typeInfo = null; value.Value = decoder.ReadVariantContents(out typeInfo); decoder.Close(); } importedNode = value; break; } case NodeClass.Method: { UAMethod o = (UAMethod)node; MethodState value = new MethodState(null); value.Executable = o.Executable; value.UserExecutable = o.UserExecutable; importedNode = value; break; } case NodeClass.View: { UAView o = (UAView)node; ViewState value = new ViewState(); value.ContainsNoLoops = o.ContainsNoLoops; importedNode = value; break; } case NodeClass.ObjectType: { UAObjectType o = (UAObjectType)node; BaseObjectTypeState value = new BaseObjectTypeState(); value.IsAbstract = o.IsAbstract; importedNode = value; break; } case NodeClass.VariableType: { UAVariableType o = (UAVariableType)node; BaseVariableTypeState value = new BaseDataVariableTypeState(); value.IsAbstract = o.IsAbstract; value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true); value.ValueRank = o.ValueRank; value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions); if (o.Value != null) { XmlDecoder decoder = CreateDecoder(context, o.Value); TypeInfo typeInfo = null; value.Value = decoder.ReadVariantContents(out typeInfo); decoder.Close(); } importedNode = value; break; } case NodeClass.DataType: { UADataType o = (UADataType)node; DataTypeState value = new DataTypeState(); value.IsAbstract = o.IsAbstract; value.Definition = Import(o.Definition, context.NamespaceUris); importedNode = value; break; } case NodeClass.ReferenceType: { UAReferenceType o = (UAReferenceType)node; ReferenceTypeState value = new ReferenceTypeState(); value.IsAbstract = o.IsAbstract; value.InverseName = Import(o.InverseName); value.Symmetric = o.Symmetric; importedNode = value; break; } } importedNode.NodeId = ImportNodeId(node.NodeId, context.NamespaceUris, false); importedNode.BrowseName = ImportQualifiedName(node.BrowseName, context.NamespaceUris); importedNode.DisplayName = Import(node.DisplayName); importedNode.Description = Import(node.Description); importedNode.WriteMask = (AttributeWriteMask)node.WriteMask; importedNode.UserWriteMask = (AttributeWriteMask)node.UserWriteMask; if (!String.IsNullOrEmpty(node.SymbolicName)) { importedNode.SymbolicName = node.SymbolicName; } if (node.References != null) { BaseInstanceState instance = importedNode as BaseInstanceState; BaseTypeState type = importedNode as BaseTypeState; for (int ii = 0; ii < node.References.Length; ii++) { Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true); bool isInverse = !node.References[ii].IsForward; Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris); if (instance != null) { if (referenceTypeId == ReferenceTypeIds.HasModellingRule && !isInverse) { instance.ModellingRuleId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { instance.TypeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } if (type != null) { if (referenceTypeId == ReferenceTypeIds.HasSubtype && isInverse) { type.SuperTypeId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } importedNode.AddReference(referenceTypeId, isInverse, targetId); } } return importedNode; }
public SwitchOffMethodState(MethodState source) : base(source) { }
public TCDMethodState(MethodState source) : base(source.Parent) { Initialize(new SystemContext(), source); }
public ResetAllErrorsMethodState(MethodState source) : base(source) { }
public void Execute(MethodState state, Instruction inst) { // Does nothing. }
/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (Lock) { #region Setup IList <IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List <IReference>(); } #endregion try { #region Initialize string alarmsName = "Alarms"; string alarmsNodeName = alarmsName; Type alarmControllerType = Type.GetType("Alarms.AlarmController"); int interval = 1000; string intervalString = interval.ToString(); int conditionTypeIndex = 0; #endregion #region Create Alarm Folder FolderState alarmsFolder = CreateFolder(null, alarmsNodeName, alarmsName); alarmsFolder.AddReference(ReferenceTypes.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypes.Organizes, false, alarmsFolder.NodeId)); alarmsFolder.EventNotifier = EventNotifiers.SubscribeToEvents; AddRootNotifier(alarmsFolder); #endregion #region Create Methods string startMethodName = "Start"; string startMethodNodeName = alarmsNodeName + "." + startMethodName; MethodState startMethod = AlarmHelpers.CreateMethod(alarmsFolder, NamespaceIndex, startMethodNodeName, startMethodName); AlarmHelpers.AddStartInputParameters(startMethod, NamespaceIndex); startMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnStart); string startBranchMethodName = "StartBranch"; string startBranchMethodNodeName = alarmsNodeName + "." + startBranchMethodName; MethodState startBranchMethod = AlarmHelpers.CreateMethod(alarmsFolder, NamespaceIndex, startBranchMethodNodeName, startBranchMethodName); AlarmHelpers.AddStartInputParameters(startBranchMethod, NamespaceIndex); startBranchMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnStartBranch); string endMethodName = "End"; string endMethodNodeName = alarmsNodeName + "." + endMethodName; MethodState endMethod = AlarmHelpers.CreateMethod(alarmsFolder, NamespaceIndex, endMethodNodeName, endMethodName); endMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnEnd); #endregion #region Create Variables string analogTriggerName = "AnalogSource"; string analogTriggerNodeName = alarmsNodeName + "." + analogTriggerName; BaseDataVariableState analogTrigger = AlarmHelpers.CreateVariable(alarmsFolder, NamespaceIndex, analogTriggerNodeName, analogTriggerName); analogTrigger.OnWriteValue = OnWriteAlarmTrigger; AlarmController analogAlarmController = (AlarmController)Activator.CreateInstance(alarmControllerType, analogTrigger, interval, false); SourceController analogSourceController = new SourceController(analogTrigger, analogAlarmController); m_triggerMap.Add("Analog", analogSourceController); string booleanTriggerName = "BooleanSource"; string booleanTriggerNodeName = alarmsNodeName + "." + booleanTriggerName; BaseDataVariableState booleanTrigger = AlarmHelpers.CreateVariable(alarmsFolder, NamespaceIndex, booleanTriggerNodeName, booleanTriggerName, boolValue: true); booleanTrigger.OnWriteValue = OnWriteAlarmTrigger; AlarmController booleanAlarmController = (AlarmController)Activator.CreateInstance(alarmControllerType, booleanTrigger, interval, true); SourceController booleanSourceController = new SourceController(booleanTrigger, booleanAlarmController); m_triggerMap.Add("Boolean", booleanSourceController); #endregion #region Create Alarms AlarmHolder mandatoryExclusiveLevel = new ExclusiveLevelHolder( this, alarmsFolder, analogSourceController, intervalString, GetSupportedAlarmConditionType(ref conditionTypeIndex), alarmControllerType, interval, optional: false); m_alarms.Add(mandatoryExclusiveLevel.AlarmNodeName, mandatoryExclusiveLevel); AlarmHolder mandatoryNonExclusiveLevel = new NonExclusiveLevelHolder( this, alarmsFolder, analogSourceController, intervalString, GetSupportedAlarmConditionType(ref conditionTypeIndex), alarmControllerType, interval, optional: false); m_alarms.Add(mandatoryNonExclusiveLevel.AlarmNodeName, mandatoryNonExclusiveLevel); AlarmHolder offNormal = new OffNormalAlarmTypeHolder( this, alarmsFolder, booleanSourceController, intervalString, GetSupportedAlarmConditionType(ref conditionTypeIndex), alarmControllerType, interval, optional: false); m_alarms.Add(offNormal.AlarmNodeName, offNormal); #endregion AddPredefinedNode(SystemContext, alarmsFolder); StartTimer(); m_allowEntry = true; } catch (Exception e) { Utils.LogError(e, "Error creating the AlarmNodeManager address space."); } } }
/// <summary> /// Method exposed as a node in the server to publish a node to IoT Hub that it is connected to /// </summary> private ServiceResult PublishNodeMethod(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { if (inputArguments[0] == null || inputArguments[1] == null) { Trace("PublishNodeMethod: Invalid Arguments!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!")); } NodeToPublish nodeToPublish; string nodeId = inputArguments[0] as string; string endpointUrl = inputArguments[1] as string; if (string.IsNullOrEmpty(nodeId) || string.IsNullOrEmpty(endpointUrl)) { Trace($"PublishNodeMethod: Arguments (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}') are not valid strings!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!")); } try { nodeToPublish = new NodeToPublish(nodeId, endpointUrl); } catch (UriFormatException) { Trace($"PublishNodeMethod: The endpointUrl is invalid (0 (nodeId): '{nodeId}', 1 (endpointUrl):'{endpointUrl}')!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!")); } // Create session and add item to monitor, what ever is needed. try { // find the session we need to monitor the node OpcSession opcSession = OpcSessions.First(s => s.EndpointUri == nodeToPublish.EndPointUri); // Add a new session. if (opcSession == null) { // create new session info. opcSession = new OpcSession(nodeToPublish.EndPointUri, OpcSessionCreationTimeout); OpcSessions.Add(opcSession); Trace($"DoPublish: No matching session found for endpoint '{nodeToPublish.EndPointUri.AbsolutePath}'. Requested to create a new one."); } else { Trace($"DoPublish: Session found for endpoint '{nodeToPublish.EndPointUri.AbsolutePath}'"); } // add the node info to the sessions monitored items list. opcSession.AddNodeForMonitoring(nodeToPublish.NodeId); Trace("DoPublish: Requested to monitor item."); // start monitoring the node Task monitorTask = Task.Run(async() => await opcSession.ConnectAndMonitor()); monitorTask.Wait(); Trace("DoPublish: Session processing completed."); // update our data NodesToPublish.Add(nodeToPublish); // persist it to disk File.WriteAllText(NodesToPublishAbsFilename, JsonConvert.SerializeObject(NodesToPublish)); Trace($"DoPublish: Now publishing: {nodeToPublish.ToString()}"); return(ServiceResult.Good); } catch (Exception e) { Trace(e, $"DoPublish: Exception while trying to configure publishing node '{nodeToPublish.ToString()}'"); return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error publishing node: {e.Message}")); } }
/// <summary> /// Handles a request to refresh conditions for a subscription. /// </summary> private ServiceResult OnConditionRefresh( ISystemContext context, MethodState method, NodeId objectId, uint subscriptionId) { ServerSystemContext systemContext = context as ServerSystemContext; if (systemContext == null) { systemContext = this.SystemContext; } Server.ConditionRefresh(systemContext.OperationContext, subscriptionId); return ServiceResult.Good; }
/// <summary> /// Finds the child with the specified browse name. /// </summary> protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return(null); } BaseInstanceState instance = null; switch (browseName.Name) { case DataTypeTest.BrowseNames.Name: { if (createOrReplace) { if (Name == null) { if (replacement == null) { Name = new PropertyState <string>(this); } else { Name = (PropertyState <string>)replacement; } } } instance = Name; break; } case DataTypeTest.BrowseNames.Description: { if (createOrReplace) { if (Description == null) { if (replacement == null) { Description = new PropertyState <string>(this); } else { Description = (PropertyState <string>)replacement; } } } instance = Description; break; } case DataTypeTest.BrowseNames.Price: { if (createOrReplace) { if (Price == null) { if (replacement == null) { Price = new PropertyState(this); } else { Price = (PropertyState)replacement; } } } instance = Price; break; } case DataTypeTest.BrowseNames.Dish: { if (createOrReplace) { if (Dish == null) { if (replacement == null) { Dish = new MethodState(this); } else { Dish = (MethodState)replacement; } } } instance = Dish; break; } case DataTypeTest.BrowseNames.DishId: { if (createOrReplace) { if (DishId == null) { if (replacement == null) { DishId = new PropertyState(this); } else { DishId = (PropertyState)replacement; } } } instance = DishId; break; } } if (instance != null) { return(instance); } return(base.FindChild(context, browseName, createOrReplace, replacement)); }
public MethodState CreateAddMethodState( NodeState parent, AasUaBaseEntity.CreateMode mode, string browseDisplayName, Argument[] inputArgs = null, Argument[] outputArgs = null, NodeId referenceTypeFromParentId = null, NodeId methodDeclarationId = null, GenericMethodCalledEventHandler onCalled = null) { // method node var m = new MethodState(parent); m.BrowseName = "" + browseDisplayName; m.DisplayName = "" + browseDisplayName; m.Description = new LocalizedText("en", browseDisplayName); m.NodeId = nodeMgr.New(nodeMgr.SystemContext, mode, m); if (methodDeclarationId != null) { m.MethodDeclarationId = methodDeclarationId; } m.Executable = true; m.UserExecutable = true; nodeMgr.AddPredefinedNode(nodeMgr.SystemContext, m); if (parent != null) { parent.AddChild(m); } if (referenceTypeFromParentId != null) { if (parent != null) { parent.AddReference(referenceTypeFromParentId, false, m.NodeId); if (referenceTypeFromParentId == ReferenceTypeIds.HasComponent) { m.AddReference(referenceTypeFromParentId, true, parent.NodeId); } if (referenceTypeFromParentId == ReferenceTypeIds.HasProperty) { m.AddReference(referenceTypeFromParentId, true, parent.NodeId); } } } // can have inputs, outputs for (int i = 0; i < 2; i++) { // pretty argument list var arguments = (i == 0) ? inputArgs : outputArgs; if (arguments == null || arguments.Length < 1) { continue; } // make a property for this var prop = CreateAddPropertyState <Argument[]>( m, mode, (i == 0) ? "InputArguments" : "OutputArguments", DataTypeIds.Argument, arguments, ReferenceTypeIds.HasProperty, typeDefinitionId: VariableTypeIds.PropertyType, valueRank: 1); // explicitely add arguments ass well? if (i == 0) { m.InputArguments = prop; } if (i == 1) { m.OutputArguments = prop; } } // event handler if (onCalled != null) { m.OnCallMethod = onCalled; } return(m); }
/// <summary> /// Finds the child with the specified browse name. /// </summary> protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return(null); } BaseInstanceState instance = null; switch (browseName.Name) { case DataTypeTest.BrowseNames.Id: { if (createOrReplace) { if (Id == null) { if (replacement == null) { Id = new BaseDataVariableState(this); } else { Id = (BaseDataVariableState)replacement; } } } instance = Id; break; } case DataTypeTest.BrowseNames.NameNotSet52: { if (createOrReplace) { if (NameNotSet52 == null) { if (replacement == null) { NameNotSet52 = new BaseDataVariableState <string>(this); } else { NameNotSet52 = (BaseDataVariableState <string>)replacement; } } } instance = NameNotSet52; break; } case DataTypeTest.BrowseNames.Dishes: { if (createOrReplace) { if (Dishes == null) { if (replacement == null) { Dishes = new BaseObjectState(this); } else { Dishes = (BaseObjectState)replacement; } } } instance = Dishes; break; } case DataTypeTest.BrowseNames.Menu: { if (createOrReplace) { if (Menu == null) { if (replacement == null) { Menu = new MethodState(this); } else { Menu = (MethodState)replacement; } } } instance = Menu; break; } } if (instance != null) { return(instance); } return(base.FindChild(context, browseName, createOrReplace, replacement)); }
/// <summary> /// Method to start monitoring a node and publish the data to IoTHub. Executes synchronously. /// </summary> private ServiceResult OnPublishNodeCall(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { if (string.IsNullOrEmpty(inputArguments[0] as string) || string.IsNullOrEmpty(inputArguments[1] as string)) { Trace("PublishNode: Invalid Arguments when trying to publish a node."); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!")); } NodeId nodeId = null; ExpandedNodeId expandedNodeId = null; Uri endpointUri = null; bool isNodeIdFormat = true; try { string id = inputArguments[0] as string; if (id.Contains("nsu=")) { expandedNodeId = ExpandedNodeId.Parse(id); isNodeIdFormat = false; } else { nodeId = NodeId.Parse(id); isNodeIdFormat = true; } endpointUri = new Uri(inputArguments[1] as string); } catch (UriFormatException) { Trace($"PublishNode: The EndpointUri has an invalid format '{inputArguments[1] as string}'!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!")); } catch (Exception e) { Trace(e, $"PublishNode: The NodeId has an invalid format '{inputArguments[0] as string}'!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA NodeId in NodeId or ExpandedNodeId format as first argument!")); } // find/create a session to the endpoint URL and start monitoring the node. try { // lock the publishing configuration till we are done OpcSessionsListSemaphore.Wait(); if (ShutdownTokenSource.IsCancellationRequested) { return(ServiceResult.Create(StatusCodes.BadUnexpectedError, $"Publisher shutdown in progress.")); } // find the session we need to monitor the node OpcSession opcSession = null; opcSession = OpcSessions.FirstOrDefault(s => s.EndpointUri.AbsoluteUri.Equals(endpointUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase)); // add a new session. if (opcSession == null) { // create new session info. opcSession = new OpcSession(endpointUri, true, OpcSessionCreationTimeout); OpcSessions.Add(opcSession); Trace($"PublishNode: No matching session found for endpoint '{endpointUri.OriginalString}'. Requested to create a new one."); } if (isNodeIdFormat) { // add the node info to the subscription with the default publishing interval, execute syncronously Trace($"PublishNode: Request to monitor item with NodeId '{nodeId.ToString()}' (PublishingInterval: {OpcPublishingInterval}, SamplingInterval: {OpcSamplingInterval})"); opcSession.AddNodeForMonitoringAsync(nodeId, null, OpcPublishingInterval, OpcSamplingInterval, ShutdownTokenSource.Token).Wait(); } else { // add the node info to the subscription with the default publishing interval, execute syncronously Trace($"PublishNode: Request to monitor item with ExpandedNodeId '{expandedNodeId.ToString()}' (PublishingInterval: {OpcPublishingInterval}, SamplingInterval: {OpcSamplingInterval})"); opcSession.AddNodeForMonitoringAsync(null, expandedNodeId, OpcPublishingInterval, OpcSamplingInterval, ShutdownTokenSource.Token).Wait(); } } catch (Exception e) { Trace(e, $"PublishNode: Exception while trying to configure publishing node '{(isNodeIdFormat ? nodeId.ToString() : expandedNodeId.ToString())}'"); return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error publishing node: {e.Message}")); } finally { OpcSessionsListSemaphore.Release(); } return(ServiceResult.Good); }
protected override ServiceResult Call(ISystemContext context, CallMethodRequest methodToCall, MethodState method, CallMethodResult result) { if (methodToCall.MethodId == new NodeId("Robot1_Stop", NamespaceIndex)) { _mode.Value = (short)1; _mode.Timestamp = DateTime.UtcNow; _mode.ClearChangeMasks(SystemContext, false); _laser.Value = false; _laser.Timestamp = DateTime.UtcNow; _laser.ClearChangeMasks(SystemContext, false); result.StatusCode = StatusCodes.Good; return(StatusCodes.Good); } if (methodToCall.MethodId == new NodeId("Robot1_Multiply", NamespaceIndex)) { try { var a = Convert.ToDouble(methodToCall.InputArguments[0].Value); var b = Convert.ToDouble(methodToCall.InputArguments[1].Value); result.OutputArguments.Add(new Variant(a * b)); result.StatusCode = StatusCodes.Good; return(StatusCodes.Good); } catch (Exception e) { Console.WriteLine(e); result.StatusCode = StatusCodes.BadInvalidArgument; return(StatusCodes.BadInvalidArgument); } } return(base.Call(context, methodToCall, method, result)); }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // load existing application cert and private key if (!Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { string password = String.Empty; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKey(password).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = CertificateFactory.CreateCertificateFromPKCS12(privateKey, password); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, password); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; return(ServiceResult.Good); }
public override void Execute(MethodContext context, MethodState state, object localInx = null) { base.Execute(context, state, 1); }
private static void EmitClassMethod(MethodJITInfo method, IntPtr objectptr, IntPtr methodptr, TypeBuilder builder, FieldBuilder addressAssistant) { MethodState state = new MethodState(); state.NativeArgs.Add(typeof(IntPtr)); // thisptr state.ReturnTypeByStack = method.ReturnType.DetermineProps(); if (state.ReturnTypeByStack) { // ref to the native return type state.NativeArgs.Add(method.ReturnType.NativeType.MakeByRefType()); state.NativeReturn = null; } else if (method.ReturnType.IsStringClass) { // special case for strings, we will marshal it in ourselves state.NativeReturn = typeof(IntPtr); } else { state.NativeReturn = method.ReturnType.NativeType; } state.MethodReturn = method.ReturnType.Type; foreach (TypeJITInfo typeInfo in method.Args) { // populate MethodArgs and NativeArgs now typeInfo.DetermineProps(); state.MethodArgs.Add(typeInfo.Type); if (typeInfo.IsStringClass) { // we need to specially marshal strings state.NativeArgs.Add(typeof(IntPtr)); } else if (!typeInfo.IsParams) { if (typeInfo.IsByRef && typeInfo.NativeType.IsValueType) { state.NativeArgs.Add(typeInfo.NativeType.MakeByRefType()); } else { state.NativeArgs.Add(typeInfo.NativeType); } } } // add a native version parameter if the return type is detected as a versioned class if (method.ReturnType.IsGeneric || (method.ReturnType.IsCreatableClass && method.ReturnType.IsInterfaceVersioned)) { state.NativeArgs.Add(typeof(string)); } MethodBuilder mbuilder = builder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, CallingConventions.HasThis); if (method.ReturnType.IsGeneric) { // create generic param GenericTypeParameterBuilder[] gtypeParameters; gtypeParameters = mbuilder.DefineGenericParameters(new string[] { "TClass" }); state.MethodReturn = gtypeParameters[0]; gtypeParameters[0].SetGenericParameterAttributes(GenericParameterAttributes.ReferenceTypeConstraint); } mbuilder.SetReturnType(state.MethodReturn); mbuilder.SetParameters(state.MethodArgs.ToArray()); builder.DefineMethodOverride(mbuilder, method.MethodInfo); ILGenerator ilgen = mbuilder.GetILGenerator(); // load object pointer EmitPlatformLoad(ilgen, objectptr); if (state.ReturnTypeByStack) { // allocate local to hold the return state.localReturn = ilgen.DeclareLocal(method.ReturnType.NativeType); state.localReturn.SetLocalSymInfo("nativeReturnPlaceholder"); ilgen.Emit(OpCodes.Ldloca_S, state.localReturn.LocalIndex); } int argindex = 0; foreach (TypeJITInfo typeInfo in method.Args) { argindex++; // perform any conversions necessary if (typeInfo.NativeType != typeInfo.Type && typeInfo.IsByRef) { LocalBuilder localArg = ilgen.DeclareLocal(typeInfo.NativeType); localArg.SetLocalSymInfo("byrefarg" + argindex); var helper = new MethodState.RefArgLocal(); helper.builder = localArg; helper.argIndex = argindex; helper.paramType = typeInfo.PierceType; state.refargLocals.Add(helper); ilgen.Emit(OpCodes.Ldloca_S, localArg); } else if (typeInfo.NativeType != typeInfo.Type && !typeInfo.Type.IsEnum) { EmitPrettyLoad(ilgen, argindex); ilgen.EmitCall(OpCodes.Call, typeInfo.Type.GetMethod("GetValue"), null); } else { EmitPrettyLoad(ilgen, argindex); } if ((typeInfo.IsStringClass || typeInfo.IsParams) && method.HasParams) { if (!typeInfo.IsParams) { continue; } ilgen.EmitCall(OpCodes.Call, typeof(String).GetMethod("Format", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(object[]) }, null), null); } if (typeInfo.IsStringClass || typeInfo.IsParams) { LocalBuilder localString = ilgen.DeclareLocal(typeof(GCHandle)); localString.SetLocalSymInfo("nativeString" + argindex); state.unmanagedMemory.Add(localString); // we need to specially marshal strings ilgen.Emit(OpCodes.Ldloca, localString.LocalIndex); ilgen.EmitCall(OpCodes.Call, typeof(InteropHelp).GetMethod("EncodeUTF8String"), null); } else if (typeInfo.IsCreatableClass) { // if this argument is a class we understand: get the object pointer ilgen.Emit(OpCodes.Ldfld, addressAssistant); } } if (method.ReturnType.IsGeneric || (method.ReturnType.IsCreatableClass && method.ReturnType.IsInterfaceVersioned)) { ilgen.Emit(OpCodes.Ldtoken, method.ReturnType.Type); ilgen.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public), null); ilgen.EmitCall(OpCodes.Call, typeof(InterfaceVersions).GetMethod("GetInterfaceIdentifier", BindingFlags.Static | BindingFlags.Public), null); } // load vtable method pointer EmitPlatformLoad(ilgen, methodptr); CallingConvention ccv = CallingConvention.ThisCall; if (method.HasParams) { ccv = CallingConvention.Cdecl; } if (state.NativeReturn == typeof(bool)) { state.NativeReturn = typeof(byte); } ilgen.EmitCalli(OpCodes.Calli, ccv, state.NativeReturn, state.NativeArgs.ToArray()); // populate byref args foreach (var local in state.refargLocals) { EmitPrettyLoad(ilgen, local.argIndex); EmitPrettyLoadLocal(ilgen, local.builder.LocalIndex); ilgen.Emit(OpCodes.Newobj, local.paramType.GetConstructor(new Type[] { local.builder.LocalType })); ilgen.Emit(OpCodes.Stind_Ref); } // clean up unmanaged memory foreach (LocalBuilder localbuilder in state.unmanagedMemory) { ilgen.Emit(OpCodes.Ldloca, localbuilder.LocalIndex); ilgen.EmitCall(OpCodes.Call, typeof(InteropHelp).GetMethod("FreeString"), null); } if (state.ReturnTypeByStack) { EmitPrettyLoadLocal(ilgen, state.localReturn.LocalIndex); // reconstruct return type if (state.localReturn.LocalType != state.MethodReturn) { ilgen.Emit(OpCodes.Newobj, state.MethodReturn.GetConstructor(new Type[] { state.localReturn.LocalType })); } } else if (method.ReturnType.IsCreatableClass) { if (method.ReturnType.IsGeneric) { ilgen.EmitCall(OpCodes.Call, typeof(JITEngine).GetMethod("GenerateClass", BindingFlags.Static | BindingFlags.Public), null); } else if (method.ReturnType.IsDelegate) { ilgen.Emit(OpCodes.Ldtoken, method.ReturnType.Type); ilgen.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); ilgen.EmitCall(OpCodes.Call, typeof(Marshal).GetMethod("GetDelegateForFunctionPointer", BindingFlags.Static | BindingFlags.Public), null); ilgen.Emit(OpCodes.Castclass, method.ReturnType.Type); } else { ilgen.EmitCall(OpCodes.Call, typeof(JITEngine).GetMethod("GenerateClass", BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(method.ReturnType.Type), null); } } else if (method.ReturnType.IsStringClass) { // marshal string return ilgen.EmitCall(OpCodes.Call, typeof(InteropHelp).GetMethod("DecodeUTF8String"), null); } ilgen.Emit(OpCodes.Ret); }
private ServiceResult Open( ISystemContext context, MethodState method, NodeId objectId, OpenFileMode mode, TrustListMasks masks, ref uint fileHandle) { HasSecureReadAccess(context); if (mode == OpenFileMode.Read) { HasSecureReadAccess(context); } else if (mode == (OpenFileMode.Write | OpenFileMode.EraseExisting)) { HasSecureWriteAccess(context); } else { return(StatusCodes.BadNotWritable); } lock (m_lock) { if (m_sessionId != null) { // to avoid deadlocks, last open always wins m_sessionId = null; m_strm = null; m_node.OpenCount.Value = 0; } m_readMode = mode == OpenFileMode.Read; m_sessionId = context.SessionId; fileHandle = ++m_fileHandle; TrustListDataType trustList = new TrustListDataType() { SpecifiedLists = (uint)masks }; using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_trustedStorePath)) { if ((masks & TrustListMasks.TrustedCertificates) != 0) { X509Certificate2Collection certificates = store.Enumerate().Result; foreach (var certificate in certificates) { trustList.TrustedCertificates.Add(certificate.RawData); } } if ((masks & TrustListMasks.TrustedCrls) != 0) { foreach (var crl in store.EnumerateCRLs()) { trustList.TrustedCrls.Add(crl.RawData); } } } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_issuerStorePath)) { if ((masks & TrustListMasks.IssuerCertificates) != 0) { X509Certificate2Collection certificates = store.Enumerate().Result; foreach (var certificate in certificates) { trustList.IssuerCertificates.Add(certificate.RawData); } } if ((masks & TrustListMasks.IssuerCrls) != 0) { foreach (var crl in store.EnumerateCRLs()) { trustList.IssuerCrls.Add(crl.RawData); } } } if (m_readMode) { m_strm = EncodeTrustListData(context, trustList); } else { m_strm = new MemoryStream(DefaultTrustListCapacity); } m_node.OpenCount.Value = 1; } return(ServiceResult.Good); }
private ServiceResult RemoveCertificate( ISystemContext context, MethodState method, NodeId objectId, string thumbprint, bool isTrustedCertificate) { HasSecureWriteAccess(context); lock (m_lock) { if (m_sessionId != null) { return(StatusCodes.BadInvalidState); } if (String.IsNullOrEmpty(thumbprint)) { return(StatusCodes.BadInvalidArgument); } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { var certCollection = store.FindByThumbprint(thumbprint).Result; if (certCollection.Count == 0) { return(StatusCodes.BadInvalidArgument); } // delete all CRLs signed by cert var crlsToDelete = new List <X509CRL>(); foreach (var crl in store.EnumerateCRLs()) { foreach (var cert in certCollection) { if (Utils.CompareDistinguishedName(cert.Subject, crl.Issuer) && crl.VerifySignature(cert, false)) { crlsToDelete.Add(crl); break; } } } if (!store.Delete(thumbprint).Result) { return(StatusCodes.BadInvalidArgument); } foreach (var crl in crlsToDelete) { if (!store.DeleteCRL(crl)) { // intentionally ignore errors, try best effort Utils.Trace("RemoveCertificate: Failed to delete CRL {0}.", crl.ToString()); } } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } return(ServiceResult.Good); }
/// <summary> /// Imports a node from the set. /// </summary> private NodeState Import(ISystemContext context, UANode node) { NodeState importedNode = null; NodeClass nodeClass = NodeClass.Unspecified; if (node is UAObject) { nodeClass = NodeClass.Object; } else if (node is UAVariable) { nodeClass = NodeClass.Variable; } else if (node is UAMethod) { nodeClass = NodeClass.Method; } else if (node is UAObjectType) { nodeClass = NodeClass.ObjectType; } else if (node is UAVariableType) { nodeClass = NodeClass.VariableType; } else if (node is UADataType) { nodeClass = NodeClass.DataType; } else if (node is UAReferenceType) { nodeClass = NodeClass.ReferenceType; } else if (node is UAView) { nodeClass = NodeClass.View; } switch (nodeClass) { case NodeClass.Object: { UAObject o = (UAObject)node; BaseObjectState value = new BaseObjectState(null); value.EventNotifier = o.EventNotifier; importedNode = value; break; } case NodeClass.Variable: { UAVariable o = (UAVariable)node; NodeId typeDefinitionId = null; if (node.References != null) { for (int ii = 0; ii < node.References.Length; ii++) { Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true); bool isInverse = !node.References[ii].IsForward; Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris); if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { typeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); break; } } } BaseVariableState value = null; if (typeDefinitionId == Opc.Ua.VariableTypeIds.PropertyType) { value = new PropertyState(null); } else { value = new BaseDataVariableState(null); } value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true); value.ValueRank = o.ValueRank; value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions); value.AccessLevelEx = o.AccessLevel; value.UserAccessLevel = (byte)(o.AccessLevel & 0xFF); value.MinimumSamplingInterval = o.MinimumSamplingInterval; value.Historizing = o.Historizing; if (o.Value != null) { XmlDecoder decoder = CreateDecoder(context, o.Value); TypeInfo typeInfo = null; value.Value = decoder.ReadVariantContents(out typeInfo); decoder.Close(); } importedNode = value; break; } case NodeClass.Method: { UAMethod o = (UAMethod)node; MethodState value = new MethodState(null); value.Executable = o.Executable; value.UserExecutable = o.Executable; value.TypeDefinitionId = ImportNodeId(o.MethodDeclarationId, context.NamespaceUris, true); importedNode = value; break; } case NodeClass.View: { UAView o = (UAView)node; ViewState value = new ViewState(); value.ContainsNoLoops = o.ContainsNoLoops; importedNode = value; break; } case NodeClass.ObjectType: { UAObjectType o = (UAObjectType)node; BaseObjectTypeState value = new BaseObjectTypeState(); value.IsAbstract = o.IsAbstract; importedNode = value; break; } case NodeClass.VariableType: { UAVariableType o = (UAVariableType)node; BaseVariableTypeState value = new BaseDataVariableTypeState(); value.IsAbstract = o.IsAbstract; value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true); value.ValueRank = o.ValueRank; value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions); if (o.Value != null) { XmlDecoder decoder = CreateDecoder(context, o.Value); TypeInfo typeInfo = null; value.Value = decoder.ReadVariantContents(out typeInfo); decoder.Close(); } importedNode = value; break; } case NodeClass.DataType: { UADataType o = (UADataType)node; DataTypeState value = new DataTypeState(); value.IsAbstract = o.IsAbstract; Opc.Ua.DataTypeDefinition dataTypeDefinition = Import(o, o.Definition, context.NamespaceUris); value.DataTypeDefinition = new ExtensionObject(dataTypeDefinition); value.Purpose = o.Purpose; value.DataTypeModifier = DataTypeModifier.None; if (o.Definition != null) { if (o.Definition.IsOptionSet) { value.DataTypeModifier = DataTypeModifier.OptionSet; } else if (o.Definition.IsUnion) { value.DataTypeModifier = DataTypeModifier.Union; } } importedNode = value; break; } case NodeClass.ReferenceType: { UAReferenceType o = (UAReferenceType)node; ReferenceTypeState value = new ReferenceTypeState(); value.IsAbstract = o.IsAbstract; value.InverseName = Import(o.InverseName); value.Symmetric = o.Symmetric; importedNode = value; break; } } importedNode.NodeId = ImportNodeId(node.NodeId, context.NamespaceUris, false); importedNode.BrowseName = ImportQualifiedName(node.BrowseName, context.NamespaceUris); importedNode.DisplayName = Import(node.DisplayName); if (importedNode.DisplayName == null) { importedNode.DisplayName = new Ua.LocalizedText(importedNode.BrowseName.Name); } importedNode.Description = Import(node.Description); importedNode.Categories = (node.Category != null && node.Category.Length > 0) ? node.Category : null; importedNode.ReleaseStatus = node.ReleaseStatus; importedNode.WriteMask = (AttributeWriteMask)node.WriteMask; importedNode.UserWriteMask = (AttributeWriteMask)node.UserWriteMask; if (!String.IsNullOrEmpty(node.SymbolicName)) { importedNode.SymbolicName = node.SymbolicName; } if (node.References != null) { BaseInstanceState instance = importedNode as BaseInstanceState; BaseTypeState type = importedNode as BaseTypeState; for (int ii = 0; ii < node.References.Length; ii++) { Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true); bool isInverse = !node.References[ii].IsForward; Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris); if (instance != null) { if (referenceTypeId == ReferenceTypeIds.HasModellingRule && !isInverse) { instance.ModellingRuleId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { instance.TypeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } if (type != null) { if (referenceTypeId == ReferenceTypeIds.HasSubtype && isInverse) { type.SuperTypeId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } importedNode.AddReference(referenceTypeId, isInverse, targetId); } } return(importedNode); }
/// <summary> /// Adds a node to the set. /// </summary> public void Export(ISystemContext context, NodeState node, bool outputRedundantNames = true) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (Opc.Ua.NodeId.IsNull(node.NodeId)) { throw new ArgumentException("A non-null NodeId must be specified."); } UANode exportedNode = null; switch (node.NodeClass) { case NodeClass.Object: { BaseObjectState o = (BaseObjectState)node; UAObject value = new UAObject(); value.EventNotifier = o.EventNotifier; if (o.Parent != null) { value.ParentNodeId = ExportAlias(o.Parent.NodeId, context.NamespaceUris); } exportedNode = value; break; } case NodeClass.Variable: { BaseVariableState o = (BaseVariableState)node; UAVariable value = new UAVariable(); value.DataType = ExportAlias(o.DataType, context.NamespaceUris); value.ValueRank = o.ValueRank; value.ArrayDimensions = Export(o.ArrayDimensions); value.AccessLevel = o.AccessLevelEx; value.MinimumSamplingInterval = o.MinimumSamplingInterval; value.Historizing = o.Historizing; if (o.Parent != null) { value.ParentNodeId = ExportAlias(o.Parent.NodeId, context.NamespaceUris); } if (o.Value != null) { XmlEncoder encoder = CreateEncoder(context); Variant variant = new Variant(o.Value); encoder.WriteVariantContents(variant.Value, variant.TypeInfo); XmlDocument document = new XmlDocument(); document.InnerXml = encoder.Close(); value.Value = document.DocumentElement; } exportedNode = value; break; } case NodeClass.Method: { MethodState o = (MethodState)node; UAMethod value = new UAMethod(); value.Executable = o.Executable; if (o.TypeDefinitionId != o.NodeId) { value.MethodDeclarationId = Export(o.TypeDefinitionId, context.NamespaceUris); } if (o.Parent != null) { value.ParentNodeId = ExportAlias(o.Parent.NodeId, context.NamespaceUris); } exportedNode = value; break; } case NodeClass.View: { ViewState o = (ViewState)node; UAView value = new UAView(); value.ContainsNoLoops = o.ContainsNoLoops; exportedNode = value; break; } case NodeClass.ObjectType: { BaseObjectTypeState o = (BaseObjectTypeState)node; UAObjectType value = new UAObjectType(); value.IsAbstract = o.IsAbstract; exportedNode = value; break; } case NodeClass.VariableType: { BaseVariableTypeState o = (BaseVariableTypeState)node; UAVariableType value = new UAVariableType(); value.IsAbstract = o.IsAbstract; value.DataType = ExportAlias(o.DataType, context.NamespaceUris); value.ValueRank = o.ValueRank; value.ArrayDimensions = Export(o.ArrayDimensions); if (o.Value != null) { XmlEncoder encoder = CreateEncoder(context); Variant variant = new Variant(o.Value); encoder.WriteVariantContents(variant.Value, variant.TypeInfo); XmlDocument document = new XmlDocument(); document.InnerXml = encoder.Close(); value.Value = document.DocumentElement; } exportedNode = value; break; } case NodeClass.DataType: { DataTypeState o = (DataTypeState)node; UADataType value = new UADataType(); value.IsAbstract = o.IsAbstract; value.Definition = Export(o, o.DataTypeDefinition, context.NamespaceUris, outputRedundantNames); value.Purpose = o.Purpose; exportedNode = value; break; } case NodeClass.ReferenceType: { ReferenceTypeState o = (ReferenceTypeState)node; UAReferenceType value = new UAReferenceType(); value.IsAbstract = o.IsAbstract; if (!Opc.Ua.LocalizedText.IsNullOrEmpty(o.InverseName)) { value.InverseName = Export(new Opc.Ua.LocalizedText[] { o.InverseName }); } value.Symmetric = o.Symmetric; exportedNode = value; break; } } exportedNode.NodeId = Export(node.NodeId, context.NamespaceUris); exportedNode.BrowseName = Export(node.BrowseName, context.NamespaceUris); if (outputRedundantNames || node.DisplayName.Text != node.BrowseName.Name) { exportedNode.DisplayName = Export(new Opc.Ua.LocalizedText[] { node.DisplayName }); } else { exportedNode.DisplayName = null; } if (node.Description != null && !String.IsNullOrEmpty(node.Description.Text)) { exportedNode.Description = Export(new Opc.Ua.LocalizedText[] { node.Description }); } else { exportedNode.Description = new LocalizedText[0]; } exportedNode.Category = (node.Categories != null && node.Categories.Count > 0) ? new List <string>(node.Categories).ToArray() : null; exportedNode.ReleaseStatus = node.ReleaseStatus; exportedNode.WriteMask = (uint)node.WriteMask; exportedNode.UserWriteMask = (uint)node.UserWriteMask; if (!String.IsNullOrEmpty(node.SymbolicName) && node.SymbolicName != node.BrowseName.Name) { exportedNode.SymbolicName = node.SymbolicName; } // export references. INodeBrowser browser = node.CreateBrowser(context, null, null, true, BrowseDirection.Both, null, null, true); List <Reference> exportedReferences = new List <Reference>(); IReference reference = browser.Next(); while (reference != null) { if (node.NodeClass == NodeClass.Method) { if (!reference.IsInverse && reference.ReferenceTypeId == ReferenceTypeIds.HasTypeDefinition) { reference = browser.Next(); continue; } } Reference exportedReference = new Reference(); exportedReference.ReferenceType = ExportAlias(reference.ReferenceTypeId, context.NamespaceUris); exportedReference.IsForward = !reference.IsInverse; exportedReference.Value = Export(reference.TargetId, context.NamespaceUris, context.ServerUris); exportedReferences.Add(exportedReference); reference = browser.Next(); } exportedNode.References = exportedReferences.ToArray(); // add node to list. UANode[] nodes = null; int count = 1; if (this.Items == null) { nodes = new UANode[count]; } else { count += this.Items.Length; nodes = new UANode[count]; Array.Copy(this.Items, nodes, this.Items.Length); } nodes[count - 1] = exportedNode; this.Items = nodes; // recusively process children. List <BaseInstanceState> children = new List <BaseInstanceState>(); node.GetChildren(context, children); for (int ii = 0; ii < children.Count; ii++) { Export(context, children[ii], outputRedundantNames); } }
/// <summary> /// Method to start monitoring a node and publish the data to IoTHub. Executes synchronously. /// </summary> private ServiceResult OnPublishNodeCall(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { string logPrefix = "OnPublishNodeCall:"; if (string.IsNullOrEmpty(inputArguments[0] as string) || string.IsNullOrEmpty(inputArguments[1] as string)) { Logger.Error($"{logPrefix} Invalid Arguments when trying to publish a node."); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!")); } HttpStatusCode statusCode = HttpStatusCode.InternalServerError; NodeId nodeId = null; ExpandedNodeId expandedNodeId = null; Uri endpointUri = null; bool isNodeIdFormat = true; try { string id = inputArguments[0] as string; if (id.Contains("nsu=", StringComparison.InvariantCulture)) { expandedNodeId = ExpandedNodeId.Parse(id); isNodeIdFormat = false; } else { nodeId = NodeId.Parse(id); isNodeIdFormat = true; } endpointUri = new Uri(inputArguments[1] as string); } catch (UriFormatException) { Logger.Error($"{logPrefix} The EndpointUrl has an invalid format '{inputArguments[1] as string}'!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!")); } catch (Exception e) { Logger.Error(e, $"{logPrefix} The NodeId has an invalid format '{inputArguments[0] as string}'!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA NodeId in NodeId or ExpandedNodeId format as first argument!")); } // find/create a session to the endpoint URL and start monitoring the node. try { // lock the publishing configuration till we are done NodeConfiguration.OpcSessionsListSemaphore.Wait(); if (ShutdownTokenSource.IsCancellationRequested) { return(ServiceResult.Create(StatusCodes.BadUnexpectedError, $"Publisher shutdown in progress.")); } // find the session we need to monitor the node IOpcSession opcSession = null; opcSession = NodeConfiguration.OpcSessions.FirstOrDefault(s => s.EndpointUrl.Equals(endpointUri.OriginalString, StringComparison.OrdinalIgnoreCase)); // add a new session. if (opcSession == null) { // create new session info. // endpointName is null here. Since we currently do not have to support configuration of OPC Publisher by OPC server this is ok for now. opcSession = new OpcSession(Guid.NewGuid(), null, endpointUri.OriginalString, true, OpcSessionCreationTimeout, OpcAuthenticationMode.Anonymous, null); NodeConfiguration.OpcSessions.Add(opcSession); Logger.Information($"OnPublishNodeCall: No matching session found for endpoint '{endpointUri.OriginalString}'. Requested to create a new one."); } // Add a node. The key for the new node is the node id / expanded node id if (isNodeIdFormat) { // add the node info to the subscription with the default publishing interval, execute syncronously Logger.Debug($"{logPrefix} Request to monitor item with NodeId '{nodeId.ToString()}' (with default PublishingInterval and SamplingInterval)"); statusCode = opcSession.AddNodeForMonitoringAsync(nodeId, null, null, null, nodeId.ToString(), null, null, null, ShutdownTokenSource.Token, null).Result; } else { // add the node info to the subscription with the default publishing interval, execute syncronously Logger.Debug($"{logPrefix} Request to monitor item with ExpandedNodeId '{expandedNodeId.ToString()}' (with default PublishingInterval and SamplingInterval)"); statusCode = opcSession.AddNodeForMonitoringAsync(null, expandedNodeId, null, null, expandedNodeId.ToString(), null, null, null, ShutdownTokenSource.Token, null).Result; } } catch (Exception e) { Logger.Error(e, $"{logPrefix} Exception while trying to configure publishing node '{(isNodeIdFormat ? nodeId.ToString() : expandedNodeId.ToString())}'"); return(ServiceResult.Create(e, StatusCodes.BadUnexpectedError, $"Unexpected error publishing node: {e.Message}")); } finally { NodeConfiguration.OpcSessionsListSemaphore.Release(); } if (statusCode == HttpStatusCode.OK || statusCode == HttpStatusCode.Accepted) { return(ServiceResult.Good); } return(ServiceResult.Create(StatusCodes.Bad, "Can not start monitoring node! Reason unknown.")); }
public void Execute(MethodState state, Instruction inst) { state.InstructionPointer = MethodState.RETURN_INSTRUCTION_POINTER; }
/// <summary> /// Method exposed as a node in the server to un-publish a node from IoT Hub that it is connected to /// </summary> private ServiceResult UnPublishNodeMethod(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { if (inputArguments[0] == null || inputArguments[1] == null) { Program.Trace("UnPublishNodeMethod: Invalid arguments!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!")); } string nodeID = inputArguments[0] as string; string uri = inputArguments[1] as string; if (string.IsNullOrEmpty(nodeID) || string.IsNullOrEmpty(uri)) { Program.Trace("UnPublishNodeMethod: Arguments are not valid strings!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!")); } NodeLookup lookup = new NodeLookup(); lookup.NodeID = new NodeId(nodeID); try { lookup.EndPointURL = new Uri(uri); } catch (UriFormatException) { Program.Trace("UnPublishNodeMethod: Invalid endpoint URL!"); return(ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!")); } // find the right session using our lookup Session matchingSession = null; foreach (Session session in Program.m_sessions) { char[] trimChars = { '/', ' ' }; if (session.Endpoint.EndpointUrl.TrimEnd(trimChars).Equals(lookup.EndPointURL.ToString().TrimEnd(trimChars), StringComparison.OrdinalIgnoreCase)) { matchingSession = session; break; } } if (matchingSession == null) { Program.Trace("UnPublishNodeMethod: Session for published node not found: " + lookup.EndPointURL.ToString()); return(ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for published node not found!")); } // find the right monitored item to remove foreach (MonitoredItem item in matchingSession.DefaultSubscription.MonitoredItems) { if (item.StartNodeId == lookup.NodeID) { matchingSession.DefaultSubscription.RemoveItem(item); Program.Trace("UnPublishNodeMethod: Successful unpublish: " + lookup.NodeID.ToString()); // update our data on success only // we keep the session to the server, as there may be other nodes still published on it var itemToRemove = Program.m_nodesLookups.Find(l => l.NodeID == lookup.NodeID && l.EndPointURL == lookup.EndPointURL); Program.m_nodesLookups.Remove(itemToRemove); //serialize Program.m_nodesLookups to disk string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json"; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_PNFP"))) { publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP"); } File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Program.m_nodesLookups)); return(ServiceResult.Good); } } Program.Trace("UnPublishNodeMethod: Monitored item for node ID not found " + lookup.NodeID.ToString()); return(ServiceResult.Create(StatusCodes.BadNodeIdInvalid, "Monitored item for node ID not found!")); }
public override void Execute(MethodContext context, MethodState state, object operand = null) { base.Execute(context, state, operand); }
/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (Lock) { // create a object to represent the process being controlled. BaseObjectState process = new BaseObjectState(null); process.NodeId = new NodeId(1, NamespaceIndex); process.BrowseName = new QualifiedName("My Process", NamespaceIndex); process.DisplayName = process.BrowseName.Name; process.TypeDefinitionId = ObjectTypeIds.BaseObjectType; // ensure the process object can be found via the server object. IList <IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List <IReference>(); } process.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, process.NodeId)); // a property to report the process state. PropertyState <uint> state = m_stateNode = new PropertyState <uint>(process); state.NodeId = new NodeId(2, NamespaceIndex); state.BrowseName = new QualifiedName("State", NamespaceIndex); state.DisplayName = state.BrowseName.Name; state.TypeDefinitionId = VariableTypeIds.PropertyType; state.ReferenceTypeId = ReferenceTypeIds.HasProperty; state.DataType = DataTypeIds.UInt32; state.ValueRank = ValueRanks.Scalar; process.AddChild(state); // a method to start the process. MethodState start = new MethodState(process); start.NodeId = new NodeId(3, NamespaceIndex); start.BrowseName = new QualifiedName("Start", NamespaceIndex); start.DisplayName = start.BrowseName.Name; start.ReferenceTypeId = ReferenceTypeIds.HasComponent; start.UserExecutable = true; start.Executable = true; // add input arguments. start.InputArguments = new PropertyState <Argument[]>(start); start.InputArguments.NodeId = new NodeId(4, NamespaceIndex); start.InputArguments.BrowseName = BrowseNames.InputArguments; start.InputArguments.DisplayName = start.InputArguments.BrowseName.Name; start.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; start.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; start.InputArguments.DataType = DataTypeIds.Argument; start.InputArguments.ValueRank = ValueRanks.OneDimension; Argument[] args = new Argument[2]; args[0] = new Argument(); args[0].Name = "Initial State"; args[0].Description = "The initialize state for the process."; args[0].DataType = DataTypeIds.UInt32; args[0].ValueRank = ValueRanks.Scalar; args[1] = new Argument(); args[1].Name = "Final State"; args[1].Description = "The final state for the process."; args[1].DataType = DataTypeIds.UInt32; args[1].ValueRank = ValueRanks.Scalar; start.InputArguments.Value = args; // add output arguments. start.OutputArguments = new PropertyState <Argument[]>(start); start.OutputArguments.NodeId = new NodeId(5, NamespaceIndex); start.OutputArguments.BrowseName = BrowseNames.OutputArguments; start.OutputArguments.DisplayName = start.OutputArguments.BrowseName.Name; start.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; start.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; start.OutputArguments.DataType = DataTypeIds.Argument; start.OutputArguments.ValueRank = ValueRanks.OneDimension; args = new Argument[2]; args[0] = new Argument(); args[0].Name = "Revised Initial State"; args[0].Description = "The revised initialize state for the process."; args[0].DataType = DataTypeIds.UInt32; args[0].ValueRank = ValueRanks.Scalar; args[1] = new Argument(); args[1].Name = "Revised Final State"; args[1].Description = "The revised final state for the process."; args[1].DataType = DataTypeIds.UInt32; args[1].ValueRank = ValueRanks.Scalar; start.OutputArguments.Value = args; process.AddChild(start); // save in dictionary. AddPredefinedNode(SystemContext, process); // set up method handlers. start.OnCallMethod = new GenericMethodCalledEventHandler(OnStart); } }
/// <summary> /// Calls a method on the specified nodes. /// </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>(); bool didRefresh = false; for (int ii = 0; ii < methodsToCall.Count; ii++) { CallMethodRequest methodToCall = methodsToCall[ii]; bool refreshMethod = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_ConditionRefresh) || methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_ConditionRefresh2); if (refreshMethod) { if (didRefresh) { errors[ii] = StatusCodes.BadRefreshInProgress; methodToCall.Processed = true; continue; } else { didRefresh = true; } } bool ackMethod = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.AcknowledgeableConditionType_Acknowledge); bool confirmMethod = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.AcknowledgeableConditionType_Confirm); bool commentMethod = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_AddComment); bool ackConfirmMethod = ackMethod || confirmMethod || commentMethod; // Need to try to capture any calls to ConditionType::Acknowledge if (methodToCall.ObjectId.Equals(Opc.Ua.ObjectTypeIds.ConditionType) && (ackConfirmMethod)) { // Mantis Issue 6944 which is a duplicate of 5544 - result is Confirm should be Bad_NodeIdInvalid // Override any other errors that may be there, even if this is 'Processed' errors[ii] = StatusCodes.BadNodeIdInvalid; methodToCall.Processed = true; continue; } // skip items that have already been processed. if (methodToCall.Processed) { continue; } MethodState method = null; lock (Lock) { // check for valid handle. NodeHandle initialHandle = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache); if (initialHandle == null) { if (ackConfirmMethod) { // Mantis 6944 errors[ii] = StatusCodes.BadNodeIdUnknown; methodToCall.Processed = true; } continue; } // owned by this node manager. methodToCall.Processed = true; // Look for an alarm branchId to operate on. NodeHandle handle = FindBranchNodeHandle(systemContext, initialHandle, methodToCall); // validate the source node. NodeState source = ValidateNode(systemContext, handle, operationCache); if (source == null) { errors[ii] = StatusCodes.BadNodeIdUnknown; continue; } // 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; } } } // call the method. CallMethodResult result = results[ii] = new CallMethodResult(); errors[ii] = Call( systemContext, methodToCall, method, result); } }
protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode) { // add behaviour to our methods MethodState methodState = predefinedNode as MethodState; if (methodState != null) { if (methodState.DisplayName == "Execute") { methodState.OnCallMethod = new GenericMethodCalledEventHandler(Execute); // define the method's input argument (the serial number) methodState.InputArguments = new PropertyState <Argument[]>(methodState) { NodeId = new NodeId(methodState.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; methodState.InputArguments.DisplayName = methodState.InputArguments.BrowseName.Name; methodState.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; methodState.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; methodState.InputArguments.DataType = DataTypeIds.Argument; methodState.InputArguments.ValueRank = ValueRanks.OneDimension; methodState.InputArguments.Value = new Argument[] { new Argument { Name = "SerialNumber", Description = "Serial number of the product to make.", DataType = DataTypeIds.UInt64, ValueRank = ValueRanks.Scalar } }; return(predefinedNode); } if (methodState.DisplayName == "Reset") { methodState.OnCallMethod = new GenericMethodCalledEventHandler(Reset); return(predefinedNode); } if (methodState.DisplayName == "OpenPressureReleaseValve") { methodState.OnCallMethod = new GenericMethodCalledEventHandler(OpenPressureReleaseValve); return(predefinedNode); } } // also capture the nodeIDs of our instance variables (i.e. NOT the model!) BaseDataVariableState variableState = predefinedNode as BaseDataVariableState; if ((variableState != null) && (variableState.ModellingRuleId == null)) { if (variableState.DisplayName == "NumberOfManufacturedProducts") { m_NumberOfManufacturedProductsID = variableState.NodeId; } if (variableState.DisplayName == "NumberOfDiscardedProducts") { m_NumberOfDiscardedProductsID = variableState.NodeId; } if (variableState.DisplayName == "ProductSerialNumber") { m_ProductSerialNumberID = variableState.NodeId; } if (variableState.DisplayName == "ActualCycleTime") { m_ActualCycleTimeID = variableState.NodeId; } if (variableState.DisplayName == "EnergyConsumption") { m_EnergyConsumptionID = variableState.NodeId; } if (variableState.DisplayName == "FaultyTime") { m_FaultyTimeID = variableState.NodeId; } if (variableState.DisplayName == "IdealCycleTime") { m_IdealCycleTimeID = variableState.NodeId; } if (variableState.DisplayName == "OverallRunningTime") { m_OverallRunningTimeID = variableState.NodeId; } if (variableState.DisplayName == "Pressure") { m_PressureID = variableState.NodeId; } if (variableState.DisplayName == "Status") { m_StatusID = variableState.NodeId; } } return(predefinedNode); }
/// <summary> /// Called when a client locks the server. /// </summary> public ServiceResult OnUnlockServer( ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments) { ServerSystemContext systemContext = context as ServerSystemContext; if (m_serverLockHolder != null) { if (m_serverLockHolder != systemContext.SessionId) { return StatusCodes.BadSessionIdInvalid; } } m_serverLockHolder = null; return ServiceResult.Good; }
private ServiceResult Reset(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { m_status = StationStatus.Ready; return(ServiceResult.Good); }
/// <summary> /// Calls a method on an object. /// </summary> protected virtual ServiceResult Call( ISystemContext context, CallMethodRequest methodToCall, NodeState source, MethodState method, CallMethodResult result) { ServerSystemContext systemContext = context as ServerSystemContext; List<ServiceResult> argumentErrors = new List<ServiceResult>(); VariantCollection outputArguments = new VariantCollection(); ServiceResult error = method.Call( context, source.NodeId, methodToCall.InputArguments, argumentErrors, outputArguments); if (ServiceResult.IsBad(error)) { return error; } // check for argument errors. bool argumentsValid = true; for (int jj = 0; jj < argumentErrors.Count; jj++) { ServiceResult argumentError = argumentErrors[jj]; if (argumentError != null) { result.InputArgumentResults.Add(argumentError.StatusCode); if (ServiceResult.IsBad(argumentError)) { argumentsValid = false; } } else { result.InputArgumentResults.Add(StatusCodes.Good); } // only fill in diagnostic info if it is requested. if ((systemContext.OperationContext.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) { if (ServiceResult.IsBad(argumentError)) { argumentsValid = false; result.InputArgumentDiagnosticInfos.Add(new DiagnosticInfo(argumentError, systemContext.OperationContext.DiagnosticsMask, false, systemContext.OperationContext.StringTable)); } else { result.InputArgumentDiagnosticInfos.Add(null); } } } // check for validation errors. if (!argumentsValid) { result.StatusCode = StatusCodes.BadInvalidArgument; return result.StatusCode; } // do not return diagnostics if there are no errors. result.InputArgumentDiagnosticInfos.Clear(); // return output arguments. result.OutputArguments = outputArguments; return ServiceResult.Good; }
private ServiceResult OpenPressureReleaseValve(ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { m_pressure = 1000; return(ServiceResult.Good); }