diff options
Diffstat (limited to 'pjsip/src/pjsip-ua/sip_inv.c')
-rw-r--r-- | pjsip/src/pjsip-ua/sip_inv.c | 94 |
1 files changed, 87 insertions, 7 deletions
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c index 9f561763..0243452a 100644 --- a/pjsip/src/pjsip-ua/sip_inv.c +++ b/pjsip/src/pjsip-ua/sip_inv.c @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <pjsip-ua/sip_inv.h> +#include <pjsip-ua/sip_100rel.h> #include <pjsip/sip_module.h> #include <pjsip/sip_endpoint.h> #include <pjsip/sip_event.h> @@ -31,7 +32,7 @@ #include <pj/log.h> -#define THIS_FILE "sip_invite_session.c" +#define THIS_FILE "sip_inv.c" static const char *inv_state_names[] = { @@ -305,6 +306,10 @@ static pj_bool_t mod_inv_on_rx_request(pjsip_rx_data *rdata) pjsip_tsx_terminate(inv->invite_tsx, inv->invite_tsx->status_code); inv->invite_tsx = NULL; + if (inv->last_answer) { + pjsip_tx_data_dec_ref(inv->last_answer); + inv->last_answer = NULL; + } } /* On receipt of ACK, only set state to confirmed when state @@ -395,8 +400,13 @@ static void mod_inv_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e) * terminated, but this didn't work when ACK has the same Via branch * value as the INVITE (see http://www.pjsip.org/trac/ticket/113) */ - if (tsx->state>=PJSIP_TSX_STATE_CONFIRMED && tsx == inv->invite_tsx) + if (tsx->state>=PJSIP_TSX_STATE_CONFIRMED && tsx == inv->invite_tsx) { inv->invite_tsx = NULL; + if (inv->last_answer) { + pjsip_tx_data_dec_ref(inv->last_answer); + inv->last_answer = NULL; + } + } } @@ -482,6 +492,14 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg, if (options & PJSIP_INV_REQUIRE_100REL) options |= PJSIP_INV_SUPPORT_100REL; +#if !PJSIP_HAS_100REL + /* options cannot specify 100rel if 100rel is disabled */ + PJ_ASSERT_RETURN( + (options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0, + PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION)); + +#endif + if (options & PJSIP_INV_REQUIRE_TIMER) options |= PJSIP_INV_SUPPORT_TIMER; @@ -520,6 +538,11 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg, /* Increment dialog session */ pjsip_dlg_inc_session(dlg, &mod_inv.mod); +#if PJSIP_HAS_100REL + /* Create 100rel handler */ + pjsip_100rel_attach(inv); +#endif + /* Done */ *p_inv = inv; @@ -829,6 +852,18 @@ PJ_DEF(pj_status_t) pjsip_inv_verify_request(pjsip_rx_data *rdata, goto on_return; } + /* If remote Require something that we support, make us Require + * that feature too. + */ + if (rem_option & PJSIP_INV_REQUIRE_100REL) { + pj_assert(*options & PJSIP_INV_SUPPORT_100REL); + *options |= PJSIP_INV_REQUIRE_100REL; + } + if (rem_option & PJSIP_INV_REQUIRE_TIMER) { + pj_assert(*options & PJSIP_INV_SUPPORT_TIMER); + *options |= PJSIP_INV_REQUIRE_TIMER; + } + on_return: /* Create response if necessary */ @@ -908,6 +943,14 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uas( pjsip_dialog *dlg, if (options & PJSIP_INV_REQUIRE_100REL) options |= PJSIP_INV_SUPPORT_100REL; +#if !PJSIP_HAS_100REL + /* options cannot specify 100rel if 100rel is disabled */ + PJ_ASSERT_RETURN( + (options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0, + PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION)); + +#endif + if (options & PJSIP_INV_REQUIRE_TIMER) options |= PJSIP_INV_SUPPORT_TIMER; @@ -977,6 +1020,13 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uas( pjsip_dialog *dlg, tsx_inv_data->inv = inv; inv->invite_tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; +#if PJSIP_HAS_100REL + /* Create 100rel handler */ + if (inv->options & PJSIP_INV_REQUIRE_100REL) { + pjsip_100rel_attach(inv); + } +#endif + /* Done */ pjsip_dlg_dec_lock(dlg); *p_inv = inv; @@ -1168,7 +1218,15 @@ PJ_DEF(pj_status_t) pjsip_inv_invite( pjsip_inv_session *inv, } /* Add Require header. */ - PJ_TODO(INVITE_ADD_REQUIRE_HEADER); + if (inv->options & PJSIP_INV_REQUIRE_100REL) { + const pj_str_t HREQ = { "Require", 7 }; + const pj_str_t tag_100rel = { "100rel", 6 }; + pjsip_generic_string_hdr *hreq; + + hreq = pjsip_generic_string_hdr_create(tdata->pool, &HREQ, + &tag_100rel); + pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) hreq); + } /* Done. */ *p_tdata = tdata; @@ -1452,6 +1510,12 @@ PJ_DEF(pj_status_t) pjsip_inv_initial_answer( pjsip_inv_session *inv, goto on_return; } + /* Save this answer */ + inv->last_answer = tdata; + pjsip_tx_data_add_ref(inv->last_answer); + PJ_LOG(5,(inv->dlg->obj_name, "Initial answer %s", + pjsip_tx_data_get_info(inv->last_answer))); + *p_tdata = tdata; on_return: @@ -1479,17 +1543,21 @@ PJ_DEF(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv, /* Must have INVITE transaction. */ PJ_ASSERT_RETURN(inv->invite_tsx, PJ_EBUG); - /* INVITE transaction MUST have transmitted a response (e.g. 100) */ - PJ_ASSERT_RETURN(inv->invite_tsx->last_tx, PJ_EINVALIDOP); + /* Must have created an answer before */ + PJ_ASSERT_RETURN(inv->last_answer, PJ_EINVALIDOP); pjsip_dlg_inc_lock(inv->dlg); /* Modify last response. */ - last_res = inv->invite_tsx->last_tx; + last_res = inv->last_answer; status = pjsip_dlg_modify_response(inv->dlg, last_res, st_code, st_text); if (status != PJ_SUCCESS) goto on_return; + /* For non-2xx final response, strip message body */ + if (st_code >= 300) { + last_res->msg->body = NULL; + } /* Process SDP in answer */ status = process_answer(inv, st_code, last_res, local_sdp); @@ -1764,7 +1832,15 @@ PJ_DEF(pj_status_t) pjsip_inv_send_msg( pjsip_inv_session *inv, && (cseq->cseq == inv->invite_tsx->cseq), PJ_EINVALIDOP); - status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata); +#if PJSIP_HAS_100REL + if (inv->options & PJSIP_INV_REQUIRE_100REL) { + status = pjsip_100rel_tx_response(inv, tdata); + } else +#endif + { + status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata); + } + if (status != PJ_SUCCESS) return status; } @@ -2042,6 +2118,10 @@ static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e) /* Restart session. */ inv->state = PJSIP_INV_STATE_NULL; inv->invite_tsx = NULL; + if (inv->last_answer) { + pjsip_tx_data_dec_ref(inv->last_answer); + inv->last_answer = NULL; + } /* Send the request. */ status = pjsip_inv_send_msg(inv, tdata); |