liblinphone
liblinphone copied to clipboard
Requesting chat room of call results in a crash
I am facing a crash (exception) when trying to access the ChatRoom
object of a Call
via C++ bindings:
void myFunction() {
call->getChatRoom();
}
The call itself is working correctly and in a good state (i.e. is not terminated, aborted or any of that). This is the stack trace:
1 raise
2 abort
3 __gnu_cxx::__verbose_terminat_handler() [clonde.cold]
4 __cxxabiv1::___terminate(void ( *)())
5 std::terminate()
6 __cxa_throw
7 std::__throw_logic_error(const char *)
8 std::string::basic_string(const char *, std::allocator<char> const&) [clone.constprop.0]
9 LinphonePrivate::Call::getChatRoom()
10 linphone_call_get_chat_room
11 linphone::Call::getChatRoom()
12 myFunction
This is the exception output:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
Following the stack trace, we figured out that in call.cpp the callId
is NULL
:
shared_ptr<AbstractChatRoom> Call::getChatRoom () {
if ((getState() != CallSession::State::End) && (getState() != CallSession::State::Released)) {
mChatRoom = getCore()->getOrCreateBasicChatRoom(getLocalAddress(), *getRemoteAddress());
if (mChatRoom) {
const char *callId = linphone_call_log_get_call_id(getLog());
lInfo() << "Setting call id [" << callId << "] to ChatRoom [" << mChatRoom << "]";
mChatRoom->getPrivate()->setCallId(callId);
}
}
return mChatRoom;
}
Thus, when accessing callId
in the lInfo
line, it causes the exception and breaks. The stdout shows:
"Setting call id ["
because it breaks while reading the callId
.
So far for the error.
We also tried to figure out how the callId
is set into the CallLog
(getLog()
in the snipped above retrieves the CallLog
from the Call
object). We are using linphone::Core::inviteAddressWithParams
, which calls linphone_core_invite_address_with_params which then calls linphone_call_new_outgoing:
LinphoneCall *linphone_call_new_outgoing (LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg) {
LinphoneCall *lcall = Call::createCObject(L_GET_CPP_PTR_FROM_C_OBJECT(lc), LinphoneCallOutgoing,
*L_GET_CPP_PTR_FROM_C_OBJECT(from), *L_GET_CPP_PTR_FROM_C_OBJECT(to),
cfg, nullptr, L_GET_CPP_PTR_FROM_C_OBJECT(params));
return lcall;
}
Please note that the second to last argument of the constructor call is nullptr
. This parameter is SalCallOp *op
:
Call::Call (
shared_ptr<Core> core,
LinphoneCallDir direction,
const Address &from,
const Address &to,
LinphoneProxyConfig *cfg,
SalCallOp *op,
const MediaSessionParams *msp
) : CoreAccessor(core) {
mNextVideoFrameDecoded._func = nullptr;
mNextVideoFrameDecoded._user_data = nullptr;
mBgTask.setName("Liblinphone call notification");
//create session
mParticipant = Participant::create(nullptr, IdentityAddress((direction == LinphoneCallIncoming) ? to : from));
mParticipant->createSession(getCore(), msp, TRUE, this);
mParticipant->getSession()->configure(direction, cfg, op, from, to);
}
In the last line of the constructor, the session's configure
function is called with the same argument (op
= nullptr
):
mParticipant->getSession()->configure(direction, cfg, op, from, to);
In configure
there is this part which sets the call id:
if (op) {
/* We already have an op for incoming calls */
d->op = op;
d->op->setUserPointer(this);
op->enableCapabilityNegotiation (isCapabilityNegotiationEnabled());
op->enableCnxIpTo0000IfSendOnly(
!!linphone_config_get_default_int(
linphone_core_get_config(core), "sip", "cnx_ip_to_0000_if_sendonly_enabled", 0
)
);
linphone_call_log_set_call_id(d->log, op->getCallId().c_str()); /* Must be known at that time */
}
But because op
is always nullptr
, the if branch is not used and the call id therefore is never set. We can verify this when we show the id of the CallLog
object in our own (C++) code:
myLog() << call->getCallLog()->getCallId(); // Yields empty string
So retrieving the ChatRoom
of a Call
requires a callId
of the CallLog
object, but that never receives the id. How can this ever work?