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 <pjsua-lib/pjsua_internal.h>
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@3330 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index dc013c0..d178a86 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -2041,6 +2041,45 @@
/**
+ * 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
* this structure first by calling #pjsua_acc_config_default().
@@ -2370,6 +2409,14 @@
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 f9146fb..ff57d29 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -61,6 +61,7 @@
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 2caaee1..216efe8 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -82,7 +82,7 @@
/* 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 @@
/* 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 @@
* 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 @@
}
-/* 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 @@
/* 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 @@
}
}
- *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 @@
/* 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 4adc191..ac9bbfd 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -189,6 +189,7 @@
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)