⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjsua_call.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		     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 + -