1 //----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------------------
4 namespace System.ServiceModel.Channels
7 using System.ServiceModel.Diagnostics;
9 sealed class InternalDuplexChannelListener : DelegatingChannelListener<IDuplexChannel>
11 IChannelFactory<IOutputChannel> innerChannelFactory;
12 bool providesCorrelation;
14 internal InternalDuplexChannelListener(InternalDuplexBindingElement bindingElement, BindingContext context)
15 : base(context.Binding, context.Clone().BuildInnerChannelListener<IInputChannel>())
17 this.innerChannelFactory = context.BuildInnerChannelFactory<IOutputChannel>();
18 this.providesCorrelation = bindingElement.ProvidesCorrelation;
21 IOutputChannel GetOutputChannel(Uri to, TimeoutHelper timeoutHelper)
23 IOutputChannel channel = this.innerChannelFactory.CreateChannel(new EndpointAddress(to));
24 channel.Open(timeoutHelper.RemainingTime());
28 protected override void OnAbort()
32 this.innerChannelFactory.Abort();
40 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
42 return new ChainedCloseAsyncResult(timeout, callback, state, base.OnBeginClose, base.OnEndClose, this.innerChannelFactory);
45 protected override void OnEndClose(IAsyncResult result)
47 ChainedCloseAsyncResult.End(result);
50 protected override void OnClose(TimeSpan timeout)
52 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
53 base.OnClose(timeoutHelper.RemainingTime());
54 this.innerChannelFactory.Close(timeoutHelper.RemainingTime());
57 protected override void OnOpening()
60 this.Acceptor = (IChannelAcceptor<IDuplexChannel>)(object)new CompositeDuplexChannelAcceptor(this, (IChannelListener<IInputChannel>)this.InnerChannelListener);
63 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
65 return new ChainedOpenAsyncResult(timeout, callback, state, base.OnBeginOpen, base.OnEndOpen, this.innerChannelFactory);
68 protected override void OnEndOpen(IAsyncResult result)
70 ChainedOpenAsyncResult.End(result);
73 protected override void OnOpen(TimeSpan timeout)
75 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
76 base.OnOpen(timeoutHelper.RemainingTime());
77 this.innerChannelFactory.Open(timeoutHelper.RemainingTime());
80 public override T GetProperty<T>()
82 if (typeof(T) == typeof(IChannelFactory))
84 return (T)(object)innerChannelFactory;
87 if (typeof(T) == typeof(ISecurityCapabilities) && !this.providesCorrelation)
89 return InternalDuplexBindingElement.GetSecurityCapabilities<T>(base.GetProperty<ISecurityCapabilities>());
92 T baseProperty = base.GetProperty<T>();
93 if (baseProperty != null)
98 return this.innerChannelFactory.GetProperty<T>();
101 sealed class CompositeDuplexChannelAcceptor : LayeredChannelAcceptor<IDuplexChannel, IInputChannel>
103 public CompositeDuplexChannelAcceptor(InternalDuplexChannelListener listener, IChannelListener<IInputChannel> innerListener)
104 : base(listener, innerListener)
108 protected override IDuplexChannel OnAcceptChannel(IInputChannel innerChannel)
110 return new ServerCompositeDuplexChannel((InternalDuplexChannelListener)ChannelManager, innerChannel);
114 sealed class ServerCompositeDuplexChannel : ChannelBase, IDuplexChannel
116 IInputChannel innerInputChannel;
117 TimeSpan sendTimeout;
119 public ServerCompositeDuplexChannel(InternalDuplexChannelListener listener, IInputChannel innerInputChannel)
122 this.innerInputChannel = innerInputChannel;
123 this.sendTimeout = listener.DefaultSendTimeout;
126 InternalDuplexChannelListener Listener
128 get { return (InternalDuplexChannelListener)base.Manager; }
131 public EndpointAddress LocalAddress
133 get { return this.innerInputChannel.LocalAddress; }
136 public EndpointAddress RemoteAddress
146 public Message Receive()
148 return this.Receive(this.DefaultReceiveTimeout);
151 public Message Receive(TimeSpan timeout)
153 return InputChannel.HelpReceive(this, timeout);
156 public IAsyncResult BeginReceive(AsyncCallback callback, object state)
158 return this.BeginReceive(this.DefaultReceiveTimeout, callback, state);
161 public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
163 return InputChannel.HelpBeginReceive(this, timeout, callback, state);
166 public Message EndReceive(IAsyncResult result)
168 return InputChannel.HelpEndReceive(result);
171 public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
173 return this.innerInputChannel.BeginTryReceive(timeout, callback, state);
176 public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
178 return this.BeginSend(message, this.DefaultSendTimeout, callback, state);
181 public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
183 return new SendAsyncResult(this, message, timeout, callback, state);
186 public bool EndTryReceive(IAsyncResult result, out Message message)
188 return this.innerInputChannel.EndTryReceive(result, out message);
191 public void EndSend(IAsyncResult result)
193 SendAsyncResult.End(result);
196 protected override void OnAbort()
198 this.innerInputChannel.Abort();
201 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
203 return this.innerInputChannel.BeginClose(timeout, callback, state);
206 protected override void OnEndClose(IAsyncResult result)
208 this.innerInputChannel.EndClose(result);
211 protected override void OnClose(TimeSpan timeout)
213 if (this.innerInputChannel.State == CommunicationState.Opened)
214 this.innerInputChannel.Close(timeout);
217 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
219 return this.innerInputChannel.BeginOpen(callback, state);
222 protected override void OnEndOpen(IAsyncResult result)
224 this.innerInputChannel.EndOpen(result);
227 protected override void OnOpen(TimeSpan timeout)
229 this.innerInputChannel.Open(timeout);
232 public bool TryReceive(TimeSpan timeout, out Message message)
234 return this.innerInputChannel.TryReceive(timeout, out message);
237 public void Send(Message message)
239 this.Send(message, this.DefaultSendTimeout);
242 public void Send(Message message, TimeSpan timeout)
244 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
245 IOutputChannel outputChannel = ValidateStateAndGetOutputChannel(message, timeoutHelper);
248 outputChannel.Send(message, timeoutHelper.RemainingTime());
249 outputChannel.Close(timeoutHelper.RemainingTime());
253 outputChannel.Abort();
257 IOutputChannel ValidateStateAndGetOutputChannel(Message message, TimeoutHelper timeoutHelper)
259 ThrowIfDisposedOrNotOpen();
262 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
264 Uri to = message.Properties.Via;
267 to = message.Headers.To;
270 throw TraceUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageMustHaveViaOrToSetForSendingOnServerSideCompositeDuplexChannels)), message);
272 //Check for EndpointAddress.AnonymousUri is just redundant
273 else if (to.Equals(EndpointAddress.AnonymousUri) || to.Equals(message.Version.Addressing.AnonymousUri))
275 throw TraceUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageToCannotBeAddressedToAnonymousOnServerSideCompositeDuplexChannels, to)), message);
278 //Check for EndpointAddress.AnonymousUri is just redundant
279 else if (to.Equals(EndpointAddress.AnonymousUri) || to.Equals(message.Version.Addressing.AnonymousUri))
281 throw TraceUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageViaCannotBeAddressedToAnonymousOnServerSideCompositeDuplexChannels, to)), message);
283 return this.Listener.GetOutputChannel(to, timeoutHelper);
286 class SendAsyncResult : AsyncResult
288 IOutputChannel outputChannel;
289 static AsyncCallback sendCompleteCallback = Fx.ThunkCallback(new AsyncCallback(SendCompleteCallback));
290 TimeoutHelper timeoutHelper;
292 public SendAsyncResult(ServerCompositeDuplexChannel outer, Message message, TimeSpan timeout, AsyncCallback callback, object state)
293 : base(callback, state)
295 this.timeoutHelper = new TimeoutHelper(timeout);
296 this.outputChannel = outer.ValidateStateAndGetOutputChannel(message, timeoutHelper);
298 bool success = false;
301 IAsyncResult result = outputChannel.BeginSend(message, timeoutHelper.RemainingTime(), sendCompleteCallback, this);
302 if (result.CompletedSynchronously)
304 CompleteSend(result);
312 this.outputChannel.Abort();
316 void CompleteSend(IAsyncResult result)
320 outputChannel.EndSend(result);
321 outputChannel.Close();
325 outputChannel.Abort();
329 internal static void End(IAsyncResult result)
331 AsyncResult.End<SendAsyncResult>(result);
334 static void SendCompleteCallback(IAsyncResult result)
336 if (result.CompletedSynchronously)
341 SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState;
343 Exception completionException = null;
346 thisPtr.CompleteSend(result);
348 #pragma warning suppress 56500 // Microsoft, transferring exception to another thread
355 completionException = e;
357 thisPtr.Complete(false, completionException);
361 public bool WaitForMessage(TimeSpan timeout)
363 return innerInputChannel.WaitForMessage(timeout);
366 public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
368 return innerInputChannel.BeginWaitForMessage(timeout, callback, state);
371 public bool EndWaitForMessage(IAsyncResult result)
373 return innerInputChannel.EndWaitForMessage(result);