Пример #1
0
        private void ShutdownPresenceView(AsyncTask task, object state)
        {
            RemotePresenceView presenceView = m_remotePresenceView;

            if (presenceView == null)
            {
                task.Complete(null);
                return;
            }
            m_remotePresenceView.PresenceNotificationReceived -= this.PresenceView_NotificationReceived;
            task.DoOneStep(
                delegate()
            {
                presenceView.BeginTerminate(
                    delegate(IAsyncResult ar)
                {
                    task.DoFinalStep(
                        delegate()
                    {
                        presenceView.EndTerminate(ar);
                    });
                },
                    null);
            });
        }
Пример #2
0
        private bool InitializeRemotePresenceView()
        {
            try
            {
                // RemotePresenceView provides a unified way to request presence for a set of presentities
                m_remotePresenceView = new RemotePresenceView(
                    m_applicationEndpoint,
                    new RemotePresenceViewSettings()
                {
                    SubscriptionMode = RemotePresenceViewSubscriptionMode.Default
                });


                // Wire up NotificationReceived before adding targets
                m_remotePresenceView.PresenceNotificationReceived +=
                    new EventHandler <RemotePresentitiesNotificationEventArgs>(RemotePresenceView_PresenceNotificationReceived);
                Helper.Logger.Info("UcPresenceProvider started");
                return(true);
            }
            catch (Exception ex)
            {
                Helper.Logger.Error("UCPresenceProvider failed: Could not initialize remote presence view {0}", ex);
                return(false);
            }
        }
Пример #3
0
        /// <summary>
        /// Constructor of a presence watcher supporting persistent, polling and on-demand subscriptions 
        /// to presence categories published by specified remote presentities. on-demand subscription is 
        /// also known as presence query. The code here also handles self-presence.
        /// </summary>
        /// <param name="endpoint"></param>
        public PresenceWatcher(LocalEndpoint endpoint)
        {
            _remotePresenceServices = endpoint.PresenceServices;

            // RemotePresenceView for persitent subscription:
            RemotePresenceViewSettings rpvs = new RemotePresenceViewSettings();
            rpvs.SubscriptionMode = RemotePresenceViewSubscriptionMode.Persistent;
            
            _persistentPresenceView = new RemotePresenceView(endpoint, rpvs);
            _persistentPresenceView.PresenceNotificationReceived += new EventHandler<RemotePresentitiesNotificationEventArgs>(PersistentPresenceReceivedEventHandler);
            
            _persistentPresenceView.SubscriptionStateChanged += new EventHandler<RemoteSubscriptionStateChangedEventArgs>(PersistentSubscriptionStateChangedEventHandler);
            
            // RemotePresenceView for polling subscription
            rpvs = new RemotePresenceViewSettings();
            rpvs.SubscriptionMode = RemotePresenceViewSubscriptionMode.Polling;
            rpvs.PollingInterval = new TimeSpan(0, 5, 0);  // every 5 minutes
            _pollingPresenceView = new RemotePresenceView(endpoint, rpvs);

            _pollingPresenceView.SetPresenceSubscriptionCategoriesForPolling(new string[] { "contactCard", "state", "note", "noteHistory" });
            
            _pollingPresenceView.PresenceNotificationReceived += new EventHandler<RemotePresentitiesNotificationEventArgs>(PollingPresenceReceivedEventHandler);

            _pollingPresenceView.SubscriptionStateChanged += new EventHandler<RemoteSubscriptionStateChangedEventArgs>(PollingSubscriptionStateChangedEventHandler);

        }
