2015-07-15 1 views
1

J'essaie de démarrer une conférence en utilisant l'exemple de conférence de base UCMA 4.0 et le premier point de terminaison d'utilisateur coincé à l'établissement de l'appel (c'est lync ne sonne pas). L'exception de délai d'attente est déclenchée après un certain temps. Quel est le problème principal? BTW, la plate-forme est déjà en cours de démarrage avec la découverte de 3 points de terminaison d'application tel qu'établi.UCMA Conférence bloquée au premier participant établissant

sip: [email protected]; gruu; opaque = srvr: yyapp: EHghH8UXNVqIedXU3YgJyQAAYYApp sip: [email protected]; gruu; opaque = srvr: yyapp: EHghH8UXNVqIedXU3YgJyQAAMachine1 sip: [email protected]; gruu; opaque = srvr: yyapp: EHghH8UXNVqIedXU3YgJyQAAMachine2 sip: [email protected]; gruu; opaque = srvr: yyapp: EHghH8UXNVqIedXU3YgJyQAAMachine3 « LyncGame.Gateway.TestConnection .vshost.exe '(CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): chargé' C: \ Windows \ Microsoft.Net \ assembly \ GAC_MSIL \ System.Data.SqlXml \ v4.0_4.0.0.0__b77a5c561934e089 \ System.Data.SqlXml.dll '. Symboles de chargement ignorés. Le module est optimisé et l'option de débogage 'Just My Code' est activée. 'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): chargé 'System.Xml.Xsl.CompiledQuery.1'. Le thread 0x6e8 s'est terminé avec le code 259 (0x103). Le thread 0x3dd4 s'est terminé avec le code 259 (0x103). Le thread 0x2138 s'est terminé avec le code 259 (0x103). 'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): chargé 'C: \ Windows \ Microsoft.Net \ assembly \ GAC_MSIL \ System.Security \ v4. 0_4.0.0.0__b03f5f7f11d50a3a \ System.Security.dll '. Symboles de chargement ignorés. Le module est optimisé et l'option de débogage 'Just My Code' est activée. Le thread 0x3180 s'est terminé avec le code 259 (0x103). Le thread 0x350c s'est terminé avec le code 259 (0x103). Le thread 0x1698 s'est terminé avec le code 0 (0x0). Le thread 0x3ef4 s'est terminé avec le code 0 (0x0). Le thread 0x3f00 s'est terminé avec le code 259 (0x103). Le thread 0x2a24 s'est terminé avec le code 259 (0x103). Le thread 0x3fc0 s'est terminé avec le code 259 (0x103). Le thread 0x3750 s'est terminé avec le code 259 (0x103). Le thread 0x27b8 s'est terminé avec le code 259 (0x103). Le thread 0x11e0 s'est terminé avec le code 259 (0x103). Le thread 0x2214 s'est terminé avec le code 259 (0x103). Le thread 0x1564 s'est terminé avec le code 259 (0x103). Le thread 0x3740 s'est terminé avec le code 259 (0x103). Le thread 0x28a8 s'est terminé avec le code 259 (0x103). Le thread 0x1da8 s'est terminé avec le code 259 (0x103). Une exception de première chance de type 'Microsoft.Rtc.Signaling.OperationTimeoutException' a eu lieu dans Microsoft.Rtc.Collaboration.dll

class UCMAConference 
{ 
    #region Locals 
    // The IM to send upon joining the MCU. 
    private static String _messageToSend = "Hello, World!"; 

    private Conference _conference; 

    private ApplicationEndpoint _callerEndpoint, _calleeEndpoint; 

    //Wait handles are only present to keep things synchronous and easy to read. 
    private AutoResetEvent _waitForCallEstablish = new AutoResetEvent(false); 

    private AutoResetEvent _waitForConferenceScheduling = new AutoResetEvent(false); 

    private AutoResetEvent _waitForConferenceJoin = new AutoResetEvent(false); 

    private AutoResetEvent _waitForMessageReceived = new AutoResetEvent(false); 

