* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/07/07054e161b2620499aecda94697c0afdc6cfcaad.svn-base b/jni/pjproject-android/.svn/pristine/07/07054e161b2620499aecda94697c0afdc6cfcaad.svn-base
new file mode 100644
index 0000000..537ca9e
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/07/07054e161b2620499aecda94697c0afdc6cfcaad.svn-base
@@ -0,0 +1,598 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjsip-simple/mwi.h>
+#include <pjsip-simple/errno.h>
+#include <pjsip-simple/evsub_msg.h>
+#include <pjsip/sip_module.h>
+#include <pjsip/sip_endpoint.h>
+#include <pjsip/sip_dialog.h>
+#include <pj/assert.h>
+#include <pj/guid.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+
+#define THIS_FILE		    "mwi.c"
+
+ /*
+ * MWI module (mod-mdi)
+ */
+static struct pjsip_module mod_mwi = 
+{
+    NULL, NULL,			    /* prev, next.			*/
+    { "mod-mwi", 7 },		    /* Name.				*/
+    -1,				    /* Id				*/
+    PJSIP_MOD_PRIORITY_DIALOG_USAGE,/* Priority				*/
+    NULL,			    /* load()				*/
+    NULL,			    /* start()				*/
+    NULL,			    /* stop()				*/
+    NULL,			    /* unload()				*/
+    NULL,			    /* on_rx_request()			*/
+    NULL,			    /* on_rx_response()			*/
+    NULL,			    /* on_tx_request.			*/
+    NULL,			    /* on_tx_response()			*/
+    NULL,			    /* on_tsx_state()			*/
+};
+
+
+/*
+ * This structure describe an mwi agent (both client and server)
+ */
+typedef struct pjsip_mwi
+{
+    pjsip_evsub		*sub;		/**< Event subscribtion record.	    */
+    pjsip_dialog	*dlg;		/**< The dialog.		    */
+    pjsip_evsub_user	 user_cb;	/**< The user callback.		    */
+
+    /* These are for server subscriptions */
+    pj_pool_t		*body_pool;	/**< Pool to save message body	    */
+    pjsip_media_type	 mime_type;	/**< MIME type of last msg body	    */
+    pj_str_t		 body;		/**< Last sent message body	    */
+} pjsip_mwi;
+
+
+/*
+ * Forward decl for evsub callbacks.
+ */
+static void mwi_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
+static void mwi_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
+				    pjsip_event *event);
+static void mwi_on_evsub_rx_refresh( 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);
+static void mwi_on_evsub_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);
+static void mwi_on_evsub_client_refresh(pjsip_evsub *sub);
+static void mwi_on_evsub_server_timeout(pjsip_evsub *sub);
+
+
+/*
+ * Event subscription callback for mwi.
+ */
+static pjsip_evsub_user mwi_user = 
+{
+    &mwi_on_evsub_state,
+    &mwi_on_evsub_tsx_state,
+    &mwi_on_evsub_rx_refresh,
+    &mwi_on_evsub_rx_notify,
+    &mwi_on_evsub_client_refresh,
+    &mwi_on_evsub_server_timeout,
+};
+
+
+/*
+ * Some static constants.
+ */
+static const pj_str_t STR_EVENT		 = { "Event", 5 };
+static const pj_str_t STR_MWI		 = { "message-summary", 15 };
+static const pj_str_t STR_APP_SIMPLE_SMS = { "application/simple-message-summary", 34};
+
+/*
+ * Init mwi module.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_init_module( pjsip_endpoint *endpt,
+					   pjsip_module *mod_evsub)
+{
+    pj_status_t status;
+    pj_str_t accept[1];
+
+    /* Check arguments. */
+    PJ_ASSERT_RETURN(endpt && mod_evsub, PJ_EINVAL);
+
+    /* Must have not been registered */
+    PJ_ASSERT_RETURN(mod_mwi.id == -1, PJ_EINVALIDOP);
+
+    /* Register to endpoint */
+    status = pjsip_endpt_register_module(endpt, &mod_mwi);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    accept[0] = STR_APP_SIMPLE_SMS;
+
+    /* Register event package to event module. */
+    status = pjsip_evsub_register_pkg( &mod_mwi, &STR_MWI, 
+				       PJSIP_MWI_DEFAULT_EXPIRES, 
+				       PJ_ARRAY_SIZE(accept), accept);
+    if (status != PJ_SUCCESS) {
+	pjsip_endpt_unregister_module(endpt, &mod_mwi);
+	return status;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Get mwi module instance.
+ */
+PJ_DEF(pjsip_module*) pjsip_mwi_instance(void)
+{
+    return &mod_mwi;
+}
+
+
+/*
+ * Create client subscription.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_create_uac( pjsip_dialog *dlg,
+					  const pjsip_evsub_user *user_cb,
+					  unsigned options,
+					  pjsip_evsub **p_evsub )
+{
+    pj_status_t status;
+    pjsip_mwi *mwi;
+    pjsip_evsub *sub;
+
+    PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);
+
+    PJ_UNUSED_ARG(options);
+
+    pjsip_dlg_inc_lock(dlg);
+
+    /* Create event subscription */
+    status = pjsip_evsub_create_uac( dlg,  &mwi_user, &STR_MWI, 
+				     options, &sub);
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+    /* Create mwi */
+    mwi = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_mwi);
+    mwi->dlg = dlg;
+    mwi->sub = sub;
+    if (user_cb)
+	pj_memcpy(&mwi->user_cb, user_cb, sizeof(pjsip_evsub_user));
+
+    /* Attach to evsub */
+    pjsip_evsub_set_mod_data(sub, mod_mwi.id, mwi);
+
+    *p_evsub = sub;
+
+on_return:
+    pjsip_dlg_dec_lock(dlg);
+    return status;
+}
+
+
+/*
+ * Create server subscription.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_create_uas( pjsip_dialog *dlg,
+					  const pjsip_evsub_user *user_cb,
+					  pjsip_rx_data *rdata,
+					  pjsip_evsub **p_evsub )
+{
+    pjsip_accept_hdr *accept;
+    pjsip_event_hdr *event;
+    pjsip_evsub *sub;
+    pjsip_mwi *mwi;
+    char obj_name[PJ_MAX_OBJ_NAME];
+    pj_status_t status;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL);
+
+    /* Must be request message */
+    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
+		     PJSIP_ENOTREQUESTMSG);
+
+    /* Check that request is SUBSCRIBE */
+    PJ_ASSERT_RETURN(pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+				      &pjsip_subscribe_method)==0,
+		     PJSIP_SIMPLE_ENOTSUBSCRIBE);
+
+    /* Check that Event header contains "mwi" */
+    event = (pjsip_event_hdr*)
+    	    pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_EVENT, NULL);
+    if (!event) {
+	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);
+    }
+    if (pj_stricmp(&event->event_type, &STR_MWI) != 0) {
+	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EVENT);
+    }
+
+    /* Check that request contains compatible Accept header. */
+    accept = (pjsip_accept_hdr*)
+    	     pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
+    if (accept) {
+	unsigned i;
+	for (i=0; i<accept->count; ++i) {
+	    if (pj_stricmp(&accept->values[i], &STR_APP_SIMPLE_SMS)==0) {
+		break;
+	    }
+	}
+
+	if (i==accept->count) {
+	    /* Nothing is acceptable */
+	    return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE);
+	}
+
+    } else {
+	/* No Accept header. 
+	 * Assume client supports "application/simple-message-summary" 
+	*/
+    }
+
+    /* Lock dialog */
+    pjsip_dlg_inc_lock(dlg);
+
+
+    /* Create server subscription */
+    status = pjsip_evsub_create_uas( dlg, &mwi_user, rdata, 0, &sub);
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+    /* Create server mwi subscription */
+    mwi = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_mwi);
+    mwi->dlg = dlg;
+    mwi->sub = sub;
+    if (user_cb)
+	pj_memcpy(&mwi->user_cb, user_cb, sizeof(pjsip_evsub_user));
+
+    pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "mwibd%p", dlg->pool);
+    mwi->body_pool = pj_pool_create(dlg->pool->factory, obj_name, 
+				    512, 512, NULL);
+
+    /* Attach to evsub */
+    pjsip_evsub_set_mod_data(sub, mod_mwi.id, mwi);
+
+    /* Done: */
+    *p_evsub = sub;
+
+on_return:
+    pjsip_dlg_dec_lock(dlg);
+    return status;
+}
+
+
+/*
+ * Forcefully terminate mwi.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_terminate( pjsip_evsub *sub,
+					 pj_bool_t notify )
+{
+    return pjsip_evsub_terminate(sub, notify);
+}
+
+/*
+ * Create SUBSCRIBE
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_initiate( pjsip_evsub *sub,
+					pj_int32_t expires,
+					pjsip_tx_data **p_tdata)
+{
+    return pjsip_evsub_initiate(sub, &pjsip_subscribe_method, expires, 
+				p_tdata);
+}
+
+
+/*
+ * Accept incoming subscription.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_accept( pjsip_evsub *sub,
+				      pjsip_rx_data *rdata,
+				      int st_code,
+				      const pjsip_hdr *hdr_list )
+{
+    return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );
+}
+
+/*
+ * Create message body and attach it to the (NOTIFY) request.
+ */
+static pj_status_t mwi_create_msg_body( pjsip_mwi *mwi, 
+					pjsip_tx_data *tdata)
+{
+    pjsip_msg_body *body;
+    pj_str_t dup_text;
+
+    PJ_ASSERT_RETURN(mwi->mime_type.type.slen && mwi->body.slen, PJ_EINVALIDOP);
+    
+    /* Clone the message body and mime type */
+    pj_strdup(tdata->pool, &dup_text, &mwi->body);
+
+    /* Create the message body */
+    body = PJ_POOL_ZALLOC_T(tdata->pool, pjsip_msg_body);
+    pjsip_media_type_cp(tdata->pool, &body->content_type, &mwi->mime_type);
+    body->data = dup_text.ptr;
+    body->len = (unsigned)dup_text.slen;
+    body->print_body = &pjsip_print_text_body;
+    body->clone_data = &pjsip_clone_text_data;
+
+    /* Attach to tdata */
+    tdata->msg->body = body;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create NOTIFY
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_notify(  pjsip_evsub *sub,
+				       pjsip_evsub_state state,
+				       const pj_str_t *state_str,
+				       const pj_str_t *reason,
+				       const pjsip_media_type *mime_type,
+				       const pj_str_t *body,
+				       pjsip_tx_data **p_tdata)
+{
+    pjsip_mwi *mwi;
+    pjsip_tx_data *tdata;
+    pj_status_t status;
+    
+    /* Check arguments. */
+    PJ_ASSERT_RETURN(sub && mime_type && body && p_tdata, PJ_EINVAL);
+
+    /* Get the mwi object. */
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_RETURN(mwi != NULL, PJ_EINVALIDOP);
+
+    /* Lock object. */
+    pjsip_dlg_inc_lock(mwi->dlg);
+
+    /* Create the NOTIFY request. */
+    status = pjsip_evsub_notify( sub, state, state_str, reason, &tdata);
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+    /* Update the cached message body */
+    if (mime_type || body)
+	pj_pool_reset(mwi->body_pool);
+    if (mime_type)
+	pjsip_media_type_cp(mwi->body_pool, &mwi->mime_type, mime_type);
+    if (body)
+	pj_strdup(mwi->body_pool, &mwi->body, body);
+
+    /* Create message body */
+    status = mwi_create_msg_body( mwi, tdata );
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+    /* Done. */
+    *p_tdata = tdata;
+
+on_return:
+    pjsip_dlg_dec_lock(mwi->dlg);
+    return status;
+}
+
+
+/*
+ * Create NOTIFY that reflect current state.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_current_notify( pjsip_evsub *sub,
+					      pjsip_tx_data **p_tdata )
+{
+    pjsip_mwi *mwi;
+    pjsip_tx_data *tdata;
+    pj_status_t status;
+    
+    /* Check arguments. */
+    PJ_ASSERT_RETURN(sub && p_tdata, PJ_EINVAL);
+
+    /* Get the mwi object. */
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_RETURN(mwi != NULL, PJ_EINVALIDOP);
+
+    /* Lock object. */
+    pjsip_dlg_inc_lock(mwi->dlg);
+
+    /* Create the NOTIFY request. */
+    status = pjsip_evsub_current_notify( sub, &tdata);
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+
+    /* Create message body to reflect the mwi status. */
+    status = mwi_create_msg_body( mwi, tdata );
+    if (status != PJ_SUCCESS)
+	goto on_return;
+
+    /* Done. */
+    *p_tdata = tdata;
+
+on_return:
+    pjsip_dlg_dec_lock(mwi->dlg);
+    return status;
+}
+
+
+/*
+ * Send request.
+ */
+PJ_DEF(pj_status_t) pjsip_mwi_send_request( pjsip_evsub *sub,
+					     pjsip_tx_data *tdata )
+{
+    return pjsip_evsub_send_request(sub, tdata);
+}
+
+/*
+ * This callback is called by event subscription when subscription
+ * state has changed.
+ */
+static void mwi_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
+{
+    pjsip_mwi *mwi;
+
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
+
+    if (mwi->user_cb.on_evsub_state)
+	(*mwi->user_cb.on_evsub_state)(sub, event);
+
+    if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
+	if (mwi->body_pool) {
+	    pj_pool_release(mwi->body_pool);
+	    mwi->body_pool = NULL;
+	}
+    }
+}
+
+/*
+ * Called when transaction state has changed.
+ */
+static void mwi_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
+				     pjsip_event *event)
+{
+    pjsip_mwi *mwi;
+
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
+
+    if (mwi->user_cb.on_tsx_state)
+	(*mwi->user_cb.on_tsx_state)(sub, tsx, event);
+}
+
+
+/*
+ * Called when SUBSCRIBE is received.
+ */
+static void mwi_on_evsub_rx_refresh( 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)
+{
+    pjsip_mwi *mwi;
+
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
+
+    if (mwi->user_cb.on_rx_refresh) {
+	(*mwi->user_cb.on_rx_refresh)(sub, rdata, p_st_code, p_st_text,
+				       res_hdr, p_body);
+
+    } else {
+	/* Implementors MUST send NOTIFY if it implements on_rx_refresh */
+	pjsip_tx_data *tdata;
+	pj_str_t timeout = { "timeout", 7};
+	pj_status_t status;
+
+	if (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED) {
+	    status = pjsip_mwi_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,
+				       NULL, &timeout, NULL, NULL, &tdata);
+	} else {
+	    status = pjsip_mwi_current_notify(sub, &tdata);
+	}
+
+	if (status == PJ_SUCCESS)
+	    pjsip_mwi_send_request(sub, tdata);
+    }
+}
+
+
+/*
+ * Called when NOTIFY is received.
+ */
+static void mwi_on_evsub_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)
+{
+    pjsip_mwi *mwi;
+
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
+
+    /* Just notify application. */
+    if (mwi->user_cb.on_rx_notify) {
+	(*mwi->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text, 
+				     res_hdr, p_body);
+    }
+}
+
+/*
+ * Called when it's time to send SUBSCRIBE.
+ */
+static void mwi_on_evsub_client_refresh(pjsip_evsub *sub)
+{
+    pjsip_mwi *mwi;
+
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
+
+    if (mwi->user_cb.on_client_refresh) {
+	(*mwi->user_cb.on_client_refresh)(sub);
+    } else {
+	pj_status_t status;
+	pjsip_tx_data *tdata;
+
+	status = pjsip_mwi_initiate(sub, -1, &tdata);
+	if (status == PJ_SUCCESS)
+	    pjsip_mwi_send_request(sub, tdata);
+    }
+}
+
+/*
+ * Called when no refresh is received after the interval.
+ */
+static void mwi_on_evsub_server_timeout(pjsip_evsub *sub)
+{
+    pjsip_mwi *mwi;
+
+    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
+    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
+
+    if (mwi->user_cb.on_server_timeout) {
+	(*mwi->user_cb.on_server_timeout)(sub);
+    } else {
+	pj_status_t status;
+	pjsip_tx_data *tdata;
+	pj_str_t reason = { "timeout", 7 };
+
+	status = pjsip_mwi_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
+				   NULL, &reason, NULL, NULL, &tdata);
+	if (status == PJ_SUCCESS)
+	    pjsip_mwi_send_request(sub, tdata);
+    }
+}
+