Пример #4
0
        /// <summary>
        /// Returns <c>true</c> if the given endpoint is available.
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PresenceState> GetPresenceStateAsync(string uri, CancellationToken cancellationToken)
        {
            // cache contains our data
            lock (cache)
                if (cache.ContainsKey(uri))
                    return cache[uri];

            // endpoint is down
            if (Endpoint.State != LocalEndpointState.Established)
                return null;

            // we associate the presence context with ourselves
            var view = Endpoint.PresenceServices.GetRemotePresenceViews()
                .FirstOrDefault(i => i.ApplicationContext == this);
            if (view == null)
            {
                view = new RemotePresenceView(Endpoint, new RemotePresenceViewSettings()
                {
                    SubscriptionMode = RemotePresenceViewSubscriptionMode.Default,
                    PollingInterval = TimeSpan.FromSeconds(15),
                });
                view.ApplicationContext = this;
                view.PresenceNotificationReceived += view_PresenceNotificationReceived;
            }

            // subscribe to the requested uri if not already done
            if (!view.GetPresentities().Contains(uri))
            {
                view.StartSubscribingToPresentities(new[] { new RemotePresentitySubscriptionTarget(uri) });
                cacheWh.Reset();
            }

            // wait a bit for state to arrive
            var t1 = WaitPresenceStateAsync(uri);
            var d1 = Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
            await Task.WhenAny(t1, d1);

            // state arrived
            if (t1.IsCompleted)
                return await t1;

            // taking too long; initiate a manual query
            var t2 = GetPresenceQueryAsync(uri, cancellationToken);
            var d2 = Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
            await Task.WhenAny(t1, t2, d2);

            // state finally arrived
            if (t1.IsCompleted)
                return await t1;

            // manual query completed
            if (t2.IsCompleted && t2.Result != null)
                // insert manual query result into cache
                lock (cache)
                    return cache[uri] = t2.Result;

            // could not obtain state in any way
            return null;
        }
Пример #5
0
 /// <summary>
 /// UnRegisters event handlers.
 /// </summary>
 /// <param name="remotePresenceView">Remote presence view.</param>
 private void UnRegisterEventHandlers(RemotePresenceView remotePresenceView)
 {
     if (remotePresenceView != null)
     {
         // Wire up NotificationReceived before adding targets
         remotePresenceView.PresenceNotificationReceived -= this.RemotePresenceView_PresenceNotificationReceived;
     }
 }
Пример #6
0
 public PresenceHelper(ApplicationEndpoint appEndpoint)
 {
     _appEndpoint = appEndpoint;
     
     // Subscribe to receive presence notifications
     _remotePresenceView = new RemotePresenceView(appEndpoint);
     _remotePresenceView.PresenceNotificationReceived += new EventHandler<RemotePresentitiesNotificationEventArgs>(PresenceReceivedEventHandler);
 }
Пример #7
0
 public static Task TerminateAsync(this
                                   RemotePresenceView view)
 {
     return(Task.Factory.FromAsync(
                view.BeginTerminate,
                view.EndTerminate,
                null));
 }
Пример #8
0
 private void StartPresenceView(AsyncTask task, object state)
 {
     m_remotePresenceView = new RemotePresenceView(this.UserEndpoint, new RemotePresenceViewSettings());
     m_remotePresenceView.PresenceNotificationReceived += this.PresenceView_NotificationReceived;
     m_remotePresenceView.SubscriptionStateChanged     += RemoteSubscriptionStateChanged;
     this.SubscribeToRemotePresentities();
     task.Complete(null);
 }
Пример #9
0
        /// <summary>
        /// Checks if a given uri is already subscribed or not.
        /// </summary>
        /// <param name="sipUri">Uri. Cannot be null or empty.</param>
        /// <returns>True if the uri is already subscribed to. False otherwise.</returns>
        private bool IsAlreadySubscribed(string sipUri)
        {
            Debug.Assert(!String.IsNullOrEmpty(sipUri), "Sip uri is null or empty");
            RemotePresenceView remotePresenceView = m_remotePresenceView;
            bool retVal = false;

            if (remotePresenceView != null)
            {
                var subscriptions = remotePresenceView.GetPresentities();
                retVal = subscriptions.Any(s => s.Equals(sipUri, StringComparison.InvariantCultureIgnoreCase));
            }
            return(retVal);
        }
