Пример #1
0
 public static Task SendSuccessDeliveryNotificationAsync(this
                                                         InstantMessagingFlow flow, InstantMessageId messageId)
 {
     return(Task.Factory.FromAsync(flow.BeginSendSuccessDeliveryNotification,
                                   flow.EndSendSuccessDeliveryNotification, messageId,
                                   null));
 }
Пример #2
0
        private void instantMessagingFlow2_MessageReceived(object sender, InstantMessageReceivedEventArgs e)
        {
            InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;

            //On an incoming Instant Message, print the contents to the console.
            Console.WriteLine("In callee's message handler: " + e.Sender.DisplayName + " said: " + e.TextBody);

            //Shutdown the platform
            if (e.TextBody.Equals("bye", StringComparison.OrdinalIgnoreCase))
            {
                _helper.ShutdownPlatform();
                _waitForShutdown.Set();
                return;
            }

            Console.WriteLine("Message received will be echoed");
            _messageToSend = "echo: " + e.TextBody;
            //Send the message on the InstantMessagingFlow.
            if (_IMFlow2 != null && _IMFlow2.State == MediaFlowState.Active)
            {
                _IMFlow2.BeginSendInstantMessage(_messageToSend, EndSendMessage, instantMessagingFlow);
            }
            else
            {
                Console.WriteLine("Could not echo message because flow was either null or inactive");
            }

            _waitForMessage2Received.Set();
        }
Пример #3
0
 /// <summary>
 /// Send status message to customer on the IM channel.
 /// </summary>
 public void SendStatusMessageToCustomer(ContentType contentType, byte[] body)
 {
     try
     {
         InstantMessagingFlow imFlow = this.imCall.Flow;
         imFlow.BeginSendInstantMessage(contentType,
                                        body,
                                        (asyncResult) =>
         {
             try
             {
                 imFlow.EndSendInstantMessage(asyncResult);
             }
             catch (RealTimeException rte)
             {
                 Console.WriteLine("Exception while sending message {0}", rte);
                 this.logger.Log("Exception while sending message {0}", rte);
             }
         },
                                        null);
     }
     catch (InvalidOperationException ioe)
     {
         Console.WriteLine("Exception while sending message {0}", ioe);
         this.logger.Log("Exception while sending message {0}", ioe);
     }
 }
Пример #4
0
        private void InstantMessagingFlow_MessageReceived(object sender, InstantMessageReceivedEventArgs e)
        {
            //xueming
            InstantMessagingFlow _instantMessagingFlow = sender as InstantMessagingFlow;

            // On an incoming Instant Message, print the contents to the console.
            Console.WriteLine(e.Sender.Uri + " said: " + e.TextBody);

            // Shutdown if the far end tells us to.
            if (e.TextBody.Equals("bye", StringComparison.OrdinalIgnoreCase))
            {
                // Shutting down the platform will terminate all attached objects.
                // If this was a production application, it would tear down the
                // Call/Conversation, rather than terminating the entire platform.
                _instantMessagingFlow.BeginSendInstantMessage("Shutting Down...", SendMessageCompleted,
                                                              _instantMessagingFlow);
                _helper.ShutdownPlatform();
                _OCSCompletedEvent.Set();
            }
            else
            {
                // Echo the instant message back to the far end (the sender of
                // the instant message).
                // Change the composing state of the local end user while sending messages to the far end.
                // A delay is introduced purposely to demonstrate the typing notification displayed by the
                // far end client; otherwise the notification will not last long enough to notice.
                _instantMessagingFlow.LocalComposingState = ComposingState.Composing;
                Thread.Sleep(2000);

                //Echo the message with an "Echo" prefix.
                _instantMessagingFlow.BeginSendInstantMessage("Echo: " + e.TextBody, SendMessageCompleted,
                                                              _instantMessagingFlow);
            }
        }
Пример #5
0
 public static Task <SendInstantMessageResult> SendInstantMessageAsync(this
                                                                       InstantMessagingFlow flow, ContentType contentType,
                                                                       byte[] body)
 {
     return(Task <SendInstantMessageResult> .Factory.FromAsync(flow.BeginSendInstantMessage,
                                                               flow.EndSendInstantMessage, contentType, body, null));
 }
