TransactionChannel.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System.Collections.Generic;
  7. using System.ServiceModel.Description;
  8. using System.Diagnostics;
  9. using System.ServiceModel;
  10. using System.ServiceModel.Security;
  11. using System.Transactions;
  12. using System.ServiceModel.Transactions;
  13. using System.Runtime.CompilerServices;
  14. using System.Runtime.Remoting;
  15. using System.Runtime.Remoting.Messaging;
  16. using SR = System.ServiceModel.SR;
  17. using System.ServiceModel.Diagnostics;
  18. internal interface ITransactionChannel
  19. {
  20. // These get run on forward-going messages only
  21. void WriteTransactionDataToMessage(Message message, MessageDirection direction);
  22. void ReadTransactionDataFromMessage(Message message, MessageDirection direction);
  23. // These get run in both directions (request and reply). If other flowable-things are added
  24. // that need to flow both ways, these methods should be renamed and generalized to do it
  25. void ReadIssuedTokens(Message message, MessageDirection direction);
  26. void WriteIssuedTokens(Message message, MessageDirection direction);
  27. }
  28. abstract class TransactionChannel<TChannel>
  29. : LayeredChannel<TChannel>, ITransactionChannel
  30. where TChannel : class, IChannel
  31. {
  32. ITransactionChannelManager factory;
  33. TransactionFormatter formatter;
  34. protected TransactionChannel(ChannelManagerBase channelManager, TChannel innerChannel)
  35. : base(channelManager, innerChannel)
  36. {
  37. this.factory = (ITransactionChannelManager)channelManager;
  38. if (this.factory.TransactionProtocol == TransactionProtocol.OleTransactions)
  39. {
  40. this.formatter = TransactionFormatter.OleTxFormatter;
  41. }
  42. else if (this.factory.TransactionProtocol == TransactionProtocol.WSAtomicTransactionOctober2004)
  43. {
  44. this.formatter = TransactionFormatter.WsatFormatter10;
  45. }
  46. else if (this.factory.TransactionProtocol == TransactionProtocol.WSAtomicTransaction11)
  47. {
  48. this.formatter = TransactionFormatter.WsatFormatter11;
  49. }
  50. else
  51. {
  52. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  53. new ArgumentException(SR.GetString(SR.SFxBadTransactionProtocols)));
  54. }
  55. }
  56. internal TransactionFormatter Formatter
  57. {
  58. get
  59. {
  60. return this.formatter;
  61. }
  62. }
  63. internal TransactionProtocol Protocol
  64. {
  65. get
  66. {
  67. return this.factory.TransactionProtocol;
  68. }
  69. }
  70. public override T GetProperty<T>()
  71. {
  72. if (typeof(T) == typeof(FaultConverter))
  73. {
  74. return (T)(object)new TransactionChannelFaultConverter<TChannel>(this);
  75. }
  76. return base.GetProperty<T>();
  77. }
  78. public T GetInnerProperty<T>() where T : class
  79. {
  80. return base.InnerChannel.GetProperty<T>();
  81. }
  82. static bool Found(int index)
  83. {
  84. return index != -1;
  85. }
  86. void FaultOnMessage(Message message, string reason, string codeString)
  87. {
  88. FaultCode code = FaultCode.CreateSenderFaultCode(codeString, FaultCodeConstants.Namespaces.Transactions);
  89. FaultException fault = new FaultException(reason, code, FaultCodeConstants.Actions.Transactions);
  90. throw TraceUtility.ThrowHelperError(fault, message);
  91. }
  92. ICollection<RequestSecurityTokenResponse> GetIssuedTokens(Message message)
  93. {
  94. return IssuedTokensHeader.ExtractIssuances(message, this.factory.StandardsManager, message.Version.Envelope.UltimateDestinationActorValues, null);
  95. }
  96. public void ReadIssuedTokens(Message message, MessageDirection direction)
  97. {
  98. TransactionFlowOption option = this.factory.FlowIssuedTokens;
  99. ICollection<RequestSecurityTokenResponse> issuances = this.GetIssuedTokens(message);
  100. if (issuances != null && issuances.Count != 0)
  101. {
  102. if (option == TransactionFlowOption.NotAllowed)
  103. {
  104. FaultOnMessage(message, SR.GetString(SR.IssuedTokenFlowNotAllowed), FaultCodeConstants.Codes.IssuedTokenFlowNotAllowed);
  105. }
  106. foreach (RequestSecurityTokenResponse rstr in issuances)
  107. {
  108. TransactionFlowProperty.Ensure(message).IssuedTokens.Add(rstr);
  109. }
  110. }
  111. }
  112. void ReadTransactionFromMessage(Message message, TransactionFlowOption txFlowOption)
  113. {
  114. TransactionInfo transactionInfo = null;
  115. try
  116. {
  117. transactionInfo = this.formatter.ReadTransaction(message);
  118. }
  119. catch (TransactionException e)
  120. {
  121. DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
  122. FaultOnMessage(message, SR.GetString(SR.SFxTransactionDeserializationFailed, e.Message), FaultCodeConstants.Codes.TransactionHeaderMalformed);
  123. }
  124. if (transactionInfo != null)
  125. {
  126. TransactionMessageProperty.Set(transactionInfo, message);
  127. }
  128. else if (txFlowOption == TransactionFlowOption.Mandatory)
  129. {
  130. FaultOnMessage(message, SR.GetString(SR.SFxTransactionFlowRequired), FaultCodeConstants.Codes.TransactionHeaderMissing);
  131. }
  132. }
  133. public virtual void ReadTransactionDataFromMessage(Message message, MessageDirection direction)
  134. {
  135. this.ReadIssuedTokens(message, direction);
  136. TransactionFlowOption txFlowOption = this.factory.GetTransaction(direction, message.Headers.Action);
  137. if (TransactionFlowOptionHelper.AllowedOrRequired(txFlowOption))
  138. {
  139. this.ReadTransactionFromMessage(message, txFlowOption);
  140. }
  141. }
  142. public void WriteTransactionDataToMessage(Message message, MessageDirection direction)
  143. {
  144. TransactionFlowOption txFlowOption = this.factory.GetTransaction(direction, message.Headers.Action);
  145. if (TransactionFlowOptionHelper.AllowedOrRequired(txFlowOption))
  146. {
  147. this.WriteTransactionToMessage(message, txFlowOption);
  148. }
  149. if (TransactionFlowOptionHelper.AllowedOrRequired(this.factory.FlowIssuedTokens))
  150. {
  151. this.WriteIssuedTokens(message, direction);
  152. }
  153. }
  154. [MethodImpl(MethodImplOptions.NoInlining)]
  155. void WriteTransactionToMessage(Message message, TransactionFlowOption txFlowOption)
  156. {
  157. Transaction transaction = TransactionFlowProperty.TryGetTransaction(message);
  158. if (transaction != null)
  159. {
  160. try
  161. {
  162. this.formatter.WriteTransaction(transaction, message);
  163. }
  164. catch (TransactionException e)
  165. {
  166. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(e.Message, e));
  167. }
  168. }
  169. else if (txFlowOption == TransactionFlowOption.Mandatory)
  170. {
  171. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.SFxTransactionFlowRequired)));
  172. }
  173. }
  174. public void WriteIssuedTokens(Message message, MessageDirection direction)
  175. {
  176. ICollection<RequestSecurityTokenResponse> issuances = TransactionFlowProperty.TryGetIssuedTokens(message);
  177. if (issuances != null)
  178. {
  179. IssuedTokensHeader header = new IssuedTokensHeader(issuances, this.factory.StandardsManager);
  180. message.Headers.Add(header);
  181. }
  182. }
  183. }
  184. }