NetHttpBinding.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. // <copyright>
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // </copyright>
  4. namespace System.ServiceModel
  5. {
  6. using System;
  7. using System.ComponentModel;
  8. using System.Configuration;
  9. using System.Runtime;
  10. using System.ServiceModel.Channels;
  11. using System.ServiceModel.Configuration;
  12. using System.Text;
  13. using System.Xml;
  14. public class NetHttpBinding : HttpBindingBase
  15. {
  16. BinaryMessageEncodingBindingElement binaryMessageEncodingBindingElement;
  17. ReliableSessionBindingElement session;
  18. OptionalReliableSession reliableSession;
  19. NetHttpMessageEncoding messageEncoding;
  20. BasicHttpSecurity basicHttpSecurity;
  21. public NetHttpBinding()
  22. : this(BasicHttpSecurityMode.None)
  23. {
  24. }
  25. public NetHttpBinding(BasicHttpSecurityMode securityMode)
  26. : base()
  27. {
  28. this.Initialize();
  29. this.basicHttpSecurity.Mode = securityMode;
  30. }
  31. public NetHttpBinding(BasicHttpSecurityMode securityMode, bool reliableSessionEnabled)
  32. : this(securityMode)
  33. {
  34. this.ReliableSession.Enabled = reliableSessionEnabled;
  35. }
  36. public NetHttpBinding(string configurationName)
  37. : base()
  38. {
  39. this.Initialize();
  40. this.ApplyConfiguration(configurationName);
  41. }
  42. NetHttpBinding(BasicHttpSecurity security)
  43. : base()
  44. {
  45. this.Initialize();
  46. this.basicHttpSecurity = security;
  47. }
  48. [DefaultValue(NetHttpMessageEncoding.Binary)]
  49. public NetHttpMessageEncoding MessageEncoding
  50. {
  51. get { return this.messageEncoding; }
  52. set { this.messageEncoding = value; }
  53. }
  54. public BasicHttpSecurity Security
  55. {
  56. get
  57. {
  58. return this.basicHttpSecurity;
  59. }
  60. set
  61. {
  62. if (value == null)
  63. {
  64. throw FxTrace.Exception.ArgumentNull("value");
  65. }
  66. this.basicHttpSecurity = value;
  67. }
  68. }
  69. public OptionalReliableSession ReliableSession
  70. {
  71. get
  72. {
  73. return this.reliableSession;
  74. }
  75. set
  76. {
  77. if (value == null)
  78. {
  79. throw FxTrace.Exception.ArgumentNull("value");
  80. }
  81. this.reliableSession.CopySettings(value);
  82. }
  83. }
  84. public WebSocketTransportSettings WebSocketSettings
  85. {
  86. get
  87. {
  88. return this.InternalWebSocketSettings;
  89. }
  90. }
  91. internal override BasicHttpSecurity BasicHttpSecurity
  92. {
  93. get
  94. {
  95. return this.basicHttpSecurity;
  96. }
  97. }
  98. public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingParameterCollection parameters)
  99. {
  100. if ((this.BasicHttpSecurity.Mode == BasicHttpSecurityMode.Transport ||
  101. this.BasicHttpSecurity.Mode == BasicHttpSecurityMode.TransportCredentialOnly) &&
  102. this.BasicHttpSecurity.Transport.ClientCredentialType == HttpClientCredentialType.InheritedFromHost)
  103. {
  104. throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(SR.HttpClientCredentialTypeInvalid, this.BasicHttpSecurity.Transport.ClientCredentialType)));
  105. }
  106. return base.BuildChannelFactory<TChannel>(parameters);
  107. }
  108. public override BindingElementCollection CreateBindingElements()
  109. {
  110. this.CheckSettings();
  111. // return collection of BindingElements
  112. BindingElementCollection bindingElements = new BindingElementCollection();
  113. // order of BindingElements is important
  114. // add session
  115. if (this.reliableSession.Enabled)
  116. {
  117. bindingElements.Add(this.session);
  118. }
  119. // add security (*optional)
  120. SecurityBindingElement messageSecurity = this.BasicHttpSecurity.CreateMessageSecurity();
  121. if (messageSecurity != null)
  122. {
  123. bindingElements.Add(messageSecurity);
  124. }
  125. // add encoding
  126. switch (this.MessageEncoding)
  127. {
  128. case NetHttpMessageEncoding.Text:
  129. bindingElements.Add(this.TextMessageEncodingBindingElement);
  130. break;
  131. case NetHttpMessageEncoding.Mtom:
  132. bindingElements.Add(this.MtomMessageEncodingBindingElement);
  133. break;
  134. default:
  135. bindingElements.Add(this.binaryMessageEncodingBindingElement);
  136. break;
  137. }
  138. // add transport (http or https)
  139. bindingElements.Add(this.GetTransport());
  140. return bindingElements.Clone();
  141. }
  142. [EditorBrowsable(EditorBrowsableState.Never)]
  143. public bool ShouldSerializeReliableSession()
  144. {
  145. return this.ReliableSession.Ordered != ReliableSessionDefaults.Ordered
  146. || this.ReliableSession.InactivityTimeout != ReliableSessionDefaults.InactivityTimeout
  147. || this.ReliableSession.Enabled != ReliableSessionDefaults.Enabled;
  148. }
  149. [EditorBrowsable(EditorBrowsableState.Never)]
  150. public bool ShouldSerializeSecurity()
  151. {
  152. return this.Security.InternalShouldSerialize();
  153. }
  154. internal static bool TryCreate(BindingElementCollection elements, out Binding binding)
  155. {
  156. binding = null;
  157. if (elements.Count > 4)
  158. {
  159. return false;
  160. }
  161. ReliableSessionBindingElement session = null;
  162. SecurityBindingElement securityElement = null;
  163. MessageEncodingBindingElement encoding = null;
  164. HttpTransportBindingElement transport = null;
  165. foreach (BindingElement element in elements)
  166. {
  167. if (element is ReliableSessionBindingElement)
  168. {
  169. session = element as ReliableSessionBindingElement;
  170. }
  171. if (element is SecurityBindingElement)
  172. {
  173. securityElement = element as SecurityBindingElement;
  174. }
  175. else if (element is TransportBindingElement)
  176. {
  177. transport = element as HttpTransportBindingElement;
  178. }
  179. else if (element is MessageEncodingBindingElement)
  180. {
  181. encoding = element as MessageEncodingBindingElement;
  182. }
  183. else
  184. {
  185. return false;
  186. }
  187. }
  188. if (transport == null || transport.WebSocketSettings.TransportUsage != WebSocketTransportUsage.Always)
  189. {
  190. return false;
  191. }
  192. HttpsTransportBindingElement httpsTransport = transport as HttpsTransportBindingElement;
  193. if ((securityElement != null) && (httpsTransport != null) && (httpsTransport.RequireClientCertificate != TransportDefaults.RequireClientCertificate))
  194. {
  195. return false;
  196. }
  197. // process transport binding element
  198. UnifiedSecurityMode mode;
  199. HttpTransportSecurity transportSecurity = new HttpTransportSecurity();
  200. if (!GetSecurityModeFromTransport(transport, transportSecurity, out mode))
  201. {
  202. return false;
  203. }
  204. if (encoding == null)
  205. {
  206. return false;
  207. }
  208. if (!(encoding is TextMessageEncodingBindingElement || encoding is MtomMessageEncodingBindingElement || encoding is BinaryMessageEncodingBindingElement))
  209. {
  210. return false;
  211. }
  212. if (encoding.MessageVersion != MessageVersion.Soap12WSAddressing10)
  213. {
  214. return false;
  215. }
  216. BasicHttpSecurity security;
  217. if (!TryCreateSecurity(securityElement, mode, transportSecurity, out security))
  218. {
  219. return false;
  220. }
  221. NetHttpBinding netHttpBinding = new NetHttpBinding(security);
  222. netHttpBinding.InitializeFrom(transport, encoding, session);
  223. // make sure all our defaults match
  224. if (!netHttpBinding.IsBindingElementsMatch(transport, encoding, session))
  225. {
  226. return false;
  227. }
  228. binding = netHttpBinding;
  229. return true;
  230. }
  231. internal override void SetReaderQuotas(XmlDictionaryReaderQuotas readerQuotas)
  232. {
  233. readerQuotas.CopyTo(this.binaryMessageEncodingBindingElement.ReaderQuotas);
  234. }
  235. internal override EnvelopeVersion GetEnvelopeVersion()
  236. {
  237. return EnvelopeVersion.Soap12;
  238. }
  239. internal override void CheckSettings()
  240. {
  241. base.CheckSettings();
  242. // In the Win8 profile, Mtom is not supported.
  243. if ((this.MessageEncoding == NetHttpMessageEncoding.Mtom) && UnsafeNativeMethods.IsTailoredApplication.Value)
  244. {
  245. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedBindingProperty, "MessageEncoding", this.MessageEncoding)));
  246. }
  247. }
  248. void Initialize()
  249. {
  250. this.messageEncoding = NetHttpBindingDefaults.MessageEncoding;
  251. this.binaryMessageEncodingBindingElement = new BinaryMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap12WSAddressing10 };
  252. this.TextMessageEncodingBindingElement.MessageVersion = MessageVersion.Soap12WSAddressing10;
  253. this.MtomMessageEncodingBindingElement.MessageVersion = MessageVersion.Soap12WSAddressing10;
  254. this.session = new ReliableSessionBindingElement();
  255. this.reliableSession = new OptionalReliableSession(this.session);
  256. this.WebSocketSettings.TransportUsage = NetHttpBindingDefaults.TransportUsage;
  257. this.WebSocketSettings.SubProtocol = WebSocketTransportSettings.SoapSubProtocol;
  258. this.basicHttpSecurity = new BasicHttpSecurity();
  259. }
  260. void InitializeFrom(HttpTransportBindingElement transport, MessageEncodingBindingElement encoding, ReliableSessionBindingElement session)
  261. {
  262. this.InitializeFrom(transport, encoding);
  263. if (encoding is BinaryMessageEncodingBindingElement)
  264. {
  265. this.messageEncoding = NetHttpMessageEncoding.Binary;
  266. BinaryMessageEncodingBindingElement binary = (BinaryMessageEncodingBindingElement)encoding;
  267. this.ReaderQuotas = binary.ReaderQuotas;
  268. }
  269. if (encoding is TextMessageEncodingBindingElement)
  270. {
  271. this.messageEncoding = NetHttpMessageEncoding.Text;
  272. }
  273. else if (encoding is MtomMessageEncodingBindingElement)
  274. {
  275. this.messageEncoding = NetHttpMessageEncoding.Mtom;
  276. }
  277. if (session != null)
  278. {
  279. // only set properties that have standard binding manifestations
  280. this.session.InactivityTimeout = session.InactivityTimeout;
  281. this.session.Ordered = session.Ordered;
  282. }
  283. }
  284. void ApplyConfiguration(string configurationName)
  285. {
  286. NetHttpBindingCollectionElement section = NetHttpBindingCollectionElement.GetBindingCollectionElement();
  287. NetHttpBindingElement element = section.Bindings[configurationName];
  288. if (element == null)
  289. {
  290. throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(
  291. SR.ConfigInvalidBindingConfigurationName,
  292. configurationName,
  293. ConfigurationStrings.NetHttpBindingCollectionElementName)));
  294. }
  295. else
  296. {
  297. element.ApplyConfiguration(this);
  298. }
  299. }
  300. bool IsBindingElementsMatch(HttpTransportBindingElement transport, MessageEncodingBindingElement encoding, ReliableSessionBindingElement session)
  301. {
  302. if (this.reliableSession.Enabled)
  303. {
  304. if (!this.session.IsMatch(session))
  305. {
  306. return false;
  307. }
  308. }
  309. else if (session != null)
  310. {
  311. return false;
  312. }
  313. switch (this.MessageEncoding)
  314. {
  315. case NetHttpMessageEncoding.Text:
  316. if (!this.TextMessageEncodingBindingElement.IsMatch(encoding))
  317. {
  318. return false;
  319. }
  320. break;
  321. case NetHttpMessageEncoding.Mtom:
  322. if (!this.MtomMessageEncodingBindingElement.IsMatch(encoding))
  323. {
  324. return false;
  325. }
  326. break;
  327. default: // NetHttpMessageEncoding.Binary
  328. if (!this.binaryMessageEncodingBindingElement.IsMatch(encoding))
  329. {
  330. return false;
  331. }
  332. break;
  333. }
  334. if (!this.GetTransport().IsMatch(transport))
  335. {
  336. return false;
  337. }
  338. return true;
  339. }
  340. }
  341. }