【问题标题】:How to connect UCMA 4.0/5.0 client to LYNC server如何将 UCMA 4.0/5.0 客户端连接到 LYNC 服务器
【发布时间】:2017-11-10 13:39:44
【问题描述】:

我正在使用UserEndpoint 创建一个 UCMA 客户端应用程序。当连接到内部域内我们组织的 Lync 服务器时,我的 UCMA 应用程序能够与服务器建立连接。

using System;
using System.Threading;
using Microsoft.Rtc.Collaboration;

namespace SimpleUserUCMA
{
    class Program
    {
        private const string sipaddress = "sip:example@domain.com";
        private const string username = "example@domain.com";
        private const string password = "password@1234";
        private const string domain = "domain.com";
        private const string destinationSip = "liveagent1@ngwplab.com";//serveraddress@domain.com
        private const string IMMessage = "Hello";


        static CollaborationPlatform _collabPlatform { get; set; }
        static UserEndpoint _endpoint { get; set; }
        static bool _OKToQuit = false;
        private static InstantMessagingCall call;
        private static InstantMessagingFlow flow;
        private static string incomingMessage;
        private static ManualResetEvent incomingMessageWaiter = new ManualResetEvent(false);
        private static ManualResetEvent flowWaiter = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            string userAgent = "Mozilla/5.0 (X11; CrOS x86_64 8172.45.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36";

            var platformSettings = new ClientPlatformSettings(userAgent, Microsoft.Rtc.Signaling.SipTransportType.Tls);
            _collabPlatform = new CollaborationPlatform(platformSettings);

            //Start up the platform, calling back asynchronously once it's done.
            _collabPlatform.BeginStartup(EndCollabPlatformStartup, null);

            // Wait for a message to arrive and the flow to be ready.
            incomingMessageWaiter.WaitOne();
            flowWaiter.WaitOne();

            // Process the incoming message. For this example just echo what was received.
            var reply = "You send me: " + incomingMessage;

            // And reply to the sender.
            SendReplyMessage(reply);
            //In this example, wait for everything to finish before exiting
            while (!_OKToQuit)
            {
                Thread.Sleep(2000);
            }
        }
        private static void EndCollabPlatformStartup(IAsyncResult ar)
        {
            _collabPlatform.EndStartup(ar);
            //A collaboration plaform can have one or more Endpoints. An Endpoint is tied to a SIP Address.            
            UserEndpointSettings settings = new UserEndpointSettings(sipaddress,"00.000.63.216",5061);
            settings.Credential = new System.Net.NetworkCredential(username, password, domain);
            settings.AutomaticPresencePublicationEnabled = true;

            _endpoint = new UserEndpoint(_collabPlatform, settings);
            _endpoint.BeginEstablish(UserEndpointEstablishCompleted, _endpoint);

        }


        private static void UserEndpointEstablishCompleted(IAsyncResult ar)
        {

            try
            {
                var currentEndpoint = ar.AsyncState as LocalEndpoint;
                <strong>currentEndpoint.EndEstablish(ar);</strong>

                //Once the endpoint is in place, wait for a conversation to arrive.
                _endpoint.RegisterForIncomingCall<InstantMessagingCall>(HandleInstantMessagingCall);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR : " + ex);
            }


        }

        private static void HandleInstantMessagingCall(object sender, CallReceivedEventArgs<InstantMessagingCall> e)
        {
            if (e.ToastMessage != null && e.ToastMessage.HasTextMessage)
            {
                // Store the incoming message text.
                incomingMessage = e.ToastMessage.Message;
                // Signal that we have a message.
                incomingMessageWaiter.Set();
            }

            call = e.Call;
            call.InstantMessagingFlowConfigurationRequested += HandleInstantMessagingFlowConfigurationRequested;
            call.BeginAccept(EndCallAccept, null);
        }

        private static void EndCallAccept(IAsyncResult ar)
        {
            call.EndAccept(ar);
        }

