Compare commits

...

10 Commits

Author SHA1 Message Date
Riza Sulistyo 70a3e2e1a4 Add call_id to the callback param 2023-10-03 07:43:26 +07:00
Riza Sulistyo eb77f1f7dc Fix build error on C89 compiler (e.g: VS2005) and change the status code to using defined/enum error for uniformity 2023-09-25 19:26:51 +07:00
Riza Sulistyo f7e28fcc2a Add doc 2023-09-25 12:27:27 +07:00
Riza Sulistyo c2ff1540c3 Modification based on comments 2023-09-22 18:11:29 +07:00
Riza Sulistyo b4565c3374 Modification based on comments 2023-09-18 13:48:44 +07:00
Riza Sulistyo e74e036ae5 Remove tdata from callback param 2023-09-15 18:54:55 +07:00
Riza Sulistyo c8bde05f9b Call the callback from pjsua_call_on_incoming() 2023-09-14 23:06:56 +07:00
Riza Sulistyo dc723740db Fix failed unit test 2023-09-12 07:37:05 +07:00
Riza Sulistyo c780fe7cb2 Modification based on comments
- save incoming rdata to be passed as callback parameter
2023-09-09 16:47:57 +07:00
Riza Sulistyo 2fa315e321 Add on_rejected_incoming_call() callback 2023-09-04 23:26:20 +07:00
4 changed files with 273 additions and 37 deletions

View File

@ -1080,6 +1080,63 @@ typedef struct pjsua_call_setting
} pjsua_call_setting; } pjsua_call_setting;
/**
* This will contain the information passed from the callback
* \a pjsua_on_rejected_incoming_call_cb.
*/
typedef struct pjsua_on_rejected_incoming_call_param {
/**
* The incoming call id. This will be set to PJSUA_INVALID_ID when there is
* no available call slot at the time.
*/
pjsua_call_id call_id;
/**
* Local URI.
*/
pj_str_t local_info;
/**
* Remote URI.
*/
pj_str_t remote_info;
/**
* Rejection code.
*/
int st_code;
/**
* Rejection text.
*/
pj_str_t st_text;
/**
* The original INVITE message, if it's not available this will be set
* to NULL.
*/
pjsip_rx_data *rdata;
/**
* Internal.
*/
struct {
char local_info[PJSIP_MAX_URL_SIZE];
char remote_info[PJSIP_MAX_URL_SIZE];
} buf_;
} pjsua_on_rejected_incoming_call_param;
/**
* Type of callback to be called when incoming call is rejected.
*
* @param param The rejected call information.
*
*/
typedef void (*pjsua_on_rejected_incoming_call_cb)(
const pjsua_on_rejected_incoming_call_param *param);
/** /**
* This structure describes application callback to receive various event * This structure describes application callback to receive various event
* notification from PJSUA-API. All of these callbacks are OPTIONAL, * notification from PJSUA-API. All of these callbacks are OPTIONAL,
@ -1967,6 +2024,23 @@ typedef struct pjsua_callback
*/ */
void (*on_media_event)(pjmedia_event *event); void (*on_media_event)(pjmedia_event *event);
/**
* This callback will be invoked when the library implicitly rejects
* an incoming call.
*
* In addition to being declined explicitly using the
* #pjsua_call_answer()/#pjsua_call_answer2() method,
* the library may also automatically reject the incoming call due
* to different scenarios, e.g:
* - no available call slot.
* - no available account to handle the call.
* - when an incoming INVITE is received with, for instance, a message
* containing invalid SDP.
*
* See also #pjsua_on_rejected_incoming_call_cb.
*/
pjsua_on_rejected_incoming_call_cb on_rejected_incoming_call;
} pjsua_callback; } pjsua_callback;

View File

