DiscoveryClient.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 / DiscoveryClient.cs / 1305376 / DiscoveryClient.cs

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

namespace System.ServiceModel.Discovery 
{
    using System; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel;
    using System.Globalization; 
    using System.Runtime;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.ServiceModel.Discovery.Configuration; 
    using System.Threading;
    using System.Xml; 
    using SR2 = System.ServiceModel.Discovery.SR; 

    [Fx.Tag.XamlVisible(false)] 
    public sealed class DiscoveryClient : ICommunicationObject, IDiscoveryInnerClientResponse, IDisposable
    {
        static TimeSpan defaultCloseDuration = TimeSpan.FromSeconds(60);
 
        SendOrPostCallback findCompletedDelegate;
        SendOrPostCallback findProgressChangedDelegate; 
        SendOrPostCallback resolveCompletedDelegate; 
        SendOrPostCallback proxyAvailableDelegate;
        Action findOperationTimeoutCallbackDelegate; 
        Action resolveOperationTimeoutCallbackDelegate;
        AsyncCallback probeOperationCallbackDelegate;
        AsyncCallback resolveOperationCallbackDelegate;
 
        IDiscoveryInnerClient innerClient;
 
        [Fx.Tag.Queue(typeof(AsyncOperationContext))] 
        AsyncOperationLifetimeManager asyncOperationsLifetimeManager;
 
        [Fx.Tag.SynchronizationObject(Blocking = false, Kind = Fx.Tag.SynchronizationKind.InterlockedNoSpin)]
        int closeCalled;

        public DiscoveryClient() 
            : this("*")
        { 
        } 

        public DiscoveryClient(string endpointConfigurationName) 
        {
            if (endpointConfigurationName == null)
            {
                throw FxTrace.Exception.ArgumentNull("endpointConfigurationName"); 
            }
 
            DiscoveryEndpoint discoveryEndpoint = 
                ConfigurationUtility.LookupEndpointFromClientSection(
                endpointConfigurationName); 

            this.Initialize(discoveryEndpoint);
        }
 
        public DiscoveryClient(DiscoveryEndpoint discoveryEndpoint)
        { 
            if (discoveryEndpoint == null) 
            {
                throw FxTrace.Exception.ArgumentNull("serviceDiscoveryEndpoint"); 
            }

            this.Initialize(discoveryEndpoint);
        } 

        public event EventHandler FindCompleted; 
        public event EventHandler FindProgressChanged; 
        public event EventHandler ProxyAvailable;
        public event EventHandler ResolveCompleted; 

        event EventHandler ICommunicationObject.Opening
        {
            add 
            {
                if (this.InternalOpening == null) 
                { 
                    this.InnerCommunicationObject.Opening += OnInnerCommunicationObjectOpening;
                } 
                this.InternalOpening += value;
            }
            remove
            { 
                this.InternalOpening -= value;
                if (this.InternalOpening == null) 
                { 
                    this.InnerCommunicationObject.Opening -= OnInnerCommunicationObjectOpening;
                } 
            }
        }

        event EventHandler ICommunicationObject.Opened 
        {
            add 
            { 
                if (this.InternalOpened == null)
                { 
                    this.InnerCommunicationObject.Opened += OnInnerCommunicationObjectOpened;
                }
                this.InternalOpened += value;
            } 

            remove 
            { 
                this.InternalOpened -= value;
                if (this.InternalOpened == null) 
                {
                    this.InnerCommunicationObject.Opened -= OnInnerCommunicationObjectOpened;
                }
            } 
        }
 
        event EventHandler ICommunicationObject.Closing 
        {
            add 
            {
                if (this.InternalClosing == null)
                {
                    this.InnerCommunicationObject.Closing += OnInnerCommunicationObjectClosing; 
                }
                this.InternalClosing += value; 
            } 

            remove 
            {
                this.InternalClosing -= value;
                if (this.InternalClosing == null)
                { 
                    this.InnerCommunicationObject.Closing -= OnInnerCommunicationObjectClosing;
                } 
            } 
        }
 
        event EventHandler ICommunicationObject.Closed
        {
            add
            { 
                if (this.InternalClosed == null)
                { 
                    this.InnerCommunicationObject.Closed += OnInnerCommunicationObjectClosed; 
                }
                this.InternalClosed += value; 
            }

            remove
            { 
                this.InternalClosed -= value;
                if (this.InternalClosed == null) 
                { 
                    this.InnerCommunicationObject.Closed -= OnInnerCommunicationObjectClosed;
                } 
            }
        }

        event EventHandler ICommunicationObject.Faulted 
        {
            add 
            { 
                if (this.InternalFaulted == null)
                { 
                    this.InnerCommunicationObject.Faulted += OnInnerCommunicationObjectFaulted;
                }
                this.InternalFaulted += value;
            } 

            remove 
            { 
                this.InternalFaulted -= value;
                if (this.InternalFaulted == null) 
                {
                    this.InnerCommunicationObject.Faulted -= OnInnerCommunicationObjectFaulted;
                }
            } 
        }
 