Пример #10
0
        /// <summary>
        /// Starts the provider.
        /// </summary>
        /// <returns>True if uc presence prvovider was started successfully.</returns>
        internal void Start()
        {
            // RemotePresenceView provides a unified way to request presence for a set of presentities
            m_remotePresenceView = new RemotePresenceView(
                m_applicationEndpoint,
                new RemotePresenceViewSettings()
            {
                SubscriptionMode = RemotePresenceViewSubscriptionMode.Default
            });

            this.RegisterEventHandlers(m_remotePresenceView);
            Helper.Logger.Info("UcPresenceProvider started");
        }
Пример #11
0
        /// <summary>
        /// Log the subscription states that have changed.
        /// </summary>
        /// <param name="sender">
        /// View that saw subscription state changes.
        /// </param>
        /// <param name="e">Data about the state changes</param>
        private void RemotePresenceView_SubscriptionStateChanged(
            object sender,
            RemoteSubscriptionStateChangedEventArgs e)
        {
            // Extract the view that raised the event.
            RemotePresenceView view = sender as RemotePresenceView;

            // The event args can contain multiple StateChanged notifications
            foreach (KeyValuePair <RealTimeAddress, RemotePresentityStateChange> stateChanged in
                     e.SubscriptionStateChanges)
            {
                Console.WriteLine("\nView: " + view.ApplicationContext
                                  + "; SubscriptionState for user: "******" has changed from: " + stateChanged.Value.PreviousState
                                  + " to: " + stateChanged.Value.State + ".");
            }
        }
        // Helper method that is called by the imFlow_MessageReceived delegate.
        // This method returns the URI of the first available contact in a particular group.
        // The group is determined in the handler for the NotificationReceived event,
        // the ContactGroupServices_NotificationReceived delegate.
        private Uri GetFirstAvailableContact()
        {
            int ThreadID = Thread.CurrentThread.ManagedThreadId;

            Console.WriteLine("In getFirstAvailable - thread ID: " + ThreadID);
            RemotePresenceViewSettings presenceViewSettings = new RemotePresenceViewSettings();

            presenceViewSettings.SubscriptionMode = RemotePresenceViewSubscriptionMode.Persistent;
            _remotePresenceView = new RemotePresenceView(_userEndpoint, presenceViewSettings);

            _remotePresenceView.PresenceNotificationReceived += new EventHandler <
                RemotePresentitiesNotificationEventArgs>(RemotePresenceView_PresenceNotificationReceived);
            _userEndpoint.ContactGroupServices.NotificationReceived += new EventHandler
                                                                       <Microsoft.Rtc.Collaboration.ContactsGroups.ContactGroupNotificationEventArgs>(
                ContactGroupServices_NotificationReceived);
            Console.WriteLine("In getFirstAvailable, ContactGroupServices state: {0}", _userEndpoint.ContactGroupServices.CurrentState.ToString());
            _userEndpoint.ContactGroupServices.BeginSubscribe(ContactGroupSubscribeCB,
                                                              _userEndpoint.ContactGroupServices);
            return(_remoteContactUri);
        }
Пример #13
0
        private void StartupPresenceView(AsyncTask task, object state)
        {
            task.DoFinalStep(
                delegate()
            {
                CallbackRequest callbackRequest = (CallbackRequest)state;
                var viewSettings = new RemotePresenceViewSettings();
                viewSettings.SubscriptionMode = RemotePresenceViewSubscriptionMode.Persistent;
                var presenceView = new RemotePresenceView(callbackRequest.CutomerEndpoint, viewSettings);
                presenceView.ApplicationContext = callbackRequest;

                var target = new RemotePresentitySubscriptionTarget(callbackRequest.TargetUri);

                presenceView.PresenceNotificationReceived += this.PresenceView_NotificationReceived;
                presenceView.SubscriptionStateChanged     += this.PresenceView_SubscriptionStateChanged;

                callbackRequest.PresenceView = presenceView;

                presenceView.StartSubscribingToPresentities(
                    new RemotePresentitySubscriptionTarget[] { target });
            });
        }