@ -436,6 +436,43 @@ struct OnMediaEventParam
MediaEvent ev; MediaEvent ev;
}; };
/**
* Parameter of Endpoint::onRejectedIncomingCall() callback.
*/
struct OnRejectedIncomingCallParam
{
/**
* The incoming call id. This will be set to PJSUA_INVALID_ID when there is
* no available call slot at the time.
*/
pjsua_call_id callId;
/**
* Local URI.
*/
std::string localInfo;
/**
* Remote URI.
*/
std::string remoteInfo;
/**
* Rejection code.
*/
int statusCode;
/**
* Rejection text.
*/
std::string reason;
/**
* The original INVITE message, on some cases it is not available.
*/
SipRxData rdata;
};
/** /**
* This structure describes authentication challenge used in Proxy-Authenticate * This structure describes authentication challenge used in Proxy-Authenticate
* or WWW-Authenticate for digest authentication scheme. * or WWW-Authenticate for digest authentication scheme.
@ -1898,6 +1935,23 @@ public:
*/ */
virtual pj_status_t onCredAuth(OnCredAuthParam &prm); virtual pj_status_t onCredAuth(OnCredAuthParam &prm);
/**
* This callback will be invoked when the library implicitly rejects
* an incoming call.
*
* In addition to being declined explicitly using the Call::answer()
* method, the library may also automatically reject the incoming call
* due to different scenarios, e.g:
* - no available call slot.
* - no available account to handle the call.
* - when an incoming INVITE is received with, for instance, a message
* containing invalid SDP.
*
* @param prm Callback parameters.
*/
virtual void onRejectedIncomingCall(OnRejectedIncomingCallParam &prm)
{ PJ_UNUSED_ARG(prm); }
private: private:
static Endpoint *instance_; // static instance static Endpoint *instance_; // static instance
LogWriter *writer; // Custom writer, if any LogWriter *writer; // Custom writer, if any
@ -2078,6 +2132,10 @@ private:
const pjsip_cred_info *cred, const pjsip_cred_info *cred,
const pj_str_t *method, const pj_str_t *method,
pjsip_digest_credential *auth); pjsip_digest_credential *auth);
static void on_rejected_incoming_call(
const pjsua_on_rejected_incoming_call_param *param);
friend class Account; friend class Account;

View File

