2 // ChannelListenerBase.cs
4 // Author: Atsushi Enomoto (atsushi@ximian.com)
6 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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:
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
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.
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.
45 context
.ListenUriRelativeAddress
!= null ?
46 new Uri (context
.ListenUriBaseAddress
, context
.ListenUriRelativeAddress
) :
47 context
.ListenUriBaseAddress
;
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
,
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
;
100 return OnAcceptChannel (tout
);
102 CurrentAsyncThread
= null;
103 CurrentAsyncResult
= null;
107 CurrentAsyncResult
= accept_channel_delegate
.BeginInvoke (timeout
, callback
, asyncState
);
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
);