关闭pjsip应用程序的正确方法是什么?

时间:2014-08-15 10:58:47

标签: c++ sip pjsip

我在pjsip(pjsua2)上编写了简单的应用程序。 如果我在有活动呼叫时关闭我的应用程序,我在Endpoint :: on_call_state中有内存访问错误(pjsua_call_id call_id,pjsip_event * e)

我在关闭前尝试

Endpoint::instance().hangupAllCalls();
pj_thread_sleep(2000);

有一段时间2秒足够时间关闭和app正确关闭,但有些时间没有。

关闭pjsua2应用程序的正确方法是什么? 如何等待所有通话都挂断?

1 个答案:

答案 0 :(得分:1)

从我使用PJSUA2开始,正确的退出方法是确保在pj :: Account析构函数之前调用所有调用的析构函数,并在pj :: Endpoint析构函数之前调用pj :: Account的desturctor。

在我的应用程序中,我有整数调用计数器,并在pj :: Account派生类中退出bool标志,如:

class MyAccount : public pj::Account
{
public:
    ...
    void incrementCallsCount() { ++_callsCount; }
    void decrementCallsCount() { --_callsCount; }
    size_t getCallsCount() const { return _callsCount; }
    ...
    void setWantExit(boot wantExitFlag) { _wantExitFlag = wantExitFlag; }
    void onIncomingCall(pj::OnIncomingCallParam &prm)
    {
       if (_wantExitFlag)
           return;
       MyCall *call = MyCall::create(*this, prm.callId);
       // Do your stuff with call:
       // - add to map id->call
       // - answer SIP 180 Ringing / SIP 200 OK
    }
    ...
private:
    std::atomic<size_t> _callsCount;
    bool _wantExitFlag;
};

在pj的构造函数中:调用派生类我调用incrementCallsCount(),在析构函数中我调用decrementCallsCount(),如:

class MyCall : public pj::Call
{
public:
    typedef pj::Call base_class;
    static MyCall *create(MyAccount &account, int callId)
    {
        return new MyCall(account, callId);
    }

    virtual void onCallState(pj::OnCallStateParam& prm)
    {
        pj::CallInfo ci = getInfo();
        if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
        {
            // You may call some onDisconnected() handler function here
            delete this;
            return;
        }
    }
    ...
private:
    MyCall(MyAccount &account, int callId)
        : base_class(account, callId)
        , _myAccount(account)
    {
        _myAccount.incrementCallsCount();
    }

    virtual ~MyCall()
    {
        _myAccount.decrementCallsCount();
    }

    MyAccount &_myAccount;
};

注意构造函数和析构函数声明为private,以确保用户通过静态函数MyCall :: create()创建调用! MyCall类负责内存管理:仅当PJSUA2指示删除呼叫(PJSIP_INV_STATE_DISCONNECTED呼叫状态)时才调用已删除。

考虑到这些功能和类,如果您只是想立即退出应用程序,您应该:

  • 停止在_myAccount.setWantExit(true)的MyAccount中创建MyCall。当pj::Call::onIncomingCall()函数立即返回时,PJSUA2通过立即执行hangup()来执行此操作。

  • 致电Endpoint::instance().hangupAllCalls()

  • 等到MyAccount::getCallsCount()返回0

  • 确保在Enpoint的析构函数之前调用MyAccount的析构函数

  • 退出申请