2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Channels / ChannelListenerBase_1.cs
blobbe4ff59937a85d6340f0d20209c5bfb06c58bb3e
1 //
2 // ChannelListenerBase.cs
3 //
4 // Author: Atsushi Enomoto (atsushi@ximian.com)
5 //
6 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 using System;
28 using System.Collections.Generic;
29 using System.ServiceModel;
30 using System.ServiceModel.Description;
31 using System.Threading;
33 namespace System.ServiceModel.Channels
35 internal abstract class InternalChannelListenerBase<TChannel>
36 : ChannelListenerBase<TChannel>
37 where TChannel : class, IChannel
39 protected InternalChannelListenerBase (BindingContext context)
40 : base (context.Binding)
42 // for ListenUriMode(.Unique), the URI uniqueness
43 // should be assured by the derived types.
44 listen_uri =
45 context.ListenUriRelativeAddress != null ?
46 new Uri (context.ListenUriBaseAddress, context.ListenUriRelativeAddress) :
47 context.ListenUriBaseAddress;
50 Uri listen_uri;
51 Func<TimeSpan,TChannel> accept_channel_delegate;
52 Func<TimeSpan,bool> wait_delegate;
53 Action<TimeSpan> open_delegate, close_delegate;
55 public MessageEncoder MessageEncoder { get; internal set; }
57 public override Uri Uri {
58 get { return listen_uri; }
61 protected Thread CurrentAsyncThread { get; private set; }
62 protected IAsyncResult CurrentAsyncResult { get; private set; }
64 protected override void OnAbort ()
66 if (CurrentAsyncThread != null)
67 CurrentAsyncThread.Abort (); // it is not beautiful but there is no other way to stop it.
70 protected override void OnClose (TimeSpan timeout)
72 if (CurrentAsyncThread != null)
73 if (!CancelAsync (timeout))
74 if (CurrentAsyncThread != null) // being careful
75 CurrentAsyncThread.Abort (); // it is not beautiful but there is no other way to stop it.
78 // cancel ongoing async operations and return if it was
79 // completed successfully. If not, it will abort.
80 public virtual bool CancelAsync (TimeSpan timeout)
82 return CurrentAsyncResult == null || CurrentAsyncResult.AsyncWaitHandle.WaitOne (timeout);
85 protected override IAsyncResult OnBeginAcceptChannel (
86 TimeSpan timeout, AsyncCallback callback,
87 object asyncState)
89 //if (CurrentAsyncResult != null)
90 // throw new InvalidOperationException ("Another AcceptChannel operation is in progress");
92 ManualResetEvent wait = new ManualResetEvent (false);
94 if (accept_channel_delegate == null)
95 accept_channel_delegate = new Func<TimeSpan,TChannel> (delegate (TimeSpan tout) {
96 wait.WaitOne (); // make sure that CurrentAsyncResult is set.
97 CurrentAsyncThread = Thread.CurrentThread;
99 try {
100 return OnAcceptChannel (tout);
101 } finally {
102 CurrentAsyncThread = null;
103 CurrentAsyncResult = null;
107 CurrentAsyncResult = accept_channel_delegate.BeginInvoke (timeout, callback, asyncState);
108 wait.Set ();
109 return CurrentAsyncResult;
112 protected override TChannel OnEndAcceptChannel (IAsyncResult result)
114 if (accept_channel_delegate == null)
115 throw new InvalidOperationException ("Async AcceptChannel operation has not started");
116 // FIXME: what's wrong with this?
117 //if (CurrentAsyncResult == null)
118 // throw new InvalidOperationException ("Async AcceptChannel operation has not started. Argument result was: " + result);
119 return accept_channel_delegate.EndInvoke (result);
122 protected override IAsyncResult OnBeginWaitForChannel (
123 TimeSpan timeout, AsyncCallback callback, object state)
125 if (wait_delegate == null)
126 wait_delegate = new Func<TimeSpan,bool> (OnWaitForChannel);
127 return wait_delegate.BeginInvoke (timeout, callback, state);
130 protected override bool OnEndWaitForChannel (IAsyncResult result)
132 if (wait_delegate == null)
133 throw new InvalidOperationException ("Async WaitForChannel operation has not started");
134 return wait_delegate.EndInvoke (result);
137 protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
138 AsyncCallback callback, object state)
140 if (open_delegate == null)
141 open_delegate = new Action<TimeSpan> (OnOpen);
142 return open_delegate.BeginInvoke (timeout, callback, state);
145 protected override void OnEndOpen (IAsyncResult result)
147 if (open_delegate == null)
148 throw new InvalidOperationException ("Async Open operation has not started");
149 open_delegate.EndInvoke (result);
152 protected override IAsyncResult OnBeginClose (TimeSpan timeout,
153 AsyncCallback callback, object state)
155 if (close_delegate == null)
156 close_delegate = new Action<TimeSpan> (OnClose);
157 return close_delegate.BeginInvoke (timeout, callback, state);
160 protected override void OnEndClose (IAsyncResult result)
162 if (close_delegate == null)
163 throw new InvalidOperationException ("Async Close operation has not started");
164 close_delegate.EndInvoke (result);
168 public abstract class ChannelListenerBase<TChannel>
169 : ChannelListenerBase, IChannelListener<TChannel>,
170 IChannelListener, ICommunicationObject
171 where TChannel : class, IChannel
173 IDefaultCommunicationTimeouts timeouts;
175 protected ChannelListenerBase ()
176 : this (DefaultCommunicationTimeouts.Instance)
180 protected ChannelListenerBase (
181 IDefaultCommunicationTimeouts timeouts)
183 if (timeouts == null)
184 throw new ArgumentNullException ("timeouts");
185 this.timeouts = timeouts;
188 public TChannel AcceptChannel ()
190 return AcceptChannel (timeouts.ReceiveTimeout);
193 public TChannel AcceptChannel (TimeSpan timeout)
195 ThrowIfDisposedOrNotOpen ();
196 return OnAcceptChannel (timeout);
199 public IAsyncResult BeginAcceptChannel (
200 AsyncCallback callback, object asyncState)
202 return BeginAcceptChannel (
203 timeouts.ReceiveTimeout, callback, asyncState);
206 public IAsyncResult BeginAcceptChannel (TimeSpan timeout,
207 AsyncCallback callback, object asyncState)
209 return OnBeginAcceptChannel (timeout, callback, asyncState);
212 public TChannel EndAcceptChannel (IAsyncResult result)
214 return OnEndAcceptChannel (result);
217 protected abstract TChannel OnAcceptChannel (TimeSpan timeout);
219 protected abstract IAsyncResult OnBeginAcceptChannel (TimeSpan timeout,
220 AsyncCallback callback, object asyncState);
222 protected abstract TChannel OnEndAcceptChannel (IAsyncResult result);