DiscoveryClientChannelBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Discovery / System / ServiceModel / Discovery / DiscoveryClientChannelBase.cs / 1305376 / DiscoveryClientChannelBase.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

namespace System.ServiceModel.Discovery 
{
    using System; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Runtime; 
    using System.Security;
    using System.ServiceModel.Channels;
    using System.Threading;
 
    abstract partial class DiscoveryClientChannelBase : ChannelBase
        where TChannel : class, IChannel 
    { 
        TChannel innerChannel;
 
        IChannelFactory innerChannelFactory;
        FindCriteria findCriteria;
        DiscoveryEndpointProvider discoveryEndpointProvider;
 
        DiscoveryClient discoveryClient;
 
        InputQueue discoveredEndpoints; 
        Exception exception;
        int totalExpectedEndpoints; 
        int totalDiscoveredEndpoints;
        bool discoveryCompleted;

        [Fx.Tag.SynchronizationObject] 
        object thisLock;
 
        public DiscoveryClientChannelBase( 
            ChannelManagerBase channelManagerBase,
            IChannelFactory innerChannelFactory, 
            FindCriteria findCriteria,
            DiscoveryEndpointProvider discoveryEndpointProvider)
            : base(channelManagerBase)
        { 
            Fx.Assert(findCriteria != null, "The findCriteria must be non null.");
            Fx.Assert(discoveryEndpointProvider != null, "The discoveryEndpointProvider must be non null."); 
            Fx.Assert(innerChannelFactory != null, "The innerChannelFactory must be non null."); 

            this.innerChannelFactory = innerChannelFactory; 
            this.findCriteria = findCriteria;
            this.discoveryEndpointProvider = discoveryEndpointProvider;

            this.discoveredEndpoints = new InputQueue(); 
            this.totalExpectedEndpoints = int.MaxValue;
            this.totalDiscoveredEndpoints = 0; 
            this.discoveryCompleted = false; 
            this.thisLock = new object();
        } 

        protected TChannel InnerChannel
        {
            get 
            {
                return this.innerChannel; 
            } 
        }
 
        public override T GetProperty()
        {
            T baseProperty = base.GetProperty();
            if (baseProperty != null) 
            {
                return baseProperty; 
            } 

            if (this.innerChannel != null) 
            {
                return this.InnerChannel.GetProperty();
            }
 
            return null;
        } 
 
        protected override void OnOpen(TimeSpan timeout)
        { 
            this.innerChannel = this.BuildChannel(timeout);
            this.innerChannel.Faulted += new EventHandler(OnInnerChannelFaulted);
        }
 
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return new DiscoveryChannelBuilderAsyncResult( 
                this,
                timeout, 
                callback,
                state);
        }
 
        protected override void OnEndOpen(IAsyncResult result)
        { 
            this.innerChannel = DiscoveryChannelBuilderAsyncResult.End(result); 
            this.innerChannel.Faulted += new EventHandler(OnInnerChannelFaulted);
        } 

        protected override void OnClosing()
        {
            if (this.innerChannel != null) 
            {
                this.innerChannel.Faulted -= new EventHandler(OnInnerChannelFaulted); 
            } 
            base.OnClosing();
        } 

        protected override void OnClose(TimeSpan timeout)
        {
            if (this.innerChannel != null) 
            {
                this.innerChannel.Close(timeout); 
            } 
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CloseAsyncResult(
                this.innerChannel, 
                timeout,
                callback, 
                state); 
        }
 
        protected override void OnEndClose(IAsyncResult result)
        {
            CloseAsyncResult.End(result);
        } 

        protected override void OnAbort() 
        { 
            if (this.innerChannel != null)
            { 
                this.innerChannel.Abort();
            }
        }
 
        void OnInnerChannelFaulted(object sender, EventArgs e)
        { 
            this.Fault(); 
        }
 