Пример #14
0
        /// <summary>
        /// Log the presence notification for the remote user.
        /// </summary>
        /// <param name="sender">View that received the notification.</param>
        /// <param name="e">Data about the notifications received.</param>
        private void RemotePresenceView_NotificationReceived(object sender,
                                                             RemotePresentitiesNotificationEventArgs e)
        {
            // Extract the RemotePresenceView that received the notification.
            RemotePresenceView view = sender as RemotePresenceView;

            // A RemotePresentityNotification will contain all the
            // categories for one user; Notifications can contain notifications
            // for multiple users.
            foreach (RemotePresentityNotification notification in e.Notifications)
            {
                Console.WriteLine("\nView: " + view.ApplicationContext
                                  + " Received a Notification for user "
                                  + notification.PresentityUri + ".");

                // If a category on notification is null, the category
                // was not present in the notification. This means there were no
                // changes in that category.
                if (notification.AggregatedPresenceState != null)
                {
                    Console.WriteLine("Aggregate State = " + notification.AggregatedPresenceState.Availability + ".");
                }

                if (notification.PersonalNote != null)
                {
                    Console.WriteLine("PersonalNote: " + notification.PersonalNote.Message + ".");
                }

                if (notification.ContactCard != null)
                {
                    // A ContactCard contains many properties; only display
                    // some.
                    ContactCard contactCard = notification.ContactCard;
                    Console.WriteLine("ContactCard Company: " + contactCard.Company + ".");
                    Console.WriteLine("ContactCard DisplayName: " + contactCard.DisplayName + ".");
                    Console.WriteLine("ContactCard EmailAddress: " + contactCard.EmailAddress + ".");
                }
            }
        }
Пример #15
0
        public static void Start()
        {
            try
            {
                var host       = Plugin.LyncPlugin.Configuration.GetString("host");
                var thumbprint = Plugin.LyncPlugin.Configuration.GetString("thumbprint");
                var gruu       = Plugin.LyncPlugin.Configuration.GetString("gruu");
                var trustPort  = Plugin.LyncPlugin.Configuration.GetInt("trustedPort");
                var appPort    = Plugin.LyncPlugin.Configuration.GetInt("appPort");
                var sip        = Plugin.LyncPlugin.Configuration.GetString("accountSip");

                var platformSettings = new ServerPlatformSettings(UserAgent, host, trustPort, gruu, CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, thumbprint));

                Platform    = new CollaborationPlatform(platformSettings);
                AppEndpoint = new ApplicationEndpoint(Platform, new ApplicationEndpointSettings(sip, host, appPort)
                {
                    UseRegistration = true
                });

                Log("Starting Lync platform.");
                Platform.EndStartup(Platform.BeginStartup(null, null));
                Log("Lync platform started.");

                AppEndpoint.EndEstablish(AppEndpoint.BeginEstablish(null, null));

                UserEndpoint = new UserEndpoint(Platform, new UserEndpointSettings(sip, host, appPort)
                {
                    AutomaticPresencePublicationEnabled = true
                });
                UserEndpoint.EndEstablish(UserEndpoint.BeginEstablish(null, null));

                RemotePresence = new RemotePresenceView(UserEndpoint, new RemotePresenceViewSettings());
                RemotePresence.PresenceNotificationReceived += PresenceNotificationReceived;
            }
            catch (Exception ex)
            {
                Error(ex.Message);
            }
        }
        // Callback method referred to in the call to BeginTerminate on the RemotePresenceView instance.
        private void ViewTerminateCB(IAsyncResult ar)
        {
            RemotePresenceView view = ar.AsyncState as RemotePresenceView;

            view.EndTerminate(ar);
        }
Пример #17
0
 /// <summary>
 /// Helper to unwire important event handlers for a RemotePresenceView.
 /// </summary>
 /// <param name="view">View to remove event handlers from.</param>
 private void UnWireHandlersForView(RemotePresenceView view)
 {
     Console.WriteLine("\nUn-wiring handlers for view: " + view.ApplicationContext);
     view.SubscriptionStateChanged     -= RemotePresenceView_SubscriptionStateChanged;
     view.PresenceNotificationReceived -= RemotePresenceView_NotificationReceived;
 }
