Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / OneWayChannelFactory.cs / 2 / OneWayChannelFactory.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Threading; using System.Runtime.Serialization; using System.ServiceModel.Diagnostics; using System.Xml; class PacketRoutableHeader : DictionaryHeader { PacketRoutableHeader() : base() { } public static void AddHeadersTo(Message message, MessageHeader header) { int index = message.Headers.FindHeader(DotNetOneWayStrings.HeaderName, DotNetOneWayStrings.Namespace); if (index == -1) { if (header == null) { header = PacketRoutableHeader.Create(); } message.Headers.Add(header); } } public static void ValidateMessage(Message message) { if (!TryValidateMessage(message)) { throw TraceUtility.ThrowHelperError( new ProtocolException(SR.GetString(SR.OneWayHeaderNotFound)), message); } } public static bool TryValidateMessage(Message message) { int index = message.Headers.FindHeader( DotNetOneWayStrings.HeaderName, DotNetOneWayStrings.Namespace); return (index != -1); } public static PacketRoutableHeader Create() { return new PacketRoutableHeader(); } public override XmlDictionaryString DictionaryName { get { return XD.DotNetOneWayDictionary.HeaderName; } } public override XmlDictionaryString DictionaryNamespace { get { return XD.DotNetOneWayDictionary.Namespace; } } protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) { // no contents necessary } } ////// OneWayChannelFactory built on top of IRequestChannel /// class RequestOneWayChannelFactory : LayeredChannelFactory{ PacketRoutableHeader packetRoutableHeader; public RequestOneWayChannelFactory(OneWayBindingElement bindingElement, BindingContext context) : base(context.Binding, context.BuildInnerChannelFactory ()) { if (bindingElement.PacketRoutable) { this.packetRoutableHeader = PacketRoutableHeader.Create(); } } protected override IOutputChannel OnCreateChannel(EndpointAddress to, Uri via) { IRequestChannel innerChannel = ((IChannelFactory )this.InnerChannelFactory).CreateChannel(to, via); return new RequestOutputChannel(this, innerChannel, this.packetRoutableHeader); } class RequestOutputChannel : OutputChannel { IRequestChannel innerChannel; MessageHeader packetRoutableHeader; public RequestOutputChannel(ChannelManagerBase factory, IRequestChannel innerChannel, MessageHeader packetRoutableHeader) : base(factory) { this.innerChannel = innerChannel; this.packetRoutableHeader = packetRoutableHeader; } #region Inner Channel delegation public override EndpointAddress RemoteAddress { get { return this.innerChannel.RemoteAddress; } } public override Uri Via { get { return this.innerChannel.Via; } } protected override void OnAbort() { this.innerChannel.Abort(); } protected override void OnOpen(TimeSpan timeout) { this.innerChannel.Open(timeout); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { return this.innerChannel.BeginOpen(timeout, callback, state); } protected override void OnEndOpen(IAsyncResult result) { this.innerChannel.EndOpen(result); } protected override void OnClose(TimeSpan timeout) { this.innerChannel.Close(timeout); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { return this.innerChannel.BeginClose(timeout, callback, state); } protected override void OnEndClose(IAsyncResult result) { this.innerChannel.EndClose(result); } #endregion // add our oneWay header to every message (if it's not already there) protected override void AddHeadersTo(Message message) { base.AddHeadersTo(message); if (this.packetRoutableHeader != null) { PacketRoutableHeader.AddHeadersTo(message, this.packetRoutableHeader); } } protected override void OnSend(Message message, TimeSpan timeout) { Message response = this.innerChannel.Request(message, timeout); using (response) { ValidateResponse(response); } } protected override IAsyncResult OnBeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state) { return this.innerChannel.BeginRequest(message, timeout, callback, state); } protected override void OnEndSend(IAsyncResult result) { Message response = this.innerChannel.EndRequest(result); using (response) { ValidateResponse(response); } } void ValidateResponse(Message response) { if (response != null) { if (response.Version == MessageVersion.None && response is NullMessage) { response.Close(); return; } Exception innerException = null; if (response.IsFault) { try { MessageFault messageFault = MessageFault.CreateFault(response, TransportDefaults.MaxFaultSize); innerException = new FaultException(messageFault); } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } if (e is CommunicationException || e is TimeoutException || e is XmlException || e is IOException) { innerException = e; // expected exception generating fault } else { throw; } } } throw TraceUtility.ThrowHelperError( new ProtocolException(SR.GetString(SR.OneWayUnexpectedResponse), innerException), response); } } } } /// /// OneWayChannelFactory built on top of IDuplexSessionChannel /// class DuplexSessionOneWayChannelFactory : LayeredChannelFactory{ ChannelPool channelPool; ChannelPoolSettings channelPoolSettings; bool packetRoutable; public DuplexSessionOneWayChannelFactory(OneWayBindingElement bindingElement, BindingContext context) : base(context.Binding, context.BuildInnerChannelFactory ()) { this.packetRoutable = bindingElement.PacketRoutable; ISecurityCapabilities innerSecurityCapabilities = this.InnerChannelFactory.GetProperty (); // can't pool across outer channels if the inner channels support client auth if (innerSecurityCapabilities != null && innerSecurityCapabilities.SupportsClientAuthentication) { this.channelPoolSettings = bindingElement.ChannelPoolSettings.Clone(); } else { this.channelPool = new ChannelPool (bindingElement.ChannelPoolSettings); } } internal ChannelPool GetChannelPool(out bool cleanupChannelPool) { if (this.channelPool != null) { cleanupChannelPool = false; return this.channelPool; } else { cleanupChannelPool = true; DiagnosticUtility.DebugAssert(this.channelPoolSettings != null, "Need either settings or a pool"); return new ChannelPool (this.channelPoolSettings); } } protected override void OnAbort() { if (this.channelPool != null) { this.channelPool.Close(TimeSpan.Zero); } base.OnAbort(); } protected override void OnClose(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); if (this.channelPool != null) { this.channelPool.Close(timeoutHelper.RemainingTime()); } base.OnClose(timeoutHelper.RemainingTime()); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); if (this.channelPool != null) { this.channelPool.Close(timeoutHelper.RemainingTime()); } return base.OnBeginClose(timeoutHelper.RemainingTime(), callback, state); } protected override IOutputChannel OnCreateChannel(EndpointAddress address, Uri via) { return new DuplexSessionOutputChannel(this, address, via); } class DuplexSessionOutputChannel : OutputChannel { ChannelPool channelPool; EndpointAddress remoteAddress; IChannelFactory innerFactory; AsyncCallback onReceive; bool packetRoutable; bool cleanupChannelPool; Uri via; public DuplexSessionOutputChannel(DuplexSessionOneWayChannelFactory factory, EndpointAddress remoteAddress, Uri via) : base(factory) { this.channelPool = factory.GetChannelPool(out cleanupChannelPool); this.packetRoutable = factory.packetRoutable; this.innerFactory = (IChannelFactory )factory.InnerChannelFactory; this.remoteAddress = remoteAddress; this.via = via; } public override EndpointAddress RemoteAddress { get { return this.remoteAddress; } } public override Uri Via { get { return this.via; } } #region Channel Lifetime protected override void OnOpen(TimeSpan timeout) { } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { return new CompletedAsyncResult(callback, state); } protected override void OnEndOpen(IAsyncResult result) { CompletedAsyncResult.End(result); } protected override void OnAbort() { if (cleanupChannelPool) { this.channelPool.Close(TimeSpan.Zero); } } protected override void OnClose(TimeSpan timeout) { if (cleanupChannelPool) { this.channelPool.Close(timeout); } } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { if (cleanupChannelPool) { this.channelPool.Close(timeout); } return new CompletedAsyncResult(callback, state); } protected override void OnEndClose(IAsyncResult result) { CompletedAsyncResult.End(result); } #endregion protected override IAsyncResult OnBeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state) { return new SendAsyncResult(this, message, timeout, callback, state); } protected override void OnEndSend(IAsyncResult result) { SendAsyncResult.End(result); } protected override void OnSend(Message message, TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); ChannelPoolKey key = null; bool isConnectionFromPool = true; IDuplexSessionChannel innerChannel = GetChannelFromPool(ref timeoutHelper, out key, out isConnectionFromPool); bool success = false; try { if (!isConnectionFromPool) { StampInitialMessage(message); innerChannel.Open(timeoutHelper.RemainingTime()); StartBackgroundReceive(innerChannel); } innerChannel.Send(message, timeoutHelper.RemainingTime()); success = true; } finally { if (!success) { CleanupChannel(innerChannel, false, key, isConnectionFromPool, ref timeoutHelper); } } CleanupChannel(innerChannel, true, key, isConnectionFromPool, ref timeoutHelper); } // kick off an async receive so that we notice when the server is trying to shutdown void StartBackgroundReceive(IDuplexSessionChannel channel) { if (this.onReceive == null) { this.onReceive = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnReceive)); } channel.BeginReceive(TimeSpan.MaxValue, this.onReceive, channel); } void OnReceive(IAsyncResult result) { IDuplexSessionChannel channel = (IDuplexSessionChannel)result.AsyncState; bool success = false; try { Message message = channel.EndReceive(result); if (message == null) { channel.Close(this.channelPool.IdleTimeout); success = true; } else { message.Close(); } } catch (CommunicationException e) { if (DiagnosticUtility.ShouldTraceInformation) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } } catch (TimeoutException e) { if (DiagnosticUtility.ShouldTraceInformation) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } } finally { if (!success) { channel.Abort(); } } } void StampInitialMessage(Message message) { if (this.packetRoutable) { PacketRoutableHeader.AddHeadersTo(message, null); } } void CleanupChannel(IDuplexSessionChannel channel, bool connectionStillGood, ChannelPoolKey key, bool isConnectionFromPool, ref TimeoutHelper timeoutHelper) { if (isConnectionFromPool) { this.channelPool.ReturnConnection(key, channel, connectionStillGood, timeoutHelper.RemainingTime()); } else { if (connectionStillGood) { this.channelPool.AddConnection(key, channel, timeoutHelper.RemainingTime()); } else { channel.Abort(); } } } IDuplexSessionChannel GetChannelFromPool(ref TimeoutHelper timeoutHelper, out ChannelPoolKey key, out bool isConnectionFromPool) { isConnectionFromPool = true; while (true) { IDuplexSessionChannel pooledChannel = this.channelPool.TakeConnection(this.RemoteAddress, this.Via, timeoutHelper.RemainingTime(), out key); if (pooledChannel == null) { isConnectionFromPool = false; return this.innerFactory.CreateChannel(RemoteAddress, Via); } // only return good connections if (pooledChannel.State == CommunicationState.Opened) { return pooledChannel; } // Abort stale connections from the pool this.channelPool.ReturnConnection(key, pooledChannel, false, timeoutHelper.RemainingTime()); } } class SendAsyncResult : AsyncResult { DuplexSessionOutputChannel parent; IDuplexSessionChannel innerChannel; Message message; TimeoutHelper timeoutHelper; static AsyncCallback onOpen; static AsyncCallback onInnerSend = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnInnerSend)); ChannelPoolKey key; bool isConnectionFromPool; public SendAsyncResult(DuplexSessionOutputChannel parent, Message message, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.parent = parent; this.message = message; this.timeoutHelper = new TimeoutHelper(timeout); this.innerChannel = parent.GetChannelFromPool(ref this.timeoutHelper, out this.key, out this.isConnectionFromPool); bool success = false; bool completeSelf = true; try { if (!this.isConnectionFromPool) { completeSelf = OpenNewChannel(); } if (completeSelf) { completeSelf = SendMessage(); } success = true; } finally { if (!success) { Cleanup(false); } } if (completeSelf) { Cleanup(true); base.Complete(true); } } public static void End(IAsyncResult result) { AsyncResult.End (result); } void Cleanup(bool connectionStillGood) { parent.CleanupChannel(this.innerChannel, connectionStillGood, this.key, this.isConnectionFromPool, ref this.timeoutHelper); } bool OpenNewChannel() { if (onOpen == null) { onOpen = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnOpen)); } this.parent.StampInitialMessage(this.message); IAsyncResult result = this.innerChannel.BeginOpen(timeoutHelper.RemainingTime(), onOpen, this); if (!result.CompletedSynchronously) { return false; } this.CompleteOpen(result); return true; } void CompleteOpen(IAsyncResult result) { this.innerChannel.EndOpen(result); this.parent.StartBackgroundReceive(this.innerChannel); } bool SendMessage() { IAsyncResult result = innerChannel.BeginSend(this.message, onInnerSend, this); if (!result.CompletedSynchronously) { return false; } innerChannel.EndSend(result); return true; } static void OnOpen(IAsyncResult result) { if (result.CompletedSynchronously) { return; } SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState; Exception completionException = null; bool completeSelf = false; try { thisPtr.CompleteOpen(result); completeSelf = thisPtr.SendMessage(); } #pragma warning suppress 56500 // [....], transferring exception to another thread catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } completeSelf = true; completionException = e; } if (completeSelf) { thisPtr.Cleanup(completionException == null); thisPtr.Complete(false, completionException); } } static void OnInnerSend(IAsyncResult result) { if (result.CompletedSynchronously) { return; } SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState; Exception completionException = null; try { thisPtr.innerChannel.EndSend(result); } #pragma warning suppress 56500 // [....], transferring exception to another thread catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } completionException = e; } thisPtr.Cleanup(completionException == null); thisPtr.Complete(false, completionException); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SqlBuilder.cs
- ScrollChangedEventArgs.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- BmpBitmapEncoder.cs
- URI.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- SHA512Managed.cs
- DecoratedNameAttribute.cs
- ComponentDispatcher.cs
- ColumnResizeAdorner.cs
- ReadOnlyPropertyMetadata.cs
- MediaCommands.cs
- CopyEncoder.cs
- WpfKnownType.cs
- PropertyConverter.cs
- OdbcConnectionHandle.cs
- IFlowDocumentViewer.cs
- DelegatingConfigHost.cs
- _CookieModule.cs
- Bits.cs
- Site.cs
- PersistenceTypeAttribute.cs
- ReadWriteControlDesigner.cs
- WebConfigurationFileMap.cs
- SpecularMaterial.cs
- PointCollectionConverter.cs
- PageBreakRecord.cs
- AttributeSetAction.cs
- LicFileLicenseProvider.cs
- ImportCatalogPart.cs
- ProfileEventArgs.cs
- ImageDrawing.cs
- CompilerTypeWithParams.cs
- ListControl.cs
- PackUriHelper.cs
- ZoneButton.cs
- EncoderParameter.cs
- CompilerGeneratedAttribute.cs
- SqlDataSourceSelectingEventArgs.cs
- BufferedStream.cs
- DataGridViewRowConverter.cs
- CurrentChangingEventArgs.cs
- LoadGrammarCompletedEventArgs.cs
- IsolatedStorage.cs
- DataGridViewRowHeightInfoNeededEventArgs.cs
- XPathChildIterator.cs
- DataTransferEventArgs.cs
- SemanticResultKey.cs
- PathSegment.cs
- TransactionProtocolConverter.cs
- WorkflowRuntimeBehavior.cs
- TransferRequestHandler.cs
- ImageBrush.cs
- ResourceDescriptionAttribute.cs
- ResXFileRef.cs
- DirectionalLight.cs
- InvokeBinder.cs
- UriGenerator.cs
- AdCreatedEventArgs.cs
- StringPropertyBuilder.cs
- SystemIPGlobalProperties.cs
- TableColumn.cs
- _HelperAsyncResults.cs
- GorillaCodec.cs
- Vector3DCollectionValueSerializer.cs
- GetFileNameResult.cs
- XmlSerializerFaultFormatter.cs
- RuleElement.cs
- DifferencingCollection.cs
- BaseValidator.cs
- DynamicMetaObjectBinder.cs
- ValueSerializer.cs
- ReadOnlyDataSourceView.cs
- ToolboxCategory.cs
- DecoderFallback.cs
- Repeater.cs
- ServiceDescriptions.cs
- DownloadProgressEventArgs.cs
- WriteTimeStream.cs
- ReadOnlyTernaryTree.cs
- CacheMemory.cs
- LogManagementAsyncResult.cs
- CompositeScriptReference.cs
- ObjectSet.cs
- _ProxyChain.cs
- PackageDocument.cs
- Model3DGroup.cs
- SymmetricCryptoHandle.cs
- PointUtil.cs
- GeneralTransformCollection.cs
- QueryTaskGroupState.cs
- Native.cs
- RegionData.cs
- DataGridPageChangedEventArgs.cs
- CompiledRegexRunner.cs
- VerticalAlignConverter.cs
- XmlNotation.cs
- ProcessRequestArgs.cs
- ManualResetEvent.cs
- _ProxyChain.cs