/// <summary> /// Create encoder for content type /// </summary> /// <param name="contentType"></param> /// <param name="stream"></param> /// <param name="context"></param> /// <returns></returns> private static IDecoder CreateDecoder(string contentType, Stream stream, IServiceMessageContext context) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } switch (contentType.ToLowerInvariant()) { case ContentMimeType.Json: case ContentMimeType.UaJson: return(new JsonDecoderEx(stream, context)); case ContentMimeType.UaBinary: return(new BinaryDecoder(stream, context ?? new ServiceMessageContext())); case ContentMimeType.UaXml: return(new XmlDecoder(null, XmlReader.Create(stream), context ?? new ServiceMessageContext())); default: throw new ArgumentException(nameof(contentType)); } }
/// <summary> /// Creates a new transport channel that supports the IRegistrationChannel service contract. /// </summary> /// <param name="configuration">The application configuration.</param> /// <param name="description">The description for the endpoint.</param> /// <param name="endpointConfiguration">The configuration to use with the endpoint.</param> /// <param name="clientCertificate">The client certificate.</param> /// <param name="messageContext">The message context to use when serializing the messages.</param> /// <returns></returns> public static ITransportChannel Create( ApplicationConfiguration configuration, EndpointDescription description, EndpointConfiguration endpointConfiguration, X509Certificate2 clientCertificate, IServiceMessageContext messageContext) { // create a UA binary channel. ITransportChannel channel = CreateUaBinaryChannel( configuration, description, endpointConfiguration, clientCertificate, messageContext); // create a registration channel. if (channel == null) { Uri endpointUrl = new Uri(description.EndpointUrl); channel = new RegistrationChannel(); TransportChannelSettings settings = new TransportChannelSettings(); settings.Configuration = endpointConfiguration; settings.Description = description; settings.ClientCertificate = clientCertificate; channel.Initialize(endpointUrl, settings); } return(channel); }
/// <summary> /// Returns an expanded node id from a node uri. /// </summary> /// <param name="value"></param> /// <param name="context"></param> /// <returns></returns> public static ExpandedNodeId ToExpandedNodeId(this string value, IServiceMessageContext context) { if (value == null) { return(ExpandedNodeId.Null); } var parts = value.Split(';'); if (parts.Any(s => s.StartsWith("ns=", StringComparison.CurrentCulture) || s.StartsWith("nsu=", StringComparison.CurrentCulture))) { return(ExpandedNodeId.Parse(value)); } var identifier = ParseNodeIdUri(value, out var nsUri, out var srvUri); // Allocate entry in context if does not exist var nsIndex = context.NamespaceUris.GetIndexOrAppend(nsUri); if (!string.IsNullOrEmpty(srvUri)) { return(new ExpandedNodeId(identifier, 0, nsUri == Namespaces.OpcUa ? null : nsUri, context.ServerUris.GetIndexOrAppend(srvUri))); } return(new ExpandedNodeId(identifier, 0, nsUri == Namespaces.OpcUa ? null : nsUri, 0)); }
/// <summary> /// Encodes the object in the specified stream. /// </summary> /// <param name="messageContext">The system context.</param> /// <param name="writer">The stream to use.</param> public override void Encode(IServiceMessageContext messageContext, StreamWriter writer) { using (BinaryEncoder encoder = new BinaryEncoder(writer.BaseStream, messageContext)) { Encode(encoder); } }
/// <summary> /// Encoder factory for all encoding types. /// </summary> /// <returns></returns> protected IEncoder CreateEncoder( EncodingType encoderType, IServiceMessageContext context, Stream stream, Type systemType, bool useReversibleEncoding = true, bool topLevelIsArray = false, bool includeDefaultValues = false, bool includeDefaultNumbers = true ) { switch (encoderType) { case EncodingType.Binary: Assume.That(useReversibleEncoding, "Binary encoding only supports reversible option."); return(new BinaryEncoder(stream, context)); case EncodingType.Xml: Assume.That(useReversibleEncoding, "Xml encoding only supports reversible option."); var xmlWriter = XmlWriter.Create(stream); return(new XmlEncoder(systemType, xmlWriter, context)); case EncodingType.Json: return(new JsonEncoder(context, useReversibleEncoding, topLevelIsArray, stream) { IncludeDefaultValues = includeDefaultValues, IncludeDefaultNumberValues = includeDefaultNumbers }); } return(null); }
/// <summary> /// Encodes the object in the specified stream. /// </summary> /// <param name="messageContext">The context.</param> /// <param name="stream">The stream to use.</param> public override void Encode(IServiceMessageContext messageContext, Stream stream) { bool topLevelIsArray = !HasNetworkMessageHeader && !HasSingleDataSetMessage && !IsMetaDataMessage; using (JsonEncoder encoder = new JsonEncoder(messageContext, true, topLevelIsArray, stream)) { if (IsMetaDataMessage) { EncodeNetworkMessageHeader(encoder); encoder.WriteEncodeable(kFieldMetaData, m_metadata, null); return; } // handle no header if (HasNetworkMessageHeader) { Encode(encoder); } else if (DataSetMessages != null && DataSetMessages.Count > 0) { if (HasSingleDataSetMessage) { // encode single dataset message JsonDataSetMessage jsonDataSetMessage = DataSetMessages[0] as JsonDataSetMessage; if (jsonDataSetMessage != null) { if (!jsonDataSetMessage.HasDataSetMessageHeader) { // If the NetworkMessageHeader and the DataSetMessageHeader bits are not set // and SingleDataSetMessage bit is set, the NetworkMessage is a JSON object // containing the set of name/value pairs defined for a single DataSet. jsonDataSetMessage.EncodePayload(encoder, false); } else { // If the SingleDataSetMessage bit of the NetworkMessageContentMask is set, // the content of the Messages field is a JSON object containing a single DataSetMessage. jsonDataSetMessage.Encode(encoder); } } } else { // If the NetworkMessageHeader bit of the NetworkMessageContentMask is not set, // the NetworkMessage is the contents of the Messages field (e.g. a JSON array of DataSetMessages). foreach (var message in DataSetMessages) { JsonDataSetMessage jsonDataSetMessage = message as JsonDataSetMessage; if (jsonDataSetMessage != null) { jsonDataSetMessage.Encode(encoder); } } } } } }
/// <summary> /// Encodes the object in the specified stream. /// </summary> /// <param name="messageContext">The system context.</param> /// <param name="stream">The stream to use.</param> public override void Encode(IServiceMessageContext messageContext, Stream stream) { using (BinaryEncoder encoder = new BinaryEncoder(stream, messageContext)) { Encode(encoder); } }
/// <summary> /// Encodes the object in binary /// </summary> public static byte[] EncodeBinary(IEncodeable encodeable, IServiceMessageContext context) { BinaryEncoder encoder = new BinaryEncoder(context); encoder.WriteEncodeable(null, encodeable, null); return(encoder.CloseAndReturnBuffer()); }
/// <summary> /// Initializes the datastore with the server configuration. /// </summary> /// <param name="serverDescription">The server description.</param> /// <param name="configuration">The configuration.</param> /// <param name="messageContext">The message context.</param> /// <param name="certificateValidator">The certificate validator.</param> /// <param name="instanceCertificate">The instance certificate.</param> public ServerInternalData( ServerProperties serverDescription, ApplicationConfiguration configuration, IServiceMessageContext messageContext, CertificateValidator certificateValidator, X509Certificate2 instanceCertificate) { m_serverDescription = serverDescription; m_configuration = configuration; m_messageContext = messageContext; m_endpointAddresses = new List <Uri>(); foreach (string baseAddresses in m_configuration.ServerConfiguration.BaseAddresses) { Uri url = Utils.ParseUri(baseAddresses); if (url != null) { m_endpointAddresses.Add(url); } } m_namespaceUris = m_messageContext.NamespaceUris; m_factory = m_messageContext.Factory; m_serverUris = new StringTable(); m_typeTree = new TypeTable(m_namespaceUris); // add the server uri to the server table. m_serverUris.Append(m_configuration.ApplicationUri); // create the default system context. m_defaultSystemContext = new ServerSystemContext(this); }
/// <summary> /// Returns a node uri from an expanded node id. /// </summary> /// <param name="nodeId"></param> /// <param name="context"></param> /// <param name="noRelativeUriAllowed"></param> /// <returns></returns> public static string AsString(this ExpandedNodeId nodeId, IServiceMessageContext context, bool noRelativeUriAllowed = false) { if (NodeId.IsNull(nodeId)) { return(null); } var nsUri = nodeId.NamespaceUri; if (string.IsNullOrEmpty(nsUri) && (nodeId.NamespaceIndex != 0 || noRelativeUriAllowed)) { nsUri = context.NamespaceUris.GetString(nodeId.NamespaceIndex); if (string.IsNullOrEmpty(nsUri)) { nsUri = null; } } string srvUri = null; if (nodeId.ServerIndex != 0 && context.ServerUris != null) { srvUri = context.ServerUris.GetString(nodeId.ServerIndex); if (string.IsNullOrEmpty(srvUri)) { srvUri = null; } } if (nsUri != null && !Uri.IsWellFormedUriString(nsUri, UriKind.Absolute)) { // Fall back to nsu= format - but strip indexes return(new ExpandedNodeId(nodeId.Identifier, 0, nsUri, 0).ToString()); } return(FormatNodeIdUri(nsUri, srvUri, nodeId.IdType, nodeId.Identifier)); }
/// <summary> /// Creates a new transport channel that supports the IDiscoveryChannel service contract. /// </summary> public static ITransportChannel Create( ApplicationConfiguration configuration, Uri discoveryUrl, EndpointConfiguration endpointConfiguration, IServiceMessageContext messageContext, X509Certificate2 clientCertificate = null) { // create a default description. var endpoint = new EndpointDescription { EndpointUrl = discoveryUrl.ToString(), SecurityMode = MessageSecurityMode.None, SecurityPolicyUri = SecurityPolicies.None }; endpoint.Server.ApplicationUri = endpoint.EndpointUrl; endpoint.Server.ApplicationType = ApplicationType.DiscoveryServer; ITransportChannel channel = CreateUaBinaryChannel( configuration, endpoint, endpointConfiguration, clientCertificate, (X509Certificate2Collection)null, messageContext); return(channel); }
/// <summary> /// Returns a uri that identifies the qualified name uniquely. /// </summary> /// <param name="qn"></param> /// <param name="context"></param> /// <param name="noRelativeUriAllowed"></param> /// <returns></returns> public static string AsString(this QualifiedName qn, IServiceMessageContext context, bool noRelativeUriAllowed = false) { if (qn == null || qn == QualifiedName.Null) { return(string.Empty); } var buffer = new StringBuilder(); if (qn.NamespaceIndex != 0 || noRelativeUriAllowed) { var nsUri = context.NamespaceUris.GetString(qn.NamespaceIndex); if (!string.IsNullOrEmpty(nsUri)) { buffer.Append(nsUri); if (!string.IsNullOrEmpty(qn.Name)) { // Append name as fragment buffer.Append("#"); } } } buffer.Append(qn.Name?.UrlEncode() ?? string.Empty); return(buffer.ToString()); }
protected virtual DiscoveryClient CreateClient( string endpointUrl, string endpointTransportProfileUri) { if (String.IsNullOrEmpty(endpointUrl)) { endpointUrl = DefaultUrl; } if (!Uri.IsWellFormedUriString(endpointUrl, UriKind.Absolute)) { throw new ArgumentException("Not a valid URL.", nameof(endpointUrl)); } IServiceMessageContext context = ApplicationConfiguration.CreateMessageContext(); EndpointConfiguration configuration = EndpointConfiguration.Create(ApplicationConfiguration); if (DefaultOperationTimeout != 0) { configuration.OperationTimeout = DefaultOperationTimeout; } ITransportChannel channel = DiscoveryChannel.Create(new Uri(endpointUrl), configuration, context); DiscoveryClient client = new DiscoveryClient(channel); return(client); }
/// <summary> /// Create encoder for content type /// </summary> /// <param name="contentType"></param> /// <param name="stream"></param> /// <param name="context"></param> /// <returns></returns> private static IEncoder CreateEncoder(string contentType, Stream stream, IServiceMessageContext context) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } switch (contentType.ToLowerInvariant()) { case ContentMimeType.Json: case ContentMimeType.UaJson: return(new JsonEncoderEx(new StreamWriter(stream), context ?? new ServiceMessageContext(), JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, IgnoreDefaultValues = true }); case ContentMimeType.UaBinary: return(new BinaryEncoder(stream, context ?? new ServiceMessageContext())); case ContentMimeType.UaXml: return(new XmlEncoder((Type)null, XmlWriter.Create(stream), context ?? new ServiceMessageContext())); default: throw new ArgumentException(nameof(contentType)); } }
/// <summary> /// Convert xml to encodeable /// </summary> /// <param name="xmlElement"></param> /// <param name="typeId"></param> /// <param name="context"></param> /// <returns></returns> public static IEncodeable ToEncodeable(this XmlElement xmlElement, ExpandedNodeId typeId, IServiceMessageContext context) { using (var decoder = new XmlDecoder(xmlElement, context)) { var body = decoder.ReadExtensionObjectBody(typeId); return(body as IEncodeable); } }
/// <summary> /// Encodes the object and returns the resulting byte array. /// </summary> /// <param name="messageContext">The context.</param> public override byte[] Encode(IServiceMessageContext messageContext) { using (MemoryStream stream = new MemoryStream()) { Encode(messageContext, stream); return(stream.ToArray()); } }
/// <summary> /// Creates a new UA-binary transport channel if requested. Null otherwise. /// </summary> /// <param name="configuration">The application configuration.</param> /// <param name="description">The description for the endpoint.</param> /// <param name="endpointConfiguration">The configuration to use with the endpoint.</param> /// <param name="clientCertificate">The client certificate.</param> /// <param name="messageContext">The message context to use when serializing the messages.</param> /// <returns></returns> public static ITransportChannel CreateUaBinaryChannel( ApplicationConfiguration configuration, EndpointDescription description, EndpointConfiguration endpointConfiguration, X509Certificate2 clientCertificate, IServiceMessageContext messageContext) { return(CreateUaBinaryChannel(configuration, description, endpointConfiguration, clientCertificate, null, messageContext)); }
/// <summary> /// Convert encodeable to binary /// </summary> /// <param name="encodeable"></param> /// <param name="context"></param> /// <returns></returns> public static byte[] AsBinary(this IEncodeable encodeable, IServiceMessageContext context) { using (var stream = new MemoryStream()) { using (var encoder = new BinaryEncoder(stream, context)) { encodeable.Encode(encoder); } return(stream.ToArray()); } }
/// <summary> /// Returns a uri that identifies the node id uniquely. If the server /// uri information is provided, and the it contains a server name at /// index 0, the node id will be formatted as an expanded node id uri /// (see below). Otherwise, the resource is the namespace and not the /// server. /// </summary> /// <param name="nodeId"></param> /// <param name="context"></param> /// <param name="noRelativeUriAllowed"></param> /// <returns></returns> public static string AsString(this NodeId nodeId, IServiceMessageContext context, bool noRelativeUriAllowed = false) { if (NodeId.IsNull(nodeId)) { return(null); } return(nodeId.ToExpandedNodeId(context?.NamespaceUris).AsString(context, noRelativeUriAllowed)); }
/// <summary> /// Convert a relative path to path strings /// </summary> /// <param name="path"></param> /// <param name="context"></param> /// <returns></returns> public static string[] AsString(this RelativePath path, IServiceMessageContext context) { if (path == null) { return(null); } return(path.Elements .Select(p => FormatRelativePathElement(p, context)) .ToArray()); }
/// <summary> /// Convert service model to role permission type /// </summary> /// <param name="model"></param> /// <param name="context"></param> /// <returns></returns> public static RolePermissionType ToStackModel(this RolePermissionModel model, IServiceMessageContext context) { if (model == null) { return(null); } return(new RolePermissionType { RoleId = model.RoleId.ToNodeId(context), Permissions = (uint)model.Permissions.ToStackType() }); }
/// <summary> /// Convert to system context /// </summary> /// <param name="context"></param> public static ISystemContext ToSystemContext(this IServiceMessageContext context) { if (context == null) { return(null); } return(new SystemContext { EncodeableFactory = context.Factory, NamespaceUris = context.NamespaceUris, ServerUris = context.ServerUris }); }
/// <summary> /// Convert role permission type to service model /// </summary> /// <param name="type"></param> /// <param name="context"></param> /// <returns></returns> public static RolePermissionModel ToServiceModel(this RolePermissionType type, IServiceMessageContext context) { if (type == null) { return(null); } return(new RolePermissionModel { RoleId = type.RoleId.AsString(context), Permissions = ((PermissionType)type.Permissions).ToServiceType() }); }
/// <summary> /// Convert encodeable to xml /// </summary> /// <param name="encodeable"></param> /// <param name="context"></param> /// <returns></returns> public static XmlElement AsXmlElement(this IEncodeable encodeable, IServiceMessageContext context) { #pragma warning disable IDE0067 // Dispose objects before losing scope var encoder = new XmlEncoder(context); #pragma warning restore IDE0067 // Dispose objects before losing scope encoder.WriteExtensionObjectBody(encodeable); var document = new XmlDocument { InnerXml = encoder.Close() }; return(document.DocumentElement); }
/// <summary> /// Start the UdpDiscovery process /// </summary> /// <param name="messageContext">The <see cref="IServiceMessageContext"/> object that should be used in encode/decode messages</param> /// <returns></returns> public virtual async Task StartAsync(IServiceMessageContext messageContext) { await Task.Run(() => { lock (m_lock) { MessageContext = messageContext; // initialize Discovery channels m_discoveryUdpClients = UdpClientCreator.GetUdpClients(UsedInContext.Discovery, DiscoveryNetworkInterfaceName, DiscoveryNetworkAddressEndPoint); } }).ConfigureAwait(false); }
/// <summary> /// Convert to path object /// </summary> /// <param name="path"></param> /// <param name="context"></param> /// <returns></returns> public static RelativePath ToRelativePath(this string[] path, IServiceMessageContext context) { if (path == null) { return(new RelativePath()); } return(new RelativePath { Elements = new RelativePathElementCollection(path .Where(p => !string.IsNullOrEmpty(p)) .Select(p => ParsePathElement(p, context))) }); }
/// <summary> /// Encodes the object in XML or Binary /// </summary> public static ExtensionObject Encode(IServiceMessageContext context, IEncodeable encodeable, bool useXml) { if (useXml) { XmlElement body = EncodeableObject.EncodeXml(encodeable, context); return(new ExtensionObject(encodeable.XmlEncodingId, body)); } else { byte[] body = EncodeableObject.EncodeBinary(encodeable, context); return(new ExtensionObject(encodeable.BinaryEncodingId, body)); } }
/// <summary> /// Decodes the message /// </summary> /// <param name="context"></param> /// <param name="message"></param> /// <param name="dataSetReaders"></param> public override void Decode(IServiceMessageContext context, byte[] message, IList <DataSetReaderDataType> dataSetReaders) { if (dataSetReaders == null || dataSetReaders.Count == 0) { return; } using (BinaryDecoder decoder = new BinaryDecoder(message, context)) { //decode bytes using dataset reader information DecodeSubscribedDataSets(decoder, dataSetReaders); } }
/// <summary> /// Convert buffer to encodeable /// </summary> /// <param name="buffer"></param> /// <param name="typeId"></param> /// <param name="context"></param> /// <returns></returns> public static IEncodeable ToEncodeable(this byte[] buffer, ExpandedNodeId typeId, IServiceMessageContext context) { var systemType = TypeInfo.GetSystemType(typeId.ToNodeId(context.NamespaceUris), context.Factory); if (systemType == null) { return(null); } using (var decoder = new BinaryDecoder(buffer, context)) { return(decoder.ReadEncodeable(null, systemType)); } }
/// <summary> /// Update message context from context /// </summary> /// <param name="context"></param> /// <param name="update"></param> public static void UpdateFromContext(this IServiceMessageContext context, IServiceMessageContext update) { if (context is ServiceMessageContext serviceMessageContext) { serviceMessageContext.Factory = update.Factory; serviceMessageContext.NamespaceUris = update.NamespaceUris; serviceMessageContext.ServerUris = update.ServerUris; serviceMessageContext.MaxStringLength = update.MaxStringLength; serviceMessageContext.MaxArrayLength = update.MaxArrayLength; serviceMessageContext.MaxByteStringLength = update.MaxByteStringLength; serviceMessageContext.MaxMessageSize = update.MaxMessageSize; } }