summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua-lib/pjsua_call.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsua-lib/pjsua_call.c')
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c204
1 files changed, 187 insertions, 17 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index d6013a13..70d9a088 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -125,13 +125,130 @@ static pj_status_t call_destroy_media(int call_index)
/**
+ * Get maximum number of calls configured in pjsua.
+ */
+PJ_DEF(unsigned) pjsua_get_max_calls(void)
+{
+ return pjsua.config.max_calls;
+}
+
+
+/**
+ * Get current number of active calls.
+ */
+PJ_DEF(unsigned) pjsua_get_call_count(void)
+{
+ return pjsua.call_cnt;
+}
+
+
+/**
+ * Check if the specified call is active.
+ */
+PJ_DEF(pj_bool_t) pjsua_call_is_active(unsigned call_index)
+{
+ PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls,
+ PJ_EINVAL);
+ return pjsua.calls[call_index].inv != NULL &&
+ pjsua.calls[call_index].inv->state != PJSIP_INV_STATE_DISCONNECTED;
+}
+
+/**
+ * Check if call has a media session.
+ */
+PJ_DEF(pj_bool_t) pjsua_call_has_media(unsigned call_index)
+{
+ PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL);
+ return pjsua.calls[call_index].session != NULL;
+}
+
+
+/**
+ * Get call info.
+ */
+PJ_DEF(pj_status_t) pjsua_get_call_info( unsigned call_index,
+ pjsua_call_info *info)
+{
+ pjsua_call *call;
+
+ PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls,
+ PJ_EINVAL);
+
+ pj_memset(info, 0, sizeof(pjsua_call_info));
+
+ call = &pjsua.calls[call_index];
+ info->active = pjsua_call_is_active(call_index);
+
+ if (call->inv == NULL)
+ return PJ_SUCCESS;
+
+ info->index = call_index;
+ info->role = call->inv->role;
+ info->local_info = call->inv->dlg->local.info_str;
+ info->remote_info = call->inv->dlg->remote.info_str;
+ info->state = call->inv->state;
+ info->state_text = pj_str((char*)pjsip_inv_state_name(info->state));
+
+ if (info->state >= PJSIP_INV_STATE_DISCONNECTED) {
+
+ info->total_duration = call->dis_time;
+ PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
+
+ if (call->conn_time.sec) {
+ info->connect_duration = call->dis_time;
+ PJ_TIME_VAL_SUB(info->total_duration, call->conn_time);
+ }
+
+ } else if (info->state == PJSIP_INV_STATE_CONFIRMED) {
+
+ pj_gettimeofday(&info->total_duration);
+ PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
+
+ pj_gettimeofday(&info->connect_duration);
+ PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time);
+
+ } else {
+ pj_gettimeofday(&info->total_duration);
+ PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
+ }
+
+ info->cause = call->inv->cause;
+ info->cause_text = *pjsip_get_status_text(info->cause);
+
+ info->has_media = (call->session != NULL);
+ info->conf_slot = call->conf_slot;
+
+ return PJ_SUCCESS;
+}
+
+
+/**
+ * Duplicate call info.
+ */
+PJ_DEF(void) pjsua_dup_call_info( pj_pool_t *pool,
+ pjsua_call_info *dst_info,
+ const pjsua_call_info *src_info)
+{
+ PJ_ASSERT_ON_FAIL(pool && dst_info && src_info, return);
+
+ pj_memcpy(dst_info, src_info, sizeof(pjsua_call_info));
+
+ pj_strdup(pool, &dst_info->local_info, &src_info->local_info);
+ pj_strdup(pool, &dst_info->remote_info, &src_info->remote_info);
+
+ /* state_text and cause_text belong to pjsip, so don't need to be
+ * duplicated because they'll always be available.
+ */
+}
+
+
+/**
* Make outgoing call.
*/
-PJ_DEF(pj_status_t) pjsua_make_call(int acc_index,
- const char *cstr_dest_uri,
+PJ_DEF(pj_status_t) pjsua_make_call(unsigned acc_index,
+ const pj_str_t *dest_uri,
int *p_call_index)
{
- pj_str_t dest_uri;
pjsip_dialog *dlg = NULL;
pjmedia_sdp_session *offer;
pjsip_inv_session *inv = NULL;
@@ -139,9 +256,10 @@ PJ_DEF(pj_status_t) pjsua_make_call(int acc_index,
pjsip_tx_data *tdata;
pj_status_t status;
- /* Convert cstr_dest_uri to dest_uri */
-
- dest_uri = pj_str((char*)cstr_dest_uri);
+
+ PJ_ASSERT_RETURN(acc_index==0 || acc_index < pjsua.config.acc_cnt,
+ PJ_EINVAL);
+
/* Find free call slot. */
for (call_index=0; call_index<pjsua.config.max_calls; ++call_index) {
@@ -164,7 +282,7 @@ PJ_DEF(pj_status_t) pjsua_make_call(int acc_index,
status = pjsip_dlg_create_uac( pjsip_ua_instance(),
&pjsua.config.acc_config[acc_index].id,
&pjsua.config.acc_config[acc_index].contact,
- &dest_uri, &dest_uri,
+ dest_uri, dest_uri,
&dlg);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Dialog creation failed", status);
@@ -655,7 +773,9 @@ static void on_call_transfered( pjsip_inv_session *inv,
const pj_str_t str_refer_to = { "Refer-To", 8};
pjsip_generic_string_hdr *refer_to;
char *uri;
+ pj_str_t tmp;
struct pjsip_evsub_user xfer_cb;
+ pjsip_status_code code;
pjsip_evsub *sub;
existing_call = inv->dlg->mod_data[pjsua.mod.id];
@@ -673,6 +793,20 @@ static void on_call_transfered( pjsip_inv_session *inv,
return;
}
+ /* Notify callback */
+ code = PJSIP_SC_OK;
+ if (pjsua.cb.on_call_transfered)
+ (*pjsua.cb.on_call_transfered)(existing_call->index,
+ &refer_to->hvalue, &code);
+
+ if (code < 200)
+ code = 200;
+ if (code >= 300) {
+ /* Application rejects call transfer request */
+ pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL);
+ return;
+ }
+
PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s",
(int)inv->dlg->remote.info_str.slen,
inv->dlg->remote.info_str.ptr,
@@ -692,7 +826,7 @@ static void on_call_transfered( pjsip_inv_session *inv,
}
/* Accept the REFER request, send 200 (OK). */
- pjsip_xfer_accept(sub, rdata, 200, NULL);
+ pjsip_xfer_accept(sub, rdata, code, NULL);
/* Create initial NOTIFY request */
status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE,
@@ -718,7 +852,8 @@ static void on_call_transfered( pjsip_inv_session *inv,
uri[refer_to->hvalue.slen] = '\0';
/* Now make the outgoing call. */
- status = pjsua_make_call(existing_call->acc_index, uri, &new_call);
+ tmp = pj_str(uri);
+ status = pjsua_make_call(existing_call->acc_index, &tmp, &new_call);
if (status != PJ_SUCCESS) {
/* Notify xferer about the error */
@@ -1083,7 +1218,7 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
call->inv->role == PJSIP_ROLE_UAS)
{
- pjmedia_conf_connect_port( pjsua.mconf, pjsua.wav_slot,
+ pjmedia_conf_connect_port( pjsua.mconf, pjsua.player[0].slot,
call->conf_slot, 0);
}
@@ -1307,12 +1442,11 @@ PJ_DEF(void) pjsua_call_reinvite(int call_index)
/*
* Transfer call.
*/
-PJ_DEF(void) pjsua_call_xfer(int call_index, const char *dest)
+PJ_DEF(void) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest)
{
pjsip_evsub *sub;
pjsip_tx_data *tdata;
pjsua_call *call;
- pj_str_t tmp;
pj_status_t status;
@@ -1336,7 +1470,7 @@ PJ_DEF(void) pjsua_call_xfer(int call_index, const char *dest)
/*
* Create REFER request.
*/
- status = pjsip_xfer_initiate(sub, pj_cstr(&tmp, dest), &tdata);
+ status = pjsip_xfer_initiate(sub, dest, &tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create REFER request", status);
return;
@@ -1357,14 +1491,32 @@ PJ_DEF(void) pjsua_call_xfer(int call_index, const char *dest)
/**
+ * Dial DTMF.
+ */
+PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( unsigned call_index,
+ const pj_str_t *digits)
+{
+ pjsua_call *call = &pjsua.calls[call_index];
+
+ PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL);
+
+ if (!call->session) {
+ PJ_LOG(3,(THIS_FILE, "Media is not established yet!"));
+ return -1;
+ }
+
+ return pjmedia_session_dial_dtmf( call->session, 0, digits);
+}
+
+
+/**
* Send instant messaging inside INVITE session.
*/
-PJ_DECL(void) pjsua_call_send_im(int call_index, const char *str)
+PJ_DECL(void) pjsua_call_send_im(int call_index, const pj_str_t *str)
{
pjsua_call *call;
const pj_str_t mime_text = pj_str("text");
const pj_str_t mime_plain = pj_str("plain");
- pj_str_t text;
pjsip_tx_data *tdata;
pj_status_t status;
@@ -1392,8 +1544,7 @@ PJ_DECL(void) pjsua_call_send_im(int call_index, const char *str)
/* Create "text/plain" message body. */
tdata->msg->body = pjsip_msg_body_create( tdata->pool, &mime_text,
- &mime_plain,
- pj_cstr(&text, str));
+ &mime_plain, str);
if (tdata->msg->body == NULL) {
pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM);
pjsip_tx_data_dec_ref(tdata);
@@ -1504,3 +1655,22 @@ pj_status_t pjsua_call_init(void)
return status;
}
+
+/**
+ * Replace media transport.
+ */
+PJ_DEF(pj_status_t) pjsua_set_call_media_transport( unsigned call_index,
+ const pjmedia_sock_info *i,
+ pjmedia_transport *tp)
+{
+ pjsua_call *call = &pjsua.calls[call_index];
+
+ if (i)
+ pj_memcpy(&call->skinfo, i, sizeof(pjmedia_sock_info));
+
+ if (call->med_tp)
+ (*call->med_tp->op->destroy)(call->med_tp);
+
+ call->med_tp = tp;
+ return PJ_SUCCESS;
+}