        public TChannel BuildChannel(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
            this.InitializeAndFindAsync();
 
            TChannel innerChannel = null; 
            bool completed = false;
 
            EndpointDiscoveryMetadata currentEndpointDiscoveryMetadata = null;

            try
            { 
                do
                { 
                    try 
                    {
                        currentEndpointDiscoveryMetadata = this.discoveredEndpoints.Dequeue(timeoutHelper.RemainingTime()); 
                    }
                    catch (TimeoutException te)
                    {
                        throw FxTrace.Exception.AsError(new TimeoutException(SR.DiscoveryClientChannelOpenTimeout(timeoutHelper.OriginalTimeout), te)); 
                    }
 
                    if (currentEndpointDiscoveryMetadata == null) 
                    {
                        if (this.totalDiscoveredEndpoints < 1) 
                        {
                            throw FxTrace.Exception.AsError(new EndpointNotFoundException(SR.DiscoveryClientChannelEndpointNotFound, this.exception));
                        }
                        else 
                        {
                            throw FxTrace.Exception.AsError(new EndpointNotFoundException(SR.DiscoveryClientChannelCreationFailed(this.totalDiscoveredEndpoints), this.exception)); 
                        } 
                    }
 
                    if (timeoutHelper.RemainingTime() == TimeSpan.Zero)
                    {
                        throw FxTrace.Exception.AsError(new TimeoutException(SR.DiscoveryClientChannelOpenTimeout(timeoutHelper.OriginalTimeout)));
                    } 

                    if (currentEndpointDiscoveryMetadata.ListenUris.Count == 0) 
                    { 
                        completed = this.CreateChannel(
                            ref innerChannel, 
                            currentEndpointDiscoveryMetadata.Address,
                            currentEndpointDiscoveryMetadata.Address.Uri,
                            timeoutHelper);
                    } 
                    else
                    { 
                        foreach (Uri listenUri in currentEndpointDiscoveryMetadata.ListenUris) 
                        {
                            completed = this.CreateChannel( 
                                ref innerChannel,
                                currentEndpointDiscoveryMetadata.Address,
                                listenUri,
                                timeoutHelper); 

                            if (completed) 
                            { 
                                break;
                            } 
                        }
                    }
                }
                while (!completed); 
            }
            finally 
            { 
                if (completed && TD.InnerChannelOpenSuccededIsEnabled())
                { 
                    TD.InnerChannelOpenSucceded(
                        currentEndpointDiscoveryMetadata.Address.ToString(),
                        GetVia(innerChannel).ToString()) ;
                } 

                this.Cleanup(timeoutHelper.RemainingTime()); 
            } 

            return innerChannel; 
        }

        bool CreateChannel(ref TChannel innerChannel, EndpointAddress to, Uri via, TimeoutHelper timeoutHelper)
        { 
            bool completed = false;
            Exception exception = null; 
 
            try
            { 
                innerChannel = this.innerChannelFactory.CreateChannel(to, via);
                innerChannel.Open(timeoutHelper.RemainingTime());
                completed = true;
            } 
            catch (TimeoutException timeoutException)
            { 
                throw FxTrace.Exception.AsError(new TimeoutException(SR.DiscoveryClientChannelOpenTimeout(timeoutHelper.OriginalTimeout), timeoutException)); 
            }
            catch (CommunicationException communicationException) 
            {
                exception = communicationException;
            }
            catch (ArgumentException argumentException) 
            {
                exception = argumentException; 
            } 
            catch (InvalidOperationException invalidOperationException)
            { 
                exception = invalidOperationException;
            }
            finally
            { 
                if (exception != null)
                { 
                    TraceInnerChannelFailure(innerChannel, to, via, exception); 
                }
 
                if (!completed && innerChannel != null)
                {
                    innerChannel.Abort();
                    innerChannel = null; 
                }
            } 
 
            return completed;
        } 

        void OnFindProgressChanged(object sender, FindProgressChangedEventArgs e)
        {
            lock (this.thisLock) 
            {
                if (!this.discoveryCompleted) 
                { 
                    this.discoveredEndpoints.EnqueueAndDispatch(e.EndpointDiscoveryMetadata, null, false);
                    if (++this.totalDiscoveredEndpoints == this.totalExpectedEndpoints) 
                    {
                        this.discoveryCompleted = true;
                        this.discoveredEndpoints.Shutdown();
                    } 
                }
            } 
        } 

        void OnFindCompleted(object sender, FindCompletedEventArgs e) 
        {
            lock (this.thisLock)
            {
                if(!this.discoveryCompleted) 
                {
                    if (e.Error != null || 
                        e.Cancelled || 
                        this.totalDiscoveredEndpoints == e.Result.Endpoints.Count)
                    { 
                        this.exception = e.Error;
                        this.discoveryCompleted = true;
                        this.discoveredEndpoints.Shutdown();
                    } 
                    else
                    { 
                        this.totalExpectedEndpoints = e.Result.Endpoints.Count; 
                    }
                } 
            }
        }