Пример #6
0
        // Flow created indicates that there is a flow present to begin media
        // operations with, and that it is no longer null.
        public void InstantMessagingCall_FlowConfigurationRequested(object sender,
                                                                    InstantMessagingFlowConfigurationRequestedEventArgs e)
        {
            NonBlockingConsole.WriteLine("IM Flow Configuration Requested.");
            _instantMessagingFlow = e.Flow;

            Message m = new Message("IM Flow Configuration Requested.",
                                    MessageType.InstantMessage,
                                    _transcriptRecorder.Conversation.Id);

            _transcriptRecorder.OnMessageReceived(m);

            // Now that the flow is non-null, bind the event handlers for State
            // Changed and Message Received. When the flow goes active,
            // (as indicated by the state changed event) the program will send
            // the IM in the event handler.
            _instantMessagingFlow.StateChanged += new EventHandler <MediaFlowStateChangedEventArgs>(this.InstantMessagingFlow_StateChanged);

            // Message Received is the event used to indicate that a message has
            // been received from the far end.
            _instantMessagingFlow.MessageReceived += new EventHandler <InstantMessageReceivedEventArgs>(this.InstantMessagingFlow_MessageReceived);

            // call top level event handler
            if (_imFlowConfigurationRequestedEventHandler != null)
            {
                _imFlowConfigurationRequestedEventHandler(sender, e);
            }
        }
Пример #7
0
 public static Task SendFailureDeliveryNotificationAsync(this
                                                         InstantMessagingFlow flow, InstantMessageId messageId,
                                                         int responseCode)
 {
     return(Task.Factory.FromAsync(flow.BeginSendFailureDeliveryNotification,
                                   flow.EndSendFailureDeliveryNotification, messageId,
                                   responseCode, null));
 }
Пример #8
0
        private void instantMessagingFlow_MessageReceived(object sender, InstantMessageReceivedEventArgs e)
        {
            InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;

            //On an incoming Instant Message, print the contents to the console.
            Console.WriteLine("In caller's message handler: " + e.Sender.DisplayName + " said: " + e.TextBody);
            _waitForMessageReceived.Set();
        }
Пример #9
0
        private void instantMessagingFlow2_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
        {
            InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;

            Console.WriteLine("Flow state changed from " + e.PreviousState + " to " + e.State);

            //When flow is active, media operations (here, sending an IM) may begin.
            if (e.State == MediaFlowState.Active)
            {
                _IMFlow2 = instantMessagingFlow;
            }
        }
Пример #10
0
        /// <summary>
        /// Constructor to create new SendInstantMessageAsyncResult.
        /// </summary>
        /// <param name="request">Send Im message request. cannot be null.</param>
        /// <param name="imFlow">Instant messaging flow. Cannot be null.</param>
        /// <param name="textBody">Text body to send.</param>
        /// <param name="userCallback">User callback.</param>
        /// <param name="state">User state.</param>
        internal SendInstantMessageAsyncResult(SendInstantMessageRequest request,
                                               InstantMessagingFlow imFlow,
                                               string textBody,
                                               AsyncCallback userCallback,
                                               object state)
            : base(userCallback, state)
        {
            Debug.Assert(null != imFlow, "Im flow is null");
            Debug.Assert(null != request, "Request is null");

            m_imFlow = imFlow;
            m_sendImMessageRequest = request;
            m_textBody             = textBody;
        }
