1 //
2 // DuplexSessionChannelBase.cs
3 //
4 // Author:
5 //     Marcos Cobena (marcoscobena@gmail.com)
6 //	Atsushi Enomoto  <atsushi@ximian.com>
7 //
8 // Copyright 2007 Marcos Cobena (http://www.youcannoteatbits.org/)
9 //
10 // Copyright (C) 2009 Novell, Inc.  http://www.novell.com
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 
32 using System;
33 using System.ServiceModel.Channels;
34 
35 namespace System.ServiceModel.Channels
36 {
37 	internal abstract class DuplexChannelBase : ChannelBase, IDuplexChannel
38 	{
39 		ChannelFactoryBase channel_factory_base;
40 		ChannelListenerBase channel_listener_base;
41 		EndpointAddress local_address;
42 		EndpointAddress remote_address;
43 		Uri via;
44 
DuplexChannelBase(ChannelFactoryBase factory, EndpointAddress remoteAddress, Uri via)45 		public DuplexChannelBase (ChannelFactoryBase factory, EndpointAddress remoteAddress, Uri via) : base (factory)
46 		{
47 			channel_factory_base = factory;
48 			remote_address = remoteAddress;
49 			this.via = via;
50 			SetupDelegates ();
51 		}
52 
DuplexChannelBase(ChannelListenerBase listener)53 		public DuplexChannelBase (ChannelListenerBase listener) : base (listener)
54 		{
55 			channel_listener_base = listener;
56 			local_address = new EndpointAddress (listener.Uri);
57 			SetupDelegates ();
58 		}
59 
60 		public virtual EndpointAddress LocalAddress {
61 			get { return local_address; }
62 		}
63 
64 		public virtual EndpointAddress RemoteAddress {
65 			get { return remote_address; }
66 		}
67 
68 		public Uri Via {
69 			get { return via ?? RemoteAddress.Uri; }
70 		}
71 
SetupDelegates()72 		void SetupDelegates ()
73 		{
74 			open_handler = new Action<TimeSpan> (Open);
75 			close_handler = new Action<TimeSpan> (Close);
76 			send_handler = new AsyncSendHandler (Send);
77 			receive_handler = new AsyncReceiveHandler (Receive);
78 			wait_handler = new AsyncWaitForMessageHandler (WaitForMessage);
79 			try_receive_handler = new TryReceiveHandler (TryReceive);
80 		}
81 
GetProperty()82 		public override T GetProperty<T> ()
83 		{
84 			if (typeof (T) == typeof (MessageVersion)) {
85 				if (channel_factory_base is IHasMessageEncoder)
86 					return (T) (object) ((IHasMessageEncoder) channel_factory_base).MessageEncoder.MessageVersion;
87 				if (channel_listener_base is IHasMessageEncoder)
88 					return (T) (object) ((IHasMessageEncoder) channel_listener_base).MessageEncoder.MessageVersion;
89 			}
90 			if (typeof (T) == typeof (IChannelFactory))
91 				return (T) (object) channel_factory_base;
92 			if (typeof (T) == typeof (IChannelListener))
93 				return (T) (object) channel_listener_base;
94 			return base.GetProperty<T> ();
95 		}
96 
97 		// Open
98 		Action<TimeSpan> open_handler;
99 
OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)100 		protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
101 		{
102 			return open_handler.BeginInvoke (timeout, callback, state);
103 		}
104 
OnEndOpen(IAsyncResult result)105 		protected override void OnEndOpen (IAsyncResult result)
106 		{
107 			open_handler.EndInvoke (result);
108 		}
109 
110 		// Close
111 		Action<TimeSpan> close_handler;
112 
OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)113 		protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
114 		{
115 			return close_handler.BeginInvoke (timeout, callback, state);
116 		}
117 
OnEndClose(IAsyncResult result)118 		protected override void OnEndClose (IAsyncResult result)
119 		{
120 			close_handler.EndInvoke (result);
121 		}
122 
123 		// Send
124 
AsyncSendHandler(Message message, TimeSpan timeout)125 		delegate void AsyncSendHandler (Message message, TimeSpan timeout);
126 		AsyncSendHandler send_handler;
127 
BeginSend(Message message, AsyncCallback callback, object state)128 		public virtual IAsyncResult BeginSend (Message message, AsyncCallback callback, object state)
129 		{
130 			return BeginSend (message, DefaultSendTimeout, callback, state);
131 		}
132 
BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)133 		public virtual IAsyncResult BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
134 		{
135 			return send_handler.BeginInvoke (message, timeout, callback, state);
136 		}
137 
EndSend(IAsyncResult result)138 		public virtual void EndSend (IAsyncResult result)
139 		{
140 			send_handler.EndInvoke (result);
141 		}
142 
Send(Message message)143 		public virtual void Send (Message message)
144 		{
145 			Send (message, this.DefaultSendTimeout);
146 		}
147 
Send(Message message, TimeSpan timeout)148 		public abstract void Send (Message message, TimeSpan timeout);
149 
150 		// Receive
151 
AsyncReceiveHandler(TimeSpan timeout)152 		delegate Message AsyncReceiveHandler (TimeSpan timeout);
153 		AsyncReceiveHandler receive_handler;
154 
BeginReceive(AsyncCallback callback, object state)155 		public virtual IAsyncResult BeginReceive (AsyncCallback callback, object state)
156 		{
157 			return BeginReceive (this.DefaultReceiveTimeout, callback, state);
158 		}
159 
BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)160 		public virtual IAsyncResult BeginReceive (TimeSpan timeout, AsyncCallback callback, object state)
161 		{
162 			return receive_handler.BeginInvoke (timeout, callback, state);
163 		}
164 
EndReceive(IAsyncResult result)165 		public virtual Message EndReceive (IAsyncResult result)
166 		{
167 			return receive_handler.EndInvoke (result);
168 		}
169 
Receive()170 		public virtual Message Receive ()
171 		{
172 			return Receive (this.DefaultReceiveTimeout);
173 		}
174 
Receive(TimeSpan timeout)175 		public virtual Message Receive (TimeSpan timeout)
176 		{
177 			Message msg;
178 			if (!TryReceive (timeout, out msg))
179 				throw new TimeoutException ();
180 			return msg;
181 		}
182 
183 		// TryReceive
184 
TryReceiveHandler(TimeSpan timeout, out Message msg)185 		delegate bool TryReceiveHandler (TimeSpan timeout, out Message msg);
186 		TryReceiveHandler try_receive_handler;
187 
BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)188 		public virtual IAsyncResult BeginTryReceive (TimeSpan timeout, AsyncCallback callback, object state)
189 		{
190 			Message dummy;
191 			return try_receive_handler.BeginInvoke (timeout, out dummy, callback, state);
192 		}
193 
EndTryReceive(IAsyncResult result, out Message message)194 		public virtual bool EndTryReceive (IAsyncResult result, out Message message)
195 		{
196 			return try_receive_handler.EndInvoke (out message, result);
197 		}
198 
TryReceive(TimeSpan timeout, out Message message)199 		public abstract bool TryReceive (TimeSpan timeout, out Message message);
200 
201 		// WaitForMessage
202 
AsyncWaitForMessageHandler(TimeSpan timeout)203 		delegate bool AsyncWaitForMessageHandler (TimeSpan timeout);
204 		AsyncWaitForMessageHandler wait_handler;
205 
BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)206 		public virtual IAsyncResult BeginWaitForMessage (TimeSpan timeout, AsyncCallback callback, object state)
207 		{
208 			return wait_handler.BeginInvoke (timeout, callback, state);
209 		}
210 
EndWaitForMessage(IAsyncResult result)211 		public virtual bool EndWaitForMessage (IAsyncResult result)
212 		{
213 			return wait_handler.EndInvoke (result);
214 		}
215 
WaitForMessage(TimeSpan timeout)216 		public abstract bool WaitForMessage (TimeSpan timeout);
217 	}
218 }
219