        [SecuritySafeCritical] 
        void InitializeAndFindAsync()
        { 
            DiscoveryEndpoint discoveryEndpoint = this.discoveryEndpointProvider.GetDiscoveryEndpoint(); 

            if (discoveryEndpoint == null) 
            {
                throw FxTrace.Exception.AsError(
                    new InvalidOperationException(
                        SR.DiscoveryMethodImplementationReturnsNull("GetDiscoveryEndpoint", this.discoveryEndpointProvider.GetType()))); 
            }
 
            this.discoveryClient = new DiscoveryClient(discoveryEndpoint); 
            this.discoveryClient.FindProgressChanged += new EventHandler(OnFindProgressChanged);
            this.discoveryClient.FindCompleted += new EventHandler(OnFindCompleted); 

            SynchronizationContext originalSynchronizationContext = SynchronizationContext.Current;
            if (originalSynchronizationContext != null)
            { 
                SynchronizationContext.SetSynchronizationContext(null);
 
                if (TD.SynchronizationContextSetToNullIsEnabled()) 
                {
                    TD.SynchronizationContextSetToNull(); 
                }
            }

            try 
            {
                // AsyncOperation uses the SynchronizationContext set during its 
                // initialization to Post the FindProgressed and FindProgressCompleted 
                // events. Hence even if the async operation does not complete
                // synchronously, the right SynchronizationContext will be used by 
                // AsyncOperation.
                this.discoveryClient.FindAsync(this.findCriteria, this);
            }
            finally 
            {
                if (originalSynchronizationContext != null) 
                { 
                    SynchronizationContext.SetSynchronizationContext(originalSynchronizationContext);
 
                    if (TD.SynchronizationContextResetIsEnabled())
                    {
                        TD.SynchronizationContextReset(originalSynchronizationContext.GetType().ToString());
                    } 
                }
            } 
 
            if (TD.FindInitialitedInDiscoveryClientChannelIsEnabled())
            { 
                TD.FindInitialitedInDiscoveryClientChannel();
            }
        }
 
        void Cleanup(TimeSpan timeout)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            Exception exception = null;
 
            lock (this.thisLock)
            {
                this.discoveryCompleted = true;
            } 

            try 
            { 
                this.discoveryClient.CancelAsync(this);
                ((ICommunicationObject)this.discoveryClient).Close(timeoutHelper.RemainingTime()); 
            }
            catch (TimeoutException timeoutException)
            {
                exception = timeoutException; 
            }
            catch (CommunicationException communicationException) 
            { 
                exception = communicationException;
            } 
            finally
            {
                if (exception != null && TD.DiscoveryClientInClientChannelFailedToCloseIsEnabled())
                { 
                    TD.DiscoveryClientInClientChannelFailedToClose(exception);
                } 
            } 

            this.discoveredEndpoints.Dispose(); 

