当前位置: 首页 > 工具软件 > Sipdroid > 使用案例 >

Sipdroid源码初探(二):监听来电,通话建立流程

卫梓
2023-12-01

sip协议的相关背景知识

SIP协议是一个Client/Sever协议,因此SIP消息分两种:请求消息和响应消息。请求消息是SIP客户端为了激活特定操作而发给服务器端的消息。常用的SIP请求消息如下:
INVITE:表示主叫用户发起会话请求,邀请其他用户加入一个会话。也可以用在呼叫建立后用于更新会话(此时该INVITE又称为Re-invite)。
ACK:客户端向服务器端证实它已经收到了对INVITE请求的最终响应。
PRACK:表示对1xx响应消息的确认请求消息。
BYE:表示终止一个已经建立的呼叫。
CANCEL:表示在收到对请求的最终响应之前取消该请求,对于已完成的请求则无影响。
REGISTER:表示客户端向SIP服务器端注册列在To字段中的地址信息。
OPTIONS:表示查询被叫的相关信息和功能。

SIP协议中的响应消息用于对请求消息进行响应,指示呼叫的成功或失败状态。
常用的一些响应消息:

100试呼叫(Trying)
180振铃(Ringing)
181呼叫正在前转(Call is Being Forwarded)
200成功响应(OK)
302临时迁移(Moved Temporarily)
400错误请求(Bad Request)
401未授权(Unauthorized)
403禁止(Forbidden)
404用户不存在(Not Found)
408请求超时(Request Timeout)
480暂时无人接听(Temporarily Unavailable)
486线路忙(Busy Here)
504服务器超时(Server Time-out)
600全忙(Busy Everywhere)

以上背景知识在下面的代码分析中会用到。

开始

为了了解如何监听来电,我们从Sipdroid.StartEngine()开始,一步一步写出函数的调用过程。过程如下:
Sipdroid.StartEngine() -> Sipdroid.listen() -> UserAgent.listen() ->ExtendedCall.listen() -> ExtendedInviteDialog.listen() -> InviteTransactionServer.listen()

好戏从InviteTransactionServer.listen()开始,下面是代码:

public void listen() {
        printLog("start", LogLevel.LOW);
        if (statusIs(STATE_IDLE)) {
            changeStatus(STATE_WAITING);
            sip_provider.addSipProviderListener(new TransactionIdentifier(
                    SipMethods.INVITE), this);
            sip_provider.addSipProviderListener(new TransactionIdentifier(
                    SipMethods.OPTIONS), this);

        }
    }

大概得看上去,这里是给sip_provider添加了几个Listener,参数中寻找回调接口时发现了this,那就是在本类中了。寻找后发现回调方法就是这个了:

public void onReceivedMessage(SipProvider provider, Message msg) {
        if (msg.isRequest()) {
            String req_method = msg.getRequestLine().getMethod();

            // invite 消息收到
            if (req_method.equals(SipMethods.INVITE)) {
                if (statusIs(STATE_WAITING)) {
                    request = new Message(msg);
                    connection_id = request.getConnectionId();
                    transaction_id = request.getTransactionId();
                    sip_provider.addSipProviderListener(transaction_id, this);
                    sip_provider
                            .removeSipProviderListener(new TransactionIdentifier(
                                    SipMethods.INVITE));
                    changeStatus(STATE_TRYING);
                    // automatically send "100 Tryng" response and go to
                    // STATE_PROCEEDING
                    //自动回复"100 Tryng"消息
                    if (auto_trying) {
                        Message trying100 = MessageFactory.createResponse(
                                request, 100, SipResponses.reasonOf(100), null);
                        respondWith(trying100); // this method makes it going
                        // automatically to
                        // STATE_PROCEEDING
                    }
                    if (transaction_listener != null)
                        transaction_listener.onTransRequest(this, msg);
                    return;
                }
                if (statusIs(STATE_PROCEEDING) || statusIs(STATE_COMPLETED)) { // retransmission
                    // of
                    // the
                    // last
                    // response
                    sip_provider.sendMessage(response, connection_id);
                    return;
                }
            }

            //如果收到的是 OPTIONS 消息
            if (req_method.equals(SipMethods.OPTIONS)) {
                Message ok200 = MessageFactory.createResponse(msg, 200, SipResponses.reasonOf(200), null);
                ok200.removeServerHeader();
                ok200.addContactHeader(new ContactHeader(ok200.getToHeader().getNameAddress()), false);
                sip_provider.sendMessage(ok200, connection_id);
                return;
            }

            // ack received
            //如果收到的是 ack 消息
            if (req_method.equals(SipMethods.ACK) && statusIs(STATE_COMPLETED)) {
                retransmission_to.halt();
                end_to.halt();
                changeStatus(STATE_CONFIRMED);
                if (transaction_listener != null)
                    transaction_listener.onTransFailureAck(this, msg);
                clearing_to.start();
                return;
            }
        }
    }

初看此方法,可以发现这里面的处理分为三种情况,收到 invite 消息时,收到options 消息时,收到 ack 消息时。本类的名字是InviteTransactionServer,意思是invite消息服务器,就是说这个类是专门用来处理invite消息的,对于其他的消息的处理就在其他的专门的类中了。
结合本文开篇的背景知识,我们就能知道这里实际上就是在对sip协议中的其中三种请求进行处理。根据sip协议,当一个用户想要拨打另一用户,代理服务器会首先将invite消息发给另一用户。在此方法中,我们只看见了对于invite消息进行回复100,根据sip协议,通话的建立是需要两个客户端进行几次握手的,这里仅仅是回复了一次消息,距离通话建立还有几步,不过这里好像就没有看到后续的操作了。

sipdroid的源码分层十分明显,从底层的网络数据接受发送到上层的呼叫的各种状态的建立(来电,接通,取消,挂断等等),每一层都用了单独的类。这里简单记录一下个类的分层情况(这里是仅考虑等待来电到接通电话,其他的代码还没看),从上往下是:
UserAgent(直接处理来电)
ExtendedCall (extends Call)
ExtendedInviteDialog (extends InviteDialog)
InviteTransactionServer
每一层通过回调接口相互联系。具体的流程十分的繁杂,文字叙述还真是很不方便。

 类似资料: