From 9387bf461ffdd514de322e995f9cd0b556511c54 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 1 Oct 2010 02:03:42 +0000 Subject: Closed #1142 (Account based configuration to specify if "c=0.0.0.0" method should be used when putting call on hold): - use PJSUA_CALL_HOLD_TYPE_DEFAULT to specify default global call hold type - use pjsua_acc_config.call_hold_type to specify call hold type for the account - call hold type can also be set on per call basis by changing the call_hold_type in the call structure (requires inclusion of git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3330 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsua-lib/pjsua.h | 47 +++++++++++++++ pjsip/include/pjsua-lib/pjsua_internal.h | 1 + pjsip/src/pjsua-lib/pjsua_call.c | 98 ++++++++++++++++++++------------ pjsip/src/pjsua-lib/pjsua_core.c | 1 + 4 files changed, 112 insertions(+), 35 deletions(-) diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index dc013c0e..d178a863 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -2040,6 +2040,45 @@ PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id, #define PJSUA_REG_USE_ACC_PROXY 2 +/** + * This enumeration specifies how we should offer call hold request to + * remote peer. The default value is set by compile time constant + * PJSUA_CALL_HOLD_TYPE_DEFAULT, and application may control the setting + * on per-account basis by manipulating \a call_hold_type field in + * #pjsua_acc_config. + */ +typedef enum pjsua_call_hold_type +{ + /** + * This will follow RFC 3264 recommendation to use a=sendonly, + * a=recvonly, and a=inactive attribute as means to signal call + * hold status. This is the correct value to use. + */ + PJSUA_CALL_HOLD_TYPE_RFC3264, + + /** + * This will use the old and deprecated method as specified in RFC 2543, + * and will offer c=0.0.0.0 in the SDP instead. Using this has many + * drawbacks such as inability to keep the media transport alive while + * the call is being put on hold, and should only be used if remote + * does not understand RFC 3264 style call hold offer. + */ + PJSUA_CALL_HOLD_TYPE_RFC2543 + +} pjsua_call_hold_type; + + +/** + * Specify the default call hold type to be used in #pjsua_acc_config. + * + * Default is PJSUA_CALL_HOLD_TYPE_RFC3264, and there's no reason to change + * this except if you're communicating with an old/non-standard peer. + */ +#ifndef PJSUA_CALL_HOLD_TYPE_DEFAULT +# define PJSUA_CALL_HOLD_TYPE_DEFAULT PJSUA_CALL_HOLD_TYPE_RFC3264 +#endif + + /** * This structure describes account configuration to be specified when * adding a new account with #pjsua_acc_add(). Application MUST initialize @@ -2370,6 +2409,14 @@ typedef struct pjsua_acc_config pj_bool_t use_stream_ka; #endif + /** + * Specify how to offer call hold to remote peer. Please see the + * documentation on #pjsua_call_hold_type for more info. + * + * Default: PJSUA_CALL_HOLD_TYPE_DEFAULT + */ + pjsua_call_hold_type call_hold_type; + } pjsua_acc_config; diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index f9146fb7..ff57d29d 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -61,6 +61,7 @@ typedef struct pjsua_call pj_time_val dis_time; /**< Disconnect time. */ pjsua_acc_id acc_id; /**< Account index being used. */ int secure_level;/**< Signaling security level. */ + pjsua_call_hold_type call_hold_type; /**< How to do call hold. */ pj_bool_t local_hold;/**< Flag for call-hold by local. */ pjsua_call_media_status media_st;/**< Media state. */ pjmedia_dir media_dir; /**< Media direction. */ diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 2caaee1e..216efe83 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -82,7 +82,7 @@ static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv, /* Create SDP for call hold. */ static pj_status_t create_sdp_of_call_hold(pjsua_call *call, - pjmedia_sdp_session **p_answer); + pjmedia_sdp_session **p_sdp); /* * Callback called by event framework when the xfer subscription state @@ -404,6 +404,7 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, /* Associate session with account */ call->acc_id = acc_id; + call->call_hold_type = acc->cfg.call_hold_type; /* Create temporary pool */ tmp_pool = pjsua_pool_create("tmpcall10", 512, 256); @@ -758,6 +759,7 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) * the call. */ acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata); + call->call_hold_type = pjsua_var.acc[acc_id].cfg.call_hold_type; /* Get call's secure level */ if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) @@ -3573,25 +3575,11 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv, } -/* Create SDP for call hold. */ -static pj_status_t create_sdp_of_call_hold(pjsua_call *call, - pjmedia_sdp_session **p_answer) +/* Modify SDP for call hold. */ +static pj_status_t modify_sdp_of_call_hold(pjsua_call *call, + pj_pool_t *pool, + pjmedia_sdp_session *sdp) { - pj_status_t status; - pj_pool_t *pool; - pjmedia_sdp_session *sdp; - - /* Use call's provisional pool */ - pool = call->inv->pool_prov; - - /* Create new offer */ - status = pjsua_media_channel_create_sdp(call->index, pool, NULL, &sdp, - NULL); - if (status != PJ_SUCCESS) { - pjsua_perror(THIS_FILE, "Unable to create local SDP", status); - return status; - } - /* Call-hold is done by set the media direction to 'sendonly' * (PJMEDIA_DIR_ENCODING), except when current media direction is * 'inactive' (PJMEDIA_DIR_NONE). @@ -3600,7 +3588,33 @@ static pj_status_t create_sdp_of_call_hold(pjsua_call *call, /* http://trac.pjsip.org/repos/ticket/880 if (call->media_dir != PJMEDIA_DIR_ENCODING) { */ - if (1) { + /* https://trac.pjsip.org/repos/ticket/1142: + * configuration to use c=0.0.0.0 for call hold. + */ + if (call->call_hold_type == PJSUA_CALL_HOLD_TYPE_RFC2543) { + pjmedia_sdp_conn *conn; + pjmedia_sdp_attr *attr; + + /* Get SDP media connection line */ + conn = sdp->media[0]->conn; + if (!conn) + conn = sdp->conn; + + /* Modify address */ + conn->addr = pj_str("0.0.0.0"); + + /* Remove existing directions attributes */ + pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); + pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); + pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); + pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); + + /* Add inactive attribute */ + attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); + pjmedia_sdp_media_add_attr(sdp->media[0], attr); + + + } else { pjmedia_sdp_attr *attr; /* Remove existing directions attributes */ @@ -3620,9 +3634,35 @@ static pj_status_t create_sdp_of_call_hold(pjsua_call *call, } } - *p_answer = sdp; + return PJ_SUCCESS; +} - return status; +/* Create SDP for call hold. */ +static pj_status_t create_sdp_of_call_hold(pjsua_call *call, + pjmedia_sdp_session **p_sdp) +{ + pj_status_t status; + pj_pool_t *pool; + pjmedia_sdp_session *sdp; + + /* Use call's provisional pool */ + pool = call->inv->pool_prov; + + /* Create new offer */ + status = pjsua_media_channel_create_sdp(call->index, pool, NULL, &sdp, + NULL); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Unable to create local SDP", status); + return status; + } + + status = modify_sdp_of_call_hold(call, pool, sdp); + if (status != PJ_SUCCESS) + return status; + + *p_sdp = sdp; + + return PJ_SUCCESS; } /* @@ -3667,19 +3707,7 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, /* Check if call is on-hold */ if (call->local_hold) { - pjmedia_sdp_attr *attr; - - /* Remove existing directions attributes */ - pjmedia_sdp_media_remove_all_attr(answer->media[0], "sendrecv"); - pjmedia_sdp_media_remove_all_attr(answer->media[0], "sendonly"); - pjmedia_sdp_media_remove_all_attr(answer->media[0], "recvonly"); - pjmedia_sdp_media_remove_all_attr(answer->media[0], "inactive"); - - /* Keep call on-hold by setting 'sendonly' attribute. - * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1) - */ - attr = pjmedia_sdp_attr_create(call->inv->pool_prov, "sendonly", NULL); - pjmedia_sdp_media_add_attr(answer->media[0], attr); + modify_sdp_of_call_hold(call, call->inv->pool_prov, answer); } status = pjsip_inv_set_sdp_answer(call->inv, answer); diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 4adc191b..ac9bbfd5 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -189,6 +189,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) cfg->use_stream_ka = (PJMEDIA_STREAM_ENABLE_KA != 0); #endif pj_list_init(&cfg->reg_hdr_list); + cfg->call_hold_type = PJSUA_CALL_HOLD_TYPE_DEFAULT; } PJ_DEF(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg) -- cgit v1.2.3