1 // 2 // ChannelFactoryBase.cs 3 // 4 // Author: 5 // Atsushi Enomoto <atsushi@ximian.com> 6 // 7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com) 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 29 using System; 30 using System.Collections.Generic; 31 using System.Collections.ObjectModel; 32 using System.ServiceModel; 33 using System.ServiceModel.Dispatcher; 34 35 namespace System.ServiceModel.Channels 36 { 37 internal interface IHasMessageEncoder 38 { 39 MessageEncoder MessageEncoder { get; } 40 } 41 42 internal abstract class TransportChannelFactoryBase<TChannel> : ChannelFactoryBase<TChannel>, IHasMessageEncoder 43 { TransportChannelFactoryBase(TransportBindingElement source, BindingContext ctx)44 protected TransportChannelFactoryBase (TransportBindingElement source, BindingContext ctx) 45 { 46 Transport = source; 47 } 48 49 public TransportBindingElement Transport { get; private set; } 50 51 public MessageEncoder MessageEncoder { get; internal set; } 52 53 Action<TimeSpan> open_delegate; 54 OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)55 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, 56 AsyncCallback callback, object state) 57 { 58 if (open_delegate == null) 59 open_delegate = new Action<TimeSpan> (OnOpen); 60 return open_delegate.BeginInvoke (timeout, callback, state); 61 } 62 OnEndOpen(IAsyncResult result)63 protected override void OnEndOpen (IAsyncResult result) 64 { 65 if (open_delegate == null) 66 throw new InvalidOperationException ("Async open operation has not started"); 67 open_delegate.EndInvoke (result); 68 } 69 OnOpen(TimeSpan timeout)70 protected override void OnOpen (TimeSpan timeout) 71 { 72 } 73 74 /* commented out as it is in doubt. 75 public override T GetProperty<T> () 76 { 77 if (typeof (T) == typeof (MessageVersion)) 78 return (T) (object) MessageEncoder.MessageVersion; 79 return base.GetProperty<T> (); 80 } 81 */ 82 } 83 84 public abstract class ChannelFactoryBase<TChannel> 85 : ChannelFactoryBase, IChannelFactory<TChannel> 86 { 87 List<TChannel> channels = new List<TChannel> (); 88 ChannelFactoryBase()89 protected ChannelFactoryBase () 90 : this (DefaultCommunicationTimeouts.Instance) 91 { 92 } 93 ChannelFactoryBase( IDefaultCommunicationTimeouts timeouts)94 protected ChannelFactoryBase ( 95 IDefaultCommunicationTimeouts timeouts) 96 : base (timeouts) 97 { 98 } 99 CreateChannel( EndpointAddress address)100 public TChannel CreateChannel ( 101 EndpointAddress address) 102 { 103 if (address == null) 104 throw new ArgumentNullException ("address"); 105 return CreateChannel (address, address.Uri); 106 } 107 CreateChannel( EndpointAddress address, Uri via)108 public TChannel CreateChannel ( 109 EndpointAddress address, Uri via) 110 { 111 if (address == null) 112 throw new ArgumentNullException ("address"); 113 if (via == null) 114 throw new ArgumentNullException ("via"); 115 116 ValidateCreateChannel (); 117 var ch = OnCreateChannel (address, via); 118 channels.Add (ch); 119 return ch; 120 } 121 OnCreateChannel( EndpointAddress address, Uri via)122 protected abstract TChannel OnCreateChannel ( 123 EndpointAddress address, Uri via); 124 OnAbort()125 protected override void OnAbort () 126 { 127 // this implicitly premises: TChannel is IChannel 128 foreach (IChannel ch in channels) 129 ch.Abort (); 130 base.OnAbort (); 131 } 132 OnClose(TimeSpan timeout)133 protected override void OnClose (TimeSpan timeout) 134 { 135 DateTime start = DateTime.UtcNow; 136 // this implicitly premises: TChannel is IChannel 137 foreach (IChannel ch in channels) 138 ch.Close (timeout - (DateTime.UtcNow - start)); 139 base.OnClose (timeout - (DateTime.UtcNow - start)); 140 } 141 OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)142 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state) 143 { 144 // base impl. will call this.OnClose() 145 // FIXME: use async BeginClose/EndClose on the channels. 146 return base.OnBeginClose (timeout, callback, state); 147 } 148 OnEndClose(IAsyncResult result)149 protected override void OnEndClose (IAsyncResult result) 150 { 151 // base impl. will call this.OnClose() 152 base.OnEndClose (result); 153 } 154 ValidateCreateChannel()155 protected void ValidateCreateChannel () 156 { 157 ThrowIfDisposedOrNotOpen (); 158 if (State == CommunicationState.Faulted) 159 throw new CommunicationObjectFaultedException (); 160 } 161 } 162 163 public abstract class ChannelFactoryBase 164 : ChannelManagerBase, IChannelFactory, ICommunicationObject 165 { 166 TimeSpan open_timeout, close_timeout, receive_timeout, send_timeout; 167 ChannelFactoryBase()168 protected ChannelFactoryBase () 169 : this (DefaultCommunicationTimeouts.Instance) 170 { 171 } 172 ChannelFactoryBase( IDefaultCommunicationTimeouts timeouts)173 protected ChannelFactoryBase ( 174 IDefaultCommunicationTimeouts timeouts) 175 { 176 open_timeout = timeouts.OpenTimeout; 177 close_timeout = timeouts.CloseTimeout; 178 send_timeout = timeouts.SendTimeout; 179 receive_timeout = timeouts.ReceiveTimeout; 180 } 181 182 protected internal override TimeSpan DefaultCloseTimeout { 183 get { return close_timeout; } 184 } 185 186 protected internal override TimeSpan DefaultOpenTimeout { 187 get { return open_timeout; } 188 } 189 190 protected internal override TimeSpan DefaultReceiveTimeout { 191 get { return receive_timeout; } 192 } 193 194 protected internal override TimeSpan DefaultSendTimeout { 195 get { return send_timeout; } 196 } 197 198 public virtual T GetProperty<T> () where T : class 199 { 200 return null; 201 } 202 OnAbort()203 protected override void OnAbort () 204 { 205 // what should we do here? 206 } 207 208 Action<TimeSpan> close_delegate; 209 OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)210 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state) 211 { 212 if (close_delegate == null) 213 close_delegate = new Action<TimeSpan> (OnClose); 214 return close_delegate.BeginInvoke (timeout, callback, state); 215 } 216 OnEndClose(IAsyncResult result)217 protected override void OnEndClose (IAsyncResult result) 218 { 219 if (close_delegate == null) 220 throw new InvalidOperationException ("Async close operation has not started"); 221 close_delegate.EndInvoke (result); 222 } 223 OnClose(TimeSpan timeout)224 protected override void OnClose (TimeSpan timeout) 225 { 226 // what should we do here? 227 } 228 } 229 } 230