summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua-lib
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-10-18 17:16:34 +0000
committerBenny Prijono <bennylp@teluu.com>2006-10-18 17:16:34 +0000
commit487c0862f3e84a42d6fd0e73561c12e0c0db3c9f (patch)
tree36517e0f94e24c32840afe55082bd57e9619a6d7 /pjsip/src/pjsua-lib
parent44a124d9f6fcf4ecef9574aa66bf26b4f5018f57 (diff)
Some changes to REFER handling in PJSUA-LIB:
- added callback to report call transfer progress - changed the call transfer request callback name in pjsua - added "--norefersub" option in pjsua. - fixed bug when call transfer is done more than once in the same dialog (dialog usage can not be added) Also removed 7xx status from the SIP status codes. And added pjsip_parse_status_line() to parse sipfrag. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@780 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsua-lib')
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c191
1 files changed, 166 insertions, 25 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index d3b88a7b..36e5f737 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -71,7 +71,19 @@ static pj_status_t create_inactive_sdp(pjsua_call *call,
* Callback called by event framework when the xfer subscription state
* has changed.
*/
-static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
+static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
+static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
+
+/*
+ * Callback called by event framework when NOTIFY is received for outgoing
+ * REFER subscription.
+ */
+static void xfer_on_rx_notify(pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body);
/*
* Reset call descriptor.
@@ -1078,7 +1090,7 @@ PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id,
/* Create xfer client subscription. */
pj_bzero(&xfer_cb, sizeof(xfer_cb));
- xfer_cb.on_evsub_state = &xfer_on_evsub_state;
+ 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) {
@@ -1087,6 +1099,9 @@ PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id,
return status;
}
+ /* Associate this call with the client subscription */
+ pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, call);
+
/*
* Create REFER request.
*/
@@ -2144,37 +2159,23 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
* Callback called by event framework when the xfer subscription state
* has changed.
*/
-static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
+static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
{
PJ_UNUSED_ARG(event);
/*
- * When subscription is terminated, clear the xfer_sub member of
- * the inv_data.
- */
- if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
- pjsua_call *call;
-
- call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
- if (!call)
- return;
-
- pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
- call->xfer_sub = NULL;
-
- PJ_LOG(4,(THIS_FILE, "Xfer subscription terminated"));
-
- }
- /*
* When subscription is accepted (got 200/OK to REFER), check if
* subscription suppressed.
*/
- else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
+ if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
pjsip_rx_data *rdata;
pjsip_generic_string_hdr *refer_sub;
const pj_str_t REFER_SUB = { "Refer-Sub", 9 };
+ pjsua_call *call;
+
+ call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
/* Must be receipt of response message */
pj_assert(event->type == PJSIP_EVENT_TSX_STATE &&
@@ -2188,13 +2189,152 @@ static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
/* Check if subscription is suppressed */
if (refer_sub && pj_stricmp2(&refer_sub->hvalue, "false")==0) {
+ /* Since no subscription is desired, assume that call has been
+ * transfered successfully.
+ */
+ if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) {
+ const pj_str_t ACCEPTED = { "Accepted", 8 };
+ pj_bool_t cont = PJ_FALSE;
+ (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
+ 200,
+ &ACCEPTED,
+ PJ_TRUE,
+ &cont);
+ }
+
/* Yes, subscription is suppressed.
* Terminate our subscription now.
*/
PJ_LOG(4,(THIS_FILE, "Xfer subscription suppressed, terminating "
"event subcription..."));
pjsip_evsub_terminate(sub, PJ_TRUE);
+
+ } else {
+ /* Notify application about call transfer progress.
+ * Initially notify with 100/Accepted status.
+ */
+ if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) {
+ const pj_str_t ACCEPTED = { "Accepted", 8 };
+ pj_bool_t cont = PJ_FALSE;
+ (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
+ 100,
+ &ACCEPTED,
+ PJ_FALSE,
+ &cont);
+ }
+ }
+ }
+ /*
+ * On incoming NOTIFY, notify application about call transfer progress.
+ */
+ else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE ||
+ pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED)
+ {
+ pjsua_call *call;
+ pjsip_msg *msg;
+ pjsip_msg_body *body;
+ pjsip_status_line status_line;
+ pj_bool_t is_last;
+ pj_bool_t cont;
+ pj_status_t status;
+
+ call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
+
+ /* When subscription is terminated, clear the xfer_sub member of
+ * the inv_data.
+ */
+ if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
+ pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
+ PJ_LOG(4,(THIS_FILE, "Xfer client subscription terminated"));
+
+ }
+
+ if (!call || !event || !pjsua_var.ua_cfg.cb.on_call_transfer_status) {
+ /* Application is not interested with call progress status */
+ return;
}
+
+ /* This better be a NOTIFY request */
+ if (event->type == PJSIP_EVENT_TSX_STATE &&
+ event->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
+ {
+ pjsip_rx_data *rdata;
+
+ rdata = event->body.tsx_state.src.rdata;
+
+ /* Check if there's body */
+ msg = rdata->msg_info.msg;
+ body = msg->body;
+ if (!body) {
+ PJ_LOG(4,(THIS_FILE,
+ "Warning: received NOTIFY without message body"));
+ return;
+ }
+
+ /* Check for appropriate content */
+ if (pj_stricmp2(&body->content_type.type, "message") != 0 ||
+ pj_stricmp2(&body->content_type.subtype, "sipfrag") != 0)
+ {
+ PJ_LOG(4,(THIS_FILE,
+ "Warning: received NOTIFY with non message/sipfrag "
+ "content"));
+ return;
+ }
+
+ /* Try to parse the content */
+ status = pjsip_parse_status_line(body->data, body->len,
+ &status_line);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(4,(THIS_FILE,
+ "Warning: received NOTIFY with invalid "
+ "message/sipfrag content"));
+ return;
+ }
+
+ } else {
+ status_line.code = 500;
+ status_line.reason = *pjsip_get_status_text(500);
+ }
+
+ /* Notify application */
+ is_last = (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED);
+ cont = !is_last;
+ (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
+ status_line.code,
+ &status_line.reason,
+ is_last, &cont);
+
+ if (!cont) {
+ pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
+ }
+ }
+}
+
+
+/*
+ * Callback called by event framework when the xfer subscription state
+ * has changed.
+ */
+static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
+{
+
+ PJ_UNUSED_ARG(event);
+
+ /*
+ * When subscription is terminated, clear the xfer_sub member of
+ * the inv_data.
+ */
+ if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
+ pjsua_call *call;
+
+ call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
+ if (!call)
+ return;
+
+ pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
+ call->xfer_sub = NULL;
+
+ PJ_LOG(4,(THIS_FILE, "Xfer server subscription terminated"));
}
}
@@ -2246,9 +2386,10 @@ static void on_call_transfered( pjsip_inv_session *inv,
/* Notify callback */
code = PJSIP_SC_OK;
- if (pjsua_var.ua_cfg.cb.on_call_transfered)
- (*pjsua_var.ua_cfg.cb.on_call_transfered)(existing_call->index,
- &refer_to->hvalue, &code);
+ if (pjsua_var.ua_cfg.cb.on_call_transfer_request)
+ (*pjsua_var.ua_cfg.cb.on_call_transfer_request)(existing_call->index,
+ &refer_to->hvalue,
+ &code);
if (code < 200)
code = 200;
@@ -2304,7 +2445,7 @@ static void on_call_transfered( pjsip_inv_session *inv,
/* Init callback */
pj_bzero(&xfer_cb, sizeof(xfer_cb));
- xfer_cb.on_evsub_state = &xfer_on_evsub_state;
+ xfer_cb.on_evsub_state = &xfer_server_on_evsub_state;
/* Init additional header list to be sent with REFER response */
pj_list_init(&hdr_list);