ContextChannelRequestContext.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System;
  7. using System.Runtime;
  8. using System.ServiceModel;
  9. class ContextChannelRequestContext : RequestContext
  10. {
  11. ContextProtocol contextProtocol;
  12. TimeSpan defaultSendTimeout;
  13. RequestContext innerContext;
  14. public ContextChannelRequestContext(RequestContext innerContext, ContextProtocol contextProtocol, TimeSpan defaultSendTimeout)
  15. {
  16. if (innerContext == null)
  17. {
  18. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("innerContext");
  19. }
  20. if (contextProtocol == null)
  21. {
  22. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextProtocol");
  23. }
  24. this.innerContext = innerContext;
  25. this.contextProtocol = contextProtocol;
  26. this.defaultSendTimeout = defaultSendTimeout;
  27. }
  28. public override Message RequestMessage
  29. {
  30. get { return this.innerContext.RequestMessage; }
  31. }
  32. public override void Abort()
  33. {
  34. this.innerContext.Abort();
  35. }
  36. public override IAsyncResult BeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  37. {
  38. return new ReplyAsyncResult(message, this, timeout, callback, state);
  39. }
  40. public override IAsyncResult BeginReply(Message message, AsyncCallback callback, object state)
  41. {
  42. return this.BeginReply(message, this.defaultSendTimeout, callback, state);
  43. }
  44. public override void Close(TimeSpan timeout)
  45. {
  46. this.innerContext.Close(timeout);
  47. }
  48. public override void Close()
  49. {
  50. this.innerContext.Close();
  51. }
  52. public override void EndReply(IAsyncResult result)
  53. {
  54. ReplyAsyncResult.End(result);
  55. }
  56. public override void Reply(Message message, TimeSpan timeout)
  57. {
  58. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  59. Message replyMessage = message;
  60. if (message != null)
  61. {
  62. this.contextProtocol.OnOutgoingMessage(message, this);
  63. CorrelationCallbackMessageProperty callback;
  64. if (CorrelationCallbackMessageProperty.TryGet(message, out callback))
  65. {
  66. ContextExchangeCorrelationHelper.AddOutgoingCorrelationCallbackData(callback, message, false);
  67. if (callback.IsFullyDefined)
  68. {
  69. replyMessage = callback.FinalizeCorrelation(message, timeoutHelper.RemainingTime());
  70. // we are done finalizing correlation, removing the messageproperty since we do not need it anymore
  71. replyMessage.Properties.Remove(CorrelationCallbackMessageProperty.Name);
  72. }
  73. }
  74. }
  75. try
  76. {
  77. this.innerContext.Reply(replyMessage, timeoutHelper.RemainingTime());
  78. }
  79. finally
  80. {
  81. if (message != null && !object.ReferenceEquals(message, replyMessage))
  82. {
  83. replyMessage.Close();
  84. }
  85. }
  86. }
  87. public override void Reply(Message message)
  88. {
  89. this.Reply(message, this.defaultSendTimeout);
  90. }
  91. class ReplyAsyncResult : AsyncResult
  92. {
  93. static AsyncCallback onFinalizeCorrelation = Fx.ThunkCallback(new AsyncCallback(OnFinalizeCorrelationCompletedCallback));
  94. static AsyncCallback onReply = Fx.ThunkCallback(new AsyncCallback(OnReplyCompletedCallback));
  95. ContextChannelRequestContext context;
  96. CorrelationCallbackMessageProperty correlationCallback;
  97. Message message;
  98. Message replyMessage;
  99. TimeoutHelper timeoutHelper;
  100. public ReplyAsyncResult(Message message, ContextChannelRequestContext context, TimeSpan timeout, AsyncCallback callback, object state)
  101. : base(callback, state)
  102. {
  103. this.context = context;
  104. this.message = this.replyMessage = message;
  105. this.timeoutHelper = new TimeoutHelper(timeout);
  106. bool shouldReply = true;
  107. if (message != null)
  108. {
  109. this.context.contextProtocol.OnOutgoingMessage(message, this.context);
  110. if (CorrelationCallbackMessageProperty.TryGet(message, out this.correlationCallback))
  111. {
  112. ContextExchangeCorrelationHelper.AddOutgoingCorrelationCallbackData(this.correlationCallback, message, false);
  113. if (this.correlationCallback.IsFullyDefined)
  114. {
  115. IAsyncResult result = correlationCallback.BeginFinalizeCorrelation(this.message, this.timeoutHelper.RemainingTime(), onFinalizeCorrelation, this);
  116. if (result.CompletedSynchronously)
  117. {
  118. if (OnFinalizeCorrelationCompleted(result))
  119. {
  120. base.Complete(true);
  121. }
  122. }
  123. shouldReply = false;
  124. }
  125. }
  126. }
  127. if (shouldReply)
  128. {
  129. IAsyncResult result = this.context.innerContext.BeginReply(this.message, this.timeoutHelper.RemainingTime(), onReply, this);
  130. if (result.CompletedSynchronously)
  131. {
  132. OnReplyCompleted(result);
  133. base.Complete(true);
  134. }
  135. }
  136. }
  137. public static void End(IAsyncResult result)
  138. {
  139. AsyncResult.End<ReplyAsyncResult>(result);
  140. }
  141. static void OnFinalizeCorrelationCompletedCallback(IAsyncResult result)
  142. {
  143. if (result.CompletedSynchronously)
  144. {
  145. return;
  146. }
  147. ReplyAsyncResult thisPtr = (ReplyAsyncResult)result.AsyncState;
  148. Exception completionException = null;
  149. bool completeSelf;
  150. try
  151. {
  152. completeSelf = thisPtr.OnFinalizeCorrelationCompleted(result);
  153. }
  154. catch (Exception e)
  155. {
  156. if (Fx.IsFatal(e))
  157. {
  158. throw;
  159. }
  160. completionException = e;
  161. completeSelf = true;
  162. }
  163. if (completeSelf)
  164. {
  165. thisPtr.Complete(false, completionException);
  166. }
  167. }
  168. static void OnReplyCompletedCallback(IAsyncResult result)
  169. {
  170. if (result.CompletedSynchronously)
  171. {
  172. return;
  173. }
  174. ReplyAsyncResult thisPtr = (ReplyAsyncResult)result.AsyncState;
  175. Exception completionException = null;
  176. try
  177. {
  178. thisPtr.OnReplyCompleted(result);
  179. }
  180. catch (Exception e)
  181. {
  182. if (Fx.IsFatal(e))
  183. {
  184. throw;
  185. }
  186. completionException = e;
  187. }
  188. thisPtr.Complete(false, completionException);
  189. }
  190. bool OnFinalizeCorrelationCompleted(IAsyncResult result)
  191. {
  192. this.replyMessage = this.correlationCallback.EndFinalizeCorrelation(result);
  193. bool throwing = true;
  194. IAsyncResult replyResult;
  195. try
  196. {
  197. replyResult = this.context.innerContext.BeginReply(this.replyMessage, this.timeoutHelper.RemainingTime(), onReply, this);
  198. throwing = false;
  199. }
  200. finally
  201. {
  202. if (throwing)
  203. {
  204. if (this.message != null && !object.ReferenceEquals(this.message, this.replyMessage))
  205. {
  206. this.replyMessage.Close();
  207. }
  208. }
  209. }
  210. if (replyResult.CompletedSynchronously)
  211. {
  212. OnReplyCompleted(replyResult);
  213. return true;
  214. }
  215. return false;
  216. }
  217. void OnReplyCompleted(IAsyncResult result)
  218. {
  219. try
  220. {
  221. this.context.innerContext.EndReply(result);
  222. }
  223. finally
  224. {
  225. if (this.message != null && !object.ReferenceEquals(this.message, this.replyMessage))
  226. {
  227. this.replyMessage.Close();
  228. }
  229. }
  230. }
  231. }
  232. }
  233. }