📄 pjsua_call.c
字号:
PJ_EINVAL); status = acquire_call("pjsua_call_answer()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; if (call->res_time.sec == 0) pj_gettimeofday(&call->res_time); if (reason && reason->slen == 0) reason = NULL; /* Create response message */ status = pjsip_inv_answer(call->inv, code, reason, NULL, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error creating response", status); pjsip_dlg_dec_lock(dlg); return status; } /* Call might have been disconnected if application is answering with * 200/OK and the media failed to start. */ if (call->inv == NULL) { pjsip_dlg_dec_lock(dlg); return PJSIP_ESESSIONTERMINATED; } /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); /* Send the message */ status = pjsip_inv_send_msg(call->inv, tdata); if (status != PJ_SUCCESS) pjsua_perror(THIS_FILE, "Error sending response", status); pjsip_dlg_dec_lock(dlg); return status;}/* * Hangup call by using method that is appropriate according to the * call state. */PJ_DEF(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id, unsigned code, const pj_str_t *reason, const pjsua_msg_data *msg_data){ pjsua_call *call; pjsip_dialog *dlg; pj_status_t status; pjsip_tx_data *tdata; if (call_id<0 || call_id>=(int)pjsua_var.ua_cfg.max_calls) { PJ_LOG(1,(THIS_FILE, "pjsua_call_hangup(): invalid call id %d", call_id)); } PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_hangup()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; if (code==0) { if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) code = PJSIP_SC_OK; else if (call->inv->role == PJSIP_ROLE_UAS) code = PJSIP_SC_DECLINE; else code = PJSIP_SC_REQUEST_TERMINATED; } status = pjsip_inv_end_session(call->inv, code, reason, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Failed to create end session message", status); pjsip_dlg_dec_lock(dlg); return status; } /* pjsip_inv_end_session may return PJ_SUCCESS with NULL * as p_tdata when INVITE transaction has not been answered * with any provisional responses. */ if (tdata == NULL) { pjsip_dlg_dec_lock(dlg); return PJ_SUCCESS; } /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); /* Send the message */ status = pjsip_inv_send_msg(call->inv, tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Failed to send end session message", status); pjsip_dlg_dec_lock(dlg); return status; } pjsip_dlg_dec_lock(dlg); return PJ_SUCCESS;}/* * Put the specified call on hold. */PJ_DEF(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, const pjsua_msg_data *msg_data){ pjmedia_sdp_session *sdp; pjsua_call *call; pjsip_dialog *dlg; pjsip_tx_data *tdata; pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_set_hold()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed")); pjsip_dlg_dec_lock(dlg); return PJSIP_ESESSIONSTATE; } status = create_inactive_sdp(call, &sdp); if (status != PJ_SUCCESS) { pjsip_dlg_dec_lock(dlg); return status; } /* Create re-INVITE with new offer */ status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); pjsip_dlg_dec_lock(dlg); return status; } /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); /* Send the request */ status = pjsip_inv_send_msg( call->inv, tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); pjsip_dlg_dec_lock(dlg); return status; } pjsip_dlg_dec_lock(dlg); return PJ_SUCCESS;}/* * Send re-INVITE (to release hold). */PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, pj_bool_t unhold, const pjsua_msg_data *msg_data){ pjmedia_sdp_session *sdp; pjsip_tx_data *tdata; pjsua_call *call; pjsip_dialog *dlg; pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_reinvite()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); pjsip_dlg_dec_lock(dlg); return PJSIP_ESESSIONSTATE; } /* Create SDP */ PJ_UNUSED_ARG(unhold); PJ_TODO(create_active_inactive_sdp_based_on_unhold_arg); status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, call->inv->pool, 1, &call->skinfo, &sdp); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", status); pjsip_dlg_dec_lock(dlg); return status; } /* Create re-INVITE with new offer */ status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); pjsip_dlg_dec_lock(dlg); return status; } /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); /* Send the request */ status = pjsip_inv_send_msg( call->inv, tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); pjsip_dlg_dec_lock(dlg); return status; } pjsip_dlg_dec_lock(dlg); return PJ_SUCCESS;}/* * Initiate call transfer to the specified address. */PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id, const pj_str_t *dest, const pjsua_msg_data *msg_data){ pjsip_evsub *sub; pjsip_tx_data *tdata; pjsua_call *call; pjsip_dialog *dlg; pjsip_generic_string_hdr *gs_hdr; const pj_str_t str_ref_by = { "Referred-By", 11 }; struct pjsip_evsub_user xfer_cb; pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_xfer()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; /* Create xfer client subscription. */ pj_bzero(&xfer_cb, sizeof(xfer_cb)); xfer_cb.on_evsub_state = &xfer_client_on_evsub_state; status = pjsip_xfer_create_uac(call->inv->dlg, &xfer_cb, &sub); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create xfer", status); pjsip_dlg_dec_lock(dlg); return status; } /* Associate this call with the client subscription */ pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, call); /* * Create REFER request. */ status = pjsip_xfer_initiate(sub, dest, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create REFER request", status); pjsip_dlg_dec_lock(dlg); return status; } /* Add Referred-By header */ gs_hdr = pjsip_generic_string_hdr_create(tdata->pool, &str_ref_by, &dlg->local.info_str); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)gs_hdr); /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); /* Send. */ status = pjsip_xfer_send_request(sub, tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send REFER request", status); pjsip_dlg_dec_lock(dlg); return status; } /* For simplicity (that's what this program is intended to be!), * leave the original invite session as it is. More advanced application * may want to hold the INVITE, or terminate the invite, or whatever. */ pjsip_dlg_dec_lock(dlg); return PJ_SUCCESS;}/* * Initiate attended call transfer to the specified address. */PJ_DEF(pj_status_t) pjsua_call_xfer_replaces( pjsua_call_id call_id, pjsua_call_id dest_call_id, unsigned options, const pjsua_msg_data *msg_data){ pjsua_call *dest_call; pjsip_dialog *dest_dlg; char str_dest_buf[512]; pj_str_t str_dest; int len; pjsip_uri *uri; pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); PJ_ASSERT_RETURN(dest_call_id>=0 && dest_call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_xfer_replaces()", dest_call_id, &dest_call, &dest_dlg); if (status != PJ_SUCCESS) return status; /* * Create REFER destination URI with Replaces field. */ /* Make sure we have sufficient buffer's length */ PJ_ASSERT_RETURN( dest_dlg->remote.info_str.slen + dest_dlg->call_id->id.slen + dest_dlg->remote.info->tag.slen + dest_dlg->local.info->tag.slen + 32 < sizeof(str_dest_buf), PJSIP_EURITOOLONG); /* Print URI */ str_dest_buf[0] = '<'; str_dest.slen = 1; uri = pjsip_uri_get_uri(dest_dlg->remote.info->uri); len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, str_dest_buf+1, sizeof(str_dest_buf)-1); if (len < 0) return PJSIP_EURITOOLONG; str_dest.slen += len; /* Build the URI */ len = pj_ansi_snprintf(str_dest_buf + str_dest.slen, sizeof(str_dest_buf) - str_dest.slen, "?%s" "Replaces=%.*s" "%%3Bto-tag%%3D%.*s" "%%3Bfrom-tag%%3D%.*s>", ((options&PJSUA_XFER_NO_REQUIRE_REPLACES) ? "" : "Require=replaces&"), (int)dest_dlg->call_id->id.slen, dest_dlg->call_id->id.ptr, (int)dest_dlg->remote.info->tag.slen, dest_dlg->remote.info->tag.ptr, (int)dest_dlg->local.info->tag.slen, dest_dlg->local.info->tag.ptr); PJ_ASSERT_RETURN(len > 0 && len <= (int)sizeof(str_dest_buf)-str_dest.slen, PJSIP_EURITOOLONG); str_dest.ptr = str_dest_buf; str_dest.slen += len; pjsip_dlg_dec_lock(dest_dlg); return pjsua_call_xfer(call_id, &str_dest, msg_data);}/* * Send DTMF digits to remote using RFC 2833 payload formats. */PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( pjsua_call_id call_id, const pj_str_t *digits){ pjsua_call *call; pjsip_dialog *dlg; pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_dial_dtmf()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; if (!call->session) { PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); pjsip_dlg_dec_lock(dlg); return PJ_EINVALIDOP; } status = pjmedia_session_dial_dtmf( call->session, 0, digits); pjsip_dlg_dec_lock(dlg); return status;}/** * Send instant messaging inside INVITE session. */PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id, const pj_str_t *mime_type, const pj_str_t *content, const pjsua_msg_data *msg_data, void *user_data){ pjsua_call *call; pjsip_dialog *dlg; const pj_str_t mime_text_plain = pj_str("text/plain"); pjsip_media_type ctype; pjsua_im_data *im_data; pjsip_tx_data *tdata; pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); status = acquire_call("pjsua_call_send_im()", call_id, &call, &dlg); if (status != PJ_SUCCESS) return status; /* Set default media type if none is specified */ if (mime_type == NULL) { mime_type = &mime_text_plain; } /* Create request message. */ status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, -1, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); goto on_return; } /* Add accept header. */ pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); /* Parse MIME type */ pjsua_parse_media_type(tdata->pool, mime_type, &ctype); /* Create "text/plain" message body. */ tdata->msg->body = pjsip_msg_body_create( tdata->pool, &ctype.type, &ctype.subtype, content); if (tdata->msg->body == NULL) { pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); pjsip_tx_data_dec_ref(tdata); goto on_return; } /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); /* Create IM data and attach to the request. */ im_data = pj_pool_zalloc(tdata->pool, sizeof(*im_data)); im_data->acc_id = call->acc_id; im_data->call_id = call_id; im_data->to = call->inv->dlg->remote.info_str; pj_strdup_with_null(tdata->pool, &im_data->body, content); im_data->user_data = user_data; /* Send the request. */ status = pjsip_dlg_send_request( call->inv->dlg, tdata, pjsua_var.mod.id, im_data); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); goto on_return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -