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

What correct way to close pjsip app?

本文关键字:方法 是什么 pjsip 应用程序 关闭      更新时间:2023-10-16

我基于pjsip (pjsua2)编写了这个简单的应用程序。如果我关闭我的应用程序,当我有活动调用,我有内存访问错误在端点::on_call_state(pjsua_call_id call_id, pjsip_event *e)

I try before close do

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

有些时间2秒足够关闭和应用程序正确关闭,但有些时间没有。

关闭pjsua2应用程序的正确方法是什么?等什么电话都挂了?

根据我使用PJSUA2的经验,退出的正确方法是确保在pj::Account析构函数之前调用所有调用的析构函数,并且在pj::Endpoint析构函数之前调用pj::Account的析构函数。

在我的应用程序中,我在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;
};

注意构造函数和析构函数声明为私有,以确保用户只能通过静态函数MyCall::create()创建调用!MyCall类负责内存管理:只有当PJSUA2告诉删除调用(PJSIP_INV_STATE_DISCONNECTED调用状态)时,才删除调用。

记住这些函数和类,如果你只是想立即退出应用程序,你应该:

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

  • call Endpoint::instance().hangupAllCalls()

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

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

  • 退出应用