@ -1352,6 +1352,59 @@ static pj_status_t verify_request(const pjsua_call *call,
return status; return status;
} }
static void rejected_incoming_call_cb(pjsua_call_id call_id,
pjsip_rx_data *rdata,
pjsip_tx_data *tdata,
int st_code,
pj_str_t *st_text)
{
pjsip_from_hdr *from_hdr = NULL;
pjsip_to_hdr *to_hdr = NULL;
pjsip_sip_uri *uri;
pjsua_on_rejected_incoming_call_param param;
if (!pjsua_var.ua_cfg.cb.on_rejected_incoming_call)
return;
pj_bzero(&param, sizeof(pjsua_on_rejected_incoming_call_param));
param.call_id = call_id;
param.st_code = st_code;
if (rdata) {
param.rdata = rdata;
to_hdr = rdata->msg_info.to;
from_hdr = rdata->msg_info.from;
} else if (tdata) {
pjsip_msg *msg = tdata->msg;
to_hdr = PJSIP_MSG_TO_HDR(msg);
from_hdr = PJSIP_MSG_FROM_HDR(msg);
}
if (to_hdr) {
param.local_info.ptr = param.buf_.local_info;
uri = (pjsip_sip_uri*)pjsip_uri_get_uri(to_hdr->uri);
param.local_info.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
uri,
param.buf_.local_info,
sizeof(param.buf_.local_info));
}
if (from_hdr) {
param.remote_info.ptr = param.buf_.remote_info;
uri = (pjsip_sip_uri*)pjsip_uri_get_uri(from_hdr->uri);
param.remote_info.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
uri,
param.buf_.remote_info,
sizeof(param.buf_.remote_info));
}
if (st_text && st_text->slen) {
pj_strassign(&param.st_text, st_text);
} else {
param.st_text = *pjsip_get_status_text(st_code);
}
pjsua_var.ua_cfg.cb.on_rejected_incoming_call(&param);
}
/* Incoming call callback when media transport creation is completed. */ /* Incoming call callback when media transport creation is completed. */
static pj_status_t static pj_status_t
on_incoming_call_med_tp_complete2(pjsua_call_id call_id, on_incoming_call_med_tp_complete2(pjsua_call_id call_id,
@ -1406,15 +1459,21 @@ on_return:
*/ */
if (call->inv->state > PJSIP_INV_STATE_NULL) { if (call->inv->state > PJSIP_INV_STATE_NULL) {
pj_status_t status_ = PJ_SUCCESS; pj_status_t status_ = PJ_SUCCESS;
pj_str_t reason = pj_str("");
if (response == NULL) { if (response == NULL) {
pj_str_t reason = pj_str("Failed creating media transport"); reason = pj_str("Failed creating media transport");
status_ = pjsip_inv_end_session(call->inv, err_code, &reason, status_ = pjsip_inv_end_session(call->inv, err_code, &reason,
&response); &response);
} }
if (status_ == PJ_SUCCESS && response) if (status_ == PJ_SUCCESS && response)
status_ = pjsip_inv_send_msg(call->inv, response); status_ = pjsip_inv_send_msg(call->inv, response);
if ((err_code / 100 != 1) && (err_code / 100 != 2)) {
rejected_incoming_call_cb(call->index, rdata, response,
err_code, &reason);
}
} }
pjsua_media_channel_deinit(call->index); pjsua_media_channel_deinit(call->index);
} }
@ -1453,7 +1512,6 @@ on_incoming_call_med_tp_complete(pjsua_call_id call_id,
return on_incoming_call_med_tp_complete2(call_id, info, NULL, NULL, NULL); return on_incoming_call_med_tp_complete2(call_id, info, NULL, NULL, NULL);
} }
/** /**
* Handle incoming INVITE request. * Handle incoming INVITE request.
* Called by pjsua_core.c * Called by pjsua_core.c
@ -1470,11 +1528,13 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
pjsip_inv_session *inv = NULL; pjsip_inv_session *inv = NULL;
int acc_id; int acc_id;
pjsua_call *call = NULL; pjsua_call *call = NULL;
int call_id = -1; int call_id = PJSUA_INVALID_ID;
int sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR; int sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
pjmedia_sdp_session *offer=NULL; pjmedia_sdp_session *offer=NULL;
pj_bool_t should_dec_dlg = PJ_FALSE; pj_bool_t should_dec_dlg = PJ_FALSE;
pjsip_tpselector tp_sel; pjsip_tpselector tp_sel;
pj_str_t st_reason = pj_str("");
int ret_st_code = 0;
pj_status_t status; pj_status_t status;
/* Don't want to handle anything but INVITE */ /* Don't want to handle anything but INVITE */
@ -1504,9 +1564,9 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
call_id = alloc_call_id(); call_id = alloc_call_id();
if (call_id == PJSUA_INVALID_ID) { if (call_id == PJSUA_INVALID_ID) {
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code = PJSIP_SC_BUSY_HERE;
PJSIP_SC_BUSY_HERE, NULL, pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code,
NULL, NULL); NULL, NULL, NULL);
PJ_LOG(2,(THIS_FILE, PJ_LOG(2,(THIS_FILE,
"Unable to accept incoming call (too many calls)")); "Unable to accept incoming call (too many calls)"));
goto on_return; goto on_return;
@ -1534,16 +1594,17 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
*/ */
if (response) { if (response) {
pjsip_response_addr res_addr; pjsip_response_addr res_addr;
ret_st_code = response->msg->line.status.code;
pjsip_get_response_addr(response->pool, rdata, &res_addr); pjsip_get_response_addr(response->pool, rdata, &res_addr);
status = pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response, status = pjsip_endpt_send_response(pjsua_var.endpt, &res_addr,
NULL, NULL); response, NULL, NULL);
if (status != PJ_SUCCESS) pjsip_tx_data_dec_ref(response); if (status != PJ_SUCCESS) pjsip_tx_data_dec_ref(response);
} else { } else {
ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
/* Respond with 500 (Internal Server Error) */ /* Respond with 500 (Internal Server Error) */
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code,
NULL, NULL); NULL, NULL, NULL);
} }
goto on_return; goto on_return;
@ -1597,6 +1658,7 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
st_code, &st_text, NULL, NULL, NULL); st_code, &st_text, NULL, NULL, NULL);
ret_st_code = st_code;
goto on_return; goto on_return;
} }
@ -1625,8 +1687,8 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
} else { } else {
acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata); acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata);
if (acc_id == PJSUA_INVALID_ID) { if (acc_id == PJSUA_INVALID_ID) {
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
PJSIP_SC_TEMPORARILY_UNAVAILABLE, pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code,
NULL, NULL, NULL); NULL, NULL, NULL);
PJ_LOG(2,(THIS_FILE, PJ_LOG(2,(THIS_FILE,
@ -1681,13 +1743,13 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
acc->values[acc->count++] = pj_str("application/sdp"); acc->values[acc->count++] = pj_str("application/sdp");
pj_list_init(&hdr_list); pj_list_init(&hdr_list);
pj_list_push_back(&hdr_list, acc); pj_list_push_back(&hdr_list, acc);
ret_st_code = PJSIP_SC_UNSUPPORTED_MEDIA_TYPE;
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, ret_st_code,
PJSIP_SC_UNSUPPORTED_MEDIA_TYPE,
NULL, &hdr_list, NULL, NULL); NULL, &hdr_list, NULL, NULL);
} else { } else {
const pj_str_t reason = pj_str("Bad SDP");
pjsip_warning_hdr *w; pjsip_warning_hdr *w;
st_reason = pj_str("Bad SDP");
pjsua_perror(THIS_FILE, "Bad SDP in incoming INVITE", pjsua_perror(THIS_FILE, "Bad SDP in incoming INVITE",
status); status);
@ -1697,9 +1759,10 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
status); status);
pj_list_init(&hdr_list); pj_list_init(&hdr_list);
pj_list_push_back(&hdr_list, w); pj_list_push_back(&hdr_list, w);
ret_st_code = PJSIP_SC_BAD_REQUEST;
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, ret_st_code,
&reason, &hdr_list, NULL, NULL); &st_reason, &hdr_list, NULL, NULL);
} }
goto on_return; goto on_return;
} }
@ -1708,9 +1771,11 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
* checks will be done in pjsip_inv_verify_request2() below. * checks will be done in pjsip_inv_verify_request2() below.
*/ */
if ((offer) && (offer->media_count==0)) { if ((offer) && (offer->media_count==0)) {
const pj_str_t reason = pj_str("Missing media in SDP"); st_reason = pj_str("Missing media in SDP");
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, &reason, ret_st_code = PJSIP_SC_BAD_REQUEST;
NULL, NULL, NULL);
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, ret_st_code,
&st_reason, NULL, NULL, NULL);
goto on_return; goto on_return;
} }
@ -1745,16 +1810,18 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
*/ */
if (response) { if (response) {
pjsip_response_addr res_addr; pjsip_response_addr res_addr;
ret_st_code = response->msg->line.status.code;
pjsip_get_response_addr(response->pool, rdata, &res_addr); pjsip_get_response_addr(response->pool, rdata, &res_addr);
status = pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response, status = pjsip_endpt_send_response(pjsua_var.endpt, &res_addr,
NULL, NULL); response, NULL, NULL);
if (status != PJ_SUCCESS) pjsip_tx_data_dec_ref(response); if (status != PJ_SUCCESS) pjsip_tx_data_dec_ref(response);
} else { } else {
/* Respond with 500 (Internal Server Error) */ /* Respond with 500 (Internal Server Error) */
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 500, NULL, ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
NULL, NULL, NULL); pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, ret_st_code,
NULL, NULL, NULL, NULL);
} }
goto on_return; goto on_return;
@ -1767,10 +1834,11 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact, status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact,
acc_id, rdata); acc_id, rdata);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
pjsua_perror(THIS_FILE, "Unable to generate Contact header", pjsua_perror(THIS_FILE, "Unable to generate Contact header",
status); status);
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code,
NULL, NULL); NULL, NULL, NULL);
goto on_return; goto on_return;
} }
} }
@ -1779,8 +1847,9 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(), rdata, status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(), rdata,
&contact, &dlg); &contact, &dlg);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
NULL, NULL); pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, ret_st_code,
NULL, NULL, NULL);
goto on_return; goto on_return;
} }
@ -1859,8 +1928,8 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
status); status);
pj_list_init(&hdr_list); pj_list_init(&hdr_list);
pj_list_push_back(&hdr_list, w); pj_list_push_back(&hdr_list, w);
ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
pjsip_dlg_respond(dlg, rdata, 500, NULL, &hdr_list, NULL); pjsip_dlg_respond(dlg, rdata, ret_st_code, NULL, &hdr_list, NULL);
/* Can't terminate dialog because transaction is in progress. /* Can't terminate dialog because transaction is in progress.
pjsip_dlg_terminate(dlg); pjsip_dlg_terminate(dlg);
@ -1901,8 +1970,12 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
pjsip_dlg_inc_lock(dlg); pjsip_dlg_inc_lock(dlg);
if (response) { if (response) {
ret_st_code = response->msg->line.status.code;
pjsip_dlg_send_response(dlg, call->inv->invite_tsx, response); pjsip_dlg_send_response(dlg, call->inv->invite_tsx, response);
} else { } else {
ret_st_code = sip_err_code;
pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL);
} }
@ -1944,10 +2017,14 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
pjsip_dlg_inc_lock(dlg); pjsip_dlg_inc_lock(dlg);
if (response) { if (response) {
ret_st_code = response->msg->line.status.code;
pjsip_dlg_send_response(dlg, call->inv->invite_tsx, pjsip_dlg_send_response(dlg, call->inv->invite_tsx,
response); response);
} else { } else {
ret_st_code = sip_err_code;
pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL,
NULL); NULL);
} }
@ -1965,6 +2042,7 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
pjsua_perror(THIS_FILE, "Error initializing media channel", status); pjsua_perror(THIS_FILE, "Error initializing media channel", status);
pjsip_dlg_inc_lock(dlg); pjsip_dlg_inc_lock(dlg);
ret_st_code = sip_err_code;
pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL);
if (call->inv->dlg) { if (call->inv->dlg) {
pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE);
@ -1994,8 +2072,9 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
&pjsua_var.acc[acc_id].cfg.timer_setting); &pjsua_var.acc[acc_id].cfg.timer_setting);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Session Timer init failed", status); pjsua_perror(THIS_FILE, "Session Timer init failed", status);
pjsip_dlg_respond(dlg, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL); ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
pjsip_inv_terminate(inv, PJSIP_SC_INTERNAL_SERVER_ERROR, PJ_FALSE); pjsip_dlg_respond(dlg, rdata, ret_st_code, NULL, NULL, NULL);
pjsip_inv_terminate(inv, ret_st_code, PJ_FALSE);
pjsua_media_channel_deinit(call->index); pjsua_media_channel_deinit(call->index);
call->inv = NULL; call->inv = NULL;
@ -2030,12 +2109,14 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
if (response == NULL) { if (response == NULL) {
pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE", pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE",
status); status);
pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); ret_st_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
pjsip_inv_terminate(inv, 500, PJ_FALSE); pjsip_dlg_respond(dlg, rdata, ret_st_code, NULL, NULL, NULL);
pjsip_inv_terminate(inv, ret_st_code, PJ_FALSE);
} else { } else {
ret_st_code = response->msg->line.status.code;
pjsip_inv_send_msg(inv, response); pjsip_inv_send_msg(inv, response);
pjsip_inv_terminate(inv, response->msg->line.status.code, pjsip_inv_terminate(inv, ret_st_code, PJ_FALSE);
PJ_FALSE);
} }
pjsua_media_channel_deinit(call->index); pjsua_media_channel_deinit(call->index);
call->inv = NULL; call->inv = NULL;
@ -2122,6 +2203,13 @@ on_return:
pjsip_rx_data_free_cloned(call->incoming_data); pjsip_rx_data_free_cloned(call->incoming_data);
call->incoming_data = NULL; call->incoming_data = NULL;
} }
if ((ret_st_code != 0) && (ret_st_code / 100 != 1) &&
(ret_st_code / 100 != 2))
{
rejected_incoming_call_cb(call_id, rdata, NULL, ret_st_code,
&st_reason);
}
pj_log_pop_indent(); pj_log_pop_indent();
PJSUA_UNLOCK(); PJSUA_UNLOCK();

View File

@ -1962,6 +1962,7 @@ void Endpoint::libInit(const EpConfig &prmEpConfig) PJSUA2_THROW(Error)
ua_cfg.cb.on_create_media_transport = &Endpoint::on_create_media_transport; ua_cfg.cb.on_create_media_transport = &Endpoint::on_create_media_transport;
ua_cfg.cb.on_stun_resolution_complete = ua_cfg.cb.on_stun_resolution_complete =
&Endpoint::stun_resolve_cb; &Endpoint::stun_resolve_cb;
ua_cfg.cb.on_rejected_incoming_call = &Endpoint::on_rejected_incoming_call;
/* Init! */ /* Init! */
PJSUA2_CHECK_EXPR( pjsua_init(&ua_cfg, &log_cfg, &med_cfg) ); PJSUA2_CHECK_EXPR( pjsua_init(&ua_cfg, &log_cfg, &med_cfg) );
@ -2687,3 +2688,18 @@ pj_status_t Endpoint::on_auth_create_aka_response_callback(pj_pool_t *pool,
#endif #endif
return status; return status;
} }
void Endpoint::on_rejected_incoming_call(
const pjsua_on_rejected_incoming_call_param *param)
{
OnRejectedIncomingCallParam prm;
prm.callId = param->call_id;
prm.localInfo = pj2Str(param->local_info);
prm.remoteInfo = pj2Str(param->remote_info);
prm.statusCode = param->st_code;
prm.reason = pj2Str(param->st_text);
if (param->rdata)
prm.rdata.fromPj(*param->rdata);
Endpoint::instance().onRejectedIncomingCall(prm);
}