WSDualHttpBinding.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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.Xml;
  20. using System.ComponentModel;
  21. public class WSDualHttpBinding : Binding, IBindingRuntimePreferences
  22. {
  23. WSMessageEncoding messageEncoding;
  24. ReliableSession reliableSession;
  25. // private BindingElements
  26. HttpTransportBindingElement httpTransport;
  27. TextMessageEncodingBindingElement textEncoding;
  28. MtomMessageEncodingBindingElement mtomEncoding;
  29. TransactionFlowBindingElement txFlow;
  30. ReliableSessionBindingElement session;
  31. CompositeDuplexBindingElement compositeDuplex;
  32. OneWayBindingElement oneWay;
  33. WSDualHttpSecurity security = new WSDualHttpSecurity();
  34. public WSDualHttpBinding(string configName)
  35. : this()
  36. {
  37. ApplyConfiguration(configName);
  38. }
  39. public WSDualHttpBinding(WSDualHttpSecurityMode securityMode)
  40. : this()
  41. {
  42. this.security.Mode = securityMode;
  43. }
  44. public WSDualHttpBinding()
  45. {
  46. Initialize();
  47. }
  48. WSDualHttpBinding(
  49. HttpTransportBindingElement transport,
  50. MessageEncodingBindingElement encoding,
  51. TransactionFlowBindingElement txFlow,
  52. ReliableSessionBindingElement session,
  53. CompositeDuplexBindingElement compositeDuplex,
  54. OneWayBindingElement oneWay,
  55. WSDualHttpSecurity security)
  56. : this()
  57. {
  58. this.security = security;
  59. InitializeFrom(transport, encoding, txFlow, session, compositeDuplex, oneWay);
  60. }
  61. [DefaultValue(HttpTransportDefaults.BypassProxyOnLocal)]
  62. public bool BypassProxyOnLocal
  63. {
  64. get { return httpTransport.BypassProxyOnLocal; }
  65. set { httpTransport.BypassProxyOnLocal = value; }
  66. }
  67. [DefaultValue(null)]
  68. public Uri ClientBaseAddress
  69. {
  70. get { return this.compositeDuplex.ClientBaseAddress; }
  71. set { this.compositeDuplex.ClientBaseAddress = value; }
  72. }
  73. [DefaultValue(false)]
  74. public bool TransactionFlow
  75. {
  76. get { return this.txFlow.Transactions; }
  77. set { this.txFlow.Transactions = value; }
  78. }
  79. [DefaultValue(HttpTransportDefaults.HostNameComparisonMode)]
  80. public HostNameComparisonMode HostNameComparisonMode
  81. {
  82. get { return httpTransport.HostNameComparisonMode; }
  83. set { httpTransport.HostNameComparisonMode = value; }
  84. }
  85. [DefaultValue(TransportDefaults.MaxBufferPoolSize)]
  86. public long MaxBufferPoolSize
  87. {
  88. get { return httpTransport.MaxBufferPoolSize; }
  89. set
  90. {
  91. httpTransport.MaxBufferPoolSize = value;
  92. }
  93. }
  94. [DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
  95. public long MaxReceivedMessageSize
  96. {
  97. get { return httpTransport.MaxReceivedMessageSize; }
  98. set
  99. {
  100. if (value > int.MaxValue)
  101. {
  102. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  103. new ArgumentOutOfRangeException("value.MaxReceivedMessageSize",
  104. SR.GetString(SR.MaxReceivedMessageSizeMustBeInIntegerRange)));
  105. }
  106. httpTransport.MaxReceivedMessageSize = value;
  107. mtomEncoding.MaxBufferSize = (int)value;
  108. }
  109. }
  110. [DefaultValue(WSMessageEncoding.Text)]
  111. public WSMessageEncoding MessageEncoding
  112. {
  113. get { return messageEncoding; }
  114. set { messageEncoding = value; }
  115. }
  116. [DefaultValue(HttpTransportDefaults.ProxyAddress)]
  117. public Uri ProxyAddress
  118. {
  119. get { return httpTransport.ProxyAddress; }
  120. set { httpTransport.ProxyAddress = value; }
  121. }
  122. public XmlDictionaryReaderQuotas ReaderQuotas
  123. {
  124. get { return textEncoding.ReaderQuotas; }
  125. set
  126. {
  127. if (value == null)
  128. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  129. value.CopyTo(textEncoding.ReaderQuotas);
  130. value.CopyTo(mtomEncoding.ReaderQuotas);
  131. }
  132. }
  133. public ReliableSession ReliableSession
  134. {
  135. get
  136. {
  137. return reliableSession;
  138. }
  139. set
  140. {
  141. if (value == null)
  142. {
  143. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
  144. }
  145. this.reliableSession.CopySettings(value);
  146. }
  147. }
  148. public override string Scheme { get { return httpTransport.Scheme; } }
  149. public EnvelopeVersion EnvelopeVersion
  150. {
  151. get { return EnvelopeVersion.Soap12; }
  152. }
  153. [TypeConverter(typeof(EncodingConverter))]
  154. public System.Text.Encoding TextEncoding
  155. {
  156. get { return textEncoding.WriteEncoding; }
  157. set
  158. {
  159. textEncoding.WriteEncoding = value;
  160. mtomEncoding.WriteEncoding = value;
  161. }
  162. }
  163. [DefaultValue(HttpTransportDefaults.UseDefaultWebProxy)]
  164. public bool UseDefaultWebProxy
  165. {
  166. get { return httpTransport.UseDefaultWebProxy; }
  167. set { httpTransport.UseDefaultWebProxy = value; }
  168. }
  169. public WSDualHttpSecurity Security
  170. {
  171. get { return this.security; }
  172. set
  173. {
  174. if (value == null)
  175. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  176. this.security = value;
  177. }
  178. }
  179. bool IBindingRuntimePreferences.ReceiveSynchronously
  180. {
  181. get { return false; }
  182. }
  183. static TransactionFlowBindingElement GetDefaultTransactionFlowBindingElement()
  184. {
  185. TransactionFlowBindingElement tfbe = new TransactionFlowBindingElement(false);
  186. tfbe.TransactionProtocol = TransactionProtocol.WSAtomicTransactionOctober2004;
  187. return tfbe;
  188. }
  189. void Initialize()
  190. {
  191. this.httpTransport = new HttpTransportBindingElement();
  192. this.messageEncoding = WSDualHttpBindingDefaults.MessageEncoding;
  193. this.txFlow = GetDefaultTransactionFlowBindingElement();
  194. this.session = new ReliableSessionBindingElement(true);
  195. this.textEncoding = new TextMessageEncodingBindingElement();
  196. this.textEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
  197. this.mtomEncoding = new MtomMessageEncodingBindingElement();
  198. this.mtomEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
  199. this.compositeDuplex = new CompositeDuplexBindingElement();
  200. this.reliableSession = new ReliableSession(session);
  201. this.oneWay = new OneWayBindingElement();
  202. }
  203. void InitializeFrom(
  204. HttpTransportBindingElement transport,
  205. MessageEncodingBindingElement encoding,
  206. TransactionFlowBindingElement txFlow,
  207. ReliableSessionBindingElement session,
  208. CompositeDuplexBindingElement compositeDuplex,
  209. OneWayBindingElement oneWay)
  210. {
  211. // transport
  212. this.BypassProxyOnLocal = transport.BypassProxyOnLocal;
  213. this.HostNameComparisonMode = transport.HostNameComparisonMode;
  214. this.MaxBufferPoolSize = transport.MaxBufferPoolSize;
  215. this.MaxReceivedMessageSize = transport.MaxReceivedMessageSize;
  216. this.ProxyAddress = transport.ProxyAddress;
  217. this.UseDefaultWebProxy = transport.UseDefaultWebProxy;
  218. // this binding only supports Text and Mtom encoding
  219. if (encoding is TextMessageEncodingBindingElement)
  220. {
  221. this.MessageEncoding = WSMessageEncoding.Text;
  222. TextMessageEncodingBindingElement text = (TextMessageEncodingBindingElement)encoding;
  223. this.TextEncoding = text.WriteEncoding;
  224. this.ReaderQuotas = text.ReaderQuotas;
  225. }
  226. else if (encoding is MtomMessageEncodingBindingElement)
  227. {
  228. messageEncoding = WSMessageEncoding.Mtom;
  229. MtomMessageEncodingBindingElement mtom = (MtomMessageEncodingBindingElement)encoding;
  230. this.TextEncoding = mtom.WriteEncoding;
  231. this.ReaderQuotas = mtom.ReaderQuotas;
  232. }
  233. this.TransactionFlow = txFlow.Transactions;
  234. this.ClientBaseAddress = compositeDuplex.ClientBaseAddress;
  235. //session
  236. if (session != null)
  237. {
  238. // only set properties that have standard binding manifestations
  239. this.session.InactivityTimeout = session.InactivityTimeout;
  240. this.session.Ordered = session.Ordered;
  241. }
  242. }
  243. // check that properties of the HttpTransportBindingElement and
  244. // MessageEncodingBindingElement not exposed as properties on WsHttpBinding
  245. // match default values of the binding elements
  246. bool IsBindingElementsMatch(HttpTransportBindingElement transport,
  247. MessageEncodingBindingElement encoding,
  248. TransactionFlowBindingElement txFlow,
  249. ReliableSessionBindingElement session,
  250. CompositeDuplexBindingElement compositeDuplex,
  251. OneWayBindingElement oneWay)
  252. {
  253. if (!this.httpTransport.IsMatch(transport))
  254. return false;
  255. if (this.MessageEncoding == WSMessageEncoding.Text)
  256. {
  257. if (!this.textEncoding.IsMatch(encoding))
  258. return false;
  259. }
  260. else if (this.MessageEncoding == WSMessageEncoding.Mtom)
  261. {
  262. if (!this.mtomEncoding.IsMatch(encoding))
  263. return false;
  264. }
  265. if (!this.txFlow.IsMatch(txFlow))
  266. return false;
  267. if (!this.session.IsMatch(session))
  268. return false;
  269. if (!this.compositeDuplex.IsMatch(compositeDuplex))
  270. return false;
  271. if (!this.oneWay.IsMatch(oneWay))
  272. {
  273. return false;
  274. }
  275. return true;
  276. }
  277. void ApplyConfiguration(string configurationName)
  278. {
  279. WSDualHttpBindingCollectionElement section = WSDualHttpBindingCollectionElement.GetBindingCollectionElement();
  280. WSDualHttpBindingElement element = section.Bindings[configurationName];
  281. if (element == null)
  282. {
  283. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(
  284. SR.GetString(SR.ConfigInvalidBindingConfigurationName,
  285. configurationName,
  286. ConfigurationStrings.WSDualHttpBindingCollectionElementName)));
  287. }
  288. else
  289. {
  290. element.ApplyConfiguration(this);
  291. }
  292. }
  293. SecurityBindingElement CreateMessageSecurity()
  294. {
  295. return this.Security.CreateMessageSecurity();
  296. }
  297. static bool TryCreateSecurity(SecurityBindingElement securityElement, out WSDualHttpSecurity security)
  298. {
  299. return WSDualHttpSecurity.TryCreate(securityElement, out security);
  300. }
  301. public override BindingElementCollection CreateBindingElements()
  302. { // return collection of BindingElements
  303. BindingElementCollection bindingElements = new BindingElementCollection();
  304. // order of BindingElements is important
  305. // add context
  306. bindingElements.Add(txFlow);
  307. // add session
  308. bindingElements.Add(session);
  309. // add security (optional)
  310. SecurityBindingElement wsSecurity = CreateMessageSecurity();
  311. if (wsSecurity != null)
  312. {
  313. bindingElements.Add(wsSecurity);
  314. }
  315. // add duplex
  316. bindingElements.Add(compositeDuplex);
  317. // add oneWay adapter
  318. bindingElements.Add(oneWay);
  319. // add encoding (text or mtom)
  320. WSMessageEncodingHelper.SyncUpEncodingBindingElementProperties(textEncoding, mtomEncoding);
  321. if (this.MessageEncoding == WSMessageEncoding.Text)
  322. {
  323. bindingElements.Add(textEncoding);
  324. }
  325. else if (this.MessageEncoding == WSMessageEncoding.Mtom)
  326. {
  327. bindingElements.Add(mtomEncoding);
  328. }
  329. // add transport
  330. bindingElements.Add(httpTransport);
  331. return bindingElements.Clone();
  332. }
  333. internal static bool TryCreate(BindingElementCollection elements, out Binding binding)
  334. {
  335. binding = null;
  336. if (elements.Count > 7)
  337. {
  338. return false;
  339. }
  340. SecurityBindingElement sbe = null;
  341. HttpTransportBindingElement transport = null;
  342. MessageEncodingBindingElement encoding = null;
  343. TransactionFlowBindingElement txFlow = null;
  344. ReliableSessionBindingElement session = null;
  345. CompositeDuplexBindingElement compositeDuplex = null;
  346. OneWayBindingElement oneWay = null;
  347. foreach (BindingElement element in elements)
  348. {
  349. if (element is SecurityBindingElement)
  350. {
  351. sbe = element as SecurityBindingElement;
  352. }
  353. else if (element is TransportBindingElement)
  354. {
  355. transport = element as HttpTransportBindingElement;
  356. }
  357. else if (element is MessageEncodingBindingElement)
  358. {
  359. encoding = element as MessageEncodingBindingElement;
  360. }
  361. else if (element is TransactionFlowBindingElement)
  362. {
  363. txFlow = element as TransactionFlowBindingElement;
  364. }
  365. else if (element is ReliableSessionBindingElement)
  366. {
  367. session = element as ReliableSessionBindingElement;
  368. }
  369. else if (element is CompositeDuplexBindingElement)
  370. {
  371. compositeDuplex = element as CompositeDuplexBindingElement;
  372. }
  373. else if (element is OneWayBindingElement)
  374. {
  375. oneWay = element as OneWayBindingElement;
  376. }
  377. else
  378. {
  379. return false;
  380. }
  381. }
  382. if (transport == null)
  383. {
  384. return false;
  385. }
  386. if (encoding == null)
  387. {
  388. return false;
  389. }
  390. // this binding only supports Soap12
  391. if (!encoding.CheckEncodingVersion(EnvelopeVersion.Soap12))
  392. {
  393. return false;
  394. }
  395. if (compositeDuplex == null)
  396. {
  397. return false;
  398. }
  399. if (oneWay == null)
  400. {
  401. return false;
  402. }
  403. if (session == null)
  404. {
  405. return false;
  406. }
  407. if (txFlow == null)
  408. {
  409. txFlow = GetDefaultTransactionFlowBindingElement();
  410. }
  411. WSDualHttpSecurity security;
  412. if (!TryCreateSecurity(sbe, out security))
  413. return false;
  414. WSDualHttpBinding wSDualHttpBinding =
  415. new WSDualHttpBinding(transport, encoding, txFlow, session, compositeDuplex, oneWay, security);
  416. if (!wSDualHttpBinding.IsBindingElementsMatch(transport, encoding, txFlow, session, compositeDuplex, oneWay))
  417. {
  418. return false;
  419. }
  420. binding = wSDualHttpBinding;
  421. return true;
  422. }
  423. [EditorBrowsable(EditorBrowsableState.Never)]
  424. public bool ShouldSerializeReaderQuotas()
  425. {
  426. return (!EncoderDefaults.IsDefaultReaderQuotas(this.ReaderQuotas));
  427. }
  428. [EditorBrowsable(EditorBrowsableState.Never)]
  429. public bool ShouldSerializeTextEncoding()
  430. {
  431. return (!this.TextEncoding.Equals(TextEncoderDefaults.Encoding));
  432. }
  433. [EditorBrowsable(EditorBrowsableState.Never)]
  434. public bool ShouldSerializeReliableSession()
  435. {
  436. return this.ReliableSession.Ordered != ReliableSessionDefaults.Ordered
  437. || this.ReliableSession.InactivityTimeout != ReliableSessionDefaults.InactivityTimeout;
  438. }
  439. [EditorBrowsable(EditorBrowsableState.Never)]
  440. public bool ShouldSerializeSecurity()
  441. {
  442. return this.Security.InternalShouldSerialize();
  443. }
  444. }
  445. }