    private AutoResetEvent _waitForMessage2Received = new AutoResetEvent(false); 

    private AutoResetEvent waitForUserEndpointEstablish = new AutoResetEvent(false); 

    private AutoResetEvent _waitForShutdown = new AutoResetEvent(false); 

    private AutoResetEvent _waitForConversationInviteRemoteParticipants = new AutoResetEvent(false); 

    private InstantMessagingFlow _IMFlow; 

    private InstantMessagingFlow _IMFlow2; 
    #endregion 

    public Conference StartConference() 
    { 
     try 
     { 
      foreach (var item in PlatformDataProvider.DataProvider.AppEndpoints) 
      { 
       WriteLog.AddLine(item.EndpointUri + item.OwnerDisplayName); 
       Console.WriteLine(item.EndpointUri + item.OwnerDisplayName); 
      } 
      // to create end point(s) 
      UCMACoach ucmaCoach = new UCMACoach(); 
      UserEndpointSettings settings = new UserEndpointSettings("sip:[email protected]"); 

      UserEndpoint _userEndpoint = new UserEndpoint(PlatformDataProvider.DataProvider.CollabPlatform, settings); 
      _userEndpoint.BeginEstablish(ar => 
      { 
       try 
       { 
        _userEndpoint.EndEstablish(ar); 
        waitForUserEndpointEstablish.Set(); 
       } 
       catch (Exception ex) 
       { 
        WriteLog.AddLine("Error on establish: " + ex.Message); 
        waitForUserEndpointEstablish.Set(); 
       } 

      }, null); 
      waitForUserEndpointEstablish.WaitOne(); 


      WriteLog.AddLine("User endpoint has been established "); 
      _userEndpoint.LocalOwnerPresence.BeginSubscribe(r => 
      { 

      }, null); 

      //IAsyncResult result = _userEndpoint.LocalOwnerPresence.BeginPublishPresence(Microsoft.Rtc.Collaboration.Presence.PresenceAvailability.Busy); 
      // Create a user endpoint, using the network credential object 
      // defined above. 
      _callerEndpoint = PlatformDataProvider.DataProvider.AppEndpoints[1]; 
      /* friendly name for conference leader endpoint */ 

      // Create a second user endpoint, using the network credential object 
      // defined above. 
      _calleeEndpoint = PlatformDataProvider.DataProvider.AppEndpoints[2]; 
      /* friendly name for conference attendee endpoint */ 

      // Get the URI for the user logged onto Microsoft Lync 
      String _ocUserURI = "sip:[email protected]"; 

      // One of the endpoints schedules the conference in advance. At 
      // schedule time, all the conference settings are set. 

      // The base conference settings object, used to set the policies for the conference. 
      ConferenceScheduleInformation conferenceScheduleInformation = new ConferenceScheduleInformation(); 
      // An open meeting (participants can join who are not on the list), 
      // but requiring authentication (no anonymous users allowed.) 
      conferenceScheduleInformation.AccessLevel = ConferenceAccessLevel.SameEnterprise; 
      // The below flag determines whether or not the passcode is optional 
      // for users joining the conference. 
      conferenceScheduleInformation.IsPasscodeOptional = true; 
      conferenceScheduleInformation.Passcode = "1357924680"; 
      // The verbose description of the conference 
      conferenceScheduleInformation.Description = "StartReady | Conference Testing"; 
      // The below field indicates the date and time after which the conference can be deleted. 
      conferenceScheduleInformation.ExpiryTime = System.DateTime.Now.AddHours(5); 

      // These two lines assign a set of modalities (here, only 
      // InstantMessage) from the available MCUs to the conference. Custom 
      // modalities (and their corresponding MCUs) may be added at this 
      // time as part of the extensibility model. 
      ConferenceMcuInformation instantMessageMCU = new ConferenceMcuInformation(McuType.InstantMessaging); 
      conferenceScheduleInformation.Mcus.Add(instantMessageMCU); 

      // Now that the setup object is complete, schedule the conference 
      // using the conference services off of Endpoint. Note: the conference 
      // organizer is considered a leader of the conference by default. 
      _callerEndpoint.ConferenceServices.BeginScheduleConference(conferenceScheduleInformation, 
       EndScheduleConference, _callerEndpoint.ConferenceServices); 

      // Wait for the scheduling to complete. 
      _waitForConferenceScheduling.WaitOne(); 

      // Now that the conference is scheduled, it's time to join it. As we 
      // already have a reference to the conference object populated from 
      // the EndScheduleConference call, we do not need to get the 
      // conference first. Initialize a conversation off of the endpoint, 
      // and join the conference from the uri provided above. 
      Conversation callerConversation = new Conversation(_callerEndpoint); 
      callerConversation.ConferenceSession.StateChanged += new 
       EventHandler<StateChangedEventArgs<ConferenceSessionState>>(ConferenceSession_StateChanged); 

      // Join and wait, again forcing synchronization. 
      callerConversation.ConferenceSession.BeginJoin(_conference.ConferenceUri, null /*joinOptions*/, 
       EndJoinConference, callerConversation.ConferenceSession); 
      _waitForConferenceJoin.WaitOne(); 

      // Placing the calls on the conference-connected conversation 
      // connects to the respective MCUs. These calls may then be used to 
      // communicate with the conference/MCUs. 
      InstantMessagingCall instantMessagingCall = new InstantMessagingCall(callerConversation); 

      // Hooking up event handlers and then placing the call. 
      instantMessagingCall.InstantMessagingFlowConfigurationRequested += 
       this.instantMessagingCall_InstantMessagingFlowConfigurationRequested; 
      instantMessagingCall.StateChanged += this._call_StateChanged; 
      instantMessagingCall.BeginEstablish(EndCallEstablish, instantMessagingCall); 

      //Synchronize to ensure that call has completed. 
      _waitForCallEstablish.WaitOne(); 

      //send conf invite 
      ConferenceInvitationDeliverOptions deliverOptions = new ConferenceInvitationDeliverOptions(); 
      deliverOptions.ToastMessage = new ToastMessage("Welcome to conference of StartReady Demo"); 

      ConferenceInvitation invitation = new ConferenceInvitation(callerConversation); 
      invitation.BeginDeliver(_ocUserURI, deliverOptions, EndDeliverInvitation, invitation); 

      // Synchronize to ensure that invitation is complete 
      _waitForConversationInviteRemoteParticipants.WaitOne(); 

      //And from the other endpoint's perspective: 
      //Initialize a conversation off of the endpoint, and join the 
      //conference from the uri provided above. 
      Conversation calleeConversation = new Conversation(_calleeEndpoint); 
      calleeConversation.ConferenceSession.StateChanged += new 
       EventHandler<StateChangedEventArgs<ConferenceSessionState>>(ConferenceSession_StateChanged); 

      // Join and wait, again forcing synchronization. 
      calleeConversation.ConferenceSession.BeginJoin(_conference.ConferenceUri, null /*joinOptions*/, 
       EndJoinConference, calleeConversation.ConferenceSession); 
      _waitForConferenceJoin.WaitOne(); 

      // Placing the calls on the conference-connected conversation 
      // connects to the respective MCUs. These calls may then be used to 
      //communicate with the conference/MCUs. 
      InstantMessagingCall instantMessagingCall2 = new InstantMessagingCall(calleeConversation); 

      //Hooking up event handlers and then placing the call. 
      instantMessagingCall2.InstantMessagingFlowConfigurationRequested += 
       this.instantMessagingCall2_InstantMessagingFlowConfigurationRequested; 
      instantMessagingCall2.StateChanged += this._call_StateChanged; 
      instantMessagingCall2.BeginEstablish(EndCallEstablish, instantMessagingCall2); 

      //Synchronize to ensure that call has completed. 
      _waitForCallEstablish.WaitOne(); 

      //Synchronize to ensure that all messages are sent and received 
      _waitForMessageReceived.WaitOne(); 

      //Wait for shutdown initiated by user 
      //_waitForShutdown.WaitOne(); 

      //UCMASampleHelper.PauseBeforeContinuing("Press ENTER to shutdown and exit."); 

      return _conference; 
     } 
     catch (Exception ex) 
     { 
      WriteLog.AddLine("Cannot start conference: " + ex.Message); 
      return null; 
     } 
    } 