        event EventHandler InternalOpening; 
        event EventHandler InternalOpened;
        event EventHandler InternalClosing; 
        event EventHandler InternalClosed;
        event EventHandler InternalFaulted;

        public ChannelFactory ChannelFactory 
        {
            get 
            { 
                return this.InnerClient.ChannelFactory;
            } 
        }

        public ClientCredentials ClientCredentials
        { 
            get
            { 
                return this.InnerClient.ClientCredentials; 
            }
        } 

        public ServiceEndpoint Endpoint
        {
            get 
            {
                return this.InnerClient.Endpoint; 
            } 
        }
 
        public IClientChannel InnerChannel
        {
            get
            { 
                return this.InnerClient.InnerChannel;
            } 
        } 

        CommunicationState ICommunicationObject.State 
        {
            get
            {
                return this.InnerCommunicationObject.State; 
            }
        } 
 
        IDiscoveryInnerClient InnerClient
        { 
            get
            {
                return this.innerClient;
            } 
        }
 
        ICommunicationObject InnerCommunicationObject 
        {
            get 
            {
                return this.InnerClient.InnerCommunicationObject;
            }
        } 

        [Fx.Tag.InheritThrows(From = "Open", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))] 
        void ICommunicationObject.Open()
        { 
            this.InnerCommunicationObject.Open();
        }

