mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-18 14:43:08 +08:00
Reduce core dependencies, move https binding to optional assembly. (#1157)
* implement transport binding factory * split https transport into seperate nuget package * new Opc.Ua.Binding.Https assembly * Https binding is loaded on demand, if available * reduce core dependencies to kestrel and others fixes #600
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
Stack\Opc.Ua.Core\bin\Debug\netstandard2.1\Opc.Ua.Core.dll
|
||||
Stack\Opc.Ua.Core\bin\Debug\netstandard2.0\Opc.Ua.Core.dll
|
||||
Stack\Opc.Ua.Core\bin\Debug\net462\Opc.Ua.Core.dll
|
||||
Stack\Opc.Ua.Bindings.Https\bin\Debug\netstandard2.1\Opc.Ua.Bindings.Https.dll
|
||||
Stack\Opc.Ua.Bindings.Https\bin\Debug\netstandard2.0\Opc.Ua.Bindings.Https.dll
|
||||
Stack\Opc.Ua.Bindings.Https\bin\Debug\net462\Opc.Ua.Bindings.Https.dll
|
||||
Libraries\Opc.Ua.Server\bin\Debug\netstandard2.1\Opc.Ua.Server.dll
|
||||
Libraries\Opc.Ua.Server\bin\Debug\netstandard2.0\Opc.Ua.Server.dll
|
||||
Libraries\Opc.Ua.Server\bin\Debug\net462\Opc.Ua.Server.dll
|
||||
@@ -19,3 +22,5 @@ Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net462\Opc.Ua.Gds.Client.Common.dll
|
||||
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\netstandard2.1\Opc.Ua.Gds.Server.Common.dll
|
||||
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\netstandard2.0\Opc.Ua.Gds.Server.Common.dll
|
||||
Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net462\Opc.Ua.Gds.Server.Common.dll
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Stack\Opc.Ua.Core\bin\Release\netstandard2.1\Opc.Ua.Core.dll
|
||||
Stack\Opc.Ua.Core\bin\Release\netstandard2.0\Opc.Ua.Core.dll
|
||||
Stack\Opc.Ua.Core\bin\Release\net462\Opc.Ua.Core.dll
|
||||
Stack\Opc.Ua.Bindings.Https\bin\Release\netstandard2.1\Opc.Ua.Bindings.Https.dll
|
||||
Stack\Opc.Ua.Bindings.Https\bin\Release\netstandard2.0\Opc.Ua.Bindings.Https.dll
|
||||
Stack\Opc.Ua.Bindings.Https\bin\Release\net462\Opc.Ua.Bindings.Https.dll
|
||||
Libraries\Opc.Ua.Server\bin\Release\netstandard2.1\Opc.Ua.Server.dll
|
||||
Libraries\Opc.Ua.Server\bin\Release\netstandard2.0\Opc.Ua.Server.dll
|
||||
Libraries\Opc.Ua.Server\bin\Release\net462\Opc.Ua.Server.dll
|
||||
|
||||
@@ -6,12 +6,15 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>ConsoleReferenceClient</PackageId>
|
||||
<Company>OPC Foundation</Company>
|
||||
<Product>OPC UA SDK</Product>
|
||||
<Description>.NET Console Reference Client</Description>
|
||||
<Copyright>Copyright © 2004-2020 OPC Foundation, Inc</Copyright>
|
||||
<RootNamespace>Quickstarts.ConsoleReferenceClient</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(NoHttps)' != 'true' ">
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
<ProjectReference Include="..\..\Libraries\Opc.Ua.Configuration\Opc.Ua.Configuration.csproj" />
|
||||
|
||||
@@ -33,7 +33,7 @@ using Opc.Ua.Configuration;
|
||||
|
||||
namespace Quickstarts.ConsoleReferenceClient
|
||||
{
|
||||
public class Program
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>ConsoleReferenceServer</PackageId>
|
||||
<Company>OPC Foundation</Company>
|
||||
<Product>OPC UA SDK</Product>
|
||||
<Description>.NET Core Reference Server</Description>
|
||||
<Copyright>Copyright © 2004-2020 OPC Foundation, Inc</Copyright>
|
||||
</PropertyGroup>
|
||||
@@ -19,6 +18,10 @@
|
||||
<Compile Include="..\ReferenceServer\ReferenceNodeManager.cs;..\ReferenceServer\ReferenceServer.cs;..\ReferenceServer\ReferenceServerConfiguration.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(NoHttps)' != 'true' ">
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
<ProjectReference Include="..\..\Libraries\Opc.Ua.Configuration\Opc.Ua.Configuration.csproj" />
|
||||
@@ -35,8 +38,4 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -120,6 +120,10 @@
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj">
|
||||
<Project>{92d98d3d-2a7d-4f4b-8c72-1a98908d0221}</Project>
|
||||
<Name>Opc.Ua.Bindings.Https</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj">
|
||||
<Project>{4569aaa2-710b-4e8b-a4c6-f917777814da}</Project>
|
||||
<Name>Opc.Ua.Core</Name>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IdentityModel" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
@@ -134,6 +135,10 @@
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj">
|
||||
<Project>{92d98d3d-2a7d-4f4b-8c72-1a98908d0221}</Project>
|
||||
<Name>Opc.Ua.Bindings.Https</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj">
|
||||
<Project>{4569aaa2-710b-4e8b-a4c6-f917777814da}</Project>
|
||||
<Name>Opc.Ua.Core</Name>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<Reference Include="System.Reflection" />
|
||||
<Reference Include="System.Numerics" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<Reference Include="System.IdentityModel" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if SIGNASSEMBLY
|
||||
[assembly: InternalsVisibleTo("Opc.Ua.Client.Tests, PublicKey = " +
|
||||
// OPC Foundation Strong Name Public Key
|
||||
"0024000004800000940000000602000000240000525341310004000001000100d987b12f068b35" +
|
||||
"80429f3dde01397508880fc7e62621397618456ca1549aeacfbdb90c62adfe918f05ce3677b390" +
|
||||
"f78357b8745cb6e1334655afce1a9527ac92fc829ff585ea79f007e52ba0f83ead627e3edda40b" +
|
||||
"ec5ae574128fc9342cb57cb8285aa4e5b589c0ebef3be571b5c8f2ab1067f7c880e8f8882a73c8" +
|
||||
"0a12a1ef")]
|
||||
#else
|
||||
[assembly: InternalsVisibleTo("Opc.Ua.Client.Tests")]
|
||||
#endif
|
||||
@@ -16,17 +16,9 @@
|
||||
<PackageId>$(PackageId).Debug</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants Condition=" '$(NoHttps)' == 'true' ">$(DefineConstants);NO_HTTPS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<Reference Include="System.IdentityModel" />
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if SIGNASSEMBLY
|
||||
[assembly: InternalsVisibleTo("Opc.Ua.Server.Tests, PublicKey = " +
|
||||
// OPC Foundation Strong Name Public Key
|
||||
"0024000004800000940000000602000000240000525341310004000001000100d987b12f068b35" +
|
||||
"80429f3dde01397508880fc7e62621397618456ca1549aeacfbdb90c62adfe918f05ce3677b390" +
|
||||
"f78357b8745cb6e1334655afce1a9527ac92fc829ff585ea79f007e52ba0f83ead627e3edda40b" +
|
||||
"ec5ae574128fc9342cb57cb8285aa4e5b589c0ebef3be571b5c8f2ab1067f7c880e8f8882a73c8" +
|
||||
"0a12a1ef")]
|
||||
#else
|
||||
[assembly: InternalsVisibleTo("Opc.Ua.Server.Tests")]
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);NET_STANDARD</DefineConstants>
|
||||
<TargetFrameworks>$(LibTargetFrameworks)</TargetFrameworks>
|
||||
<LangVersion>6</LangVersion>
|
||||
<AssemblyName>Opc.Ua.Bindings.Https</AssemblyName>
|
||||
<PackageId>OPCFoundation.NetStandard.Opc.Ua.Bindings.Https</PackageId>
|
||||
<RootNamespace>Opc.Ua.Bindings</RootNamespace>
|
||||
<Description>OPC UA Https Binding Library</Description>
|
||||
<IsPackable>true</IsPackable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<PackageId>$(PackageId).Debug</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(SignAssembly)' == 'true'">
|
||||
<DefineConstants>$(DefineConstants);SIGNASSEMBLY</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="GetPackagingOutputs" />
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if SIGNASSEMBLY
|
||||
[assembly: InternalsVisibleTo("Opc.Ua.Core.Tests, PublicKey = " +
|
||||
// OPC Foundation Strong Name Public Key
|
||||
"0024000004800000940000000602000000240000525341310004000001000100d987b12f068b35" +
|
||||
"80429f3dde01397508880fc7e62621397618456ca1549aeacfbdb90c62adfe918f05ce3677b390" +
|
||||
"f78357b8745cb6e1334655afce1a9527ac92fc829ff585ea79f007e52ba0f83ead627e3edda40b" +
|
||||
"ec5ae574128fc9342cb57cb8285aa4e5b589c0ebef3be571b5c8f2ab1067f7c880e8f8882a73c8" +
|
||||
"0a12a1ef")]
|
||||
#else
|
||||
[assembly: InternalsVisibleTo("Opc.Ua.Core.Tests")]
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
/* ========================================================================
|
||||
* Copyright (c) 2005-2020 The OPC Foundation, Inc. All rights reserved.
|
||||
*
|
||||
* OPC Reciprocal Community License ("RCL") Version 1.00
|
||||
*
|
||||
* Unless explicitly acquired and licensed from Licensor under another
|
||||
* license, the contents of this file are subject to the Reciprocal
|
||||
* Community License ("RCL") Version 1.00, or subsequent versions
|
||||
* as allowed by the RCL, and You may not copy or use this file in either
|
||||
* source code or executable form, except in compliance with the terms and
|
||||
* conditions of the RCL.
|
||||
*
|
||||
* All software distributed under the RCL is provided strictly on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
* AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the RCL for specific
|
||||
* language governing rights and limitations under the RCL.
|
||||
*
|
||||
* The complete license agreement can be found here:
|
||||
* http://opcfoundation.org/License/RCL/1.00/
|
||||
* ======================================================================*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="HttpsTransportListener"/> with
|
||||
/// <see cref="ITransportListener"/> interface.
|
||||
/// </summary>
|
||||
public abstract class HttpsServiceHost : ITransportListenerFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The protocol supported by the listener.
|
||||
/// </summary>
|
||||
public abstract string UriScheme { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The method creates a new instance of a <see cref="HttpsTransportListener"/>.
|
||||
/// </summary>
|
||||
/// <returns>The transport listener.</returns>
|
||||
public abstract ITransportListener Create();
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>
|
||||
/// Create a new service host for UA HTTPS.
|
||||
/// </summary>
|
||||
public List<EndpointDescription> CreateServiceHost(
|
||||
ServerBase serverBase,
|
||||
IDictionary<string, Task> hosts,
|
||||
ApplicationConfiguration configuration,
|
||||
IList<string> baseAddresses,
|
||||
ApplicationDescription serverDescription,
|
||||
List<ServerSecurityPolicy> securityPolicies,
|
||||
X509Certificate2 instanceCertificate,
|
||||
X509Certificate2Collection instanceCertificateChain
|
||||
)
|
||||
{
|
||||
// generate a unique host name.
|
||||
string hostName = String.Empty;
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
{
|
||||
hostName = "/Https";
|
||||
}
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
{
|
||||
hostName += Utils.Format("/{0}", hosts.Count);
|
||||
}
|
||||
|
||||
// build list of uris.
|
||||
List<Uri> uris = new List<Uri>();
|
||||
EndpointDescriptionCollection endpoints = new EndpointDescriptionCollection();
|
||||
|
||||
// create the endpoint configuration to use.
|
||||
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
|
||||
string computerName = Utils.GetHostName();
|
||||
|
||||
for (int ii = 0; ii < baseAddresses.Count; ii++)
|
||||
{
|
||||
if (!baseAddresses[ii].StartsWith(Utils.UriSchemeHttps, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
UriBuilder uri = new UriBuilder(baseAddresses[ii]);
|
||||
|
||||
if (uri.Path[uri.Path.Length - 1] != '/')
|
||||
{
|
||||
uri.Path += "/";
|
||||
}
|
||||
|
||||
if (String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
uri.Host = computerName;
|
||||
}
|
||||
|
||||
uris.Add(uri.Uri);
|
||||
|
||||
if (uri.Scheme == Utils.UriSchemeHttps)
|
||||
{
|
||||
// Can only support one policy with HTTPS
|
||||
// So pick the first policy with security mode sign and encrypt
|
||||
ServerSecurityPolicy bestPolicy = null;
|
||||
foreach (ServerSecurityPolicy policy in securityPolicies)
|
||||
{
|
||||
if (policy.SecurityMode != MessageSecurityMode.SignAndEncrypt)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bestPolicy = policy;
|
||||
break;
|
||||
}
|
||||
|
||||
// Pick the first policy from the list if no policies with sign and encrypt defined
|
||||
if (bestPolicy == null)
|
||||
{
|
||||
bestPolicy = securityPolicies[0];
|
||||
}
|
||||
|
||||
EndpointDescription description = new EndpointDescription();
|
||||
|
||||
description.EndpointUrl = uri.ToString();
|
||||
description.Server = serverDescription;
|
||||
|
||||
if (instanceCertificate != null)
|
||||
{
|
||||
description.ServerCertificate = instanceCertificate.RawData;
|
||||
// check if complete chain should be sent.
|
||||
if (configuration.SecurityConfiguration.SendCertificateChain &&
|
||||
instanceCertificateChain != null &&
|
||||
instanceCertificateChain.Count > 0)
|
||||
{
|
||||
List<byte> serverCertificateChain = new List<byte>();
|
||||
|
||||
for (int i = 0; i < instanceCertificateChain.Count; i++)
|
||||
{
|
||||
serverCertificateChain.AddRange(instanceCertificateChain[i].RawData);
|
||||
}
|
||||
|
||||
description.ServerCertificate = serverCertificateChain.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
description.SecurityMode = bestPolicy.SecurityMode;
|
||||
description.SecurityPolicyUri = bestPolicy.SecurityPolicyUri;
|
||||
description.SecurityLevel = ServerSecurityPolicy.CalculateSecurityLevel(bestPolicy.SecurityMode, bestPolicy.SecurityPolicyUri);
|
||||
description.UserIdentityTokens = serverBase.GetUserTokenPolicies(configuration, description);
|
||||
description.TransportProfileUri = Profiles.HttpsBinaryTransport;
|
||||
|
||||
ITransportListener listener = Create();
|
||||
if (listener != null)
|
||||
{
|
||||
endpoints.Add(description);
|
||||
serverBase.CreateServiceHostEndpoint(uri.Uri, endpoints, endpointConfiguration, listener,
|
||||
configuration.CertificateValidator.GetChannelValidator());
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Error, "Failed to create endpoint {0} because the transport profile is unsupported.", uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
-43
@@ -11,18 +11,36 @@
|
||||
*/
|
||||
|
||||
|
||||
#if !NO_HTTPS
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new HttpsTransportChannel with ITransportChannel interface.
|
||||
/// </summary>
|
||||
public class HttpsTransportChannelFactory : ITransportChannelFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The protocol supported by the channel.
|
||||
/// </summary>
|
||||
public string UriScheme => Utils.UriSchemeHttps;
|
||||
|
||||
/// <summary>
|
||||
/// The method creates a new instance of a Https transport channel
|
||||
/// </summary>
|
||||
/// <returns>The transport channel</returns>
|
||||
public ITransportChannel Create()
|
||||
{
|
||||
return new HttpsTransportChannel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the HttpsTransportChannel and provides an ITransportChannel implementation.
|
||||
/// </summary>
|
||||
@@ -34,34 +52,22 @@ namespace Opc.Ua.Bindings
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TransportChannelFeatures SupportedFeatures
|
||||
{
|
||||
get { return TransportChannelFeatures.Open | TransportChannelFeatures.Reconnect | TransportChannelFeatures.BeginSendRequest; }
|
||||
}
|
||||
public string UriScheme => Utils.UriSchemeHttps;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public EndpointDescription EndpointDescription
|
||||
{
|
||||
get { return m_settings.Description; }
|
||||
}
|
||||
public TransportChannelFeatures SupportedFeatures => TransportChannelFeatures.Open | TransportChannelFeatures.Reconnect | TransportChannelFeatures.BeginSendRequest;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public EndpointConfiguration EndpointConfiguration
|
||||
{
|
||||
get { return m_settings.Configuration; }
|
||||
}
|
||||
public EndpointDescription EndpointDescription => m_settings.Description;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ServiceMessageContext MessageContext
|
||||
{
|
||||
get { return m_quotas.MessageContext; }
|
||||
}
|
||||
public EndpointConfiguration EndpointConfiguration => m_settings.Configuration;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ChannelToken CurrentToken
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
public ServiceMessageContext MessageContext => m_quotas.MessageContext;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ChannelToken CurrentToken => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int OperationTimeout
|
||||
@@ -114,8 +120,7 @@ namespace Opc.Ua.Bindings
|
||||
try
|
||||
{
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(httpRequestMessage, cert, chain, policyErrors) =>
|
||||
{
|
||||
(httpRequestMessage, cert, chain, policyErrors) => {
|
||||
try
|
||||
{
|
||||
m_quotas.CertificateValidator?.Validate(cert);
|
||||
@@ -187,22 +192,21 @@ namespace Opc.Ua.Bindings
|
||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
|
||||
AsyncResult result = new AsyncResult(callback, callbackData, m_operationTimeout, request, null);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
response = await m_client.PostAsync(m_url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Utils.Trace("Exception sending HTTPS request: " + ex.Message);
|
||||
result.Exception = ex;
|
||||
response = null;
|
||||
}
|
||||
result.Response = response;
|
||||
result.OperationCompleted();
|
||||
});
|
||||
Task.Run(async () => {
|
||||
try
|
||||
{
|
||||
response = await m_client.PostAsync(m_url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Utils.Trace("Exception sending HTTPS request: " + ex.Message);
|
||||
result.Exception = ex;
|
||||
response = null;
|
||||
}
|
||||
result.Response = response;
|
||||
result.OperationCompleted();
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -345,4 +349,4 @@ namespace Opc.Ua.Bindings
|
||||
private HttpClient m_client;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+26
-9
@@ -21,8 +21,6 @@
|
||||
* http://opcfoundation.org/License/RCL/1.00/
|
||||
* ======================================================================*/
|
||||
|
||||
#if !NO_HTTPS
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
@@ -38,14 +36,35 @@ using Microsoft.AspNetCore.Server.Kestrel.Https;
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the startup of the Https listener.
|
||||
/// Creates a new <see cref="HttpsTransportListener"/> with
|
||||
/// <see cref="ITransportListener"/> interface.
|
||||
/// </summary>
|
||||
public class HttpsTransportListenerFactory : HttpsServiceHost
|
||||
{
|
||||
/// <summary>
|
||||
/// The protocol supported by the listener.
|
||||
/// </summary>
|
||||
public override string UriScheme => Utils.UriSchemeHttps;
|
||||
|
||||
/// <summary>
|
||||
/// The method creates a new instance of a <see cref="HttpsTransportListener"/>.
|
||||
/// </summary>
|
||||
/// <returns>The transport listener.</returns>
|
||||
public override ITransportListener Create()
|
||||
{
|
||||
return new HttpsTransportListener();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the kestrel startup of the Https listener.
|
||||
/// </summary>
|
||||
public class Startup
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the Https listener.
|
||||
/// </summary>
|
||||
public static UaHttpsChannelListener Listener { get; set; }
|
||||
public static HttpsTransportListener Listener { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configure the request pipeline for the listener.
|
||||
@@ -72,13 +91,13 @@ namespace Opc.Ua.Bindings
|
||||
/// <summary>
|
||||
/// Manages the connections for a UA HTTPS server.
|
||||
/// </summary>
|
||||
public partial class UaHttpsChannelListener : ITransportListener
|
||||
public class HttpsTransportListener : ITransportListener
|
||||
{
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UaHttpsChannelListener"/> class.
|
||||
/// Initializes a new instance of the <see cref="HttpsTransportListener"/> class.
|
||||
/// </summary>
|
||||
public UaHttpsChannelListener()
|
||||
public HttpsTransportListener()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
@@ -381,5 +400,3 @@ namespace Opc.Ua.Bindings
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,7 @@
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The <b>Opc.Ua.Bindings</b> namespace contains classes that implement the WCF bindings for the
|
||||
/// The <b>Opc.Ua.Bindings</b> namespace contains classes that implement the bindings for the
|
||||
/// mappings described in Part 6 of the UA specification. It also includes an implementation for
|
||||
/// the UA TCP protocol.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
<PackageId>$(PackageId).Debug</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants Condition=" '$(NoHttps)' == 'true' ">$(DefineConstants);NO_HTTPS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(SignAssembly)' == 'true'">
|
||||
<DefineConstants>$(DefineConstants);SIGNASSEMBLY</DefineConstants>
|
||||
</PropertyGroup>
|
||||
@@ -47,33 +43,20 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<Reference Include="System.IdentityModel" />
|
||||
<Reference Include="System.IdentityModel.Selectors" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(DefineConstants.Contains('NO_HTTPS'))=='false'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<PackageReference Include="System.Data.Common" Version="4.3.0" />
|
||||
<PackageReference Include="System.ServiceModel.Primitives" Version="4.5.3" />
|
||||
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
|
||||
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.4.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
|
||||
<PackageReference Include="System.Data.Common" Version="4.3.0" />
|
||||
<PackageReference Include="System.ServiceModel.Primitives" Version="4.7.0" />
|
||||
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
|
||||
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -102,7 +102,12 @@ namespace Opc.Ua
|
||||
/// Communicates with UA TCP, UA Security and UA Binary.
|
||||
/// </summary>
|
||||
public const string UaTcpTransport = "http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Communicates with UA TCP over secure Websockets, UA Security and UA Binary.
|
||||
/// </summary>
|
||||
public const string UaWssTransport = "http://opcfoundation.org/UA-Profile/Transport/uawss-uasc-uabinary";
|
||||
|
||||
/// <summary>
|
||||
/// Communicates with UA Binary over HTTPS.
|
||||
/// </summary>
|
||||
|
||||
@@ -10,14 +10,12 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System.ServiceModel.Channels;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The binding for the UA native stack
|
||||
/// </summary>
|
||||
public abstract class BaseBinding : Binding
|
||||
public abstract class BaseBinding
|
||||
{
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an interface to the scheme of a transport binding.
|
||||
/// </summary>
|
||||
public interface ITransportBindingScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// The protocol scheme supported by the binding.
|
||||
/// </summary>
|
||||
string UriScheme { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is an interface to the factory of a transport binding.
|
||||
/// </summary>
|
||||
public interface ITransportBindingFactory<T>
|
||||
: ITransportBindingScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// The factory to create a new transport.
|
||||
/// </summary>
|
||||
/// <returns>The transport.</returns>
|
||||
T Create();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The interface to manage transport bindings.
|
||||
/// </summary>
|
||||
public interface ITransportBindings<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Get a transport binding for a uri scheme.
|
||||
/// </summary>
|
||||
/// <param name="uriScheme">The uri scheme.</param>
|
||||
T GetBinding(string uriScheme);
|
||||
|
||||
/// <summary>
|
||||
/// Return if there is a transport listener for a uri scheme.
|
||||
/// </summary>
|
||||
/// <param name="uriScheme">The uri scheme.</param>
|
||||
bool HasBinding(string uriScheme);
|
||||
|
||||
/// <summary>
|
||||
/// Set the transport factory to the binding.
|
||||
/// Overrides other bindings with the same uri scheme.
|
||||
/// </summary>
|
||||
void SetBinding(T binding);
|
||||
|
||||
/// <summary>
|
||||
/// Add all bindings with interface <see cref="T"/> exported from a assembly.
|
||||
/// </summary>
|
||||
/// <param name="assembly">The assembly with the bindings.</param>
|
||||
IEnumerable<Type> AddBindings(Assembly assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Add all bindings with interface <see cref="T"/> from a list.
|
||||
/// </summary>
|
||||
/// <param name="bindings">The array of binding types with interface <see cref="T"/>.</param>
|
||||
IEnumerable<Type> AddBindings(IEnumerable<Type> bindings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the transport listener factory interface for a binding (server).
|
||||
/// </summary>
|
||||
public interface ITransportListenerFactory :
|
||||
ITransportBindingFactory<ITransportListener>
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the service host for a server using <see cref="ServerBase"/>
|
||||
/// </summary>
|
||||
/// <param name="serverBase">The server base.</param>
|
||||
/// <param name="hosts">The service hosts are added to this list.</param>
|
||||
/// <param name="configuration">The application configuration.</param>
|
||||
/// <param name="baseAddresses">The base addreses for the service host.</param>
|
||||
/// <param name="serverDescription">The server description.</param>
|
||||
/// <param name="securityPolicies">The list of supported security policies.</param>
|
||||
/// <param name="instanceCertificate">The server certificate.</param>
|
||||
/// <param name="instanceCertificateChain">The cert cahin of the server certificate.</param>
|
||||
List<EndpointDescription> CreateServiceHost(
|
||||
ServerBase serverBase,
|
||||
IDictionary<string, Task> hosts,
|
||||
ApplicationConfiguration configuration,
|
||||
IList<string> baseAddresses,
|
||||
ApplicationDescription serverDescription,
|
||||
List<ServerSecurityPolicy> securityPolicies,
|
||||
X509Certificate2 instanceCertificate,
|
||||
X509Certificate2Collection instanceCertificateChain
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the transport channel factory interface for a binding (client).
|
||||
/// </summary>
|
||||
public interface ITransportChannelFactory :
|
||||
ITransportBindingFactory<ITransportChannel>
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The transpaort bindings available for teh stack.
|
||||
/// </summary>
|
||||
public static class TransportBindings
|
||||
{
|
||||
static TransportBindings()
|
||||
{
|
||||
Channels = new TransportChannelBindings(new Type[] { typeof(TcpTransportChannelFactory) });
|
||||
Listeners = new TransportListenerBindings(new Type[] { typeof(TcpTransportListenerFactory) });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The bindings for transport channels (client).
|
||||
/// </summary>
|
||||
public static TransportChannelBindings Channels { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The bindings for transport listeners (server).
|
||||
/// </summary>
|
||||
public static TransportListenerBindings Listeners { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The bindings for the transport channels.
|
||||
/// </summary>
|
||||
public class TransportChannelBindings :
|
||||
TransportBindingsBase<ITransportChannelFactory>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize the transport listener.
|
||||
/// </summary>
|
||||
/// <param name="defaultBindings">List of known default bindings.</param>
|
||||
public TransportChannelBindings(Type[] defaultBindings) : base(defaultBindings)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a transport channel for the specified uri scheme.
|
||||
/// </summary>
|
||||
/// <param name="uriScheme">The uri scheme of the transport.</param>
|
||||
public ITransportChannel GetChannel(string uriScheme)
|
||||
{
|
||||
var binding = GetBinding(uriScheme);
|
||||
return binding?.Create();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The bindings for the transport listeners.
|
||||
/// </summary>
|
||||
public class TransportListenerBindings :
|
||||
TransportBindingsBase<ITransportListenerFactory>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize the transport listener.
|
||||
/// </summary>
|
||||
/// <param name="defaultBindings">List of known default bindings.</param>
|
||||
public TransportListenerBindings(Type[] defaultBindings) : base(defaultBindings)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a transport listener for the specified uri scheme.
|
||||
/// </summary>
|
||||
/// <param name="uriScheme">The uri scheme of the transport.</param>
|
||||
public ITransportListener GetListener(string uriScheme)
|
||||
{
|
||||
var binding = GetBinding(uriScheme);
|
||||
return binding?.Create();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The bindings for the transport listeners.
|
||||
/// </summary>
|
||||
public class TransportBindingsBase<T> :
|
||||
ITransportBindings<T> where T : class, ITransportBindingScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// Implement the default constructor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default constructor adds all interfaces T.
|
||||
/// </remarks>
|
||||
protected TransportBindingsBase()
|
||||
{
|
||||
Bindings = new Dictionary<string, T>();
|
||||
AddBindings(typeof(TransportBindingsBase<T>).Assembly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize object with default list of bindings.
|
||||
/// </summary>
|
||||
protected TransportBindingsBase(Type[] defaultBindings)
|
||||
{
|
||||
Bindings = new Dictionary<string, T>();
|
||||
AddBindings(defaultBindings);
|
||||
}
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Dictionary of bindings of type <see cref="T"/>.
|
||||
/// </summary>
|
||||
protected Dictionary<string, T> Bindings { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region ITransportBindings
|
||||
/// <inheritdoc/>
|
||||
public T GetBinding(string uriScheme)
|
||||
{
|
||||
T binding;
|
||||
if (!Bindings.TryGetValue(uriScheme, out binding))
|
||||
{
|
||||
TryAddDefaultTransportBindings(uriScheme);
|
||||
if (!Bindings.TryGetValue(uriScheme, out binding))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool HasBinding(string uriScheme)
|
||||
{
|
||||
T binding;
|
||||
if (Bindings.TryGetValue(uriScheme, out binding))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetBinding(T binding)
|
||||
{
|
||||
Bindings[binding.UriScheme] = binding;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<Type> AddBindings(Assembly assembly)
|
||||
{
|
||||
var bindings = assembly.GetExportedTypes().Where(type => IsBindingType(type));
|
||||
return AddBindings(bindings);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<Type> AddBindings(IEnumerable<Type> bindings)
|
||||
{
|
||||
var result = new List<Type>();
|
||||
foreach (Type bindingType in bindings)
|
||||
{
|
||||
var binding = Activator.CreateInstance(bindingType) as T;
|
||||
if (binding != null)
|
||||
{
|
||||
Bindings[binding.UriScheme] = binding;
|
||||
result.Add(bindingType);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Validate the type is a transport listener.
|
||||
/// </summary>
|
||||
protected static bool IsBindingType(System.Type bindingType)
|
||||
{
|
||||
if (bindingType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var bindingTypeInfo = bindingType.GetTypeInfo();
|
||||
if (bindingTypeInfo.IsAbstract ||
|
||||
!typeof(T).GetTypeInfo().IsAssignableFrom(bindingTypeInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var listener = Activator.CreateInstance(bindingType) as T;
|
||||
if (listener == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to load a binding from well known assemblies at runtime.
|
||||
/// </summary>
|
||||
/// <param name="scheme">The uri scheme of the binding.</param>
|
||||
private bool TryAddDefaultTransportBindings(string scheme)
|
||||
{
|
||||
string assemblyName;
|
||||
if (Utils.DefaultBindings.TryGetValue(scheme, out assemblyName))
|
||||
{
|
||||
Assembly assembly = null;
|
||||
string fullName = Utils.DefaultOpcUaCoreAssemblyFullName.Replace(Utils.DefaultOpcUaCoreAssemblyName, assemblyName);
|
||||
try
|
||||
{
|
||||
assembly = Assembly.Load(fullName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Error, "Failed to load the assembly {0} for transport binding {1}.",
|
||||
fullName, scheme
|
||||
);
|
||||
}
|
||||
|
||||
if (assembly != null)
|
||||
{
|
||||
var listeners = AddBindings(assembly);
|
||||
return listeners.Count() > 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Error, "The transport binding {0} is unsupported.", scheme);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// The binding for the transport listeners.
|
||||
/// </summary>
|
||||
public static class TransportListenerBindings
|
||||
{
|
||||
static TransportListenerBindings()
|
||||
{
|
||||
TransportListeners = new Dictionary<string, Type>();
|
||||
var listeners = typeof(TransportListenerBindings).Assembly.GetExportedTypes().Where(type => IsTransportListenerType(type));
|
||||
foreach (var listenerType in listeners)
|
||||
{
|
||||
Add(listenerType);
|
||||
}
|
||||
}
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Dictionary of transported listeners.
|
||||
/// </summary>
|
||||
public static Dictionary<string, Type> TransportListeners { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a transport listener for a uri scheme.
|
||||
/// </summary>
|
||||
/// <param name="uriScheme">The uri scheme.</param>
|
||||
public static ITransportListener GetTransportListener(string uriScheme)
|
||||
{
|
||||
Type listenerType;
|
||||
if (TransportListeners.TryGetValue(uriScheme, out listenerType))
|
||||
{
|
||||
return Activator.CreateInstance(listenerType) as ITransportListener;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a transport listener to the binding.
|
||||
/// </summary>
|
||||
public static void Add(Type listenerType)
|
||||
{
|
||||
if (IsTransportListenerType(listenerType))
|
||||
{
|
||||
var listener = Activator.CreateInstance(listenerType) as ITransportListener;
|
||||
TransportListeners.Add(listener.UriScheme, listenerType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate the type is a transport listener.
|
||||
/// </summary>
|
||||
private static bool IsTransportListenerType(System.Type systemType)
|
||||
{
|
||||
if (systemType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var systemTypeInfo = systemType.GetTypeInfo();
|
||||
if (systemTypeInfo.IsAbstract ||
|
||||
!typeof(ITransportListener).GetTypeInfo().IsAssignableFrom(systemTypeInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var listener = Activator.CreateInstance(systemType) as ITransportListener;
|
||||
if (listener == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
listener.Dispose();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,13 @@ namespace Opc.Ua
|
||||
{
|
||||
if (url == null) throw new ArgumentNullException(nameof(url));
|
||||
|
||||
var listener = TransportListenerBindings.GetTransportListener(url.Scheme);
|
||||
|
||||
if (listener == null) throw new ArgumentException(nameof(url), "No suitable listener found.");
|
||||
var listener = TransportBindings.Listeners.GetListener(url.Scheme);
|
||||
if (listener == null)
|
||||
{
|
||||
throw ServiceResultException.Create(
|
||||
StatusCodes.BadProtocolVersionUnsupported,
|
||||
"Unsupported transport profile for scheme {0}\r\n", url.Scheme);
|
||||
}
|
||||
|
||||
m_listener = listener;
|
||||
Url = url;
|
||||
|
||||
@@ -692,28 +692,14 @@ namespace Opc.Ua
|
||||
X509Certificate2Collection clientCertificateChain,
|
||||
ServiceMessageContext messageContext)
|
||||
{
|
||||
bool useUaTcp = description.EndpointUrl.StartsWith(Utils.UriSchemeOpcTcp);
|
||||
bool useHttps = description.EndpointUrl.StartsWith(Utils.UriSchemeHttps);
|
||||
|
||||
// initialize the channel which will be created with the server.
|
||||
ITransportChannel channel = null;
|
||||
|
||||
if (useUaTcp)
|
||||
{
|
||||
channel = new TcpTransportChannel();
|
||||
}
|
||||
#if !NO_HTTPS
|
||||
else if (useHttps)
|
||||
{
|
||||
channel = new HttpsTransportChannel();
|
||||
}
|
||||
#endif
|
||||
|
||||
string uriScheme = new Uri(description.EndpointUrl).Scheme;
|
||||
ITransportChannel channel = TransportBindings.Channels.GetChannel(uriScheme);
|
||||
if (channel == null)
|
||||
{
|
||||
throw ServiceResultException.Create(
|
||||
StatusCodes.BadProtocolVersionUnsupported,
|
||||
"Unsupported transport profile\r\n");
|
||||
"Unsupported transport profile for scheme {0}\r\n", uriScheme);
|
||||
}
|
||||
|
||||
// create a UA channel.
|
||||
@@ -780,42 +766,37 @@ namespace Opc.Ua
|
||||
X509Certificate2Collection clientCertificateChain,
|
||||
ServiceMessageContext messageContext)
|
||||
{
|
||||
bool useUaTcp = description.EndpointUrl.StartsWith(Utils.UriSchemeOpcTcp);
|
||||
bool useHttps = description.EndpointUrl.StartsWith(Utils.UriSchemeHttps);
|
||||
string uriScheme = new Uri(description.EndpointUrl).Scheme;
|
||||
|
||||
switch (description.TransportProfileUri)
|
||||
{
|
||||
case Profiles.UaTcpTransport:
|
||||
{
|
||||
useUaTcp = true;
|
||||
uriScheme = Utils.UriSchemeOpcTcp;
|
||||
break;
|
||||
}
|
||||
|
||||
case Profiles.HttpsBinaryTransport:
|
||||
{
|
||||
useHttps = true;
|
||||
uriScheme = Utils.UriSchemeHttps;
|
||||
break;
|
||||
}
|
||||
|
||||
case Profiles.UaWssTransport:
|
||||
{
|
||||
uriScheme = Utils.UriSchemeOpcWss;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// initialize the channel which will be created with the server.
|
||||
ITransportChannel channel = null;
|
||||
if (useUaTcp)
|
||||
{
|
||||
channel = new TcpTransportChannel();
|
||||
}
|
||||
#if !NO_HTTPS
|
||||
else if (useHttps)
|
||||
{
|
||||
channel = new HttpsTransportChannel();
|
||||
}
|
||||
#endif
|
||||
|
||||
ITransportChannel channel = TransportBindings.Channels.GetChannel(uriScheme);
|
||||
if (channel == null)
|
||||
{
|
||||
throw ServiceResultException.Create(
|
||||
StatusCodes.BadProtocolVersionUnsupported,
|
||||
"Unsupported transport profile\r\n");
|
||||
"Unsupported transport profile for scheme {0}\r\n", uriScheme);
|
||||
}
|
||||
|
||||
// create a UA-TCP channel.
|
||||
|
||||
@@ -699,282 +699,60 @@ namespace Opc.Ua
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new service host for UA TCP.
|
||||
/// Create the transport listener for the service host endpoint.
|
||||
/// </summary>
|
||||
protected List<EndpointDescription> CreateUaTcpServiceHost(
|
||||
IDictionary<string, Task> hosts,
|
||||
ApplicationConfiguration configuration,
|
||||
IList<string> baseAddresses,
|
||||
ApplicationDescription serverDescription,
|
||||
List<ServerSecurityPolicy> securityPolicies)
|
||||
/// <param name="endpointUri">The endpoint Uri.</param>
|
||||
/// <param name="endpoints">The description of the endpoints.</param>
|
||||
/// <param name="endpointConfiguration">The configuration of the endpoints.</param>
|
||||
/// <param name="listener">The transport listener.</param>
|
||||
/// <param name="certificateValidator">The certificate validator for the transport.</param>
|
||||
public virtual void CreateServiceHostEndpoint(
|
||||
Uri endpointUri,
|
||||
EndpointDescriptionCollection endpoints,
|
||||
EndpointConfiguration endpointConfiguration,
|
||||
ITransportListener listener,
|
||||
ICertificateValidator certificateValidator
|
||||
)
|
||||
{
|
||||
// generate a unique host name.
|
||||
string hostName = String.Empty;
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
// create the stack listener.
|
||||
try
|
||||
{
|
||||
hostName = "/Tcp";
|
||||
}
|
||||
TransportListenerSettings settings = new TransportListenerSettings();
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
settings.Descriptions = endpoints;
|
||||
settings.Configuration = endpointConfiguration;
|
||||
settings.ServerCertificate = InstanceCertificate;
|
||||
settings.CertificateValidator = certificateValidator;
|
||||
settings.NamespaceUris = MessageContext.NamespaceUris;
|
||||
settings.Factory = MessageContext.Factory;
|
||||
|
||||
listener.Open(
|
||||
endpointUri,
|
||||
settings,
|
||||
GetEndpointInstance(this));
|
||||
|
||||
TransportListeners.Add(listener);
|
||||
|
||||
listener.ConnectionStatusChanged += OnConnectionStatusChanged;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
hostName += Utils.Format("/{0}", hosts.Count);
|
||||
string message = $"Could not load {endpointUri.Scheme} Stack Listener.";
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
message += (" " + e.InnerException.Message);
|
||||
}
|
||||
Utils.Trace(e, message);
|
||||
}
|
||||
|
||||
// build list of uris.
|
||||
List<Uri> uris = new List<Uri>();
|
||||
EndpointDescriptionCollection endpoints = new EndpointDescriptionCollection();
|
||||
|
||||
// create the endpoint configuration to use.
|
||||
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
|
||||
string computerName = Utils.GetHostName();
|
||||
|
||||
for (int ii = 0; ii < baseAddresses.Count; ii++)
|
||||
{
|
||||
// UA TCP and HTTPS endpoints support multiple policies.
|
||||
if (!baseAddresses[ii].StartsWith(Utils.UriSchemeOpcTcp, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
UriBuilder uri = new UriBuilder(baseAddresses[ii]);
|
||||
|
||||
if (String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
uri.Host = computerName;
|
||||
}
|
||||
|
||||
uris.Add(uri.Uri);
|
||||
|
||||
foreach (ServerSecurityPolicy policy in securityPolicies)
|
||||
{
|
||||
// create the endpoint description.
|
||||
EndpointDescription description = new EndpointDescription();
|
||||
|
||||
description.EndpointUrl = uri.ToString();
|
||||
description.Server = serverDescription;
|
||||
|
||||
description.SecurityMode = policy.SecurityMode;
|
||||
description.SecurityPolicyUri = policy.SecurityPolicyUri;
|
||||
description.SecurityLevel = ServerSecurityPolicy.CalculateSecurityLevel(policy.SecurityMode, policy.SecurityPolicyUri);
|
||||
description.UserIdentityTokens = GetUserTokenPolicies(configuration, description);
|
||||
description.TransportProfileUri = Profiles.UaTcpTransport;
|
||||
|
||||
bool requireEncryption = RequireEncryption(description);
|
||||
|
||||
if (requireEncryption)
|
||||
{
|
||||
description.ServerCertificate = InstanceCertificate.RawData;
|
||||
|
||||
// check if complete chain should be sent.
|
||||
if (configuration.SecurityConfiguration.SendCertificateChain &&
|
||||
InstanceCertificateChain != null &&
|
||||
InstanceCertificateChain.Count > 0)
|
||||
{
|
||||
List<byte> serverCertificateChain = new List<byte>();
|
||||
|
||||
for (int i = 0; i < InstanceCertificateChain.Count; i++)
|
||||
{
|
||||
serverCertificateChain.AddRange(InstanceCertificateChain[i].RawData);
|
||||
}
|
||||
|
||||
description.ServerCertificate = serverCertificateChain.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
endpoints.Add(description);
|
||||
}
|
||||
|
||||
// create the UA-TCP stack listener.
|
||||
try
|
||||
{
|
||||
TransportListenerSettings settings = new TransportListenerSettings();
|
||||
|
||||
settings.Descriptions = endpoints;
|
||||
settings.Configuration = endpointConfiguration;
|
||||
settings.CertificateValidator = configuration.CertificateValidator.GetChannelValidator();
|
||||
settings.NamespaceUris = this.MessageContext.NamespaceUris;
|
||||
settings.Factory = this.MessageContext.Factory;
|
||||
settings.ServerCertificate = this.InstanceCertificate;
|
||||
|
||||
if (configuration.SecurityConfiguration.SendCertificateChain)
|
||||
{
|
||||
settings.ServerCertificateChain = this.InstanceCertificateChain;
|
||||
}
|
||||
|
||||
ITransportListener listener = new Opc.Ua.Bindings.TcpListener();
|
||||
|
||||
listener.Open(
|
||||
uri.Uri,
|
||||
settings,
|
||||
GetEndpointInstance(this));
|
||||
|
||||
TransportListeners.Add(listener);
|
||||
|
||||
listener.ConnectionStatusChanged += OnConnectionStatusChanged;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Trace(e, "Could not load UA-TCP Stack Listener.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
#if !NO_HTTPS
|
||||
/// <summary>
|
||||
/// Create a new service host for UA HTTPS.
|
||||
/// </summary>
|
||||
protected List<EndpointDescription> CreateHttpsServiceHost(
|
||||
IDictionary<string, Task> hosts,
|
||||
ApplicationConfiguration configuration,
|
||||
IList<string> baseAddresses,
|
||||
ApplicationDescription serverDescription,
|
||||
List<ServerSecurityPolicy> securityPolicies)
|
||||
{
|
||||
// generate a unique host name.
|
||||
string hostName = String.Empty;
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
{
|
||||
hostName = "/Https";
|
||||
}
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
{
|
||||
hostName += Utils.Format("/{0}", hosts.Count);
|
||||
}
|
||||
|
||||
// build list of uris.
|
||||
List<Uri> uris = new List<Uri>();
|
||||
EndpointDescriptionCollection endpoints = new EndpointDescriptionCollection();
|
||||
|
||||
// create the endpoint configuration to use.
|
||||
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
|
||||
string computerName = Utils.GetHostName();
|
||||
|
||||
for (int ii = 0; ii < baseAddresses.Count; ii++)
|
||||
{
|
||||
if (!baseAddresses[ii].StartsWith(Utils.UriSchemeHttps, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
UriBuilder uri = new UriBuilder(baseAddresses[ii]);
|
||||
|
||||
if (uri.Path[uri.Path.Length - 1] != '/')
|
||||
{
|
||||
uri.Path += "/";
|
||||
}
|
||||
|
||||
if (String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
uri.Host = computerName;
|
||||
}
|
||||
|
||||
uris.Add(uri.Uri);
|
||||
|
||||
if (uri.Scheme == Utils.UriSchemeHttps)
|
||||
{
|
||||
// Can only support one policy with HTTPS
|
||||
// So pick the first policy with security mode sign and encrypt
|
||||
ServerSecurityPolicy bestPolicy = null;
|
||||
foreach (ServerSecurityPolicy policy in securityPolicies)
|
||||
{
|
||||
if (policy.SecurityMode != MessageSecurityMode.SignAndEncrypt)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bestPolicy = policy;
|
||||
break;
|
||||
}
|
||||
|
||||
// Pick the first policy from the list if no policies with sign and encrypt defined
|
||||
if (bestPolicy == null)
|
||||
{
|
||||
bestPolicy = securityPolicies[0];
|
||||
}
|
||||
|
||||
EndpointDescription description = new EndpointDescription();
|
||||
|
||||
description.EndpointUrl = uri.ToString();
|
||||
description.Server = serverDescription;
|
||||
|
||||
if (InstanceCertificate != null)
|
||||
{
|
||||
description.ServerCertificate = InstanceCertificate.RawData;
|
||||
|
||||
// check if complete chain should be sent.
|
||||
if (configuration.SecurityConfiguration.SendCertificateChain && InstanceCertificateChain != null && InstanceCertificateChain.Count > 0)
|
||||
{
|
||||
List<byte> serverCertificateChain = new List<byte>();
|
||||
|
||||
for (int i = 0; i < InstanceCertificateChain.Count; i++)
|
||||
{
|
||||
serverCertificateChain.AddRange(InstanceCertificateChain[i].RawData);
|
||||
}
|
||||
|
||||
description.ServerCertificate = serverCertificateChain.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
description.SecurityMode = bestPolicy.SecurityMode;
|
||||
description.SecurityPolicyUri = bestPolicy.SecurityPolicyUri;
|
||||
description.SecurityLevel = ServerSecurityPolicy.CalculateSecurityLevel(bestPolicy.SecurityMode, bestPolicy.SecurityPolicyUri);
|
||||
description.UserIdentityTokens = GetUserTokenPolicies(configuration, description);
|
||||
description.TransportProfileUri = Profiles.HttpsBinaryTransport;
|
||||
|
||||
endpoints.Add(description);
|
||||
}
|
||||
|
||||
// create the stack listener.
|
||||
try
|
||||
{
|
||||
TransportListenerSettings settings = new TransportListenerSettings();
|
||||
|
||||
settings.Descriptions = endpoints;
|
||||
settings.Configuration = endpointConfiguration;
|
||||
settings.ServerCertificate = this.InstanceCertificate;
|
||||
settings.CertificateValidator = configuration.CertificateValidator.GetChannelValidator();
|
||||
settings.NamespaceUris = this.MessageContext.NamespaceUris;
|
||||
settings.Factory = this.MessageContext.Factory;
|
||||
|
||||
ITransportListener listener = new Opc.Ua.Bindings.UaHttpsChannelListener();
|
||||
|
||||
listener.Open(
|
||||
uri.Uri,
|
||||
settings,
|
||||
GetEndpointInstance(this));
|
||||
|
||||
TransportListeners.Add(listener);
|
||||
|
||||
listener.ConnectionStatusChanged += OnConnectionStatusChanged;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string message = "Could not load HTTPS Stack Listener.";
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
message += (" " + e.InnerException.Message);
|
||||
}
|
||||
Utils.Trace(e, message);
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UserTokenPolicies supported by the server.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
/// <returns>Returns a collection of UserTokenPolicy objects, the return type is <seealso cref="UserTokenPolicyCollection"/> . </returns>
|
||||
protected virtual UserTokenPolicyCollection GetUserTokenPolicies(ApplicationConfiguration configuration, EndpointDescription description)
|
||||
public virtual UserTokenPolicyCollection GetUserTokenPolicies(ApplicationConfiguration configuration, EndpointDescription description)
|
||||
{
|
||||
UserTokenPolicyCollection policies = new UserTokenPolicyCollection();
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System.IdentityModel.Selectors;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -39,6 +39,11 @@ namespace Opc.Ua.Bindings
|
||||
/// </summary>
|
||||
public class TcpTransportChannelFactory : ITransportChannelFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The protocol supported by the channel.
|
||||
/// </summary>
|
||||
public string UriScheme => Utils.UriSchemeOpcTcp;
|
||||
|
||||
/// <summary>
|
||||
/// The method creates a new instance of a TCP transport channel
|
||||
/// </summary>
|
||||
@@ -311,7 +316,6 @@ namespace Opc.Ua.Bindings
|
||||
/// <value>The socket handle.</value>
|
||||
public int Handle => m_socket != null ? m_socket.GetHashCode() : -1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transport channel features implemented by this message socket.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/* Copyright (c) 1996-2020 The OPC Foundation. All rights reserved.
|
||||
The source code in this file is covered under a dual-license scenario:
|
||||
- RCL: for OPC Foundation members in good-standing
|
||||
- GPL V2: everybody else
|
||||
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
||||
GNU General Public License as published by the Free Software Foundation;
|
||||
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new Tcp service host.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class can be used by a transport which
|
||||
/// implements the <see cref="ITransportListenerFactory"/>
|
||||
/// </remarks>
|
||||
public abstract class TcpServiceHost : ITransportListenerFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public abstract string UriScheme { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract ITransportListener Create();
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>
|
||||
/// Create a new service host for UA TCP.
|
||||
/// </summary>
|
||||
public List<EndpointDescription> CreateServiceHost(
|
||||
ServerBase serverBase,
|
||||
IDictionary<string, Task> hosts,
|
||||
ApplicationConfiguration configuration,
|
||||
IList<string> baseAddresses,
|
||||
ApplicationDescription serverDescription,
|
||||
List<ServerSecurityPolicy> securityPolicies,
|
||||
X509Certificate2 instanceCertificate,
|
||||
X509Certificate2Collection instanceCertificateChain)
|
||||
{
|
||||
// generate a unique host name.
|
||||
string hostName = String.Empty;
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
{
|
||||
hostName = "/Tcp";
|
||||
}
|
||||
|
||||
if (hosts.ContainsKey(hostName))
|
||||
{
|
||||
hostName += Utils.Format("/{0}", hosts.Count);
|
||||
}
|
||||
|
||||
// build list of uris.
|
||||
List<Uri> uris = new List<Uri>();
|
||||
EndpointDescriptionCollection endpoints = new EndpointDescriptionCollection();
|
||||
|
||||
// create the endpoint configuration to use.
|
||||
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
|
||||
string computerName = Utils.GetHostName();
|
||||
|
||||
for (int ii = 0; ii < baseAddresses.Count; ii++)
|
||||
{
|
||||
// UA TCP and HTTPS endpoints support multiple policies.
|
||||
if (!baseAddresses[ii].StartsWith(Utils.UriSchemeOpcTcp, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
UriBuilder uri = new UriBuilder(baseAddresses[ii]);
|
||||
|
||||
if (String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
uri.Host = computerName;
|
||||
}
|
||||
|
||||
ITransportListener listener = this.Create();
|
||||
if (listener != null)
|
||||
{
|
||||
uris.Add(uri.Uri);
|
||||
|
||||
foreach (ServerSecurityPolicy policy in securityPolicies)
|
||||
{
|
||||
// create the endpoint description.
|
||||
EndpointDescription description = new EndpointDescription();
|
||||
|
||||
description.EndpointUrl = uri.ToString();
|
||||
description.Server = serverDescription;
|
||||
|
||||
description.SecurityMode = policy.SecurityMode;
|
||||
description.SecurityPolicyUri = policy.SecurityPolicyUri;
|
||||
description.SecurityLevel = ServerSecurityPolicy.CalculateSecurityLevel(policy.SecurityMode, policy.SecurityPolicyUri);
|
||||
description.UserIdentityTokens = serverBase.GetUserTokenPolicies(configuration, description);
|
||||
description.TransportProfileUri = Profiles.UaTcpTransport;
|
||||
|
||||
bool requireEncryption = ServerBase.RequireEncryption(description);
|
||||
|
||||
if (requireEncryption)
|
||||
{
|
||||
description.ServerCertificate = instanceCertificate.RawData;
|
||||
|
||||
// check if complete chain should be sent.
|
||||
if (configuration.SecurityConfiguration.SendCertificateChain &&
|
||||
instanceCertificateChain != null &&
|
||||
instanceCertificateChain.Count > 0)
|
||||
{
|
||||
List<byte> serverCertificateChain = new List<byte>();
|
||||
|
||||
for (int i = 0; i < instanceCertificateChain.Count; i++)
|
||||
{
|
||||
serverCertificateChain.AddRange(instanceCertificateChain[i].RawData);
|
||||
}
|
||||
|
||||
description.ServerCertificate = serverCertificateChain.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
endpoints.Add(description);
|
||||
}
|
||||
|
||||
serverBase.CreateServiceHostEndpoint(uri.Uri, endpoints, endpointConfiguration, listener,
|
||||
configuration.CertificateValidator.GetChannelValidator()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Error, "Failed to create endpoint {0} because the transport profile is unsupported.", uri);
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-2
@@ -20,9 +20,24 @@ using System.Threading.Tasks;
|
||||
namespace Opc.Ua.Bindings
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the connections for a UA TCP server.
|
||||
/// Creates a new TcpTransportListener with ITransportListener interface.
|
||||
/// </summary>
|
||||
public class TcpListener : ITransportListener, ITcpChannelListener
|
||||
public class TcpTransportListenerFactory : TcpServiceHost
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override string UriScheme => Utils.UriSchemeOpcTcp;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ITransportListener Create()
|
||||
{
|
||||
return new TcpTransportListener();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the transport for a UA TCP server.
|
||||
/// </summary>
|
||||
public class TcpTransportListener : ITransportListener, ITcpChannelListener
|
||||
{
|
||||
#region IDisposable Members
|
||||
/// <summary>
|
||||
@@ -15,18 +15,6 @@ using Opc.Ua.Bindings;
|
||||
|
||||
namespace Opc.Ua
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an interface to a channel which supports a factory
|
||||
/// </summary>
|
||||
public interface ITransportChannelFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The method creates a new transport channel
|
||||
/// </summary>
|
||||
/// <returns> the transport channel</returns>
|
||||
ITransportChannel Create();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is an interface to a channel which supports
|
||||
/// </summary>
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Opc.Ua
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Opc.Ua
|
||||
public EncodeableFactory(bool shared)
|
||||
{
|
||||
m_encodeableTypes = new Dictionary<ExpandedNodeId, System.Type>();
|
||||
AddEncodeableTypes("Opc.Ua.Core");
|
||||
AddEncodeableTypes(Utils.DefaultOpcUaCoreAssemblyFullName);
|
||||
|
||||
#if DEBUG
|
||||
m_instanceId = Interlocked.Increment(ref m_globalInstanceCount);
|
||||
|
||||
@@ -25,7 +25,7 @@ using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Net;
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Opc.Ua
|
||||
{
|
||||
@@ -50,11 +50,30 @@ namespace Opc.Ua
|
||||
/// </summary>
|
||||
public const string UriSchemeOpcTcp = "opc.tcp";
|
||||
|
||||
/// <summary>
|
||||
/// The URI scheme for the UA TCP protocol over Secure WebSockets.
|
||||
/// </summary>
|
||||
public const string UriSchemeOpcWss = "opc.wss";
|
||||
|
||||
/// <summary>
|
||||
/// The URI schemes which are supported in the core server.
|
||||
/// </summary>
|
||||
public static readonly string[] DefaultUriSchemes = new string []
|
||||
{
|
||||
Utils.UriSchemeOpcTcp,
|
||||
Utils.UriSchemeHttps
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The default port for the UA TCP protocol.
|
||||
/// </summary>
|
||||
public const int UaTcpDefaultPort = 4840;
|
||||
|
||||
/// <summary>
|
||||
/// The default port for the UA TCP protocol over WebSockets.
|
||||
/// </summary>
|
||||
public const int UaWebSocketsDefaultPort = 4843;
|
||||
|
||||
/// <summary>
|
||||
/// The urls of the discovery servers on a node.
|
||||
/// </summary>
|
||||
@@ -67,11 +86,6 @@ namespace Opc.Ua
|
||||
"http://{0}/UADiscovery/Default.svc"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The class that provides the default implementation for the UA TCP protocol.
|
||||
/// </summary>
|
||||
public const string UaTcpBindingDefault = "Opc.Ua.Bindings.UaTcpBinding";
|
||||
|
||||
/// <summary>
|
||||
/// The default certificate store's type.
|
||||
/// </summary>
|
||||
@@ -87,6 +101,23 @@ namespace Opc.Ua
|
||||
/// </summary>
|
||||
public static string DefaultLocalFolder = Directory.GetCurrentDirectory();
|
||||
|
||||
/// <summary>
|
||||
/// The full name of the Opc.Ua.Core assembly.
|
||||
/// </summary>
|
||||
public static readonly string DefaultOpcUaCoreAssemblyFullName = typeof(Utils).Assembly.GetName().FullName;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the Opc.Ua.Core assembly.
|
||||
/// </summary>
|
||||
public static readonly string DefaultOpcUaCoreAssemblyName = typeof(Utils).Assembly.GetName().Name;
|
||||
|
||||
/// <summary>
|
||||
/// List of known default bindings hosted in other assemblies.
|
||||
/// </summary>
|
||||
public static ReadOnlyDictionary<string, string> DefaultBindings = new ReadOnlyDictionary<string, string>(
|
||||
new Dictionary<string, string>() {
|
||||
{ Utils.UriSchemeHttps, "Opc.Ua.Bindings.Https"}
|
||||
});
|
||||
#endregion
|
||||
|
||||
#region Trace Support
|
||||
@@ -854,7 +885,6 @@ namespace Opc.Ua
|
||||
|
||||
#region String, Object and Data Convienence Functions
|
||||
private const int MAX_MESSAGE_LENGTH = 1024;
|
||||
|
||||
private const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
|
||||
private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
|
||||
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj" />
|
||||
<ProjectReference Include="..\..\Libraries\Opc.Ua.Client\Opc.Ua.Client.csproj" />
|
||||
<ProjectReference Include="..\..\Libraries\Opc.Ua.Configuration\Opc.Ua.Configuration.csproj" />
|
||||
<ProjectReference Include="..\..\Libraries\Opc.Ua.Server\Opc.Ua.Server.csproj" />
|
||||
|
||||
@@ -54,6 +54,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azurepipelines", "azurepipe
|
||||
.azurepipelines\testcc.yml = .azurepipelines\testcc.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.Bindings.Https", "Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj", "{759563A2-AF35-4E7B-B813-082F047C8705}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -100,6 +102,10 @@ Global
|
||||
{7F726313-45CA-4571-AC8E-67DDBC196B21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F726313-45CA-4571-AC8E-67DDBC196B21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F726313-45CA-4571-AC8E-67DDBC196B21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{759563A2-AF35-4E7B-B813-082F047C8705}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{759563A2-AF35-4E7B-B813-082F047C8705}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{759563A2-AF35-4E7B-B813-082F047C8705}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{759563A2-AF35-4E7B-B813-082F047C8705}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
+16
-2
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2010
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30523.141
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.Server", "Libraries\Opc.Ua.Server\Opc.Ua.Server.csproj", "{6C449A1E-244E-4515-9949-A7E22012537C}"
|
||||
EndProject
|
||||
@@ -37,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reference Server", "Applica
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleReferenceClient", "Applications\ConsoleReferenceClient\ConsoleReferenceClient.csproj", "{8121879E-D2FD-4B6A-97D9-0F6CBC294411}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.Bindings.Https", "Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj", "{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -180,6 +182,18 @@ Global
|
||||
{8121879E-D2FD-4B6A-97D9-0F6CBC294411}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8121879E-D2FD-4B6A-97D9-0F6CBC294411}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8121879E-D2FD-4B6A-97D9-0F6CBC294411}.Release|x86.Build.0 = Release|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Release|x64.Build.0 = Release|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{92D98D3D-2A7D-4F4B-8C72-1A98908D0221}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<tags>OPCFoundation OPC-UA netstandard ios linux dotnet net netcore uwp</tags>
|
||||
<dependencies>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Core.Debug" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Bindings.Https.Debug" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Configuration.Debug" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Client.Debug" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Server.Debug" version="$version$"/>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<tags>OPCFoundation OPC-UA netstandard ios linux dotnet net netcore uwp</tags>
|
||||
<dependencies>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Core" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Bindings.Https" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Configuration" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Client" version="$version$"/>
|
||||
<dependency id="OPCFoundation.NetStandard.Opc.Ua.Server" version="$version$"/>
|
||||
|
||||
Reference in New Issue
Block a user