1 //
2 // Author: Atsushi Enomoto <atsushi@ximian.com>
3 //
4 // Copyright (C) 2009,2010 Novell, Inc (http://www.novell.com)
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25 using System;
26 using System.Collections.Generic;
27 using System.Collections.ObjectModel;
28 using System.Linq;
29 using System.ServiceModel;
30 using System.ServiceModel.Channels;
31 using System.ServiceModel.Description;
32 using System.ServiceModel.Dispatcher;
33 
34 namespace System.ServiceModel.Discovery
35 {
36 //* Strange, but this causes compiler error at DiscoveryClientBindingElement.
37 
38 	internal class DiscoveryChannel<TChannel> : DiscoveryChannelBase, IRequestSessionChannel, IDuplexSessionChannel
39 	{
40 		DiscoveryChannelFactory<TChannel> factory;
41 		TChannel inner;
42 
DiscoveryChannel(DiscoveryChannelFactory<TChannel> factory, EndpointAddress address, Uri via)43 		public DiscoveryChannel (DiscoveryChannelFactory<TChannel> factory, EndpointAddress address, Uri via)
44 			: base (factory)
45 		{
46 			this.factory = factory;
47 			RemoteAddress = address;
48 			Via = via;
49 		}
50 
51 		public EndpointAddress RemoteAddress { get; private set; }
52 		public Uri Via { get; private set; }
53 		public EndpointAddress LocalAddress {
54 			get { return ((IDuplexSessionChannel) inner).LocalAddress; }
55 		}
56 
57 		IDuplexSession ISessionChannel<IDuplexSession>.Session {
58 			get { return ((IDuplexSessionChannel) inner).Session; }
59 		}
60 
61 		IOutputSession ISessionChannel<IOutputSession>.Session {
62 			get { return ((IOutputSessionChannel) inner).Session; }
63 		}
64 
65 		Action<TimeSpan> open_delegate, close_delegate;
66 
OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)67 		protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
68 		{
69 			if (close_delegate == null)
70 				close_delegate = new Action<TimeSpan> (OnClose);
71 			return close_delegate.BeginInvoke (timeout, callback, state);
72 		}
73 
OnEndClose(IAsyncResult result)74 		protected override void OnEndClose (IAsyncResult result)
75 		{
76 			close_delegate.EndInvoke (result);
77 		}
78 
OnAbort()79 		protected override void OnAbort ()
80 		{
81 			if (inner != null) {
82 				((IChannel) inner).Abort ();
83 				inner = default (TChannel);
84 			}
85 		}
86 
OnClose(TimeSpan timeout)87 		protected override void OnClose (TimeSpan timeout)
88 		{
89 			if (inner != null) {
90 				((IChannel) inner).Close (timeout);
91 				inner = default (TChannel);
92 			}
93 		}
94 
OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)95 		protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
96 		{
97 			if (open_delegate == null)
98 				open_delegate = new Action<TimeSpan> (OnOpen);
99 			return open_delegate.BeginInvoke (timeout, callback, state);
100 		}
101 
OnEndOpen(IAsyncResult result)102 		protected override void OnEndOpen (IAsyncResult result)
103 		{
104 			open_delegate.EndInvoke (result);
105 		}
106 
OnOpen(TimeSpan timeout)107 		protected override void OnOpen (TimeSpan timeout)
108 		{
109 			// FIXME: use timeout
110 			DateTime start = DateTime.UtcNow;
111 			inner = CreateDiscoveryInnerChannel<TChannel> (factory);
112 			((IChannel) inner).Open (timeout - (DateTime.UtcNow - start));
113 		}
114 
Request(Message msg)115 		public Message Request (Message msg)
116 		{
117 			return Request (msg, DefaultSendTimeout + DefaultReceiveTimeout);
118 		}
119 
Request(Message msg, TimeSpan timeout)120 		public Message Request (Message msg, TimeSpan timeout)
121 		{
122 			return ((IRequestChannel) inner).Request (msg, timeout);
123 		}
124 
BeginRequest(Message msg, AsyncCallback callback, object state)125 		public IAsyncResult BeginRequest (Message msg, AsyncCallback callback, object state)
126 		{
127 			return BeginRequest (msg, DefaultSendTimeout + DefaultReceiveTimeout, callback, state);
128 		}
129 
BeginRequest(Message msg, TimeSpan timeout, AsyncCallback callback, object state)130 		public IAsyncResult BeginRequest (Message msg, TimeSpan timeout, AsyncCallback callback, object state)
131 		{
132 			return ((IRequestChannel) inner).BeginRequest (msg, timeout, callback, state);
133 		}
134 
EndRequest(IAsyncResult result)135 		public Message EndRequest (IAsyncResult result)
136 		{
137 			return ((IRequestChannel) inner).EndRequest (result);
138 		}
139 
Receive()140 		public Message Receive ()
141 		{
142 			return Receive (DefaultReceiveTimeout);
143 		}
144 
Receive(TimeSpan timeout)145 		public Message Receive (TimeSpan timeout)
146 		{
147 			return ((IInputChannel) inner).Receive (timeout);
148 		}
149 
BeginReceive(AsyncCallback callback, object state)150 		public IAsyncResult BeginReceive (AsyncCallback callback, object state)
151 		{
152 			return BeginReceive (DefaultReceiveTimeout, callback, state);
153 		}
154 
BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)155 		public IAsyncResult BeginReceive (TimeSpan timeout, AsyncCallback callback, object state)
156 		{
157 			return ((IInputChannel) inner).BeginReceive (timeout, callback, state);
158 		}
159 
EndReceive(IAsyncResult result)160 		public Message EndReceive (IAsyncResult result)
161 		{
162 			return ((IInputChannel) inner).EndReceive (result);
163 		}
164 
TryReceive(out Message msg)165 		public bool TryReceive (out Message msg)
166 		{
167 			return TryReceive (DefaultReceiveTimeout, out msg);
168 		}
169 
TryReceive(TimeSpan timeout, out Message msg)170 		public bool TryReceive (TimeSpan timeout, out Message msg)
171 		{
172 			return ((IInputChannel) inner).TryReceive (timeout, out msg);
173 		}
174 
BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)175 		public IAsyncResult BeginTryReceive (TimeSpan timeout, AsyncCallback callback, object state)
176 		{
177 			return ((IInputChannel) inner).BeginTryReceive (timeout, callback, state);
178 		}
179 
EndTryReceive(IAsyncResult result, out Message msg)180 		public bool EndTryReceive (IAsyncResult result, out Message msg)
181 		{
182 			return ((IInputChannel) inner).EndTryReceive (result, out msg);
183 		}
184 
WaitForMessage(TimeSpan timeout)185 		public bool WaitForMessage (TimeSpan timeout)
186 		{
187 			return ((IInputChannel) inner).WaitForMessage (timeout);
188 		}
189 
BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)190 		public IAsyncResult BeginWaitForMessage (TimeSpan timeout, AsyncCallback callback, object state)
191 		{
192 			return ((IInputChannel) inner).BeginWaitForMessage (timeout, callback, state);
193 		}
194 
EndWaitForMessage(IAsyncResult result)195 		public bool EndWaitForMessage (IAsyncResult result)
196 		{
197 			return ((IInputChannel) inner).EndWaitForMessage (result);
198 		}
199 
Send(Message msg)200 		public void Send (Message msg)
201 		{
202 			Send (msg, DefaultSendTimeout);
203 		}
204 
Send(Message msg, TimeSpan timeout)205 		public void Send (Message msg, TimeSpan timeout)
206 		{
207 			((IOutputChannel) inner).Send (msg, timeout);
208 		}
209 
BeginSend(Message msg, AsyncCallback callback, object state)210 		public IAsyncResult BeginSend (Message msg, AsyncCallback callback, object state)
211 		{
212 			return BeginSend (msg, DefaultSendTimeout, callback, state);
213 		}
214 
BeginSend(Message msg, TimeSpan timeout, AsyncCallback callback, object state)215 		public IAsyncResult BeginSend (Message msg, TimeSpan timeout, AsyncCallback callback, object state)
216 		{
217 			return ((IOutputChannel) inner).BeginSend (msg, timeout, callback, state);
218 		}
219 
EndSend(IAsyncResult result)220 		public void EndSend (IAsyncResult result)
221 		{
222 			((IOutputChannel) inner).EndSend (result);
223 		}
224 	}
225 //*/
226 
227 	internal class DiscoveryRequestChannel : RequestChannelBase
228 	{
DiscoveryRequestChannel(DiscoveryChannelFactory<IRequestChannel> factory, EndpointAddress address, Uri via)229 		public DiscoveryRequestChannel (DiscoveryChannelFactory<IRequestChannel> factory, EndpointAddress address, Uri via)
230 			: base (factory, address, via)
231 		{
232 			this.factory = factory;
233 		}
234 
235 		DiscoveryChannelFactory<IRequestChannel> factory;
236 		IRequestChannel inner;
237 		DiscoveryClient client;
238 
OnOpen(TimeSpan timeout)239 		protected override void OnOpen (TimeSpan timeout)
240 		{
241 			inner = CreateDiscoveryInnerChannel<IRequestChannel> (factory);
242 		}
243 
OnClose(TimeSpan timeout)244 		protected override void OnClose (TimeSpan timeout)
245 		{
246 			if (inner != null) {
247 				inner.Close (timeout);
248 				inner = null;
249 			}
250 		}
251 
OnAbort()252 		protected override void OnAbort ()
253 		{
254 			if (inner != null) {
255 				inner.Abort ();
256 				inner = null;
257 			}
258 		}
259 
Request(Message input, TimeSpan timeout)260 		public override Message Request (Message input, TimeSpan timeout)
261 		{
262 			ThrowIfDisposedOrNotOpen ();
263 			return inner.Request (input, timeout);
264 		}
265 	}
266 }
267