        [Fx.Tag.InheritThrows(From = "Open", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        void ICommunicationObject.Open(TimeSpan timeout) 
        { 
            this.InnerCommunicationObject.Open(timeout);
        } 

        [Fx.Tag.InheritThrows(From = "BeginOpen", FromDeclaringType = typeof(ICommunicationObject))]
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        IAsyncResult ICommunicationObject.BeginOpen(AsyncCallback callback, object state) 
        {
            return this.InnerCommunicationObject.BeginOpen(callback, state); 
        } 

        [Fx.Tag.InheritThrows(From = "BeginOpen", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this.InnerCommunicationObject.BeginOpen(timeout, callback, state); 
        }
 
        [Fx.Tag.InheritThrows(From = "EndOpen", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        void ICommunicationObject.EndOpen(IAsyncResult result) 
        {
            this.InnerCommunicationObject.EndOpen(result);
        }
 
        [Fx.Tag.InheritThrows(From = "Close", FromDeclaringType = typeof(ICommunicationObject))]
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))] 
        void ICommunicationObject.Close() 
        {
            ((ICommunicationObject)this).Close(defaultCloseDuration); 
        }

        [Fx.Tag.InheritThrows(From = "Close", FromDeclaringType = typeof(ICommunicationObject))]
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))] 
        void ICommunicationObject.Close(TimeSpan timeout)
        { 
            if (this.IsCloseOrAbortCalled()) 
            {
                return; 
            }

            TimeoutException timeoutException = null;
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            try
            { 
                this.asyncOperationsLifetimeManager.Close(timeoutHelper.RemainingTime()); 
            }
            catch (TimeoutException e) 
            {
                timeoutException = e;
            }
 
            if (timeoutException != null)
            { 
                ((ICommunicationObject)this).Abort(); 
                throw FxTrace.Exception.AsError(new TimeoutException(SR2.DiscoveryCloseTimedOut(timeout), timeoutException));
            } 
            else
            {
                try
                { 
                    InnerCommunicationObject.Close(timeoutHelper.RemainingTime());
                } 
                catch (ProtocolException protocolException) 
                {
                    // no-op, When the client has received the required Matches and tries to 
                    // close the connection, there could be a ProtocolException if the service is
                    // trying to send more Matches. We catch such an exception and suppress it.
                    if (TD.DiscoveryClientProtocolExceptionSuppressedIsEnabled())
                    { 
                        TD.DiscoveryClientProtocolExceptionSuppressed(protocolException);
                    } 
                } 
            }
 
        }

        [Fx.Tag.InheritThrows(From = "BeginClose", FromDeclaringType = typeof(ICommunicationObject))]
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))] 
        IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object state)
        { 
            return ((ICommunicationObject)this).BeginClose(DiscoveryClient.defaultCloseDuration, callback, state); 
        }
 
        [Fx.Tag.InheritThrows(From = "BeginClose", FromDeclaringType = typeof(ICommunicationObject))]
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            if (this.IsCloseOrAbortCalled())
            { 
                return new CloseAsyncResult(callback, state); 
            }
            else 
            {
                return new CloseAsyncResult(this, timeout, callback, state);
            }
        } 

        [Fx.Tag.InheritThrows(From = "EndClose", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))] 
        void ICommunicationObject.EndClose(IAsyncResult result)
        { 
            CloseAsyncResult.End(result);
        }

        [Fx.Tag.InheritThrows(From = "Abort", FromDeclaringType = typeof(ICommunicationObject))] 
        void ICommunicationObject.Abort()
        { 
            this.InnerCommunicationObject.Abort(); 
            this.AbortActiveOperations();
        } 

        void IDisposable.Dispose()
        {
            this.Close(); 
        }
 
        [Fx.Tag.InheritThrows(From = "Open", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        public void Open() 
        {
            ((ICommunicationObject)this).Open();
        }
 
        [Fx.Tag.Throws(typeof(CommunicationException), "A communication failure interrupted this operation.")]
        [Fx.Tag.Throws.TimeoutAttribute] 
        [Fx.Tag.Blocking(CancelMethod = "Abort")] 
        public FindResponse Find(FindCriteria criteria)
        { 
            if (criteria == null)
            {
                throw FxTrace.Exception.ArgumentNull("criteria");
            } 

            if ((criteria.MaxResults == int.MaxValue) && (criteria.Duration.Equals(TimeSpan.MaxValue))) 
            { 
                throw FxTrace.Exception.AsError(new ArgumentException(SR2.DiscoveryFindCanNeverComplete));
            } 

            SyncOperationState syncOperationState = new SyncOperationState();
            this.FindAsync(criteria, syncOperationState);
 
            syncOperationState.WaitEvent.WaitOne();
            return ((FindCompletedEventArgs)syncOperationState.EventArgs).Result; 
        } 

        [Fx.Tag.NonThrowing] 
        [Fx.Tag.Blocking(CancelMethod = "Abort")]
        public void FindAsync(FindCriteria criteria)
        {
            this.FindAsync(criteria, null); 
        }
 
        [Fx.Tag.NonThrowing] 
        [Fx.Tag.Blocking(CancelMethod = "CancelAsync")]
        public void FindAsync(FindCriteria criteria, object userState) 
        {
            if (criteria == null)
            {
                throw FxTrace.Exception.ArgumentNull("criteria"); 
            }
 
            using (new DiscoveryOperationContextScope(InnerChannel)) 
            {
                this.FindAsyncOperation(criteria, userState); 
            }
        }

        [Fx.Tag.Throws(typeof(CommunicationException), "A communication failure interrupted this operation.")] 
        [Fx.Tag.Throws.TimeoutAttribute]
        [Fx.Tag.Blocking(CancelMethod = "Abort")] 
        public ResolveResponse Resolve(ResolveCriteria criteria) 
        {
            SyncOperationState syncOperationState = new SyncOperationState(); 
            this.ResolveAsync(criteria, syncOperationState);
            syncOperationState.WaitEvent.WaitOne();

            return ((ResolveCompletedEventArgs)syncOperationState.EventArgs).Result; 
        }
 
        [Fx.Tag.NonThrowing] 
        [Fx.Tag.Blocking(CancelMethod = "Abort")]
        public void ResolveAsync(ResolveCriteria criteria) 
        {
            this.ResolveAsync(criteria, null);
        }
 
        [Fx.Tag.NonThrowing]
        [Fx.Tag.Blocking(CancelMethod = "CancelAsync")] 
        public void ResolveAsync(ResolveCriteria criteria, object userState) 
        {
            if (criteria == null) 
            {
                throw FxTrace.Exception.ArgumentNull("criteria");
            }
 
            using (new DiscoveryOperationContextScope(InnerChannel))
            { 
                this.ResolveAsyncOperation(criteria, userState); 
            }
        } 

        [Fx.Tag.Throws(typeof(InvalidOperationException), "If there are more than one operations pending that are associated with the specified userState.")]
        public void CancelAsync(object userState)
        { 
            if (userState == null)
            { 
                throw FxTrace.Exception.ArgumentNull("userState"); 
            }
 
            AsyncOperationContext context = null;
            if (this.asyncOperationsLifetimeManager.TryRemoveUnique(userState, out context))
            {
                if (context is FindAsyncOperationContext) 
                {
                    this.PostFindCompleted((FindAsyncOperationContext)context, true, null); 
                } 
                else
                { 
                    this.PostResolveCompleted((ResolveAsyncOperationContext)context, true, null);
                }
            }
            else 
            {
                if (context != null) 
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR2.DiscoveryMultiplePendingOperationsPerUserState));
                } 
            }
        }

        [Fx.Tag.InheritThrows(From = "Close", FromDeclaringType = typeof(ICommunicationObject))] 
        [Fx.Tag.Blocking(CancelMethod = "Abort", CancelDeclaringType = typeof(ICommunicationObject))]
        public void Close() 
        { 
            ((ICommunicationObject)this).Close();
        } 

        void IDiscoveryInnerClientResponse.PostFindCompletedAndRemove(UniqueId operationId, bool cancelled, Exception error)
        {
            FindAsyncOperationContext context = this.asyncOperationsLifetimeManager.Remove(operationId); 
            if (context != null)
            { 
                this.PostFindCompleted(context, cancelled, error); 
            }
        } 

        void IDiscoveryInnerClientResponse.PostResolveCompletedAndRemove(UniqueId operationId, bool cancelled, Exception error)
        {
            ResolveAsyncOperationContext context = this.asyncOperationsLifetimeManager.Remove(operationId); 
            if (context != null)
            { 
                this.PostResolveCompleted(context, cancelled, error); 
            }
        } 

        void IDiscoveryInnerClientResponse.ProbeMatchOperation(UniqueId relatesTo, DiscoveryMessageSequence discoveryMessageSequence, Collection endpointDiscoveryMetadataCollection, bool findCompleted)
        {
            if (relatesTo == null) 
            {
                if (TD.DiscoveryMessageWithNullRelatesToIsEnabled()) 
                { 
                    TD.DiscoveryMessageWithNullRelatesTo(
                        ProtocolStrings.TracingStrings.ProbeMatches, 
                        OperationContext.Current.IncomingMessageHeaders.MessageId.ToString());
                }
                return;
            } 

            FindAsyncOperationContext context = null; 
            if (!this.asyncOperationsLifetimeManager.TryLookup(relatesTo, out context)) 
            {
                if (TD.DiscoveryMessageWithInvalidRelatesToOrOperationCompletedIsEnabled()) 
                {
                    TD.DiscoveryMessageWithInvalidRelatesToOrOperationCompleted(
                        ProtocolStrings.TracingStrings.ProbeMatches,
                        OperationContext.Current.IncomingMessageHeaders.MessageId.ToString(), 
                        relatesTo.ToString(),
                        ProtocolStrings.TracingStrings.FindOperation); 
                } 
                return;
            } 

            bool postCompleted = false;
            lock (context.SyncRoot)
            { 
                if (!context.IsCompleted && (context.Result.Endpoints.Count < context.MaxResults))
                { 
                    bool postProgress = (!context.IsSyncOperation && (this.FindProgressChanged != null)); 

                    foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in endpointDiscoveryMetadataCollection) 
                    {
                        context.Result.AddDiscoveredEndpoint(endpointDiscoveryMetadata, discoveryMessageSequence);
                        if (postProgress)
                        { 
                            context.AsyncOperation.Post(
                                this.findProgressChangedDelegate, 
                                new FindProgressChangedEventArgs(context.Progress, context.UserState, endpointDiscoveryMetadata, discoveryMessageSequence)); 
                        }
 
                        if (context.Result.Endpoints.Count == context.MaxResults)
                        {
                            postCompleted = true;
                            break; 
                        }
                    } 
                } 
                else
                { 
                    if (TD.DiscoveryMessageReceivedAfterOperationCompletedIsEnabled())
                    {
                        TD.DiscoveryMessageReceivedAfterOperationCompleted(
                            ProtocolStrings.TracingStrings.ProbeMatches, 
                            OperationContext.Current.IncomingMessageHeaders.MessageId.ToString(),
                            ProtocolStrings.TracingStrings.FindOperation); 
                    } 
                }
            } 

            if (postCompleted || findCompleted)
            {
                ((IDiscoveryInnerClientResponse)this).PostFindCompletedAndRemove(context.OperationId, false, null); 
            }
        } 
 
        void IDiscoveryInnerClientResponse.ResolveMatchOperation(UniqueId relatesTo, DiscoveryMessageSequence discoveryMessageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata)
        { 
            if (relatesTo == null)
            {
                TD.DiscoveryMessageWithNullRelatesTo(
                        ProtocolStrings.TracingStrings.ResolveMatches, 
                        OperationContext.Current.IncomingMessageHeaders.MessageId.ToString());
            } 
 
            ResolveAsyncOperationContext context = null;
            if (!this.asyncOperationsLifetimeManager.TryLookup(relatesTo, out context)) 
            {
                if (TD.DiscoveryMessageWithInvalidRelatesToOrOperationCompletedIsEnabled())
                {
                    TD.DiscoveryMessageWithInvalidRelatesToOrOperationCompleted( 
                        ProtocolStrings.TracingStrings.ResolveMatches,
                        OperationContext.Current.IncomingMessageHeaders.MessageId.ToString(), 
                        relatesTo.ToString(), 
                        ProtocolStrings.TracingStrings.ResolveOperation);
                } 

                return;
            }
 
            bool postCompleted = false;
            lock (context.SyncRoot) 
            { 
                if (!context.IsCompleted && (context.Result.EndpointDiscoveryMetadata == null))
                { 
                    context.Result.EndpointDiscoveryMetadata = endpointDiscoveryMetadata;
                    context.Result.MessageSequence = discoveryMessageSequence;
                    postCompleted = true;
                } 
                else
                { 
                    if (TD.DiscoveryMessageReceivedAfterOperationCompletedIsEnabled()) 
                    {
                        TD.DiscoveryMessageReceivedAfterOperationCompleted( 
                            ProtocolStrings.TracingStrings.ResolveMatches,
                            OperationContext.Current.IncomingMessageHeaders.MessageId.ToString(),
                            ProtocolStrings.TracingStrings.ResolveOperation);
                    } 
                }
            } 
 
            if (postCompleted)
            { 
                ((IDiscoveryInnerClientResponse)this).PostResolveCompletedAndRemove(context.OperationId, false, null);
            }
        }
 
        void IDiscoveryInnerClientResponse.HelloOperation(UniqueId relatesTo, DiscoveryMessageSequence proxyMessageSequence, EndpointDiscoveryMetadata proxyEndpointMetadata)
        { 
            if (relatesTo == null) 
            {
                TD.DiscoveryMessageWithNullRelatesTo( 
                        ProtocolStrings.TracingStrings.Hello,
                        OperationContext.Current.IncomingMessageHeaders.MessageId.ToString());

                return; 
            }
 
            AsyncOperationContext context = null; 
            if (!this.asyncOperationsLifetimeManager.TryLookup(relatesTo, out context))
            { 
                if (TD.DiscoveryMessageWithInvalidRelatesToOrOperationCompletedIsEnabled())
                {
                    TD.DiscoveryMessageWithInvalidRelatesToOrOperationCompleted(
                        ProtocolStrings.TracingStrings.Hello, 
                        OperationContext.Current.IncomingMessageHeaders.MessageId.ToString(),
                        relatesTo.ToString(), 
                        string.Format( 
                            CultureInfo.InvariantCulture,
                            "{0}/{1}", 
                            ProtocolStrings.TracingStrings.FindOperation,
                            ProtocolStrings.TracingStrings.ResolveOperation));
                }
                return; 
            }
 
            this.PostProxyAvailable(context, proxyEndpointMetadata, proxyMessageSequence); 
        }
 
        void Initialize(DiscoveryEndpoint discoveryEndpoint)
        {
            this.innerClient = discoveryEndpoint.DiscoveryVersion.Implementation.CreateDiscoveryInnerClient(discoveryEndpoint, this);
 
            this.asyncOperationsLifetimeManager = new AsyncOperationLifetimeManager();
 
            this.findCompletedDelegate = Fx.ThunkCallback(new SendOrPostCallback(RaiseFindCompleted)); 
            this.findProgressChangedDelegate = Fx.ThunkCallback(new SendOrPostCallback(RaiseFindProgressChanged));
            this.resolveCompletedDelegate = Fx.ThunkCallback(new SendOrPostCallback(RaiseResolveCompleted)); 
            this.proxyAvailableDelegate = Fx.ThunkCallback(new SendOrPostCallback(RaiseProxyAvailable));
            this.findOperationTimeoutCallbackDelegate = new Action(FindOperationTimeoutCallback);
            this.resolveOperationTimeoutCallbackDelegate = new Action(ResolveOperationTimeoutCallback);
 
            this.probeOperationCallbackDelegate = Fx.ThunkCallback(new AsyncCallback(ProbeOperationCompletedCallback));
            this.resolveOperationCallbackDelegate = Fx.ThunkCallback(new AsyncCallback(ResolveOperationCompletedCallback)); 
 
            this.closeCalled = 0;
        } 

        void OnInnerCommunicationObjectOpened(object sender, EventArgs e)
        {
            this.RaiseCommunicationObjectEvent(this.InternalOpened, e); 
        }
 
        void OnInnerCommunicationObjectOpening(object sender, EventArgs e) 
        {
            this.RaiseCommunicationObjectEvent(this.InternalOpening, e); 
        }

        void OnInnerCommunicationObjectClosing(object sender, EventArgs e)
        { 
            this.RaiseCommunicationObjectEvent(this.InternalClosing, e);
        } 
 
        void OnInnerCommunicationObjectClosed(object sender, EventArgs e)
        { 
            this.RaiseCommunicationObjectEvent(this.InternalClosed, e);
        }

        void OnInnerCommunicationObjectFaulted(object sender, EventArgs e) 
        {
            this.RaiseCommunicationObjectEvent(this.InternalFaulted, e); 
        } 

        void RaiseCommunicationObjectEvent(EventHandler handler, EventArgs e) 
        {
            if (handler != null)
            {
                handler(this, e); 
            }
        } 
 
        void FindAsyncOperation(FindCriteria criteria, object userState)
        { 
            AsyncOperationContext context = new FindAsyncOperationContext(
                OperationContext.Current.OutgoingMessageHeaders.MessageId,
                criteria.MaxResults,
                criteria.Duration, 
                userState);
 
            this.InitializeAsyncOperation(context); 

            Exception error = null; 
            try
            {
                if (!context.IsCompleted)
                { 
                    if (context.IsSyncOperation)
                    { 
                        this.InnerClient.ProbeOperation(criteria); 
                        this.StartTimer(context, this.findOperationTimeoutCallbackDelegate);
                    } 
                    else
                    {
                        IAsyncResult result = InnerClient.BeginProbeOperation(criteria, this.probeOperationCallbackDelegate, context);
                        if (result.CompletedSynchronously) 
                        {
                            this.CompleteProbeOperation(result); 
                        } 
                    }
                } 
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e)) 
                {
                    throw; 
                } 
                error = e;
            } 
            if (error != null)
            {
                ((IDiscoveryInnerClientResponse)this).PostFindCompletedAndRemove(context.OperationId, false, error);
            } 
        }
 
        void ResolveAsyncOperation(ResolveCriteria criteria, object userState) 
        {
            AsyncOperationContext context = 
                new ResolveAsyncOperationContext(
                OperationContext.Current.OutgoingMessageHeaders.MessageId,
                criteria.Duration,
                userState); 

            this.InitializeAsyncOperation(context); 
 
            Exception error = null;
            try 
            {
                if (context.IsSyncOperation)
                {
                    this.InnerClient.ResolveOperation(criteria); 
                    this.StartTimer(context, this.resolveOperationTimeoutCallbackDelegate);
                } 
                else 
                {
                    IAsyncResult result = InnerClient.BeginResolveOperation(criteria, this.resolveOperationCallbackDelegate, context); 
                    if (result.CompletedSynchronously)
                    {
                        this.CompleteResolveOperation(result);
                    } 
                }
            } 
            catch (Exception e) 
            {
                if (Fx.IsFatal(e)) 
                {
                    throw;
                }
                error = e; 
            }
            if (error != null) 
            { 
                ((IDiscoveryInnerClientResponse)this).PostResolveCompletedAndRemove(context.OperationId, false, error);
            } 
        }

        void InitializeAsyncOperation(AsyncOperationContext context)
        { 
            context.AsyncOperation = AsyncOperationManager.CreateOperation(context.UserState);
            if (!this.asyncOperationsLifetimeManager.TryAdd(context)) 
            { 
                if (this.asyncOperationsLifetimeManager.IsClosed || this.asyncOperationsLifetimeManager.IsAborted)
                { 
                    throw FxTrace.Exception.AsError(new ObjectDisposedException(this.GetType().Name));
                }
                else
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.DiscoveryDuplicateOperationId(context.OperationId)));
                } 
            } 
        }
 
        bool IsCloseOrAbortCalled()
        {
            return ((Interlocked.CompareExchange(ref this.closeCalled, 1, 0) == 1) || this.asyncOperationsLifetimeManager.IsAborted);
        } 

        void ProbeOperationCompletedCallback(IAsyncResult result) 
        { 
            if (result.CompletedSynchronously)
            { 
                return;
            }

            this.CompleteProbeOperation(result); 
        }
 
        void FindOperationTimeoutCallback(object state) 
        {
            AsyncOperationContext context = (AsyncOperationContext)state; 
            ((IDiscoveryInnerClientResponse)this).PostFindCompletedAndRemove(context.OperationId, false, null);
        }

        void CompleteProbeOperation(IAsyncResult result) 
        {
            AsyncOperationContext context = (AsyncOperationContext)result.AsyncState; 
 
            Exception error = null;
            try 
            {
                this.InnerClient.EndProbeOperation(result);
            }
            catch (Exception e) 
            {
                if (Fx.IsFatal(e)) 
                { 
                    throw;
                } 
                error = e;
            }

            if (error != null) 
            {
                ((IDiscoveryInnerClientResponse)this).PostFindCompletedAndRemove(context.OperationId, false, error); 
            } 
            else
            { 
                this.StartTimer(context, this.findOperationTimeoutCallbackDelegate);
            }
        }
 
        void PostFindCompleted(FindAsyncOperationContext context, bool cancelled, Exception error)
        { 
            bool completed = false; 
            lock (context.SyncRoot)
            { 
                if (!context.IsCompleted)
                {
                    context.Complete();
                    completed = true; 
                }
            } 
 
            if (completed)
            { 
                FindCompletedEventArgs e = new FindCompletedEventArgs(error, cancelled, context.UserState, context.Result);
                if (DispatchToSyncOperation(e) || (this.FindCompleted == null))
                {
                    context.AsyncOperation.OperationCompleted(); 
                }
                else 
                { 
                    context.AsyncOperation.PostOperationCompleted(this.findCompletedDelegate, e);
                } 
            }
        }

        void RaiseFindCompleted(object state) 
        {
            EventHandler handler = this.FindCompleted; 
            if (handler != null) 
            {
                handler(this, (FindCompletedEventArgs)state); 
            }
        }

        void RaiseFindProgressChanged(object state) 
        {
            EventHandler handler = this.FindProgressChanged; 
            if (handler != null) 
            {
                handler(this, (FindProgressChangedEventArgs)state); 
            }
        }

        void ResolveOperationCompletedCallback(IAsyncResult result) 
        {
            if (result.CompletedSynchronously) 
            { 
                return;
            } 

            this.CompleteResolveOperation(result);
        }
 
        void ResolveOperationTimeoutCallback(object state)
        { 
            AsyncOperationContext context = (AsyncOperationContext)state; 
            ((IDiscoveryInnerClientResponse)this).PostResolveCompletedAndRemove(context.OperationId, false, null);
        } 

        void CompleteResolveOperation(IAsyncResult result)
        {
            AsyncOperationContext context = (AsyncOperationContext)result.AsyncState; 

            Exception error = null; 
            try 
            {
                this.InnerClient.EndResolveOperation(result); 
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e)) 
                {
                    throw; 
                } 
                error = e;
            } 
            if (error != null)
            {
                ((IDiscoveryInnerClientResponse)this).PostResolveCompletedAndRemove(context.OperationId, false, error);
            } 
            else
            { 
                this.StartTimer(context, this.resolveOperationTimeoutCallbackDelegate); 
            }
        } 

        void PostResolveCompleted(ResolveAsyncOperationContext context, bool cancelled, Exception error)
        {
            bool completed = false; 
            lock (context.SyncRoot)
            { 
                if (!context.IsCompleted) 
                {
                    context.Complete(); 
                    completed = true;
                }
            }
 
            if (completed)
            { 
                ResolveCompletedEventArgs e = new ResolveCompletedEventArgs(error, cancelled, context.UserState, context.Result); 
                if (DispatchToSyncOperation(e) || (this.ResolveCompleted == null))
                { 
                    context.AsyncOperation.OperationCompleted();
                }
                else
                { 
                    context.AsyncOperation.PostOperationCompleted(this.resolveCompletedDelegate, e);
                } 
            } 
        }
 
        void RaiseResolveCompleted(object state)
        {
            EventHandler handler = this.ResolveCompleted;
            if (handler != null) 
            {
                handler(this, (ResolveCompletedEventArgs)state); 
            } 
        }
 
        void PostProxyAvailable(
            AsyncOperationContext context,
            EndpointDiscoveryMetadata proxyEndpointMetadata,
            DiscoveryMessageSequence proxyMessageSequence) 
        {
            if (TD.DiscoveryClientReceivedMulticastSuppressionIsEnabled()) 
            { 
                TD.DiscoveryClientReceivedMulticastSuppression();
            } 

            if (this.ProxyAvailable != null)
            {
                lock (context.SyncRoot) 
                {
                    if (!context.IsCompleted) 
                    { 
                        AnnouncementEventArgs e = new AnnouncementEventArgs(proxyMessageSequence, proxyEndpointMetadata);
                        context.AsyncOperation.Post(this.proxyAvailableDelegate, e); 
                    }
                }
            }
        } 

        void RaiseProxyAvailable(object state) 
        { 
            EventHandler handler = this.ProxyAvailable;
            if (handler != null) 
            {
                handler(this, (AnnouncementEventArgs)state);
            }
        } 

        void StartTimer(AsyncOperationContext context, Action operationTimeoutCallbackDelegate) 
        { 
            if (!this.InnerClient.IsRequestResponse)
            { 
                lock (context.SyncRoot)
                {
                    if (!context.IsCompleted)
                    { 
                        context.StartTimer(operationTimeoutCallbackDelegate);
                    } 
                } 
            }
        } 

        bool DispatchToSyncOperation(AsyncCompletedEventArgs e)
        {
            if (e.UserState is SyncOperationState) 
            {
                SyncOperationState syncOperationState = (SyncOperationState)e.UserState; 
                syncOperationState.EventArgs = e; 
                syncOperationState.WaitEvent.Set();
                return true; 
            }
            else
            {
                return false; 
            }
        } 
 
        void AbortActiveOperations()
        { 
            AsyncOperationContext[] activeOperations = this.asyncOperationsLifetimeManager.Abort();

            for (int i = 0; i < activeOperations.Length; i++)
            { 
                if (activeOperations[i] is FindAsyncOperationContext)
                { 
                    this.PostFindCompleted((FindAsyncOperationContext)activeOperations[i], true, null); 
                }
                else 
                {
                    this.PostResolveCompleted((ResolveAsyncOperationContext)activeOperations[i], true, null);
                }
            } 
        }
 
        class CloseAsyncResult : AsyncResult 
        {
            static AsyncCompletion onAsyncLifetimeManangerCloseCompleted = new AsyncCompletion(OnAsyncLifetimeManagerCloseCompleted); 
            static AsyncCompletion onInnerCommunicationObjectCloseCompleted = new AsyncCompletion(OnInnerCommunicationObjectCloseCompleted);

            DiscoveryClient client;
            TimeoutHelper timeoutHelper; 

            internal CloseAsyncResult(AsyncCallback callback, object state) 
                : base(callback, state) 
            {
                Complete(true); 
            }

            internal CloseAsyncResult(DiscoveryClient client, TimeSpan timeout, AsyncCallback callback, object state)
                : base(callback, state) 
            {
                this.client = client; 
                this.timeoutHelper = new TimeoutHelper(timeout); 

                IAsyncResult result = this.client.asyncOperationsLifetimeManager.BeginClose( 
                    this.timeoutHelper.RemainingTime(),
                    this.PrepareAsyncCompletion(onAsyncLifetimeManangerCloseCompleted),
                    this);
 
                if (result.CompletedSynchronously && OnAsyncLifetimeManagerCloseCompleted(result))
                { 
                    Complete(true); 
                }
            } 

            internal static void End(IAsyncResult result)
            {
                AsyncResult.End(result); 
            }
 
            static bool OnAsyncLifetimeManagerCloseCompleted(IAsyncResult result) 
            {
                CloseAsyncResult thisPtr = (CloseAsyncResult)result.AsyncState; 
                Exception timeoutException = null;
                try
                {
                    thisPtr.client.asyncOperationsLifetimeManager.EndClose(result); 
                }
                catch (TimeoutException e) 
                { 
                    timeoutException = e;
                } 

                if (timeoutException != null)
                {
                    ((ICommunicationObject)thisPtr.client).Abort(); 
                    throw FxTrace.Exception.AsError(
                        new TimeoutException( 
                        SR2.DiscoveryCloseTimedOut(thisPtr.timeoutHelper.OriginalTimeout), 
                        timeoutException));
                } 

                IAsyncResult closeAsyncResult = thisPtr.client.InnerCommunicationObject.BeginClose(
                    thisPtr.timeoutHelper.RemainingTime(),
                    thisPtr.PrepareAsyncCompletion(onInnerCommunicationObjectCloseCompleted), 
                    thisPtr);
 
                if (closeAsyncResult.CompletedSynchronously) 
                {
                    return OnInnerCommunicationObjectCloseCompleted(closeAsyncResult); 
                }
                else
                {
                    return false; 
                }
            } 
 
            static bool OnInnerCommunicationObjectCloseCompleted(IAsyncResult result)
            { 
                CloseAsyncResult thisPtr = (CloseAsyncResult)result.AsyncState;
                thisPtr.client.InnerCommunicationObject.EndClose(result);
                return true;
            } 
        }
 
        sealed class DiscoveryOperationContextScope : IDisposable 
        {
            OperationContextScope operationContextScope; 
            UniqueId originalMessageId;
            EndpointAddress originalReplyTo;
            Uri originalTo;
 
            public DiscoveryOperationContextScope(IClientChannel clientChannel)
            { 
                if (DiscoveryUtility.IsCompatible(OperationContext.Current, clientChannel)) 
                {
                    // reuse the same context 
                    this.originalMessageId = OperationContext.Current.OutgoingMessageHeaders.MessageId;
                    this.originalReplyTo = OperationContext.Current.OutgoingMessageHeaders.ReplyTo;
                    this.originalTo = OperationContext.Current.OutgoingMessageHeaders.To;
                } 
                else
                { 
                    // create new context 
                    this.operationContextScope = new OperationContextScope(clientChannel);
                } 

                if (this.originalMessageId == null)
                {
                    // this is either a new context or an existing one with no message id. 
                    OperationContext.Current.OutgoingMessageHeaders.MessageId = new UniqueId();
                } 
 
                OperationContext.Current.OutgoingMessageHeaders.ReplyTo = clientChannel.LocalAddress;
                OperationContext.Current.OutgoingMessageHeaders.To = clientChannel.RemoteAddress.Uri; 
            }

            public void Dispose()
            { 
                if (this.operationContextScope != null)
                { 
                    this.operationContextScope.Dispose(); 
                }
                else 
                {
                    OperationContext.Current.OutgoingMessageHeaders.MessageId = this.originalMessageId;
                    OperationContext.Current.OutgoingMessageHeaders.ReplyTo = this.originalReplyTo;
                    OperationContext.Current.OutgoingMessageHeaders.To = this.originalTo; 
                }
            } 
        } 

        class FindAsyncOperationContext : AsyncOperationContext 
        {
            FindResponse result;

            internal FindAsyncOperationContext(UniqueId operationId, int maxResults, TimeSpan duration, object userState) 
                : base(operationId, maxResults, duration, userState)
            { 
                this.result = new FindResponse(); 
            }
 
            public FindResponse Result
            {
                get
                { 
                    return this.result;
                } 
            } 

            public int Progress 
            {
                get
                {
                    int progress = 0; 

                    if (MaxResults != int.MaxValue) 
                    { 
                        progress = (int)((float)Result.Endpoints.Count / (float)MaxResults * 100);
                    } 
                    else if (StartedAt != null)
                    {
                        TimeSpan elaspedTime = DateTime.UtcNow.Subtract(StartedAt.Value);
                        progress = (int)(elaspedTime.TotalMilliseconds / Duration.TotalMilliseconds * 100); 
                    }
 
                    return progress; 
                }
            } 
        }

        class ResolveAsyncOperationContext : AsyncOperationContext
        { 
            ResolveResponse result;
 
            internal ResolveAsyncOperationContext(UniqueId operationId, TimeSpan duration, object userState) 
                : base(operationId, 1, duration, userState)
            { 
                this.result = new ResolveResponse();
            }

            public ResolveResponse Result 
            {
                get 
                { 
                    return this.result;
                } 
            }
        }
    }
} 

// 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