    #region side methods 
    void ConferenceSession_StateChanged(object sender, StateChangedEventArgs<ConferenceSessionState> e) 
    { 
     ConferenceSession confSession = sender as ConferenceSession; 

     //Session participants allow for disambiguation. 
     WriteLog.AddLine("The conference session with Local Participant: " + 
      confSession.Conversation.LocalParticipant + " has changed state. " + 
      "The previous conference state was: " + e.PreviousState + 
      " and the current state is: " + e.State); 
    } 

    // Flow created indicates that there is a flow present to begin media 
    // operations with, and that it is no longer null. 
    public void instantMessagingCall_InstantMessagingFlowConfigurationRequested 
     (object sender, InstantMessagingFlowConfigurationRequestedEventArgs e) 
    { 
     InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow; 
     WriteLog.AddLine("Caller's Flow Created."); 
     instantMessagingFlow = e.Flow; 
     _IMFlow = instantMessagingFlow; 

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

    // 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; 
     WriteLog.AddLine("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; 
    } 

    private void instantMessagingFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e) 
    { 
     InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow; 

     WriteLog.AddLine("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; 
      WriteLog.AddLine("Please type the message to send..."); 
      string msg = Console.ReadLine(); 
      //Send the message on the InstantMessagingFlow. 
      instantMessagingFlow.BeginSendInstantMessage(msg, EndSendMessage, instantMessagingFlow); 
     } 
    } 

    private void instantMessagingFlow2_StateChanged(object sender, MediaFlowStateChangedEventArgs e) 
    { 
     InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow; 

     WriteLog.AddLine("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; 
     } 
    } 

    private void EndSendMessage(IAsyncResult ar) 
    { 
     InstantMessagingFlow instantMessagingFlow = ar.AsyncState as InstantMessagingFlow; 
     try 
     { 
      instantMessagingFlow.EndSendInstantMessage(ar); 
      WriteLog.AddLine("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 
      WriteLog.AddLine(opTimeEx.ToString()); 
     } 
    } 
    private void instantMessagingFlow_MessageReceived(object sender, InstantMessageReceivedEventArgs e) 
    { 
     InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow; 
     //On an incoming Instant Message, print the contents to the console. 
     WriteLog.AddLine("In caller's message handler: " + e.Sender.DisplayName + " said: " + e.TextBody); 
     _waitForMessageReceived.Set(); 
    } 

    private void instantMessagingFlow2_MessageReceived(object sender, InstantMessageReceivedEventArgs e) 
    { 
     InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow; 
     //On an incoming Instant Message, print the contents to the console. 
     WriteLog.AddLine("In callee's message handler: " + e.Sender.DisplayName + " said: " + e.TextBody); 

     WriteLog.AddLine("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 
      WriteLog.AddLine("Could not echo message because flow was either null or inactive"); 

     _waitForMessage2Received.Set(); 
    } 

    private void EndCallEstablish(IAsyncResult ar) 
    { 
     Call call = ar.AsyncState as Call; 
     try 
     { 
      call.EndEstablish(ar); 
      WriteLog.AddLine("The call with Local Participant: " + call.Conversation.LocalParticipant + 
       " and Remote Participant: " + call.RemoteEndpoint.Participant + 
       " is now in the established state."); 
     } 
     catch (OperationFailureException opFailEx) 
     { 
      // OperationFailureException: Indicates failure to connect the 
      // call to the remote party. 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(opFailEx.ToString()); 
     } 
     catch (RealTimeException exception) 
     { 
      // RealTimeException may be thrown on media or link-layer 
      //failures. 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(exception.ToString()); 
     } 
     finally 
     { 
      //Again, just to sync the completion of the code. 
      _waitForCallEstablish.Set(); 
     } 
    } 

    private void EndDeliverInvitation(IAsyncResult ar) 
    { 
     ConferenceInvitation invitation = ar.AsyncState as ConferenceInvitation; 

     try 
     { 
      invitation.EndDeliver(ar); 
     } 
     catch (OperationFailureException opFailEx) 
     { 
      // OperationFailureException: Indicates failure to connect the 
      // call to the remote party. 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(opFailEx.ToString()); 
     } 
     catch (RealTimeException exception) 
     { 
      // RealTimeException may be thrown on media or link-layer failures. 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(exception.ToString()); 
     } 
     finally 
     { 
      //Again, just to sync the completion of the code. 
      _waitForConversationInviteRemoteParticipants.Set(); 
     } 
    } 

    private void EndScheduleConference(IAsyncResult ar) 
    { 
     ConferenceServices confSession = ar.AsyncState as ConferenceServices; 
     try 
     { 
      //End schedule conference returns the conference object, which 
      // contains the vast majority of the data relevant to that 
      // conference. 
      _conference = confSession.EndScheduleConference(ar); 
      WriteLog.AddLine(""); 
      WriteLog.AddLine(" The conference is now scheduled."); 
      WriteLog.AddLine(""); 

     } 
     catch (ConferenceFailureException confFailEx) 
     { 
      // ConferenceFailureException may be thrown on failures to 
      // schedule due to MCUs being absent or unsupported, or due to 
      // malformed parameters. 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(confFailEx.ToString()); 
     } 

     //Again, for sync. reasons. 
     _waitForConferenceScheduling.Set(); 
    } 
    private void EndJoinConference(IAsyncResult ar) 
    { 
     ConferenceSession confSession = ar.AsyncState as ConferenceSession; 
     try 
     { 
      confSession.EndJoin(ar); 
     } 
     catch (ConferenceFailureException confFailEx) 
     { 
      // ConferenceFailureException may be thrown on failures due to 
      // MCUs being absent or unsupported, or due to malformed parameters. 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(confFailEx.ToString()); 
     } 
     catch (RealTimeException rTEx) 
     { 
      // TODO (Left to the reader): Add error handling code 
      WriteLog.AddLine(rTEx.ToString()); 
     } 
     finally 
     { 
      //Again, for sync. reasons. 
      _waitForConferenceJoin.Set(); 
     } 
    } 

    //Just to record the state transitions in the console. 
    void _call_StateChanged(object sender, CallStateChangedEventArgs e) 
    { 
     Call call = sender as Call; 

     //Call participants allow for disambiguation. 
     WriteLog.AddLine("The call with Local Participant: " + call.Conversation.LocalParticipant + 
      " has changed state. The previous call state was: " + e.PreviousState + 
      " and the current state is: " + e.State); 
    } 

    #endregion 
} 

}

+1

Y a-t-il une chance d'obtenir une pile d'appel sur l'exception? Pour les applications UCMA, je recommanderais d'ajouter la journalisation des exceptions à chacun des gestionnaires d'événements UCMA, ce qui simplifiera considérablement le débogage de votre solution. –

Répondre

0

L'autre chose qui est vraiment utile ici est d'exécuter OCSLogger sur le serveur d'application et voir ce qui revient. Vous pouvez exécuter S4 pour obtenir des traces SIP. Peut-être juste quelque chose de simple comme vous ne pouvez pas recevoir de messages sur 5061 (ou n'importe quel port de rappel que vous avez spécifié dans votre approvisionnement). Si cela échoue uniquement sur A/V, regardez quelles adresses sont utilisées dans l'offre/réponse SDP et voyez si elles sont joignables. Encore une fois, OCSLogger (ou Lync CLS) et Snooper sont vos amis ici.