        private static void HandleInstantMessagingFlowConfigurationRequested(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
        {
            flow = e.Flow;
            flow.MessageReceived += HandleFlowMessageReceived;
            flow.StateChanged += HandleFlowStateChanged;
        }

        private static void HandleFlowMessageReceived(object sender, InstantMessageReceivedEventArgs e)
        {
            if (e.HasTextBody)
            {
                // Store the incoming message text.
                incomingMessage = e.TextBody;
                // Signal that we have a message.
                incomingMessageWaiter.Set();
            }

        }


        static void HandleFlowStateChanged(object sender, MediaFlowStateChangedEventArgs e)
        {
            if (e.State == MediaFlowState.Active)
            {
                // Signal that the flow is ready.
                flowWaiter.Set();
            }
        }

        private static void SendReplyMessage(string reply)
        {
            // Send the message to the requestor.
            flow.BeginSendInstantMessage(reply, EndBeginSendInstanceMessage, null);
        }

        private static void EndBeginSendInstanceMessage(IAsyncResult ar)
        {
            flow.EndSendInstantMessage(ar);

            // Having sent the message, terminate the conversation
            flow.Call.Conversation.BeginTerminate(EndBeginTerminate, flow.Call.Conversation);
        }

        private static void EndBeginTerminate(IAsyncResult ar)
        {
            Conversation conversation = (Conversation)ar.AsyncState;
            conversation.EndTerminate(ar);

            _OKToQuit = true;
        }
    }
}

但是当我尝试使用 UCMA 5.0 建立最终用户连接时出现错误

当我调试它在这一行中断:

var currentEndpoint = ar.AsyncState as LocalEndpoint;
currentEndpoint.EndEstablish(ar);

错误:

ERROR : ErrorCode=-2146893022
FailureReason=IncorrectNameInRemoteCertificate
LocalEndpoint=100.77.120.70:53578
RemoteEndpoint=52.176.63.216:5061
RemoteCertificate=<null>
Microsoft.Rtc.Signaling.TlsFailureException:The target principal name is incorrect ---> Microsoft.Rtc.Internal.Sip.TLSException: outgoing TLS negotiation failed; Wrong target principal name configured. HRESULT=-2146893022
   at Microsoft.Rtc.Internal.Sip.TlsTransportHelper.HandleNegotiationFailure(Int32 status, Boolean incoming)
   at Microsoft.Rtc.Internal.Sip.TlsTransportHelper.OutgoingTlsNegotiation(TransportsDataBuffer receivedData, TransportsDataBuffer& pDataToSend)
   at Microsoft.Rtc.Internal.Sip.TlsTransportHelper.NegotiateConnection(TransportsDataBuffer receivedData, TransportsDataBuffer& pDataToSend)
   at Microsoft.Rtc.Internal.Sip.TlsTransport.DelegateNegotiation(TransportsDataBuffer receivedData)
   at Microsoft.Rtc.Internal.Sip.TlsTransport.OnReceived(Object data)

【问题讨论】:

    标签: lync skype-for-business ucma


    【解决方案1】:

    你的问题是:

    UserEndpointSettings settings = new UserEndpointSettings(sipaddress,"00.000.63.216",5061);

    通过 TLS 连接时,服务器名称不能是 IP 地址,它必须与服务器返回的证书名称匹配。因此,您需要用户 uri 所在的 FE 池的服务器名称。

    为什么不使用非服务器版本的构造函数?

    UserEndpointSettings settings = new UserEndpointSettings(sipaddress);

    并让 UCMA 使用 Skypes 自动发现过程为您整理要连接的服务器?

    【讨论】:

    • 最初我只尝试过,但收到错误“SupportedAuthenticationProtocols=Ntlm, Kerberos”
    • ErrorCode=-2146893039 Microsoft.Rtc.Signaling.AuthenticationException:无法执行凭据身份验证。这就是为什么,我通过端点建立连接
    • 我认为您正在走得更远,因为这是失败的 tls 之上的一层。这远离了编程问题,更多的是系统管理员问题。您需要尝试找出身份验证失败的原因。我会转储所有异常信息,看看它在说什么。如果您运行它的机器不是域的成员,那么可能是证书问题,或者您可能需要找出 Kerberos 失败的原因(很可能在 DC 服务器上)。
    • 我不太确定我能提供更多帮助,因为这超出了我的理解范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 2016-07-22
    相关资源
    最近更新 更多