2015-07-15 6 views
1

Я пытаюсь запустить конференцию, используя базовый образец конференц-связи UCMA 4.0 и первую конечную точку пользователя, застрявшую при установлении вызова (это lync не звонит). Исключение таймаута запускается через некоторое время. В чем главная проблема?Конференц-связь UCMA, установленная при первом установлении участника

BTW, платформа запускается уже с обнаружением 3 конечных точек приложения, установленных.

глотка: [email protected]; GRUU; непрозрачным = SRVR: yyapp: EHghH8UXNVqIedXU3YgJyQAAYYApp глотка: [email protected]; GRUU; непрозрачным = SRVR: yyapp: EHghH8UXNVqIedXU3YgJyQAAMachine1 SIP: [email protected]; GRUU; непрозрачное = SRVR: yyapp: EHghH8UXNVqIedXU3YgJyQAAMachine2 глоток: [email protected]; GRUU; непрозрачное = SRVR: yyapp: EHghH8UXNVqIedXU3YgJyQAAMachine3 «LyncGame.Gateway.TestConnection .vshost.exe '(CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): Загружен' C: \ Windows \ Microsoft.Net \ assembly \ GAC_MSIL \ System.Data.SqlXml \ v4.0_4.0.0.0bbaa5c561934e089 \ System.Data.SqlXml.dll. Пропущенные символы загрузки. Модуль оптимизирован и включен параметр отладчика «Только мой код». 'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): загружен «System.Xml.Xsl.CompiledQuery.1». Поток 0x6e8 вышел с кодом 259 (0x103). Поток 0x3dd4 вышел с кодом 259 (0x103). Поток 0x2138 вышел с кодом 259 (0x103). 'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): Загружена 'C: \ Windows \ Microsoft.Net \ assembly \ GAC_MSIL \ System.Security \ v4. 0_4.0.0.0__b03f5f7f11d50a3a \ System.Security.dll. Пропущенные символы загрузки. Модуль оптимизирован и включен параметр отладчика «Только мой код». Поток 0x3180 вышел с кодом 259 (0x103). Поток 0x350c вышел с кодом 259 (0x103). Поток 0x1698 вышел с кодом 0 (0x0). Поток 0x3ef4 вышел с кодом 0 (0x0). Поток 0x3f00 вышел с кодом 259 (0x103). Поток 0x2a24 вышел с кодом 259 (0x103). Поток 0x3fc0 вышел с кодом 259 (0x103). Поток 0x3750 вышел с кодом 259 (0x103). Поток 0x27b8 вышел с кодом 259 (0x103). Поток 0x11e0 вышел с кодом 259 (0x103). Поток 0x2214 вышел с кодом 259 (0x103). Поток 0x1564 вышел с кодом 259 (0x103). Поток 0x3740 вышел с кодом 259 (0x103). Поток 0x28a8 вышел с кодом 259 (0x103). Поток 0x1da8 вышел с кодом 259 (0x103). Первый шанс исключение типа «Microsoft.Rtc.Signaling.OperationTimeoutException» произошло в 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

Есть ли вероятность получить стек вызовов для исключения. Для приложений UCMA я бы рекомендовал добавлять журналы регистрации исключений для каждого из обработчиков событий UCMA, что значительно упростит отладку вашего решения. –

ответ

0

Другое дело, что действительно полезно здесь, чтобы запустить OCSLogger на сервере приложений и посмотреть, что вернется. Вы можете запустить S4 для получения следов SIP. Может быть просто что-то простое, так как вы не можете получать сообщения на 5061 (или в зависимости от того, какой номер обратного вызова указан в вашей настройке). Если это не работает на A/V, посмотрите, какие адреса используются в предложениях/ответах SDP, и посмотрите, доступны ли они. Опять же, OCSLogger (или Lync CLS) и Snooper - ваши друзья здесь.