            this.discoveryClient = null;
            this.discoveredEndpoints = null;
            this.findCriteria = null; 
            this.discoveryEndpointProvider = null;
            this.innerChannelFactory = null; 
        } 

        static void TraceInnerChannelFailure(TChannel innerChannel, EndpointAddress to, Uri via, Exception exception) 
        {
            if (innerChannel == null && TD.InnerChannelCreationFailedIsEnabled())
            {
                TD.InnerChannelCreationFailed(to.ToString(), via.ToString(), exception); 
            }
            else if (innerChannel != null && TD.InnerChannelOpenFailedIsEnabled()) 
            { 
                TD.InnerChannelOpenFailed(to.ToString(), via.ToString(), exception);
            } 
        }

        static Uri GetVia(TChannel innerChannel)
        { 
            Fx.Assert(innerChannel != null, "TChannel must be non null");
 
            IOutputChannel outputChannel = innerChannel as IOutputChannel; 
            if (outputChannel != null)
            { 
                return outputChannel.Via;
            }

            IRequestChannel requestChannel = innerChannel as IRequestChannel; 
            if (requestChannel != null)
            { 
                return requestChannel.Via; 
            }
 
            Fx.Assert("TChannel must be a type derived from IOutputChannel or IRequestChannel");
            return null;
        }
 
        sealed class DiscoveryChannelBuilderAsyncResult : IteratorAsyncResult
        { 
            static AsyncStep openStep; 
            static AsyncStep dequeueStep;
            TChannel innerChannel; 

            EndpointDiscoveryMetadata currentEndpointDiscoveryMetadata;
            DiscoveryClientChannelBase discoveryClientChannelBase;
 
            public DiscoveryChannelBuilderAsyncResult(
                DiscoveryClientChannelBase discoveryClientChannelBase, 
                TimeSpan timeout, 
                AsyncCallback callback,
                object state) 
                : base(callback, state)
            {
                this.discoveryClientChannelBase = discoveryClientChannelBase;
 
                this.Start(this, timeout);
            } 
 
            public static TChannel End(IAsyncResult result)
            { 
                DiscoveryChannelBuilderAsyncResult thisPtr = AsyncResult.End(result);
                thisPtr.discoveryClientChannelBase.Cleanup(thisPtr.RemainingTime());
                return thisPtr.innerChannel;
            } 

            protected override IEnumerator GetAsyncSteps() 
            { 
                this.discoveryClientChannelBase.InitializeAndFindAsync();
 
                while (true)
                {
                    this.currentEndpointDiscoveryMetadata = null;
                    yield return DiscoveryChannelBuilderAsyncResult.GetDequeueStep(); 

                    Exception ex = this.CheckEndpointDiscoveryMetadataAndGetException(); 
                    if (ex != null) 
                    {
                        this.CompleteOnce(ex); 
                        yield break;
                    }

                    bool checkListenUris = (currentEndpointDiscoveryMetadata.ListenUris.Count > 0); 
                    int index = 0;
 
                    do 
                    {
                        if (checkListenUris) 
                        {
                            this.CreateChannel(
                                this.currentEndpointDiscoveryMetadata.Address,
                                this.currentEndpointDiscoveryMetadata.ListenUris[index++]); 
                        }
                        else 
                        { 
                            this.CreateChannel(
                                this.currentEndpointDiscoveryMetadata.Address, 
                                this.currentEndpointDiscoveryMetadata.Address.Uri);
                        }

                        if (this.innerChannel != null) 
                        {
                            yield return DiscoveryChannelBuilderAsyncResult.GetOpenStep(); 
 
                            if (this.innerChannel != null)
                            { 
                                // The channel was successfully opened
                                if (TD.InnerChannelOpenSuccededIsEnabled())
                                {
                                    TD.InnerChannelOpenSucceded( 
                                        this.currentEndpointDiscoveryMetadata.Address.ToString(),
                                        GetVia(this.innerChannel).ToString()); 
                                } 

                                yield break; 
                            }
                        }
                    }
                    while (index < this.currentEndpointDiscoveryMetadata.ListenUris.Count); 
                }
            } 
 
            static AsyncStep GetDequeueStep()
            { 
                if (dequeueStep == null)
                {
                    dequeueStep = DiscoveryChannelBuilderAsyncResult.CallAsync(
                        (thisPtr, t, c, s) => thisPtr.discoveryClientChannelBase.discoveredEndpoints.BeginDequeue(thisPtr.RemainingTime(), c, s), 
                        (thisPtr, r) => thisPtr.currentEndpointDiscoveryMetadata = thisPtr.discoveryClientChannelBase.discoveredEndpoints.EndDequeue(r),
                        new IAsyncCatch[] 
                        { 
                            new DiscoveryChannelBuilderAsyncResult.AsyncCatch(HandleTimeoutException)
                        }); 
                }

                return dequeueStep;
            } 

            static AsyncStep GetOpenStep() 
            { 
                if (openStep == null)
                { 
                    openStep = DiscoveryChannelBuilderAsyncResult.CallAsync(
                        (thisPtr, t, c, s) => thisPtr.innerChannel.BeginOpen(thisPtr.RemainingTime(), c, s),
                        (thisPtr, r) => thisPtr.innerChannel.EndOpen(r),
                        new IAsyncCatch[] 
                        {
                            new DiscoveryChannelBuilderAsyncResult.AsyncCatch(HandleTimeoutException), 
                            new DiscoveryChannelBuilderAsyncResult.AsyncCatch(HandleCommunicationException), 
                            new DiscoveryChannelBuilderAsyncResult.AsyncCatch(HandleException)
                        }); 
                }

                return openStep;
            } 

            static Exception HandleTimeoutException(DiscoveryChannelBuilderAsyncResult thisPtr, TimeoutException e) 
            { 
                if (thisPtr.innerChannel != null)
                { 
                    thisPtr.innerChannel.Abort();
                    thisPtr.innerChannel = null;
                }
 
                return new TimeoutException(SR.DiscoveryClientChannelOpenTimeout(thisPtr.OriginalTimeout), e);
            } 
 
            static Exception HandleException(DiscoveryChannelBuilderAsyncResult thisPtr, Exception e)
            { 
                if (thisPtr.innerChannel != null)
                {
                    thisPtr.innerChannel.Abort();
                    thisPtr.innerChannel = null; 
                }
 
                return e; 
            }
 
            static Exception HandleCommunicationException(DiscoveryChannelBuilderAsyncResult thisPtr, CommunicationException e)
            {
                if (thisPtr.innerChannel != null)
                { 
                    thisPtr.innerChannel.Abort();
 
                    if (TD.InnerChannelOpenFailedIsEnabled()) 
                    {
                        TD.InnerChannelOpenFailed( 
                            thisPtr.currentEndpointDiscoveryMetadata.Address.ToString(),
                            GetVia(thisPtr.innerChannel).ToString(),
                            e);
                    } 

                    thisPtr.innerChannel = null; 
                } 

                return null; 
            }

            void CreateChannel(EndpointAddress address, Uri listenUri)
            { 
                Exception exception = null;
 
                try 
                {
                    this.innerChannel = this.discoveryClientChannelBase.innerChannelFactory.CreateChannel( 
                        address,
                        listenUri);
                }
                catch (ArgumentException argumentException) 
                {
                    exception = argumentException; 
                } 
                catch (InvalidOperationException invalidOperationException)
                { 
                    exception = invalidOperationException;
                }
                catch (CommunicationException communicationException)
                { 
                    exception = communicationException;
                    this.CompleteOnce(communicationException); 
                } 
                finally
                { 
                    if (exception != null && TD.InnerChannelCreationFailedIsEnabled())
                    {
                        TD.InnerChannelCreationFailed(address.ToString(), listenUri.ToString(), exception);
                    } 
                }
 
            } 

            Exception CheckEndpointDiscoveryMetadataAndGetException() 
            {
                if (this.RemainingTime() == TimeSpan.Zero)
                {
                    return new TimeoutException(SR.DiscoveryClientChannelOpenTimeout(this.OriginalTimeout)); 
                }
 
                if (this.currentEndpointDiscoveryMetadata == null) 
                {
                    string exceptionMessage = (this.discoveryClientChannelBase.totalDiscoveredEndpoints < 1) ? 
                        SR.DiscoveryClientChannelEndpointNotFound :
                        SR.DiscoveryClientChannelCreationFailed(this.discoveryClientChannelBase.totalDiscoveredEndpoints);
                    return new EndpointNotFoundException(exceptionMessage, this.discoveryClientChannelBase.exception);
                } 

                return null; 
            } 
        }
 
        class CloseAsyncResult : AsyncResult
        {
            TChannel innerChannel;
 
            public CloseAsyncResult(TChannel innerChannel, TimeSpan timeout, AsyncCallback callback, object state)
                : base(callback, state) 
            { 
                this.innerChannel = innerChannel;
 
                if (this.innerChannel != null)
                {
                    IAsyncResult closeResult = this.innerChannel.BeginClose(
                        timeout, 
                        PrepareAsyncCompletion(new AsyncCompletion(OnCloseCompleted)),
                        this); 
 
                    if (closeResult.CompletedSynchronously && OnCloseCompleted(closeResult))
                    { 
                        this.Complete(true);
                    }
                }
                else 
                {
                    this.Complete(true); 
                } 
            }
 
            public static void End(IAsyncResult result)
            {
                AsyncResult.End(result);
            } 

            bool OnCloseCompleted(IAsyncResult result) 
            { 
                this.innerChannel.EndClose(result);
                return true; 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK