Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Channels / CompositeDuplexBindingElement.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.ServiceModel.Channels
6 {
7     using System.Collections.Generic;
8     using System.ComponentModel;
9     using System.Runtime.Serialization;
10     using System.ServiceModel;
11     using System.ServiceModel.Description;
12     using System.ServiceModel.Security;
13     using System.Xml;
14
15
16     public sealed class CompositeDuplexBindingElement : BindingElement, IPolicyExportExtension
17     {
18         Uri clientBaseAddress;
19
20         public CompositeDuplexBindingElement()
21         {
22         }
23
24         CompositeDuplexBindingElement(CompositeDuplexBindingElement elementToBeCloned)
25             : base(elementToBeCloned)
26         {
27             this.clientBaseAddress = elementToBeCloned.ClientBaseAddress;
28         }
29
30         [DefaultValue(null)]
31         public Uri ClientBaseAddress
32         {
33             get
34             {
35                 return this.clientBaseAddress;
36             }
37
38             set
39             {
40                 this.clientBaseAddress = value;
41             }
42         }
43
44         public override BindingElement Clone()
45         {
46             return new CompositeDuplexBindingElement(this);
47         }
48
49         public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
50         {
51             if (context == null)
52             {
53                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
54             }
55
56             if (typeof(TChannel) != typeof(IOutputChannel))
57             {
58                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel",
59                     SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel)));
60             }
61
62             return context.BuildInnerChannelFactory<TChannel>();
63         }
64
65         public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
66         {
67             if (context == null)
68             {
69                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
70             }
71
72             if (typeof(TChannel) != typeof(IInputChannel))
73             {
74                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel",
75                     SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel)));
76             }
77
78             if (context.ListenUriBaseAddress == null)
79             {
80                 if (this.clientBaseAddress != null)
81                 {
82                     context.ListenUriBaseAddress = this.clientBaseAddress;
83                     context.ListenUriRelativeAddress = Guid.NewGuid().ToString();
84                     context.ListenUriMode = ListenUriMode.Explicit;
85                 }
86                 else
87                 {
88                     // 
89 #pragma warning suppress 56506 // Microsoft, context.Binding will never be null.
90                     context.ListenUriRelativeAddress = String.Empty;
91                     context.ListenUriMode = ListenUriMode.Unique;
92                 }
93             }
94
95             return context.BuildInnerChannelListener<TChannel>();
96         }
97
98         public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
99         {
100             if (context == null)
101             {
102                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
103             }
104
105             return (typeof(TChannel) == typeof(IOutputChannel))
106                 && context.CanBuildInnerChannelFactory<IOutputChannel>();
107         }
108
109         public override bool CanBuildChannelListener<TChannel>(BindingContext context)
110         {
111             if (context == null)
112             {
113                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
114             }
115
116             return (typeof(TChannel) == typeof(IInputChannel))
117                 && context.CanBuildInnerChannelListener<IInputChannel>();
118         }
119
120         ChannelProtectionRequirements GetProtectionRequirements()
121         {
122             ChannelProtectionRequirements result = new ChannelProtectionRequirements();
123             XmlQualifiedName refPropHeaderName = new XmlQualifiedName(XD.UtilityDictionary.UniqueEndpointHeaderName.Value,
124                     XD.UtilityDictionary.UniqueEndpointHeaderNamespace.Value);
125             MessagePartSpecification headerParts = new MessagePartSpecification(refPropHeaderName);
126             headerParts.MakeReadOnly();
127             result.IncomingSignatureParts.AddParts(headerParts);
128             result.OutgoingSignatureParts.AddParts(headerParts);
129             return result;
130         }
131
132         public override T GetProperty<T>(BindingContext context)
133         {
134             if (context == null)
135             {
136                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
137             }
138             if (typeof(T) == typeof(ISecurityCapabilities))
139             {
140                 ISecurityCapabilities lowerCapabilities = context.GetInnerProperty<ISecurityCapabilities>();
141                 if (lowerCapabilities != null)
142                 {
143                     // composite duplex cannot ensure that messages it receives are from the part it sends
144                     // messages to. So it cannot offer server auth
145                     return (T)(object)(new SecurityCapabilities(lowerCapabilities.SupportsClientAuthentication,
146                         false, lowerCapabilities.SupportsClientWindowsIdentity, lowerCapabilities.SupportedRequestProtectionLevel,
147                         System.Net.Security.ProtectionLevel.None));
148                 }
149                 else
150                 {
151                     return null;
152                 }
153             }
154             else if (typeof(T) == typeof(ChannelProtectionRequirements))
155             {
156                 ChannelProtectionRequirements myRequirements = this.GetProtectionRequirements();
157                 myRequirements.Add(context.GetInnerProperty<ChannelProtectionRequirements>() ?? new ChannelProtectionRequirements());
158                 return (T)(object)myRequirements;
159             }
160             else
161             {
162                 return context.GetInnerProperty<T>();
163             }
164         }
165
166         internal override bool IsMatch(BindingElement b)
167         {
168             if (b == null)
169             {
170                 return false;
171             }
172
173             CompositeDuplexBindingElement duplex = b as CompositeDuplexBindingElement;
174             if (duplex == null)
175             {
176                 return false;
177             }
178
179             return (this.clientBaseAddress == duplex.clientBaseAddress);
180         }
181
182         void IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext context)
183         {
184             if (context == null)
185                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
186
187             exporter.State[typeof(SupportedAddressingMode).Name] = SupportedAddressingMode.NonAnonymous;
188             context.GetBindingAssertions().Add(CreateCompositeDuplexAssertion());
189         }
190
191         static XmlElement CreateCompositeDuplexAssertion()
192         {
193             XmlDocument doc = new XmlDocument();
194             return doc.CreateElement(TransportPolicyConstants.CompositeDuplexPrefix, TransportPolicyConstants.CompositeDuplex, TransportPolicyConstants.CompositeDuplexNamespace);
195         }
196     }
197 }