summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip-simple
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-07-17 13:53:41 +0000
committerBenny Prijono <bennylp@teluu.com>2008-07-17 13:53:41 +0000
commitd6f361a21e8709fe8b18d8a3bd673f830f3920e9 (patch)
tree11cdbd74af4c6a48b610e2e850a15e646bf2db89 /pjsip/src/pjsip-simple
parent01b9c5d12e4ae6e7c633b28936581e9a0e0a18dd (diff)
Ticket #574: Add new API to know why the outgoing subscription request is terminated and added support for delaying subscription acceptance
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2149 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsip-simple')
-rw-r--r--pjsip/src/pjsip-simple/evsub.c66
-rw-r--r--pjsip/src/pjsip-simple/evsub_msg.c6
-rw-r--r--pjsip/src/pjsip-simple/presence.c38
3 files changed, 77 insertions, 33 deletions
diff --git a/pjsip/src/pjsip-simple/evsub.c b/pjsip/src/pjsip-simple/evsub.c
index 085d496e..2d629c04 100644
--- a/pjsip/src/pjsip-simple/evsub.c
+++ b/pjsip/src/pjsip-simple/evsub.c
@@ -221,6 +221,7 @@ struct pjsip_evsub
pj_str_t state_str; /**< String describing the state. */
pjsip_evsub_state dst_state; /**< Pending state to be set. */
pj_str_t dst_state_str;/**< Pending state to be set. */
+ pj_str_t term_reason; /**< Termination reason. */
pjsip_method method; /**< Method that established subscr.*/
pjsip_event_hdr *event; /**< Event description. */
pjsip_expires_hdr *expires; /**< Expires header */
@@ -550,7 +551,8 @@ static void evsub_destroy( pjsip_evsub *sub )
* Set subscription session state.
*/
static void set_state( pjsip_evsub *sub, pjsip_evsub_state state,
- const pj_str_t *state_str, pjsip_event *event)
+ const pj_str_t *state_str, pjsip_event *event,
+ const pj_str_t *reason)
{
pjsip_evsub_state prev_state = sub->state;
pj_str_t old_state_str = sub->state_str;
@@ -562,6 +564,9 @@ static void set_state( pjsip_evsub *sub, pjsip_evsub_state state,
else
sub->state_str = evsub_state_names[state];
+ if (reason && sub->term_reason.slen==0)
+ pj_strdup(sub->pool, &sub->term_reason, reason);
+
PJ_LOG(4,(sub->obj_name,
"Subscription state changed %.*s --> %.*s",
(int)old_state_str.slen,
@@ -638,9 +643,12 @@ static void on_timer( pj_timer_heap_t *timer_heap,
case TIMER_TYPE_UAC_TERMINATE:
{
+ pj_str_t timeout = {"timeout", 7};
+
PJ_LOG(5,(sub->obj_name, "Timeout waiting for final NOTIFY. "
"Terminating.."));
- set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);
+ set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL,
+ &timeout);
}
break;
@@ -912,7 +920,7 @@ PJ_DEF(pj_status_t) pjsip_evsub_terminate( pjsip_evsub *sub,
*/
sub->call_cb = notify;
- set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);
+ set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL, NULL);
pjsip_dlg_dec_lock(sub->dlg);
return PJ_SUCCESS;
@@ -934,6 +942,13 @@ PJ_DEF(const char*) pjsip_evsub_get_state_name(pjsip_evsub *sub)
return sub->state_str.ptr;
}
+/*
+ * Get termination reason.
+ */
+PJ_DEF(const pj_str_t*) pjsip_evsub_get_termination_reason(pjsip_evsub *sub)
+{
+ return &sub->term_reason;
+}
/*
* Initiate client subscription
@@ -1085,10 +1100,10 @@ static pjsip_sub_state_hdr* sub_state_create( pj_pool_t *pool,
switch (state) {
case PJSIP_EVSUB_STATE_NULL:
case PJSIP_EVSUB_STATE_SENT:
- case PJSIP_EVSUB_STATE_ACCEPTED:
pj_assert(!"Invalid state!");
/* Treat as pending */
+ case PJSIP_EVSUB_STATE_ACCEPTED:
case PJSIP_EVSUB_STATE_PENDING:
sub_state->sub_state = STR_PENDING;
sub_state->expires_param = delay.sec;
@@ -1155,7 +1170,9 @@ PJ_DEF(pj_status_t) pjsip_evsub_notify( pjsip_evsub *sub,
/* Add Authentication headers. */
pjsip_auth_clt_init_req( &sub->dlg->auth_sess, tdata );
-
+ /* Update reason */
+ if (reason)
+ pj_strdup(sub->dlg->pool, &sub->term_reason, reason);
/* Save destination state. */
sub->dst_state = state;
@@ -1218,7 +1235,7 @@ PJ_DEF(pj_status_t) pjsip_evsub_send_request( pjsip_evsub *sub,
set_state(sub, sub->dst_state,
(sub->dst_state_str.slen ? &sub->dst_state_str : NULL),
- NULL);
+ NULL, NULL);
sub->dst_state = PJSIP_EVSUB_STATE_NULL;
sub->dst_state_str.slen = 0;
@@ -1546,7 +1563,7 @@ static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
if (sub->state == PJSIP_EVSUB_STATE_NULL &&
tsx->state == PJSIP_TSX_STATE_CALLING)
{
- set_state(sub, PJSIP_EVSUB_STATE_SENT, NULL, event);
+ set_state(sub, PJSIP_EVSUB_STATE_SENT, NULL, event, NULL);
return;
}
@@ -1587,8 +1604,7 @@ static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
if (status != PJ_SUCCESS) {
/* Authentication failed! */
set_state(sub, PJSIP_EVSUB_STATE_TERMINATED,
- NULL,
- event);
+ NULL, event, &tsx->status_text);
return;
}
@@ -1646,7 +1662,7 @@ static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
/* Set state, if necessary */
pj_assert(sub->state != PJSIP_EVSUB_STATE_NULL);
if (sub->state == PJSIP_EVSUB_STATE_SENT) {
- set_state(sub, PJSIP_EVSUB_STATE_ACCEPTED, NULL, event);
+ set_state(sub, PJSIP_EVSUB_STATE_ACCEPTED, NULL, event, NULL);
}
} else {
@@ -1685,7 +1701,7 @@ static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
/* Set state to TERMINATED */
set_state(sub, PJSIP_EVSUB_STATE_TERMINATED,
- NULL, event);
+ NULL, event, &tsx->status_text);
}
@@ -1771,7 +1787,12 @@ static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
unsigned timeout = TIME_UAC_WAIT_NOTIFY;
set_timer(sub, TIMER_TYPE_UAC_WAIT_NOTIFY, timeout);
} else {
- set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_str_t reason;
+
+ reason = pj_strerror(status, errmsg, sizeof(errmsg));
+ set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL,
+ &reason);
}
return;
@@ -1815,9 +1836,15 @@ static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
/* Set the state */
if (status == PJ_SUCCESS) {
- set_state(sub, new_state, new_state_str, event);
+ set_state(sub, new_state, new_state_str, event,
+ &sub_state->reason_param);
} else {
- set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event);
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_str_t reason;
+
+ reason = pj_strerror(status, errmsg, sizeof(errmsg));
+ set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event,
+ &reason);
}
@@ -1858,6 +1885,7 @@ static void on_tsx_state_uas( pjsip_evsub *sub, pjsip_transaction *tsx,
pjsip_msg_body *body = NULL;
pjsip_evsub_state old_state;
pj_str_t old_state_str;
+ pj_str_t reason = { NULL, 0 };
pj_status_t status;
@@ -1944,9 +1972,9 @@ static void on_tsx_state_uas( pjsip_evsub *sub, pjsip_transaction *tsx,
if (st_code/100==2) {
if (sub->expires->ivalue == 0) {
- set_state(sub, sub->state, NULL, event);
+ set_state(sub, sub->state, NULL, event, &reason);
} else if (sub->state == PJSIP_EVSUB_STATE_NULL) {
- set_state(sub, sub->state, NULL, event);
+ set_state(sub, sub->state, NULL, event, &reason);
}
/* Set UAS timeout timer, when state is not terminated. */
@@ -1980,7 +2008,8 @@ static void on_tsx_state_uas( pjsip_evsub *sub, pjsip_transaction *tsx,
if (status != PJ_SUCCESS) {
/* Can't authenticate. Terminate session (?) */
- set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);
+ set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL,
+ &tsx->status_text);
return;
}
@@ -1993,7 +2022,8 @@ static void on_tsx_state_uas( pjsip_evsub *sub, pjsip_transaction *tsx,
(tsx->status_code==481 || tsx->status_code==408 ||
tsx->status_code/100 == 7))
{
- set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event);
+ set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event,
+ &tsx->status_text);
return;
}
diff --git a/pjsip/src/pjsip-simple/evsub_msg.c b/pjsip/src/pjsip-simple/evsub_msg.c
index 3c3b520b..f2e59c9b 100644
--- a/pjsip/src/pjsip-simple/evsub_msg.c
+++ b/pjsip/src/pjsip-simple/evsub_msg.c
@@ -19,6 +19,7 @@
#include <pjsip-simple/evsub_msg.h>
#include <pjsip/print_util.h>
#include <pjsip/sip_parser.h>
+#include <pjlib-util/string.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/except.h>
@@ -166,8 +167,9 @@ static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
*p++ = ':';
*p++ = ' ';
- copy_advance(p, hdr->sub_state);
- copy_advance_pair(p, ";reason=", 8, hdr->reason_param);
+ copy_advance_escape(p, hdr->sub_state, pc->pjsip_TOKEN_SPEC);
+ copy_advance_pair_escape(p, ";reason=", 8, hdr->reason_param,
+ pc->pjsip_TOKEN_SPEC);
if (hdr->expires_param >= 0) {
pj_memcpy(p, ";expires=", 9);
p += 9;
diff --git a/pjsip/src/pjsip-simple/presence.c b/pjsip/src/pjsip-simple/presence.c
index 842e0a6a..b3fb85d2 100644
--- a/pjsip/src/pjsip-simple/presence.c
+++ b/pjsip/src/pjsip-simple/presence.c
@@ -461,8 +461,13 @@ PJ_DEF(pj_status_t) pjsip_pres_notify( pjsip_evsub *sub,
pres = (pjsip_pres*) pjsip_evsub_get_mod_data(sub, mod_presence.id);
PJ_ASSERT_RETURN(pres != NULL, PJSIP_SIMPLE_ENOPRESENCE);
- /* Must have at least one presence info. */
- PJ_ASSERT_RETURN(pres->status.info_cnt > 0, PJSIP_SIMPLE_ENOPRESENCEINFO);
+ /* Must have at least one presence info, unless state is
+ * PJSIP_EVSUB_STATE_TERMINATED. This could happen if subscription
+ * has not been active (e.g. we're waiting for user authorization)
+ * and remote cancels the subscription.
+ */
+ PJ_ASSERT_RETURN(state==PJSIP_EVSUB_STATE_TERMINATED ||
+ pres->status.info_cnt > 0, PJSIP_SIMPLE_ENOPRESENCEINFO);
/* Lock object. */
@@ -474,11 +479,14 @@ PJ_DEF(pj_status_t) pjsip_pres_notify( pjsip_evsub *sub,
goto on_return;
- /* Create message body to reflect the presence status. */
- status = pres_create_msg_body( pres, tdata );
- if (status != PJ_SUCCESS)
- goto on_return;
-
+ /* Create message body to reflect the presence status.
+ * Only do this if we have presence status info to send (see above).
+ */
+ if (pres->status.info_cnt > 0) {
+ status = pres_create_msg_body( pres, tdata );
+ if (status != PJ_SUCCESS)
+ goto on_return;
+ }
/* Done. */
*p_tdata = tdata;
@@ -507,8 +515,11 @@ PJ_DEF(pj_status_t) pjsip_pres_current_notify( pjsip_evsub *sub,
pres = (pjsip_pres*) pjsip_evsub_get_mod_data(sub, mod_presence.id);
PJ_ASSERT_RETURN(pres != NULL, PJSIP_SIMPLE_ENOPRESENCE);
- /* Must have at least one presence info. */
- PJ_ASSERT_RETURN(pres->status.info_cnt > 0, PJSIP_SIMPLE_ENOPRESENCEINFO);
+ /* We may not have a presence info yet, e.g. when we receive SUBSCRIBE
+ * to refresh subscription while we're waiting for user authorization.
+ */
+ //PJ_ASSERT_RETURN(pres->status.info_cnt > 0,
+ // PJSIP_SIMPLE_ENOPRESENCEINFO);
/* Lock object. */
@@ -521,10 +532,11 @@ PJ_DEF(pj_status_t) pjsip_pres_current_notify( pjsip_evsub *sub,
/* Create message body to reflect the presence status. */
- status = pres_create_msg_body( pres, tdata );
- if (status != PJ_SUCCESS)
- goto on_return;
-
+ if (pres->status.info_cnt > 0) {
+ status = pres_create_msg_body( pres, tdata );
+ if (status != PJ_SUCCESS)
+ goto on_return;
+ }
/* Done. */
*p_tdata = tdata;