Пример #11
0
        private void SendMessageCompleted(IAsyncResult result)
        {
            InstantMessagingFlow instantMessagingFlow = result.AsyncState as InstantMessagingFlow;
            Exception            ex = null;

            try
            {
                instantMessagingFlow.EndSendInstantMessage(result);
                _sendCount += 1;
                _helper.log("The message has been sent.");
            }
            catch (OperationTimeoutException opTimeEx)
            {
                // OperationFailureException: Indicates failure to connect the
                // IM to the remote party due to timeout (called party failed to
                // respond within the expected time).
                // TODO (Left to the reader): Write real error handling code.
                ex = opTimeEx;
            }
            catch (RealTimeException rte)
            {
                // Other errors may cause other RealTimeExceptions to be thrown.
                // TODO (Left to the reader): Write real error handling code.
                ex = rte;
            }
            finally
            {
                // Reset the composing state of the local end user so that the typing notifcation as seen
                // by the far end client disappears.
                //_instantMessagingFlow.LocalComposingState = ComposingState.Idle;
                instantMessagingFlow.LocalComposingState = ComposingState.Idle;
                if (ex != null)
                {
                    // If the action threw an exception, terminate the sample,
                    // and print the exception to the console.
                    // TODO (Left to the reader): Write real error handling code.
                    Console.WriteLine(ex.ToString());
                    Console.WriteLine("Shutting down platform due to error");
                    _helper.ShutdownPlatform();
                }

                //xueming
                if (_sendCount >= _sentTotal)
                {
                    _helper.log("Shutting down platform after send all Message!");
                    _OCSCompletedEvent.Set();
                    _helper.ShutdownPlatform();
                }
            }
        }
Пример #12
0
        private void instantMessagingFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
        {
            InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;

            Console.WriteLine("Flow state changed from " + e.PreviousState + " to " + e.State);

            //When flow is active, media operations (here, sending an IM) may begin.
            if (e.State == MediaFlowState.Active)
            {
                _IMFlow = instantMessagingFlow;
                Console.WriteLine("Please type the message to send...");
                string msg = Console.ReadLine();
                //Send the message on the InstantMessagingFlow.
                instantMessagingFlow.BeginSendInstantMessage(msg, EndSendMessage, instantMessagingFlow);
            }
        }
Пример #13
0
        private void EndSendMessage(IAsyncResult ar)
        {
            InstantMessagingFlow instantMessagingFlow = ar.AsyncState as InstantMessagingFlow;

            try
            {
                instantMessagingFlow.EndSendInstantMessage(ar);
                Console.WriteLine("The message has been sent.");
            }
            catch (OperationTimeoutException opTimeEx)
            {
                // OperationFailureException: Indicates failure to connect the
                // IM to the remote party due to timeout (called party failed
                // to respond within the expected time).
                // TODO (Left to the reader): Add error handling code
                Console.WriteLine(opTimeEx.ToString());
            }
        }
