WSHttpBindingBase.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel
  5. {
  6. using System;
  7. using System.Text;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.Configuration;
  11. using System.Globalization;
  12. using System.Net;
  13. using System.Net.Security;
  14. using System.Runtime.Serialization;
  15. using System.Security.Principal;
  16. using System.ServiceModel.Channels;
  17. using System.ServiceModel.Configuration;
  18. using System.ServiceModel.Security;
  19. using System.ComponentModel;
  20. using System.Xml;
  21. public abstract class WSHttpBindingBase : Binding, IBindingRuntimePreferences
  22. {
  23. WSMessageEncoding messageEncoding;
  24. OptionalReliableSession reliableSession;
  25. // private BindingElements
  26. HttpTransportBindingElement httpTransport;
  27. HttpsTransportBindingElement httpsTransport;
  28. TextMessageEncodingBindingElement textEncoding;
  29. MtomMessageEncodingBindingElement mtomEncoding;
  30. TransactionFlowBindingElement txFlow;
  31. ReliableSessionBindingElement session;
  32. protected WSHttpBindingBase()
  33. : base()
  34. {
  35. Initialize();
  36. }
  37. protected WSHttpBindingBase(bool reliableSessionEnabled)
  38. : this()
  39. {
  40. this.ReliableSession.Enabled = reliableSessionEnabled;
  41. }
  42. [DefaultValue(HttpTransportDefaults.BypassProxyOnLocal)]
  43. public bool BypassProxyOnLocal
  44. {
  45. get { return httpTransport.BypassProxyOnLocal; }
  46. set
  47. {
  48. httpTransport.BypassProxyOnLocal = value;
  49. httpsTransport.BypassProxyOnLocal = value;
  50. }
  51. }
  52. [DefaultValue(false)]
  53. public bool TransactionFlow
  54. {
  55. get { return this.txFlow.Transactions; }
  56. set { this.txFlow.Transactions = value; }
  57. }
  58. [DefaultValue(HttpTransportDefaults.HostNameComparisonMode)]
  59. public HostNameComparisonMode HostNameComparisonMode
  60. {
  61. get { return httpTransport.HostNameComparisonMode; }
  62. set
  63. {
  64. httpTransport.HostNameComparisonMode = value;
  65. httpsTransport.HostNameComparisonMode = value;
  66. }
  67. }
  68. [DefaultValue(TransportDefaults.MaxBufferPoolSize)]
  69. public long MaxBufferPoolSize
  70. {
  71. get { return httpTransport.MaxBufferPoolSize; }
  72. set
  73. {
  74. httpTransport.MaxBufferPoolSize = value;
  75. httpsTransport.MaxBufferPoolSize = value;
  76. }
  77. }
  78. [DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
  79. public long MaxReceivedMessageSize
  80. {
  81. get { return httpTransport.MaxReceivedMessageSize; }
  82. set
  83. {
  84. if (value > int.MaxValue)
  85. {
  86. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  87. new ArgumentOutOfRangeException("value.MaxReceivedMessageSize",
  88. SR.GetString(SR.MaxReceivedMessageSizeMustBeInIntegerRange)));
  89. }
  90. httpTransport.MaxReceivedMessageSize = value;
  91. httpsTransport.MaxReceivedMessageSize = value;
  92. mtomEncoding.MaxBufferSize = (int)value;
  93. }
  94. }
  95. [DefaultValue(WSHttpBindingDefaults.MessageEncoding)]
  96. public WSMessageEncoding MessageEncoding
  97. {
  98. get { return messageEncoding; }
  99. set { messageEncoding = value; }
  100. }
  101. [DefaultValue(HttpTransportDefaults.ProxyAddress)]
  102. [TypeConverter(typeof(UriTypeConverter))]
  103. public Uri ProxyAddress
  104. {
  105. get { return httpTransport.ProxyAddress; }
  106. set
  107. {
  108. httpTransport.ProxyAddress = value;
  109. httpsTransport.ProxyAddress = value;
  110. }
  111. }
  112. public XmlDictionaryReaderQuotas ReaderQuotas
  113. {
  114. get { return textEncoding.ReaderQuotas; }
  115. set
  116. {
  117. if (value == null)
  118. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  119. value.CopyTo(textEncoding.ReaderQuotas);
  120. value.CopyTo(mtomEncoding.ReaderQuotas);
  121. }
  122. }
  123. public OptionalReliableSession ReliableSession
  124. {
  125. get { return reliableSession; }
  126. set
  127. {
  128. if (value == null)
  129. {
  130. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
  131. }
  132. this.reliableSession.CopySettings(value);
  133. }
  134. }
  135. public override string Scheme { get { return GetTransport().Scheme; } }
  136. public EnvelopeVersion EnvelopeVersion
  137. {
  138. get { return EnvelopeVersion.Soap12; }
  139. }
  140. [TypeConverter(typeof(EncodingConverter))]
  141. public System.Text.Encoding TextEncoding
  142. {
  143. get { return textEncoding.WriteEncoding; }
  144. set
  145. {
  146. textEncoding.WriteEncoding = value;
  147. mtomEncoding.WriteEncoding = value;
  148. }
  149. }
  150. [DefaultValue(HttpTransportDefaults.UseDefaultWebProxy)]
  151. public bool UseDefaultWebProxy
  152. {
  153. get { return httpTransport.UseDefaultWebProxy; }
  154. set
  155. {
  156. httpTransport.UseDefaultWebProxy = value;
  157. httpsTransport.UseDefaultWebProxy = value;
  158. }
  159. }
  160. bool IBindingRuntimePreferences.ReceiveSynchronously
  161. {
  162. get { return false; }
  163. }
  164. internal HttpTransportBindingElement HttpTransport
  165. {
  166. get { return httpTransport; }
  167. }
  168. internal HttpsTransportBindingElement HttpsTransport
  169. {
  170. get { return httpsTransport; }
  171. }
  172. internal ReliableSessionBindingElement ReliableSessionBindingElement
  173. {
  174. get { return session; }
  175. }
  176. internal TransactionFlowBindingElement TransactionFlowBindingElement
  177. {
  178. get { return txFlow; }
  179. }
  180. static TransactionFlowBindingElement GetDefaultTransactionFlowBindingElement()
  181. {
  182. TransactionFlowBindingElement tfbe = new TransactionFlowBindingElement(false);
  183. tfbe.TransactionProtocol = TransactionProtocol.WSAtomicTransactionOctober2004;
  184. return tfbe;
  185. }
  186. void Initialize()
  187. {
  188. httpTransport = new HttpTransportBindingElement();
  189. httpsTransport = new HttpsTransportBindingElement();
  190. messageEncoding = WSHttpBindingDefaults.MessageEncoding;
  191. txFlow = GetDefaultTransactionFlowBindingElement();
  192. session = new ReliableSessionBindingElement(true);
  193. textEncoding = new TextMessageEncodingBindingElement();
  194. textEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
  195. mtomEncoding = new MtomMessageEncodingBindingElement();
  196. mtomEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
  197. reliableSession = new OptionalReliableSession(session);
  198. }
  199. void InitializeFrom(HttpTransportBindingElement transport, MessageEncodingBindingElement encoding, TransactionFlowBindingElement txFlow, ReliableSessionBindingElement session)
  200. {
  201. // transport
  202. this.BypassProxyOnLocal = transport.BypassProxyOnLocal;
  203. this.HostNameComparisonMode = transport.HostNameComparisonMode;
  204. this.MaxBufferPoolSize = transport.MaxBufferPoolSize;
  205. this.MaxReceivedMessageSize = transport.MaxReceivedMessageSize;
  206. this.ProxyAddress = transport.ProxyAddress;
  207. this.UseDefaultWebProxy = transport.UseDefaultWebProxy;
  208. // this binding only supports Text and Mtom encoding
  209. if (encoding is TextMessageEncodingBindingElement)
  210. {
  211. this.MessageEncoding = WSMessageEncoding.Text;
  212. TextMessageEncodingBindingElement text = (TextMessageEncodingBindingElement)encoding;
  213. this.TextEncoding = text.WriteEncoding;
  214. this.ReaderQuotas = text.ReaderQuotas;
  215. }
  216. else if (encoding is MtomMessageEncodingBindingElement)
  217. {
  218. messageEncoding = WSMessageEncoding.Mtom;
  219. MtomMessageEncodingBindingElement mtom = (MtomMessageEncodingBindingElement)encoding;
  220. this.TextEncoding = mtom.WriteEncoding;
  221. this.ReaderQuotas = mtom.ReaderQuotas;
  222. }
  223. this.TransactionFlow = txFlow.Transactions;
  224. this.reliableSession.Enabled = session != null;
  225. //session
  226. if (session != null)
  227. {
  228. // only set properties that have standard binding manifestations
  229. this.session.InactivityTimeout = session.InactivityTimeout;
  230. this.session.Ordered = session.Ordered;
  231. }
  232. }
  233. // check that properties of the HttpTransportBindingElement and
  234. // MessageEncodingBindingElement not exposed as properties on BasicHttpBinding
  235. // match default values of the binding elements
  236. bool IsBindingElementsMatch(HttpTransportBindingElement transport, MessageEncodingBindingElement encoding, TransactionFlowBindingElement txFlow, ReliableSessionBindingElement session)
  237. {
  238. if (!this.GetTransport().IsMatch(transport))
  239. return false;
  240. if (this.MessageEncoding == WSMessageEncoding.Text)
  241. {
  242. if (!this.textEncoding.IsMatch(encoding))
  243. return false;
  244. }
  245. else if (this.MessageEncoding == WSMessageEncoding.Mtom)
  246. {
  247. if (!this.mtomEncoding.IsMatch(encoding))
  248. return false;
  249. }
  250. if (!this.txFlow.IsMatch(txFlow))
  251. return false;
  252. if (reliableSession.Enabled)
  253. {
  254. if (!this.session.IsMatch(session))
  255. return false;
  256. }
  257. else if (session != null)
  258. {
  259. return false;
  260. }
  261. return true;
  262. }
  263. public override BindingElementCollection CreateBindingElements()
  264. { // return collection of BindingElements
  265. BindingElementCollection bindingElements = new BindingElementCollection();
  266. // order of BindingElements is important
  267. // context
  268. bindingElements.Add(txFlow);
  269. // reliable
  270. if (reliableSession.Enabled)
  271. {
  272. bindingElements.Add(session);
  273. }
  274. // add security (*optional)
  275. SecurityBindingElement wsSecurity = this.CreateMessageSecurity();
  276. if (wsSecurity != null)
  277. {
  278. bindingElements.Add(wsSecurity);
  279. }
  280. // add encoding (text or mtom)
  281. WSMessageEncodingHelper.SyncUpEncodingBindingElementProperties(textEncoding, mtomEncoding);
  282. if (this.MessageEncoding == WSMessageEncoding.Text)
  283. bindingElements.Add(textEncoding);
  284. else if (this.MessageEncoding == WSMessageEncoding.Mtom)
  285. bindingElements.Add(mtomEncoding);
  286. // add transport (http or https)
  287. bindingElements.Add(GetTransport());
  288. return bindingElements.Clone();
  289. }
  290. internal static bool TryCreate(BindingElementCollection elements, out Binding binding)
  291. {
  292. binding = null;
  293. if (elements.Count > 6)
  294. return false;
  295. // collect all binding elements
  296. PrivacyNoticeBindingElement privacy = null;
  297. TransactionFlowBindingElement txFlow = null;
  298. ReliableSessionBindingElement session = null;
  299. SecurityBindingElement security = null;
  300. MessageEncodingBindingElement encoding = null;
  301. HttpTransportBindingElement transport = null;
  302. foreach (BindingElement element in elements)
  303. {
  304. if (element is SecurityBindingElement)
  305. security = element as SecurityBindingElement;
  306. else if (element is TransportBindingElement)
  307. transport = element as HttpTransportBindingElement;
  308. else if (element is MessageEncodingBindingElement)
  309. encoding = element as MessageEncodingBindingElement;
  310. else if (element is TransactionFlowBindingElement)
  311. txFlow = element as TransactionFlowBindingElement;
  312. else if (element is ReliableSessionBindingElement)
  313. session = element as ReliableSessionBindingElement;
  314. else if (element is PrivacyNoticeBindingElement)
  315. privacy = element as PrivacyNoticeBindingElement;
  316. else
  317. return false;
  318. }
  319. if (transport == null)
  320. return false;
  321. if (encoding == null)
  322. return false;
  323. if (!transport.AuthenticationScheme.IsSingleton())
  324. {
  325. //multiple authentication schemes selected -- not supported in StandardBindings
  326. return false;
  327. }
  328. HttpsTransportBindingElement httpsTransport = transport as HttpsTransportBindingElement;
  329. if ( ( security != null ) && ( httpsTransport != null ) && ( httpsTransport.RequireClientCertificate != TransportDefaults.RequireClientCertificate ) )
  330. {
  331. return false;
  332. }
  333. if (null != privacy || !WSHttpBinding.TryCreate(security, transport, session, txFlow, out binding))
  334. if (!WSFederationHttpBinding.TryCreate(security, transport, privacy, session, txFlow, out binding))
  335. if (!WS2007HttpBinding.TryCreate(security, transport, session, txFlow, out binding))
  336. if (!WS2007FederationHttpBinding.TryCreate(security, transport, privacy, session, txFlow, out binding))
  337. return false;
  338. if (txFlow == null)
  339. {
  340. txFlow = GetDefaultTransactionFlowBindingElement();
  341. if ((binding is WS2007HttpBinding) || (binding is WS2007FederationHttpBinding))
  342. {
  343. txFlow.TransactionProtocol = TransactionProtocol.WSAtomicTransaction11;
  344. }
  345. }
  346. WSHttpBindingBase wSHttpBindingBase = binding as WSHttpBindingBase;
  347. wSHttpBindingBase.InitializeFrom(transport, encoding, txFlow, session);
  348. if (!wSHttpBindingBase.IsBindingElementsMatch(transport, encoding, txFlow, session))
  349. return false;
  350. return true;
  351. }
  352. protected abstract TransportBindingElement GetTransport();
  353. protected abstract SecurityBindingElement CreateMessageSecurity();
  354. [EditorBrowsable(EditorBrowsableState.Never)]
  355. public bool ShouldSerializeReaderQuotas()
  356. {
  357. return (!EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas));
  358. }
  359. [EditorBrowsable(EditorBrowsableState.Never)]
  360. public bool ShouldSerializeTextEncoding()
  361. {
  362. return (!this.TextEncoding.Equals(TextEncoderDefaults.Encoding));
  363. }
  364. [EditorBrowsable(EditorBrowsableState.Never)]
  365. public bool ShouldSerializeReliableSession()
  366. {
  367. return this.ReliableSession.Ordered != ReliableSessionDefaults.Ordered
  368. || this.ReliableSession.InactivityTimeout != ReliableSessionDefaults.InactivityTimeout
  369. || this.ReliableSession.Enabled != ReliableSessionDefaults.Enabled;
  370. }
  371. }
  372. }