Пример #18
0
        /// <summary>
        /// Retrieves the application configuration and runs the sample.
        /// </summary>
        private void Run()
        {
            // Prepare and instantiate the platform.
            _helper       = new UCMASampleHelper();
            _userEndpoint = _helper.CreateEstablishedUserEndpoint(
                "SubscribePresence Sample User" /*endpointFriendlyName*/);

            // Get the URI of the remote user whose presence to subscribe to.
            _remoteUserUri = "sip:" + UCMASampleHelper.PromptUser(
                "Please enter the URI, in the format user@host, of the user whose Presence to subscribe to "
                + "=> ", "RemoteUserURI");

            // RemotePresenceView is the class to be used to subscribe to
            // another entity's presence.
            _remotePresenceView = new RemotePresenceView(_userEndpoint);

            // Wire up event handlers to receive the incoming notifications of
            // the remote user being subscribed to.
            _remotePresenceView.SubscriptionStateChanged += new EventHandler <
                RemoteSubscriptionStateChangedEventArgs>(
                RemotePresence_SubscriptionStateNotificationReceived);
            _remotePresenceView.PresenceNotificationReceived += new EventHandler <
                RemotePresentitiesNotificationEventArgs>(RemotePresence_PresenceNotificationReceived);

            try
            {
                // Subscribe to target user.
                _target = new RemotePresentitySubscriptionTarget(_remoteUserUri);
                _remotePresenceView.StartSubscribingToPresentities(
                    new RemotePresentitySubscriptionTarget[] { _target });

                // Subscribe to ContactGroupServices.
                // This is done so that the user can add/delete groups and
                // add/delete contacts, among other operations.
                _userEndpoint.ContactGroupServices.NotificationReceived += new EventHandler
                                                                           <Microsoft.Rtc.Collaboration.ContactsGroups.ContactGroupNotificationEventArgs>(
                    ContactGroupServices_NotificationReceived);
                _userEndpoint.ContactGroupServices.SubscriptionStateChange += new EventHandler
                                                                              <PresenceSubscriptionStateChangedEventArgs>(ContactGroupServices_SubscriptionStateChange);
                _userEndpoint.ContactGroupServices.BeginSubscribe(EndSubscribeCompleted,
                                                                  _userEndpoint.ContactGroupServices);

                // Wait for subscription to ContactsGroups to be completed.
                _waitForSubscribedToContactsGroupsCompleted.WaitOne();
                Console.WriteLine("Subscription to ContactsGroups completed.");

                // Create a new group.
                _userEndpoint.ContactGroupServices.BeginAddGroup(_groupName,
                                                                 null /* group data */,
                                                                 EndAddGroupCompleted,
                                                                 _userEndpoint.ContactGroupServices);

                // Wait for group to be created.
                _waitForGroupIdSet.WaitOne();

                // Add the remote user to the newly created group.
                ContactsGroups.ContactAddOptions addOptions
                    = new Microsoft.Rtc.Collaboration.ContactsGroups.ContactAddOptions();
                addOptions.GroupIds.Add(_groupId);
                _userEndpoint.ContactGroupServices.BeginAddContact(_remoteUserUri,
                                                                   addOptions,
                                                                   EndAddContactCompleted,
                                                                   _userEndpoint.ContactGroupServices);

                UCMASampleHelper.PauseBeforeContinuing("You are now subscribed to the presence of the remote "
                                                       + "user. \nPlease toggle the user state of the remote user to get the appropriate "
                                                       + "notifications. \nPress ENTER to delete the contact, delete the group, and unsubscribe"
                                                       + "to the presence of the remote user.");

                // Remove contact from group, and delete group.
                _userEndpoint.ContactGroupServices.BeginDeleteContact(_remoteUserUri,
                                                                      EndDeleteContactCompleted,
                                                                      _userEndpoint.ContactGroupServices);
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine("Could not subscribe to the presence of the remote user: "******"\n\n********************");
            Console.WriteLine("Press ENTER to shutdown and exit.");
            Console.WriteLine("********************\n\n");
            Console.ReadLine();


            // Shutdown Platform
            _helper.ShutdownPlatform();
        }
Пример #19
0
        /// <summary>
        /// Retrieves the application configuration and begins running the
        /// sample.
        /// </summary>
        private void Run()
        {
            // Prepare and instantiate the platform and an endpoint.
            _helper       = new UCMASampleHelper();
            _userEndpoint = _helper.CreateEstablishedUserEndpoint(
                "SubscribePresenceView Sample User" /*endpointFriendlyName*/);

            // Get the Uri of the remote user to subscribe to.
            _remoteUserUri = "sip:" +
                             UCMASampleHelper.PromptUser(
                "Please enter the URI, in the format User@Host, of the user to subscribe to => ",
                "RemoteUserURI");

            Console.WriteLine("\nChanging PresenceSubscriptionCategory Filter to only include ContactCard " +
                              "and PresenceState");
            // Set category filter. This is a global filter for all persistent
            // subscriptions and can only be changed before any subscriptions
            // are active.
            // BUGBUG: error CS0618: 'Microsoft.Rtc.Collaboration.LocalEndpoint.RemotePresence' is obsolete: 'This property will be removed from future Versions. Please see RemotePresenceView and PresenceServices instead.'
            // _userEndpoint.RemotePresence.PresenceSubscriptionCategories =
            //    new string[] { PresenceCategoryNames.ContactCard, PresenceCategoryNames.State };

            // RemotePresencView objects can be used to group subscriptions.
            // When a RemotePresenceView is created, it is created with the
            // specified RemotePresenceViewSettings and associated with the
            // specified LocalEndpoint. The views can then be accessed via the
            // LocalEndpoint setting: RemotePresenceViews.

            // RemotePresenceView.ApplicationContext can be used to pass or
            // store information related to the view (seen below).

            // Create a RemotePresenceView with a persistent subscription mode.
            // This type of view can represent a contact list, for example.
            // Note: The Default SubscriptionMode will start a subscription as
            // Persistent and downgrade to Polling if an error occurs.
            var persistentSettings = new RemotePresenceViewSettings();

            persistentSettings.SubscriptionMode = RemotePresenceViewSubscriptionMode.Default;
            _persistentView = new RemotePresenceView(_userEndpoint, persistentSettings);
            _persistentView.ApplicationContext = "Persistent View";

            // Wire up event handlers for the view
            this.WireUpHandlersForView(_persistentView);

            // Create a RemotePresenceView with a polling subscription mode
            // This type of view can represent a list of people
            // on the To: line of an e-mail, for example.
            var pollingSettings = new RemotePresenceViewSettings();

            pollingSettings.SubscriptionMode = RemotePresenceViewSubscriptionMode.Polling;
            // The line below is not necessary; PollingInterval has a default
            // (and minimum) value of 5 minutes.
            pollingSettings.PollingInterval = TimeSpan.FromMinutes(5);
            _pollingView = new RemotePresenceView(_userEndpoint, pollingSettings);
            _pollingView.ApplicationContext = "Polling View";

            // Wire up event handlers for the view
            this.WireUpHandlersForView(_pollingView);

            Console.WriteLine("\nChanging Polling View's category filter to only include Note.");
            _pollingView.SetPresenceSubscriptionCategoriesForPolling(
                new string[] { PresenceCategoryNames.Note });

            try
            {
                // This constructor does very basic validation on the uri
                _target = new RemotePresentitySubscriptionTarget(_remoteUserUri);
            }
            catch (ArgumentException argumentException)
            {
                // ArgumentException will be thrown if the parameter used to
                // create the RemotePresentitySubscriptionTarget is an
                // invalid sip Uri.

                // TODO (Left to the reader): Error handling code to either
                // retry creating the target with corrected parameters, log
                // the error for debugging or gracefully exit the program.
                Console.WriteLine(argumentException.ToString());
                throw;
            }

            Console.WriteLine("\nInitiating subscriptions for both Views to user: "******"succeed", but the StateChanged notifications will indicate the
            // subscription went to a Terminated state.
            _persistentView.StartSubscribingToPresentities(new RemotePresentitySubscriptionTarget[] { _target });
            _pollingView.StartSubscribingToPresentities(new RemotePresentitySubscriptionTarget[] { _target });

            // There is no callback for the StartSubscribingToPresentities
            // operation because subscriptions to multiple targets can
            // complete at different times. Completion or failure of the
            // subscription can be monitored through the
            // SubscriptionStateChanged event handler,
            // RemotePresenceView_NotificationReceived.

            UCMASampleHelper.PauseBeforeContinuing("Press ENTER to unsubscribe.");

            Console.WriteLine("\nBoth Views are terminating any subscriptions to user: "******"Press ENTER to shutdown and exit.");

            // Shutdown Platform
            _helper.ShutdownPlatform();
        }
Пример #20
0
            /// <summary>
            /// Starts subscribing to the Presence of agents upon successful registration of the endpoint
            /// </summary>
            private void OnEstablishComplete(IAsyncResult result)
            {
                try
                {
                    _matchMaker._endpoint.EndEstablish(result);

                    //create a SubscriptionTarget for each agent
                    RemotePresentitySubscriptionTarget[] contacts = new RemotePresentitySubscriptionTarget[_matchMaker._configuration.Agents.Count];
                    for (int i = 0; i < _matchMaker.Configuration.Agents.Count; i++)
                    {
                        contacts[i] = new RemotePresentitySubscriptionTarget(_matchMaker._configuration.Agents[i].SignInAddress);
                    }


                    RemotePresenceView MatchMakerPresence = new RemotePresenceView(_matchMaker._endpoint);

                    //Initiate the persistent batch subscription to the list of agents
                    //Only interested in subscribing to the Agents Availability. We should not expect more than one category instance
                    //per Remote Presentity notification change. Always register the event handler before starting the subscription.
                    MatchMakerPresence.PresenceNotificationReceived += _matchMaker.HandleAgentAvailabilityChanged;


                    MatchMakerPresence.StartSubscribingToPresentities(contacts);

                    try
                    {
                        _matchMaker._mohServer = new AcdMusicOnHoldServer(_matchMaker, _matchMaker.Configuration.MusicOnHoldFilePath, _matchMaker._logger);

                        _matchMaker._mohServer.BeginStartUp(ar =>
                        {
                            AcdMusicOnHoldServer mohServer = ar.AsyncState as AcdMusicOnHoldServer;

                            mohServer.EndStartUp(ar);

                            lock (_matchMaker._syncRoot)
                            {
                                _matchMaker.UpdateState(MatchMakerState.Started);
                            }

                            this.SetAsCompleted(null, false);
                        },
                                                            _matchMaker._mohServer);
                    }
                    catch (RealTimeException ex)
                    {
                        _matchMaker._logger.Log("AcdAgentMatchMaker failed to subscribe to the Presence of its Agents", ex);
                        _matchMaker.BeginShutdown((asyncResult) =>
                        {
                            _matchMaker.EndShutdown(asyncResult);
                            this.SetAsCompleted(ex, false);
                        },
                                                  ex);
                    }
                }
                catch (RealTimeException ex)
                {
                    _matchMaker._logger.Log("AcdAgentMatchMaker failed to subscribe to the Presence of its Agents; verify your agent configuration.", ex);
                    this.SetAsCompleted(ex, false);
                    _matchMaker.BeginShutdown((asyncResult) =>
                    {
                        _matchMaker.EndShutdown(asyncResult);
                        this.SetAsCompleted(ex, false);
                    },
                                              ex);
                }
            }