I'm using pjsip high-level api PJSUA for doing multiple calls at one time. My sip operator support up to 3 outgoing lines for calls, so in theory it should be possible to call 3 persons at one time. The problem is, that in the operator logs i see, the message "Line limit overreached" and in pjsip, the call fails. I'm doing it like this:
Here is my class that contains methods for calling:
void Sip::InitLibrary()
{
pj::EpConfig ep_cfg;
ep_cfg.logConfig.level = 4;
ep_cfg.logConfig.consoleLevel = 4;
ep_cfg.logConfig.filename = this->log_;
ep_cfg.uaConfig.userAgent = "Ekiga";
this->ep_.libCreate();
this->ep_.libInit(ep_cfg);
}
void Sip::SetSipTransport(Sip::SipTransport transport, unsigned port)
{
TransportConfig tcfg;
tcfg.port = port;
pjsip_transport_type_e type;
switch (transport)
{
case SipTransport::TCP:
type = PJSIP_TRANSPORT_TCP;
break;
case SipTransport::UDP:
type = PJSIP_TRANSPORT_UDP;
break;
}
try {
this->transportId_ = this->ep_.transportCreate(type, tcfg);
}
catch (Error &err) {
//to log
return;
}
}
void Sip::StartLibrary()
{
this->ep_.libStart();
}
AccountInfo Sip::ConnectSipServer(string serv, string login, string pass,SipTransport transport,int port)
{
this->InitLibrary();
this->SetSipTransport(transport, port);
this->StartLibrary();
this->server_ = serv;
AccountConfig accConfig;
string uri = "<sip:" + login + "@" + serv +">";
accConfig.idUri = uri;
string regUri = "sip:" + serv;
accConfig.regConfig.registrarUri = regUri;
accConfig.sipConfig.authCreds.push_back(AuthCredInfo("digest", "*", login, 0, pass));
this->acc_ = new SipAccount();
acc_->create(accConfig, true);
{
unique_lock<mutex> locker(acc_->regLock_);
while (!acc_->regEnd_)
acc_->regDone_.wait(locker);
}
return acc_->info_;
}
bool Sip::CallNumber(string phone)
{
Call *call = new SipCall(*this->acc_);
CallOpParam prm(true);
prm.opt.audioCount = 1;
prm.opt.videoCount = 0;
call->makeCall("sip:" + phone + "@" + this->server_, prm);
SipCall *myCall = (SipCall*)call;
{
unique_lock<mutex> locker(myCall->callLock);
while (!myCall->callEnd)
myCall->callDone.wait(locker);
}
if (myCall->validPhone)
{
delete myCall;
return true;
}
delete myCall;
return false;
}
SipCall.h
SipCall(Account &acc, int call_id = PJSUA_INVALID_ID)
: Call(acc, call_id)
{
Acc = (SipAccount *)&acc;
this->callEnd = false;
this->validPhone = false;
}
~SipCall();
virtual void onCallState(OnCallStateParam &prm);
condition_variable callDone;
mutex callLock;
bool callEnd;
bool validPhone;
SipCall.cpp
void SipCall::onCallState(OnCallStateParam &prm)
{
PJ_UNUSED_ARG(prm);
CallInfo ci = getInfo();
std::cout << "*** Call: " << ci.remoteUri << " [" << ci.stateText
<< "]" << std::endl;
if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
{
unique_lock<mutex> locker(this->callLock);
this->callEnd = true;
this->callDone.notify_one();
}
}
if (ci.state == PJSIP_INV_STATE_CONFIRMED && ci.lastStatusCode == PJSIP_SC_OK)
{ //here i check that phone is valid, and just hang up the call
CallOpParam p;
this->validPhone = true;
this->hangup(p);
}
}
SipCall::~SipCall()
{
}
Since there a 3 lines avaliable im creating a three tasks to call the corresponding numbers like so:
QStringList testCalls; // initialized with numbers
struct call_result{
QString phone;
bool valid;
};
//....
QList<QFuture<call_result>> futureTestList;
while(counter < testCalls.count()) {
for(int i= 0; i < 3; i++,counter++) {
if(counter >= testCalls.count())
break;
QString number = testCalls.at(counter);
QFuture<call_result> futureResult = QtConcurrent::run(this,&sipQtThread::callNumber,number);
futureTestList.append(futureResult);
}
foreach(QFuture<call_result> future,futureTestList) {
future.waitForFinished();
call_result call = future.result();
emit phonePassed(call.phone,call.valid);
}
futureTestList.clear();
}
The correspondig task sipQtThread::callNumber
is following:
sipQtThread::call_result sipQtThread::callNumber(QString phone)
{
call_result call;
pj_thread_desc initdec;
pj_thread_t* thread = 0;
pj_status_t status;
status = pj_thread_register(NULL, initdec, &thread);
if (status != PJ_SUCCESS) {
qDebug()<<"pj_thread_register faild:"<<status;
return call;
}
bool result = sip_->CallNumber(phone.toStdString());
call.phone = phone;
call.valid = result;
return call;
}
As you can see here
if (ci.state == PJSIP_INV_STATE_CONFIRMED && ci.lastStatusCode == PJSIP_SC_OK)
{ //here i check that phone is valid, and just hang up the call
CallOpParam p;
this->validPhone = true;
this->hangup(p);
}
I just check if the phone is valid, and call is starting, and the drop it. Can pjsua2 handle multiple line calls? Or even is pjsip supporting multiple outgoing lines calls? Does the thread registered by pj_thread_register
needs to be somehow unregistered maybe?