Commit e375f828 authored by Guillaume Roguez's avatar Guillaume Roguez

fix SipsIceTransport implementation

SipsIceTransport doesn't set internal PJSIP transport correctly
causing many troubles in how our ICE/DTLS underlaying transport
works with PJSIP.

This patch:
* adds a custom dtls PJSIP transport type
* implement correctly custom PJSIP transport creation
* revert unneeded patches about IM fixes (da0a2d17 and 0cf16b30)
  as this patch fixes also the 30s issue

Side-effect: this fixes the 'call failed' effect when peer hangs-up

Change-Id: If88b8245d6c9ff76bc2f2456f06ff65bc5e723b1
parent a00b5e8a
......@@ -24,7 +24,6 @@
#include "logger.h"
#include "sip/sip_utils.h"
#include "sip/sipvoiplink.h"
#include <pjsip_ua.h>
#include <pjsip.h>
......@@ -154,61 +153,37 @@ im::fillPJSIPMessageBody(pjsip_tx_data& tdata,
}
}
static void
im_callback(void* /*token*/, pjsip_event* e)
{
if (e->type == PJSIP_EVENT_TSX_STATE) {
auto* tsx = e->body.tsx_state.tsx;
RING_DBG("[IM] status code %u", tsx->status_code);
}
}
void
im::sendSipMessage(const std::map<std::string, std::string>& payloads, pjsip_dialog* dlg)
im::sendSipMessage(pjsip_inv_session* session,
const std::map<std::string, std::string>& payloads)
{
if (payloads.empty()) {
RING_WARN("the payloads argument is empty; ignoring message");
return;
}
auto link = getSIPVoIPLink();
auto* endpt = link->getEndpoint();
// Create request message
static constexpr pjsip_method method = {PJSIP_OTHER_METHOD, CONST_PJ_STR("MESSAGE")};
pjsip_tx_data* tdata = nullptr;
pjsip_dlg_inc_lock(dlg);
auto status = pjsip_endpt_create_request_from_hdr(endpt,
&method,
dlg->target,
dlg->local.info,
dlg->remote.info,
nullptr,
dlg->call_id,
++dlg->local.cseq,
nullptr,
&tdata);
pjsip_dlg_dec_lock(dlg);
if (status != PJ_SUCCESS or !tdata) {
RING_ERR("[IM] Could not create MESSAGE request");
if (tdata)
pjsip_tx_data_dec_ref(tdata);
throw InstantMessageException("Internal SIP error");
}
const pjsip_method msg_method = {PJSIP_OTHER_METHOD, CONST_PJ_STR("MESSAGE")};
{
auto dialog = session->dlg;
sip_utils::PJDialogLock dialog_lock {dialog};
// Use dialog's transport
pjsip_tx_data_set_transport(tdata, &dlg->tp_sel);
pjsip_tx_data* tdata = nullptr;
auto status = pjsip_dlg_create_request(dialog, &msg_method, -1, &tdata);
if (status != PJ_SUCCESS) {
RING_ERR("pjsip_dlg_create_request failed: %s",
sip_utils::sip_strerror(status).c_str());
throw InstantMessageException("Internal SIP error");
}
// Fill message body
fillPJSIPMessageBody(*tdata, payloads);
fillPJSIPMessageBody(*tdata, payloads);
// Send the request
status = pjsip_endpt_send_request(endpt, tdata, -1, nullptr, &im_callback);
if (status != PJ_SUCCESS) {
RING_ERR("[IM] Could not send MESSAGE request");
pjsip_tx_data_dec_ref(tdata);
throw InstantMessageException("Internal SIP error");
status = pjsip_dlg_send_request(dialog, tdata, -1, nullptr);
if (status != PJ_SUCCESS) {
RING_ERR("pjsip_dlg_send_request failed: %s",
sip_utils::sip_strerror(status).c_str());
throw InstantMessageException("Internal SIP error");
}
}
}
......
......@@ -30,9 +30,10 @@
#include "config.h"
struct pjsip_inv_session;
struct pjsip_rx_data;
struct pjsip_msg;
struct pjsip_tx_data;
struct pjsip_dialog;
namespace ring { namespace im {
......@@ -57,11 +58,10 @@ struct InstantMessageException : std::runtime_error
* @param session SIP session
* @param payloads a map where the mime type and optional parameters are the key
* and the message payload is the value
* @param dlg SIP dialog to attach the message
*
* Exception: throw InstantMessageException if no message sent
*/
void sendSipMessage(const std::map<std::string, std::string>& payloads, pjsip_dialog* dlg);
void sendSipMessage(pjsip_inv_session* session, const std::map<std::string, std::string>& payloads);
/**
* Parses given SIP message into a map where the key is the contents of the Content-Type header
......
......@@ -534,9 +534,6 @@ RingAccount::SIPStartCall(const std::shared_ptr<SIPCall>& call, IpAddr target)
return false;
}
// Add our instant message module as usage of created dialog
link_->registerDialog(dialog, call.get());
pj_str_t subj_hdr_name = CONST_PJ_STR("Subject");
pjsip_hdr* subj_hdr = (pjsip_hdr*) pjsip_parse_hdr(dialog->pool, &subj_hdr_name, (char *) "Phone call", 10, NULL);
......@@ -2393,7 +2390,7 @@ std::string
RingAccount::getToUri(const std::string& to) const
{
RING_DBG("getToUri %s", to.c_str());
return "<sips:" + to + ";transport=tls>";
return "<sips:" + to + ";transport=dtls>";
}
pj_str_t
......@@ -2404,7 +2401,7 @@ RingAccount::getContactHeader(pjsip_transport* t)
auto tlsTr = reinterpret_cast<tls::SipsIceTransport::TransportData*>(t)->self;
auto address = tlsTr->getLocalAddress().toString(true);
contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE,
"%s%s<sips:%s%s%s;transport=tls>",
"%s%s<sips:%s%s%s;transport=dtls>",
displayName_.c_str(),
(displayName_.empty() ? "" : " "),
identity_.second->getId().toString().c_str(),
......
......@@ -133,6 +133,7 @@ tls_status_from_err(int err)
}
SipsIceTransport::SipsIceTransport(pjsip_endpoint* endpt,
int tp_type,
const TlsParams& param,
const std::shared_ptr<ring::IceTransport>& ice,
int comp_id)
......@@ -150,13 +151,13 @@ SipsIceTransport::SipsIceTransport(pjsip_endpoint* endpt,
trData_.self = this; // up-link for PJSIP callbacks
pool_ = std::move(sip_utils::smart_alloc_pool(endpt, "SipsIceTransport.pool",
pool_ = std::move(sip_utils::smart_alloc_pool(endpt, "dtls.pool",
POOL_TP_INIT, POOL_TP_INC));
auto& base = trData_.base;
std::memset(&rdata_, 0, sizeof(pjsip_rx_data));
std::memset(&base, 0, sizeof(base));
pj_ansi_snprintf(base.obj_name, PJ_MAX_OBJ_NAME, "SipsIceTransport");
pj_ansi_snprintf(base.obj_name, PJ_MAX_OBJ_NAME, "dtls%p", &base);
base.endpt = endpt;
base.tpmgr = pjsip_endpt_get_tpmgr(endpt);
base.pool = pool_.get();
......@@ -164,24 +165,24 @@ SipsIceTransport::SipsIceTransport(pjsip_endpoint* endpt,
if (pj_atomic_create(pool_.get(), 0, &base.ref_cnt) != PJ_SUCCESS)
throw std::runtime_error("Can't create PJSIP atomic.");
if (pj_lock_create_recursive_mutex(pool_.get(), "SipsIceTransport.mutex",
if (pj_lock_create_recursive_mutex(pool_.get(), "dtls",
&base.lock) != PJ_SUCCESS)
throw std::runtime_error("Can't create PJSIP mutex.");
local_ = ice->getLocalAddress(comp_id);
remote_ = ice->getRemoteAddress(comp_id);
pj_sockaddr_cp(&base.key.rem_addr, remote_.pjPtr());
base.key.type = local_.isIpv6() ? PJSIP_TRANSPORT_TLS6 : PJSIP_TRANSPORT_TLS;
base.type_name = (char*)pjsip_transport_get_type_name((pjsip_transport_type_e)base.key.type);
base.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)base.key.type);
base.info = (char*) pj_pool_alloc(pool_.get(), TRANSPORT_INFO_LENGTH);
base.key.type = tp_type;
auto raw_tp_type = static_cast<pjsip_transport_type_e>(base.key.type);
base.type_name = const_cast<char*>(pjsip_transport_get_type_name(raw_tp_type));
base.flag = pjsip_transport_get_flag_from_type(raw_tp_type);
base.info = static_cast<char*>(pj_pool_alloc(pool_.get(), TRANSPORT_INFO_LENGTH));
char print_addr[PJ_INET6_ADDRSTRLEN+10];
auto remote_addr = remote_.toString();
pj_ansi_snprintf(base.info, TRANSPORT_INFO_LENGTH, "%s to %s", base.type_name,
pj_sockaddr_print(remote_.pjPtr(), print_addr, sizeof(print_addr), 3));
remote_addr.c_str());
base.addr_len = remote_.getLength();
base.dir = PJSIP_TP_DIR_NONE;
base.data = nullptr;
/* Set initial local address */
auto local = ice->getDefaultLocalAddress();
......@@ -223,7 +224,7 @@ SipsIceTransport::SipsIceTransport(pjsip_endpoint* endpt,
/* Init rdata_ */
std::memset(&rdata_, 0, sizeof(pjsip_rx_data));
rxPool_ = std::move(sip_utils::smart_alloc_pool(endpt, "SipsIceTransport.rxPool",
rxPool_ = std::move(sip_utils::smart_alloc_pool(endpt, "dtls.rxPool",
PJSIP_POOL_RDATA_LEN, PJSIP_POOL_RDATA_LEN));
rdata_.tp_info.pool = rxPool_.get();
rdata_.tp_info.transport = &base;
......@@ -308,6 +309,7 @@ SipsIceTransport::handleEvents()
if (evdata.state != PJSIP_TP_STATE_DISCONNECTED) {
(*state_cb)(&trData_.base, evdata.state, &evdata.state_info);
} else {
RING_WARN("[SIPS] got disconnected event!");
disconnectedEvent = std::move(evdata);
disconnected = true;
break;
......@@ -384,8 +386,10 @@ SipsIceTransport::handleEvents()
}
// Time to deliver disconnected event if exists
if (disconnected and state_cb)
if (disconnected and state_cb) {
RING_WARN("[SIPS] process disconnect event");
(*state_cb)(&trData_.base, disconnectedEvent.state, &disconnectedEvent.state_info);
}
}
void
......
......@@ -62,7 +62,7 @@ struct SipsIceTransport
static_assert(std::is_standard_layout<TransportData>::value,
"TranportData requires standard-layout");
SipsIceTransport(pjsip_endpoint* endpt, const TlsParams& param,
SipsIceTransport(pjsip_endpoint* endpt, int tp_type, const TlsParams& param,
const std::shared_ptr<IceTransport>& ice, int comp_id);
~SipsIceTransport();
......
......@@ -347,9 +347,6 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
return false;
}
// Add our instant message module as usage of created dialog
link_->registerDialog(dialog, call.get());
auto subj_hdr_name = CONST_PJ_STR("Subject");
pjsip_hdr* subj_hdr = (pjsip_hdr*) pjsip_parse_hdr(dialog->pool, &subj_hdr_name, (char *) "Phone call", 10, NULL);
......
......@@ -263,28 +263,15 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
if (not inv or not inv->dlg)
throw VoipLinkException("Couldn't get invite dialog");
auto dlg = inv->dlg;
// Create request
static constexpr pjsip_method method = {PJSIP_OTHER_METHOD, CONST_PJ_STR("INFO")};
pjsip_tx_data* tdata = nullptr;
pjsip_dlg_inc_lock(dlg);
auto status = pjsip_endpt_create_request_from_hdr(dlg->endpt,
&method,
dlg->target,
dlg->local.info,
dlg->remote.info,
nullptr,
dlg->call_id,
++dlg->local.cseq,
nullptr,
&tdata);
pjsip_dlg_dec_lock(dlg);
if (status != PJ_SUCCESS or !tdata) {
RING_ERR("[call:%s] Could not create INFO request", getCallId().c_str());
if (tdata)
pjsip_tx_data_dec_ref(tdata);
pj_str_t methodName = CONST_PJ_STR("INFO");
pjsip_method method;
pjsip_method_init_np(&method, &methodName);
/* Create request message. */
pjsip_tx_data *tdata;
if (pjsip_dlg_create_request(inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) {
RING_ERR("[call:%s] Could not create dialog", getCallId().c_str());
return;
}
......@@ -295,19 +282,11 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
pj_str_t pj_subtype;
pj_cstr(&pj_subtype, subtype);
tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &pj_subtype, &content);
if (tdata->msg->body == nullptr) {
RING_ERR("[call:%s] Could not create INFO msg body", getCallId().c_str());
pjsip_tx_data_dec_ref(tdata);
return;
}
// Send the request
status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata, nullptr, nullptr);
if (status != PJ_SUCCESS) {
RING_ERR("[call:%s] Could not send INFO request", getCallId().c_str());
if (tdata->msg->body == NULL)
pjsip_tx_data_dec_ref(tdata);
return;
}
else
pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
}
void
......@@ -691,9 +670,9 @@ SIPCall::sendTextMessage(const std::map<std::string, std::string>& messages,
for (auto& c : subcalls)
c->sendTextMessage(messages, from);
} else {
if (inv and inv->dlg) {
if (inv) {
try {
im::sendSipMessage(messages, inv->dlg);
im::sendSipMessage(inv.get(), messages);
} catch (...) {}
} else {
pendingOutMessages_.emplace_back(messages, from);
......@@ -1144,7 +1123,6 @@ SIPCall::merge(std::shared_ptr<SIPCall> scall)
RING_WARN("SIPCall::merge %s -> %s", scall->getCallId().c_str(), getCallId().c_str());
inv = std::move(scall->inv);
inv->mod_data[getSIPVoIPLink()->getModId()] = this;
pjsip_dlg_set_mod_data(inv->dlg, getSIPVoIPLink()->getImModule().id, this);
setTransport(scall->transport_);
sdp_ = std::move(scall->sdp_);
peerHolding_ = scall->peerHolding_;
......
......@@ -181,6 +181,9 @@ cp_(cp), pool_(pool), endpt_(endpt)
pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP),
&ice_pj_transport_type_);
*/
pjsip_transport_register_type(PJSIP_TRANSPORT_SECURE, "DTLS",
pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_TLS),
&dtls_pj_transport_type_);
RING_DBG("SipTransportBroker@%p", this);
}
......@@ -441,7 +444,7 @@ SipTransportBroker::getTlsIceTransport(const std::shared_ptr<ring::IceTransport>
const tls::TlsParams& params)
{
auto sip_ice_tr = std::unique_ptr<tls::SipsIceTransport>(
new tls::SipsIceTransport(endpt_, params, ice, comp_id));
new tls::SipsIceTransport(endpt_, dtls_pj_transport_type_, params, ice, comp_id));
auto tr = sip_ice_tr->getTransportBase();
auto sip_tr = std::make_shared<SipTransport>(tr);
sip_ice_tr.release(); // managed by PJSIP now
......
......@@ -219,6 +219,11 @@ private:
*/
int ice_pj_transport_type_ {PJSIP_TRANSPORT_START_OTHER};
/**
* Storage for SIP/DTLS transport instances.
*/
int dtls_pj_transport_type_ {PJSIP_TRANSPORT_START_OTHER};
pj_caching_pool& cp_;
pj_pool_t& pool_;
pjsip_endpoint *endpt_;
......
......@@ -81,17 +81,9 @@ static void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event
static void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e);
static void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
static std::shared_ptr<SIPCall> getCallFromInvite(pjsip_inv_session* inv);
static bool handleMediaControl(SIPCall& call, pjsip_msg_body* body);
decltype(getGlobalInstance<SIPVoIPLink>)& getSIPVoIPLink = getGlobalInstance<SIPVoIPLink>;
static void
TRY(pj_status_t ret)
{
if (ret != PJ_SUCCESS)
throw VoipLinkException("PJSIP call failure");
}
static void
handleIncomingOptions(pjsip_rx_data *rdata)
{
......@@ -362,9 +354,6 @@ transaction_request_cb(pjsip_rx_data *rdata)
return PJ_FALSE;
}
// Add our instant message module as usage of created dialog
link->registerDialog(dialog, call.get());
pjsip_tpselector tp_sel = SIPVoIPLink::getTransportSelector(transport->get());
if (!dialog or pjsip_dlg_set_transport(dialog, &tp_sel) != PJ_SUCCESS) {
RING_ERR("Could not set transport for dialog");
......@@ -497,6 +486,11 @@ SIPVoIPLink::getCachingPool() noexcept
SIPVoIPLink::SIPVoIPLink() : pool_(nullptr, pj_pool_release)
{
#define TRY(ret) do { \
if (ret != PJ_SUCCESS) \
throw VoipLinkException(#ret " failed"); \
} while (0)
pj_caching_pool_init(&cp_, &pj_pool_factory_default_policy, 0);
pool_.reset(pj_pool_create(&cp_.factory, PACKAGE, 4096, 4096, nullptr));
if (!pool_)
......@@ -564,20 +558,26 @@ SIPVoIPLink::SIPVoIPLink() : pool_(nullptr, pj_pool_release)
};
TRY(pjsip_inv_usage_init(endpt_, &inv_cb));
registerImModule();
static const pj_str_t allowed[] = {
CONST_PJ_STR("INFO"),
CONST_PJ_STR("OPTIONS"),
CONST_PJ_STR("MESSAGE"),
CONST_PJ_STR("PUBLISH"),
};
pjsip_endpt_add_capability(endpt_, &mod_ua_, PJSIP_H_ALLOW, nullptr, PJ_ARRAY_SIZE(allowed), allowed);
static const pj_str_t text_plain = CONST_PJ_STR("text/plain");
pjsip_endpt_add_capability(endpt_, &mod_ua_, PJSIP_H_ACCEPT, nullptr, 1, &text_plain);
static const pj_str_t accepted = CONST_PJ_STR("application/sdp");
pjsip_endpt_add_capability(endpt_, &mod_ua_, PJSIP_H_ACCEPT, nullptr, 1, &accepted);
static const pj_str_t iscomposing = CONST_PJ_STR("application/im-iscomposing+xml");
pjsip_endpt_add_capability(endpt_, &mod_ua_, PJSIP_H_ACCEPT, nullptr, 1, &iscomposing);
TRY(pjsip_replaces_init_module(endpt_));
#undef TRY
// ready to handle events
// Implementation note: we don't use std::bind(xxx, this) here
......@@ -776,120 +776,6 @@ SIPVoIPLink::requestKeyframe(const std::string &callID)
}
#endif
/*************************************************************************************************/
static constexpr pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, CONST_PJ_STR("MESSAGE")};
/**
* Check if we can accept the message.
*/
static pj_bool_t
im_accept_message(pjsip_rx_data* /*rdata*/, pjsip_accept_hdr** /*p_accept_hdr*/)
{
// Nothing to do here yet
return PJ_TRUE;
}
static pj_bool_t
im_on_rx_request(pjsip_rx_data* rdata)
{
auto msg = rdata->msg_info.msg;
// Handle only MESSAGE requests
if (pjsip_method_cmp(&msg->line.req.method, &pjsip_message_method) != 0) {
return PJ_FALSE;
}
// Check if we can accept the message
pjsip_accept_hdr* accept_hdr;
if (!im_accept_message(rdata, &accept_hdr)) {
pjsip_hdr hdr_list;
pj_list_init(&hdr_list);
pj_list_push_back(&hdr_list, accept_hdr);
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,
nullptr, &hdr_list, nullptr);
return PJ_TRUE;
}
/* Respond with OK (200) first, so that remote doesn't retransmit in case
* the UI takes too long to process the message.
*/
pjsip_endpt_respond(endpt_, nullptr, rdata, PJSIP_SC_OK,
nullptr, nullptr, nullptr, nullptr);
// We need a dialog attached to find the call object
auto dlg = pjsip_rdata_get_dlg(rdata);
if (dlg == nullptr) {
RING_ERR("[IM] no attached dialog");
return PJ_TRUE;
}
const auto im_mod_id = getSIPVoIPLink()->getImModule().id;
auto call_ptr = static_cast<SIPCall*>(pjsip_dlg_get_mod_data(dlg, im_mod_id));
if (!call_ptr) {
RING_ERR("[IM] no attached call pointer");
return PJ_TRUE;
}
auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this());
if (!call) {
RING_ERR("[IM] no attached SIPCall");
return PJ_TRUE;
}
if (msg->body) {
call->onTextMessage(im::parseSipMessage(msg));
} else {
RING_ERR("rx msg: <no body>");
}
return PJ_TRUE;
}
pjsip_module&
SIPVoIPLink::getImModule()
{
static pjsip_module mod_im = {
nullptr, nullptr, /* prev, next. */
CONST_PJ_STR( "mod-im" ), /* Name. */
-1, /* Id */
PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
nullptr, /* load() */
nullptr, /* start() */
nullptr, /* stop() */
nullptr, /* unload() */
&im_on_rx_request, /* on_rx_request() */
nullptr, /* on_rx_response() */
nullptr, /* on_tx_request. */
nullptr, /* on_tx_response() */
nullptr, /* on_tsx_state() */
};
return mod_im;
}
void
SIPVoIPLink::registerImModule()
{
auto& mod = getImModule();
static constexpr pj_str_t STR_MSG_TAG = CONST_PJ_STR("MESSAGE");
static constexpr pj_str_t STR_MIME_TEXT_PLAIN = CONST_PJ_STR("text/plain");
static constexpr pj_str_t STR_MIME_APP_ISCOMPOSING = CONST_PJ_STR("application/im-iscomposing+xml");
TRY(pjsip_endpt_register_module(endpt_, &mod));
TRY(pjsip_endpt_add_capability(endpt_, &mod, PJSIP_H_ALLOW,
nullptr, 1, &STR_MSG_TAG));
TRY(pjsip_endpt_add_capability(endpt_, &mod, PJSIP_H_ACCEPT,
nullptr, 1, &STR_MIME_APP_ISCOMPOSING));
TRY(pjsip_endpt_add_capability(endpt_, &mod, PJSIP_H_ACCEPT,
nullptr, 1, &STR_MIME_TEXT_PLAIN));
}
///////////////////////////////////////////////////////////////////////////////
// Private functions
///////////////////////////////////////////////////////////////////////////////
......@@ -1260,6 +1146,9 @@ transaction_state_changed_cb(pjsip_inv_session* inv, pjsip_transaction* tsx, pjs
onRequestInfo(inv, rdata, msg, *call);
else if (methodName == "NOTIFY")
onRequestNotify(inv, rdata, msg, *call);
else if (methodName == "MESSAGE")
if (msg->body)
call->onTextMessage(im::parseSipMessage(msg));
}
int SIPVoIPLink::getModId()
......@@ -1485,21 +1374,4 @@ SIPVoIPLink::findLocalAddressFromSTUN(pjsip_transport* transport,
}
#undef RETURN_IF_NULL
#undef RETURN_FALSE_IF_NULL
bool
SIPVoIPLink::registerDialog(pjsip_dialog* dlg, void* mod_data)
{
pjsip_dlg_inc_lock(dlg);
if (pjsip_dlg_add_usage(dlg, &getImModule(), mod_data) != PJ_SUCCESS) {
RING_ERR("Unable to add IM module to a dialog");
pjsip_dlg_dec_lock(dlg);
return false;
}
pjsip_dlg_inc_session(dlg, &getImModule());
pjsip_dlg_dec_lock(dlg);
return true;
}
} // namespace ring
......@@ -130,8 +130,6 @@ class SIPVoIPLink {
pjsip_endpoint * getEndpoint();
pjsip_module * getMod();
void registerModuleIM();
pj_caching_pool* getCachingPool() noexcept;
pj_pool_t* getPool() noexcept;
......@@ -164,10 +162,6 @@ class SIPVoIPLink {
return tp;
}
static pjsip_module& getImModule();
void registerImModule();
bool registerDialog(pjsip_dialog* dlg, void* mod_data);
private:
NON_COPYABLE(SIPVoIPLink);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment