1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 5 namespace System.ServiceModel.Channels 6 { 7 using System.Collections.Generic; 8 using System.Runtime; 9 using System.ServiceModel; 10 11 class ReplyChannel : InputQueueChannel<RequestContext>, IReplyChannel 12 { 13 EndpointAddress localAddress; 14 ReplyChannel(ChannelManagerBase channelManager, EndpointAddress localAddress)15 public ReplyChannel(ChannelManagerBase channelManager, EndpointAddress localAddress) 16 : base(channelManager) 17 { 18 this.localAddress = localAddress; 19 } 20 21 public EndpointAddress LocalAddress 22 { 23 get { return localAddress; } 24 } 25 GetProperty()26 public override T GetProperty<T>() 27 { 28 if (typeof(T) == typeof(IReplyChannel)) 29 { 30 return (T)(object)this; 31 } 32 33 T baseProperty = base.GetProperty<T>(); 34 if (baseProperty != null) 35 { 36 return baseProperty; 37 } 38 39 return default(T); 40 } 41 OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)42 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 43 { 44 return new CompletedAsyncResult(callback, state); 45 } 46 OnEndOpen(IAsyncResult result)47 protected override void OnEndOpen(IAsyncResult result) 48 { 49 CompletedAsyncResult.End(result); 50 } 51 OnOpen(TimeSpan timeout)52 protected override void OnOpen(TimeSpan timeout) 53 { 54 } 55 56 #region static Helpers to convert TryReceiveRequest to ReceiveRequest HelpReceiveRequest(IReplyChannel channel, TimeSpan timeout)57 internal static RequestContext HelpReceiveRequest(IReplyChannel channel, TimeSpan timeout) 58 { 59 RequestContext requestContext; 60 if (channel.TryReceiveRequest(timeout, out requestContext)) 61 { 62 return requestContext; 63 } 64 else 65 { 66 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 67 ReplyChannel.CreateReceiveRequestTimedOutException(channel, timeout)); 68 } 69 } 70 HelpBeginReceiveRequest(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state)71 internal static IAsyncResult HelpBeginReceiveRequest(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state) 72 { 73 return new HelpReceiveRequestAsyncResult(channel, timeout, callback, state); 74 } 75 HelpEndReceiveRequest(IAsyncResult result)76 internal static RequestContext HelpEndReceiveRequest(IAsyncResult result) 77 { 78 return HelpReceiveRequestAsyncResult.End(result); 79 } 80 81 class HelpReceiveRequestAsyncResult : AsyncResult 82 { 83 IReplyChannel channel; 84 TimeSpan timeout; 85 static AsyncCallback onReceiveRequest = Fx.ThunkCallback(new AsyncCallback(OnReceiveRequest)); 86 RequestContext requestContext; 87 HelpReceiveRequestAsyncResult(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state)88 public HelpReceiveRequestAsyncResult(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state) 89 : base(callback, state) 90 { 91 this.channel = channel; 92 this.timeout = timeout; 93 IAsyncResult result = channel.BeginTryReceiveRequest(timeout, onReceiveRequest, this); 94 95 if (!result.CompletedSynchronously) 96 { 97 return; 98 } 99 100 HandleReceiveRequestComplete(result); 101 base.Complete(true); 102 } 103 End(IAsyncResult result)104 public static RequestContext End(IAsyncResult result) 105 { 106 HelpReceiveRequestAsyncResult thisPtr = AsyncResult.End<HelpReceiveRequestAsyncResult>(result); 107 return thisPtr.requestContext; 108 } 109 HandleReceiveRequestComplete(IAsyncResult result)110 void HandleReceiveRequestComplete(IAsyncResult result) 111 { 112 if (!this.channel.EndTryReceiveRequest(result, out this.requestContext)) 113 { 114 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 115 ReplyChannel.CreateReceiveRequestTimedOutException(this.channel, this.timeout)); 116 } 117 } 118 OnReceiveRequest(IAsyncResult result)119 static void OnReceiveRequest(IAsyncResult result) 120 { 121 if (result.CompletedSynchronously) 122 { 123 return; 124 } 125 126 HelpReceiveRequestAsyncResult thisPtr = (HelpReceiveRequestAsyncResult)result.AsyncState; 127 Exception completionException = null; 128 try 129 { 130 thisPtr.HandleReceiveRequestComplete(result); 131 } 132 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread 133 catch (Exception e) 134 { 135 if (Fx.IsFatal(e)) 136 { 137 throw; 138 } 139 140 completionException = e; 141 } 142 143 thisPtr.Complete(false, completionException); 144 } 145 } 146 CreateReceiveRequestTimedOutException(IReplyChannel channel, TimeSpan timeout)147 static Exception CreateReceiveRequestTimedOutException(IReplyChannel channel, TimeSpan timeout) 148 { 149 if (channel.LocalAddress != null) 150 { 151 return new TimeoutException(SR.GetString(SR.ReceiveRequestTimedOut, channel.LocalAddress.Uri.AbsoluteUri, timeout)); 152 } 153 else 154 { 155 return new TimeoutException(SR.GetString(SR.ReceiveRequestTimedOutNoLocalAddress, timeout)); 156 } 157 } 158 #endregion 159 160 ReceiveRequest()161 public RequestContext ReceiveRequest() 162 { 163 return this.ReceiveRequest(this.DefaultReceiveTimeout); 164 } 165 ReceiveRequest(TimeSpan timeout)166 public RequestContext ReceiveRequest(TimeSpan timeout) 167 { 168 if (timeout < TimeSpan.Zero) 169 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 170 new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 171 172 this.ThrowPending(); 173 return ReplyChannel.HelpReceiveRequest(this, timeout); 174 } 175 BeginReceiveRequest(AsyncCallback callback, object state)176 public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state) 177 { 178 return this.BeginReceiveRequest(this.DefaultReceiveTimeout, callback, state); 179 } 180 BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)181 public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) 182 { 183 if (timeout < TimeSpan.Zero) 184 { 185 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 186 new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 187 } 188 189 this.ThrowPending(); 190 return ReplyChannel.HelpBeginReceiveRequest(this, timeout, callback, state); 191 } 192 EndReceiveRequest(IAsyncResult result)193 public RequestContext EndReceiveRequest(IAsyncResult result) 194 { 195 return ReplyChannel.HelpEndReceiveRequest(result); 196 } 197 TryReceiveRequest(TimeSpan timeout, out RequestContext context)198 public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context) 199 { 200 if (timeout < TimeSpan.Zero) 201 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 202 new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 203 204 this.ThrowPending(); 205 return base.Dequeue(timeout, out context); 206 } 207 BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)208 public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) 209 { 210 if (timeout < TimeSpan.Zero) 211 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 212 new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 213 214 this.ThrowPending(); 215 return base.BeginDequeue(timeout, callback, state); 216 } 217 EndTryReceiveRequest(IAsyncResult result, out RequestContext context)218 public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context) 219 { 220 return base.EndDequeue(result, out context); 221 } 222 WaitForRequest(TimeSpan timeout)223 public bool WaitForRequest(TimeSpan timeout) 224 { 225 if (timeout < TimeSpan.Zero) 226 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 227 new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 228 229 this.ThrowPending(); 230 return base.WaitForItem(timeout); 231 } 232 BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)233 public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state) 234 { 235 if (timeout < TimeSpan.Zero) 236 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 237 new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0))); 238 239 this.ThrowPending(); 240 return base.BeginWaitForItem(timeout, callback, state); 241 } 242 EndWaitForRequest(IAsyncResult result)243 public bool EndWaitForRequest(IAsyncResult result) 244 { 245 return base.EndWaitForItem(result); 246 } 247 } 248 } 249