Пример #14
0
        // Flow created indicates that there is a flow present to begin media
        // operations with, and that it is no longer null.
        public void instantMessagingCall2_InstantMessagingFlowConfigurationRequested(
            object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
        {
            InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;

            Console.WriteLine("Callee's Flow Created.");
            instantMessagingFlow = e.Flow;
            _IMFlow2             = instantMessagingFlow;

            // Now that the flow is non-null, bind the event handlers for State
            // Changed and Message Received. When the flow goes active, the
            // program will send the IM in the event handler.
            instantMessagingFlow.StateChanged += this.instantMessagingFlow2_StateChanged;

            // Message Received is the event used to indicate that a message
            // from the far end has been received.
            instantMessagingFlow.MessageReceived += this.instantMessagingFlow2_MessageReceived;
        }
Пример #15
0
        /// <summary>
        /// Im flow message received event handler.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ImFlowMessageReceived(object sender, InstantMessageReceivedEventArgs e)
        {
            if (Boolean.Parse(System.Configuration.ConfigurationManager.AppSettings["UseUserEndPoint"]))
            {
                if (this.isUserEndpointFirstMessage)
                {
                    this.isUserEndpointFirstMessage = false;
                    return;
                }
            }

            InstantMessagingFlow imFlow = sender as InstantMessagingFlow;
            string userResponse         = e.TextBody.Trim();

            Console.WriteLine("Received _ :" + userResponse + " from " + e.Sender.Uri);
            MimePartContentDescription package = this.menu.HandleUserInput(userResponse);

            if (package != null)
            {
                try
                {
                    imFlow.BeginSendInstantMessage(package.ContentType,
                                                   package.GetBody(),
                                                   (asyncResult) =>
                    {
                        try
                        {
                            imFlow.EndSendInstantMessage(asyncResult);
                        }
                        catch (RealTimeException rte)
                        {
                            Console.WriteLine("Exception while sending message {0}", rte);
                            this.logger.Log("Exception while sending message {0}", rte);
                        }
                    },
                                                   null);
                }
                catch (InvalidOperationException ioe)
                {
                    Console.WriteLine("Exception while sending message {0}", ioe);
                    this.logger.Log("Exception while sending message {0}", ioe);
                }
            }
        }
Пример #16
0
        private void InstantMessagingFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
        {
            Console.WriteLine("Flow state changed from " + e.PreviousState + " to " + e.State);
            // When flow is active, media operations (here, sending an IM)
            // may begin.
            //xueming
            InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;

            if (e.State == MediaFlowState.Active)
            {
                // Send the message on the InstantMessagingFlow.
                // _instantMessagingFlow.BeginSendInstantMessage(_messageToSend, SendMessageCompleted,
                //    _instantMessagingFlow);
                string str   = _messageToSend.ToString();
                byte[] bytes = Encoding.UTF8.GetBytes(str);
                instantMessagingFlow.BeginSendInstantMessage(new ContentType("text/html"), bytes, SendMessageCompleted,
                                                             instantMessagingFlow);
            }
        }
Пример #17
0
 private void SendIMResponse(InstantMessagingFlow imFlow, string message)
 {
     try
     {
         imFlow.BeginSendInstantMessage(
             message,
             delegate(IAsyncResult ar)
         {
             try
             {
                 imFlow.EndSendInstantMessage(ar);
             }
             catch (RealTimeException)
             {
             }
         },
             null);
     }
     catch (InvalidOperationException)
     {
     }
 }
Пример #18
0
        /// <summary>
        /// Im flow state changed event handler.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ImFlowStateChanged(object sender, MediaFlowStateChangedEventArgs e)
        {
            if (e.State == MediaFlowState.Active)
            {
                InstantMessagingFlow imFlow = sender as InstantMessagingFlow;

                MimePartContentDescription package = null;
                // Get the top level menu.
                if (this.menu.Level == MenuLevel.None)
                {
                    package = this.menu.HandleUserInput(" ");
                }
                else
                {
                    package = this.menu.GetMessage();
                }
                if (package != null)
                {
                    this.SendStatusMessageToCustomer(package.ContentType, package.GetBody());
                }
            }
        }
Пример #19
0
        // Flow created indicates that there is a flow present to begin media
        // operations with, and that it is no longer null.
        public void InstantMessagingCall_FlowConfigurationRequested(object sender,
                                                                    InstantMessagingFlowConfigurationRequestedEventArgs e)
        {
            Console.WriteLine("Flow Created.");
            _instantMessagingFlow = e.Flow;

            // Now that the flow is non-null, bind the event handlers for State
            // Changed and Message Received. When the flow goes active,
            // (as indicated by the state changed event) the program will send
            // the IM in the event handler.
            _instantMessagingFlow.StateChanged += this.InstantMessagingFlow_StateChanged;

            // Message Received is the event used to indicate that a message has
            // been received from the far end.
            _instantMessagingFlow.MessageReceived += this.InstantMessagingFlow_MessageReceived;

            // Also, here is a good place to bind to the
            // InstantMessagingFlow.RemoteComposingStateChanged event to receive
            // typing notifications of the far end user.
            _instantMessagingFlow.RemoteComposingStateChanged +=
                this.InstantMessagingFlow_RemoteComposingStateChanged;
        }
Пример #20
0
        public void TerminateCall()
        {
            if (_instantMessagingFlow != null)
            {
                _instantMessagingFlow.StateChanged    -= this.InstantMessagingFlow_StateChanged;
                _instantMessagingFlow.MessageReceived -= this.InstantMessagingFlow_MessageReceived;
                _instantMessagingFlow = null;
            }

            if (_instantMessagingCall != null)
            {
                _instantMessagingCall.BeginTerminate(InstantMessagingCallTerminated, _instantMessagingCall);
                _instantMessagingCall.StateChanged -= this.InstantMessagingCall_StateChanged;
                _instantMessagingCall.InstantMessagingFlowConfigurationRequested -= this.InstantMessagingCall_FlowConfigurationRequested;
                _instantMessagingCall.ConversationChanged -= this.InstantMessagingCall_ConversationChanged;
                _instantMessagingCall = null;
            }
            else
            {
                _waitForIMCallTerminated.Set();
            }

            if (_subConversation != null)
            {
                _transcriptRecorder.OnSubConversationRemoved(_subConversation, this);
                _transcriptRecorder = null;
            }
            if (_subConversation != null)
            {
                _transcriptRecorder.OnSubConversationRemoved(_subConversation, this);
                _subConversation = null;
            }

            _waitForIMCallAccepted.Reset();
            _waitForIMFlowStateChangedToActiveCompleted.Reset();
        }
        public void TerminateCall()
        {
            if (_instantMessagingFlow != null)
            {
                _instantMessagingFlow.StateChanged -= this.InstantMessagingFlow_StateChanged;
                _instantMessagingFlow.MessageReceived -= this.InstantMessagingFlow_MessageReceived;
                _instantMessagingFlow = null;
            }

            if (_instantMessagingCall != null)
            {
                _instantMessagingCall.BeginTerminate(InstantMessagingCallTerminated, _instantMessagingCall);
                _instantMessagingCall.StateChanged -= this.InstantMessagingCall_StateChanged;
                _instantMessagingCall.InstantMessagingFlowConfigurationRequested -= this.InstantMessagingCall_FlowConfigurationRequested;
                _instantMessagingCall.ConversationChanged -= this.InstantMessagingCall_ConversationChanged;
                _instantMessagingCall = null;
            }
            else
            {
                _waitForIMCallTerminated.Set();
            }

            if (_subConversation != null)
            {
                _transcriptRecorder.OnSubConversationRemoved(_subConversation, this);
                _transcriptRecorder = null;
            }
            if (_subConversation != null)
            {
                _transcriptRecorder.OnSubConversationRemoved(_subConversation, this);
                _subConversation = null;
            }

            _waitForIMCallAccepted.Reset();
            _waitForIMFlowStateChangedToActiveCompleted.Reset();
        }
Пример #22
0
 /// <summary>
 /// Unregisters event handlers for im flow.
 /// </summary>
 private void UnregisterIMflowEventHandlers(InstantMessagingFlow imFlow)
 {
     imFlow.StateChanged    -= this.ImFlowStateChanged;
     imFlow.MessageReceived -= this.ImFlowMessageReceived;
 }
Пример #23
0
 public static Task <SendInstantMessageResult> SendInstantMessageAsync(this
                                                                       InstantMessagingFlow flow, string textBody)
 {
     return(Task <SendInstantMessageResult> .Factory.FromAsync(flow.BeginSendInstantMessage,
                                                               flow.EndSendInstantMessage, textBody, null));
 }
Пример #24
0
        private void HandleIMCall(object state)
        {
            CallReceivedEventArgs <InstantMessagingCall> e = state as CallReceivedEventArgs <InstantMessagingCall>;
            ConversationParticipant caller = e.Call.RemoteEndpoint.Participant;
            InstantMessagingCall    imCall = e.Call;
            InstantMessagingFlow    imFlow = null;
            int messageCount = 0;

            imCall.InstantMessagingFlowConfigurationRequested +=
                delegate(object sender2, InstantMessagingFlowConfigurationRequestedEventArgs e2)
            {
                imFlow = e2.Flow;
                imFlow.MessageReceived +=
                    delegate(object sender3, InstantMessageReceivedEventArgs e3)
                {
                    messageCount++;
                    string message = e3.TextBody;
                    message = message.Trim();
                    if (!String.IsNullOrEmpty(message) && message.StartsWith("add", StringComparison.OrdinalIgnoreCase))
                    {
                        string[] tokens = message.Split(' ');
                        if (this.AppPlatform.ReverseNumberLookUp.AddEntry(tokens[1], caller.Uri))
                        {
                            this.SendIMResponse(imFlow, "Added telephone number.");
                        }
                        else
                        {
                            this.SendIMResponse(imFlow, "Telephone number exists.");
                        }
                    }
                    else if (!String.IsNullOrEmpty(message) && message.StartsWith("remove", StringComparison.OrdinalIgnoreCase))
                    {
                        string[] tokens = message.Split(' ');
                        if (this.AppPlatform.ReverseNumberLookUp.RemoveEntry(tokens[1], caller.Uri))
                        {
                            this.SendIMResponse(imFlow, "Removed telephone number.");
                        }
                        else
                        {
                            this.SendIMResponse(imFlow, "Telephone number does not exist or you do not own the tel #.");
                        }
                    }
                    else if (!String.IsNullOrEmpty(message) && message.Equals("list", StringComparison.OrdinalIgnoreCase))
                    {
                        Collection <string> list     = this.AppPlatform.ReverseNumberLookUp.FindPhoneNumbers(caller.Uri);
                        StringBuilder       response = new StringBuilder();
                        foreach (string s in list)
                        {
                            response.Append(s); response.Append("\r\n");
                        }
                        this.SendIMResponse(imFlow, response.ToString());
                    }
                    else
                    {
                        this.SendIMHelpMessage(imFlow);
                    }
                    if (messageCount > 5)         // We could also terminate based on timer.
                    {
                        this.TerminateIMCall(imCall);
                    }
                };
            };
            try
            {
                imCall.BeginAccept(
                    delegate(IAsyncResult ar)
                {
                    try
                    {
                        imCall.EndAccept(ar);
                        this.SendIMHelpMessage(imFlow);
                    }
                    catch (RealTimeException)
                    {
                    }
                },
                    null);
            }
            catch (InvalidOperationException)
            {
            }
        }
Пример #25
0
        /// <summary>
        /// Sends IM help message to caller.
        /// </summary>
        /// <param name="imFlow">The IM flow.</param>
        private void SendIMHelpMessage(InstantMessagingFlow imFlow)
        {
            string helpMessage = "The following commands are supported:\r\n1. add <tel>.\r\n2. remove <tel>.\r\n3. list.";

            this.SendIMResponse(imFlow, helpMessage);
        }
 //Handler for the InstantMessagingCall.InstantMessagingFlowConfigurationRequested event.
 void ImCall_InstantMessagingFlowConfigurationRequested(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
 {
     ImFlow = e.Flow;
     ImFlow.StateChanged += new EventHandler <MediaFlowStateChangedEventArgs>(ImFlow_StateChanged);
 }
Пример #27
0
 private void Call_InstantMessagingFlowConfigurationRequested(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
 {
     _flow = e.Flow;
     e.Flow.StateChanged += Flow_StateChanged;
     e.Flow.MessageReceived += Flow_MessageReceived;
 }
Пример #28
0
 private void SendMessage(InstantMessagingFlow flow, string message)
 {
     try
     {
         flow.BeginSendInstantMessage(message, ar =>
         {
             try
             {
                 flow.EndSendInstantMessage(ar);
             }
             catch (RealTimeException ex)
             {
                 Console.WriteLine(ex);
             }
         },
         null);
     }
     catch (InvalidOperationException ex)
     {
         Console.WriteLine(ex);
     }
 }
Пример #29
0
 private void _call_InstantMessagingFlowConfigurationRequested(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
 {
     _imFlow = e.Flow;
 }
        private void Run()
        {
            // A helper class to take care of platform and endpoint setup and cleanup.
            _helper = new UCMASampleHelper();

            // Create and establish a user endpoint using the user’s network credentials.
            _userEndpoint = _helper.CreateEstablishedUserEndpoint(
                "FindContact Sample User" /* endpointFriendlyName */);

            // Register a delegate to be called when an incoming InstantMessagingCall arrives.
            _userEndpoint.RegisterForIncomingCall <InstantMessagingCall>(InstantMessagingCall_Received);

            Console.WriteLine("Waiting for an incoming instant messaging call...");
            int ThreadID = Thread.CurrentThread.ManagedThreadId;

            Console.WriteLine("Main thread: ID " + ThreadID);
            // Pause main thread until an incoming call arrives and is accepted.
            _waitUntilIncomingCallIsAccepted.WaitOne();

            InstantMessagingFlow imFlow = _instantMessagingCall.Flow;

            imFlow.BeginSendInstantMessage("Press 1 for Service Department.\n" +
                                           "Press 2 for Sales Department.", CallSendInstantMessageCB, _instantMessagingCall);
            imFlow.MessageReceived += new EventHandler <InstantMessageReceivedEventArgs>(IMFlow_MessageReceived);
            _waitForAvailableTarget.WaitOne();

            if (_remoteContactUri != null)
            {
                imFlow.BeginSendInstantMessage("Contact found: " + _remoteContactUri.ToString(), CallSendInstantMessageCB, _instantMessagingCall);
                // Join the conversation to the IM MCU.
                _conferenceSession = _incomingConversation.ConferenceSession;
                ConferenceJoinOptions confJoinOptions = new ConferenceJoinOptions();
                confJoinOptions.JoinMode = JoinMode.Default;
                _conferenceSession.BeginJoin(confJoinOptions, ConferenceJoinCB, _conferenceSession);

                ThreadID = Thread.CurrentThread.ManagedThreadId;
                Console.WriteLine("Main thread: ID " + ThreadID);
                _waitUntilConferenceInvitationIsDelivered.WaitOne();
            }
            else
            {
                Console.WriteLine("Could not find an available contact.");
                imFlow.BeginSendInstantMessage("Could not find an available contact.\nPlease call again later.", CallSendInstantMessageCB, _instantMessagingCall);
            }
            // Unregister for notification of the MessageReceived event.
            imFlow.MessageReceived -= new EventHandler <InstantMessageReceivedEventArgs>(IMFlow_MessageReceived);
            // Cancel the subscription to the presence session by unsubscribing.
            _userEndpoint.ContactGroupServices.BeginUnsubscribe(ContactGroupUnsubscribeCB, _userEndpoint.ContactGroupServices);
            _remotePresenceView.BeginTerminate(ViewTerminateCB, _remotePresenceView);
            UCMASampleHelper.PauseBeforeContinuing("Press ENTER to shut down and exit.");

            // Terminate the call, the conversation, and then unregister the
            // endpoint from receiving an incoming call. Terminating these
            // additional objects individually is made redundant by shutting down
            // the platform right after, but in the multiple call case, this is
            // needed for object hygiene. Terminating a Conversation terminates
            // all its associated calls, and terminating an endpoint
            // terminates all conversations on that endpoint.
            _instantMessagingCall.BeginTerminate(CallTerminateCB, _instantMessagingCall);
            _waitUntilConversationIsTerminated.WaitOne();
            _userEndpoint.UnregisterForIncomingCall <InstantMessagingCall>(InstantMessagingCall_Received);

            // Clean up by shutting down the platform.
            _helper.ShutdownPlatform();
        }
        // Flow created indicates that there is a flow present to begin media 
        // operations with, and that it is no longer null.
        public void InstantMessagingCall_FlowConfigurationRequested(object sender,
            InstantMessagingFlowConfigurationRequestedEventArgs e)
        {
            NonBlockingConsole.WriteLine("IM Flow Configuration Requested.");
            _instantMessagingFlow = e.Flow;

            Message m = new Message("IM Flow Configuration Requested.",
                MessageType.InstantMessage,
                _transcriptRecorder.Conversation.Id);
            _transcriptRecorder.OnMessageReceived(m);

            // Now that the flow is non-null, bind the event handlers for State 
            // Changed and Message Received. When the flow goes active, 
            // (as indicated by the state changed event) the program will send 
            // the IM in the event handler.
            _instantMessagingFlow.StateChanged += new EventHandler<MediaFlowStateChangedEventArgs>(this.InstantMessagingFlow_StateChanged);

            // Message Received is the event used to indicate that a message has
            // been received from the far end.
            _instantMessagingFlow.MessageReceived += new EventHandler<InstantMessageReceivedEventArgs>(this.InstantMessagingFlow_MessageReceived);

            // call top level event handler
            if (_imFlowConfigurationRequestedEventHandler != null)
            {
                _imFlowConfigurationRequestedEventHandler(sender, e);
            }
        }