Changeset 2370 for pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
- Timestamp:
- Nov 27, 2008 12:06:46 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
r2362 r2370 226 226 inv->last_ack = NULL; 227 227 } 228 if (inv->invite_req) { 229 pjsip_tx_data_dec_ref(inv->invite_req); 230 inv->invite_req = NULL; 231 } 228 232 pjsip_100rel_end_session(inv); 229 233 pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); … … 1220 1224 1221 1225 1226 /* 1227 * Restart UAC session, possibly because app or us wants to re-send the 1228 * INVITE request due to 401/407 challenge or 3xx response. 1229 */ 1230 PJ_DEF(pj_status_t) pjsip_inv_uac_restart(pjsip_inv_session *inv, 1231 pj_bool_t new_offer) 1232 { 1233 PJ_ASSERT_RETURN(inv, PJ_EINVAL); 1234 1235 inv->state = PJSIP_INV_STATE_NULL; 1236 inv->invite_tsx = NULL; 1237 if (inv->last_answer) { 1238 pjsip_tx_data_dec_ref(inv->last_answer); 1239 inv->last_answer = NULL; 1240 } 1241 1242 if (new_offer && inv->neg) { 1243 pjmedia_sdp_neg_state neg_state; 1244 1245 neg_state = pjmedia_sdp_neg_get_state(inv->neg); 1246 if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { 1247 pjmedia_sdp_neg_cancel_offer(inv->neg); 1248 } 1249 } 1250 1251 return PJ_SUCCESS; 1252 } 1253 1254 1222 1255 static void *clone_sdp(pj_pool_t *pool, const void *data, unsigned len) 1223 1256 { … … 1890 1923 1891 1924 return PJ_SUCCESS; 1925 } 1926 1927 /* Following redirection recursion, get next target from the target set and 1928 * notify user. 1929 * 1930 * Returns PJ_FALSE if recursion fails (either because there's no more target 1931 * or user rejects the recursion). If we return PJ_FALSE, caller should 1932 * disconnect the session. 1933 * 1934 * Note: 1935 * the event 'e' argument may be NULL. 1936 */ 1937 static pj_bool_t inv_uac_recurse(pjsip_inv_session *inv, int code, 1938 const pj_str_t *reason, pjsip_event *e) 1939 { 1940 pjsip_redirect_op op = PJSIP_REDIRECT_ACCEPT; 1941 pjsip_target *target; 1942 1943 /* Won't redirect if the callback is not implemented. */ 1944 if (mod_inv.cb.on_redirected == NULL) 1945 return PJ_FALSE; 1946 1947 if (reason == NULL) 1948 reason = pjsip_get_status_text(code); 1949 1950 /* Set status of current target */ 1951 pjsip_target_assign_status(inv->dlg->target_set.current, inv->dlg->pool, 1952 code, reason); 1953 1954 /* Fetch next target from the target set. We only want to 1955 * process SIP/SIPS URI for now. 1956 */ 1957 for (;;) { 1958 target = pjsip_target_set_get_next(&inv->dlg->target_set); 1959 if (target == NULL) { 1960 /* No more target. */ 1961 return PJ_FALSE; 1962 } 1963 1964 if (!PJSIP_URI_SCHEME_IS_SIP(target->uri) && 1965 !PJSIP_URI_SCHEME_IS_SIPS(target->uri)) 1966 { 1967 code = PJSIP_SC_UNSUPPORTED_URI_SCHEME; 1968 reason = pjsip_get_status_text(code); 1969 1970 /* Mark this target as unusable and fetch next target. */ 1971 pjsip_target_assign_status(target, inv->dlg->pool, code, reason); 1972 } else { 1973 /* Found a target */ 1974 break; 1975 } 1976 } 1977 1978 /* We have target in 'target'. Set this target as current target 1979 * and notify callback. 1980 */ 1981 pjsip_target_set_set_current(&inv->dlg->target_set, target); 1982 1983 (*mod_inv.cb.on_redirected)(inv, target->uri, &op, e); 1984 1985 1986 /* Check what the application wants to do now */ 1987 switch (op) { 1988 case PJSIP_REDIRECT_ACCEPT: 1989 case PJSIP_REDIRECT_STOP: 1990 /* Must increment session counter, that's the convention of the 1991 * pjsip_inv_process_redirect(). 1992 */ 1993 pjsip_dlg_inc_session(inv->dlg, &mod_inv.mod); 1994 1995 /* Act on the recursion */ 1996 pjsip_inv_process_redirect(inv, op, e); 1997 return PJ_TRUE; 1998 1999 case PJSIP_REDIRECT_PENDING: 2000 /* Increment session so that the dialog/session is not destroyed 2001 * while we're waiting for user confirmation. 2002 */ 2003 pjsip_dlg_inc_session(inv->dlg, &mod_inv.mod); 2004 2005 /* Also clear the invite_tsx variable, otherwise when this tsx is 2006 * terminated, it will also terminate the session. 2007 */ 2008 inv->invite_tsx = NULL; 2009 2010 /* Done. The processing will continue once the application calls 2011 * pjsip_inv_process_redirect(). 2012 */ 2013 return PJ_TRUE; 2014 2015 case PJSIP_REDIRECT_REJECT: 2016 /* Recursively call this function again to fetch next target, if any. 2017 */ 2018 return inv_uac_recurse(inv, PJSIP_SC_REQUEST_TERMINATED, NULL, e); 2019 2020 } 2021 2022 pj_assert(!"Should not reach here"); 2023 return PJ_FALSE; 2024 } 2025 2026 2027 /* Process redirection/recursion */ 2028 PJ_DEF(pj_status_t) pjsip_inv_process_redirect( pjsip_inv_session *inv, 2029 pjsip_redirect_op op, 2030 pjsip_event *e) 2031 { 2032 const pjsip_status_code cancel_code = PJSIP_SC_REQUEST_TERMINATED; 2033 pjsip_event usr_event; 2034 pj_status_t status = PJ_SUCCESS; 2035 2036 PJ_ASSERT_RETURN(inv && op != PJSIP_REDIRECT_PENDING, PJ_EINVAL); 2037 2038 if (e == NULL) { 2039 PJSIP_EVENT_INIT_USER(usr_event, NULL, NULL, NULL, NULL); 2040 e = &usr_event; 2041 } 2042 2043 pjsip_dlg_inc_lock(inv->dlg); 2044 2045 /* Decrement session. That's the convention here to prevent the dialog 2046 * or session from being destroyed while we're waiting for user 2047 * confirmation. 2048 */ 2049 pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); 2050 2051 /* See what the application wants to do now */ 2052 switch (op) { 2053 case PJSIP_REDIRECT_ACCEPT: 2054 /* User accept the redirection. Reset the session and resend the 2055 * INVITE request. 2056 */ 2057 { 2058 pjsip_tx_data *tdata; 2059 pjsip_via_hdr *via; 2060 2061 /* Get the original INVITE request. */ 2062 tdata = inv->invite_req; 2063 pjsip_tx_data_add_ref(tdata); 2064 2065 /* Restore strict route set. 2066 * See http://trac.pjsip.org/repos/ticket/492 2067 */ 2068 pjsip_restore_strict_route_set(tdata); 2069 2070 /* Set target */ 2071 tdata->msg->line.req.uri = 2072 pjsip_uri_clone(tdata->pool, inv->dlg->target_set.current->uri); 2073 2074 /* Remove branch param in Via header. */ 2075 via = (pjsip_via_hdr*) 2076 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); 2077 via->branch_param.slen = 0; 2078 2079 /* Must invalidate the message! */ 2080 pjsip_tx_data_invalidate_msg(tdata); 2081 2082 /* Reset the session */ 2083 pjsip_inv_uac_restart(inv, PJ_FALSE); 2084 2085 /* (re)Send the INVITE request */ 2086 status = pjsip_inv_send_msg(inv, tdata); 2087 } 2088 break; 2089 2090 case PJSIP_REDIRECT_STOP: 2091 /* User doesn't want the redirection. Disconnect the session now. */ 2092 inv_set_cause(inv, cancel_code, pjsip_get_status_text(cancel_code)); 2093 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 2094 2095 /* Caller should expect that the invite session is gone now, so 2096 * we don't need to set status to PJSIP_ESESSIONTERMINATED here. 2097 */ 2098 break; 2099 2100 case PJSIP_REDIRECT_REJECT: 2101 /* Current target is rejected. Fetch next target if any. */ 2102 if (inv_uac_recurse(inv, cancel_code, NULL, NULL) == PJ_FALSE) { 2103 inv_set_cause(inv, cancel_code, 2104 pjsip_get_status_text(cancel_code)); 2105 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 2106 2107 /* Tell caller that the invite session is gone now */ 2108 status = PJSIP_ESESSIONTERMINATED; 2109 } 2110 break; 2111 2112 2113 case PJSIP_REDIRECT_PENDING: 2114 pj_assert(!"Should not happen"); 2115 break; 2116 } 2117 2118 2119 pjsip_dlg_dec_lock(inv->dlg); 2120 2121 return status; 1892 2122 } 1893 2123 … … 2553 2783 if (dlg->role == PJSIP_ROLE_UAC) { 2554 2784 2785 /* Save the original INVITE request, if on_redirected() callback 2786 * is implemented. We may need to resend the INVITE if we receive 2787 * redirection response. 2788 */ 2789 if (mod_inv.cb.on_redirected) { 2790 if (inv->invite_req) { 2791 pjsip_tx_data_dec_ref(inv->invite_req); 2792 inv->invite_req = NULL; 2793 } 2794 inv->invite_req = tsx->last_tx; 2795 pjsip_tx_data_add_ref(inv->invite_req); 2796 } 2797 2555 2798 switch (tsx->state) { 2556 2799 case PJSIP_TSX_STATE_CALLING: … … 2674 2917 2675 2918 2919 /* Handle call rejection, especially with regard to processing call 2920 * redirection. We need to handle the following scenarios: 2921 * - 3xx response is received -- see if on_redirected() callback is 2922 * implemented. If so, add the Contact URIs in the response to the 2923 * target set and notify user. 2924 * - 4xx - 6xx resposne is received -- see if we're currently recursing, 2925 * if so fetch the next target if any and notify the on_redirected() 2926 * callback. 2927 * - for other cases -- disconnect the session. 2928 */ 2929 static void handle_uac_call_rejection(pjsip_inv_session *inv, pjsip_event *e) 2930 { 2931 pjsip_transaction *tsx = e->body.tsx_state.tsx; 2932 pj_status_t status; 2933 2934 if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 300)) { 2935 2936 if (mod_inv.cb.on_redirected == NULL) { 2937 2938 /* Redirection callback is not implemented, disconnect the 2939 * call. 2940 */ 2941 goto terminate_session; 2942 2943 } else { 2944 const pjsip_msg *res_msg; 2945 2946 res_msg = e->body.tsx_state.src.rdata->msg_info.msg; 2947 2948 /* Gather all Contact URI's in the response and add them 2949 * to target set. The function will take care of removing 2950 * duplicate URI's. 2951 */ 2952 pjsip_target_set_add_from_msg(&inv->dlg->target_set, 2953 inv->dlg->pool, res_msg); 2954 2955 /* Recurse to alternate targets if application allows us */ 2956 if (!inv_uac_recurse(inv, tsx->status_code, &tsx->status_text, e)) 2957 { 2958 /* Recursion fails, terminate session now */ 2959 goto terminate_session; 2960 } 2961 2962 /* Done */ 2963 } 2964 2965 } else if ((tsx->status_code==401 || tsx->status_code==407) && 2966 !inv->cancelling) 2967 { 2968 2969 /* Handle authentication failure: 2970 * Resend the request with Authorization header. 2971 */ 2972 pjsip_tx_data *tdata; 2973 2974 status = pjsip_auth_clt_reinit_req(&inv->dlg->auth_sess, 2975 e->body.tsx_state.src.rdata, 2976 tsx->last_tx, 2977 &tdata); 2978 2979 if (status != PJ_SUCCESS) { 2980 2981 /* Does not have proper credentials. If we are currently 2982 * recursing, try the next target. Otherwise end the session. 2983 */ 2984 if (!inv_uac_recurse(inv, tsx->status_code, &tsx->status_text, e)) 2985 { 2986 /* Recursion fails, terminate session now */ 2987 goto terminate_session; 2988 } 2989 2990 } else { 2991 2992 /* Restart session. */ 2993 pjsip_inv_uac_restart(inv, PJ_FALSE); 2994 2995 /* Send the request. */ 2996 status = pjsip_inv_send_msg(inv, tdata); 2997 } 2998 2999 } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 600)) { 3000 /* Global error */ 3001 goto terminate_session; 3002 3003 } else { 3004 /* See if we have alternate target to try */ 3005 if (!inv_uac_recurse(inv, tsx->status_code, &tsx->status_text, e)) { 3006 /* Recursion fails, terminate session now */ 3007 goto terminate_session; 3008 } 3009 } 3010 return; 3011 3012 terminate_session: 3013 inv_set_cause(inv, tsx->status_code, &tsx->status_text); 3014 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 3015 } 3016 3017 2676 3018 /* 2677 3019 * State CALLING is after sending initial INVITE request but before … … 2736 3078 e->body.tsx_state.src.rdata); 2737 3079 2738 } else if ((tsx->status_code==401 || tsx->status_code==407) &&2739 !inv->cancelling)2740 {2741 2742 /* Handle authentication failure:2743 * Resend the request with Authorization header.2744 */2745 pjsip_tx_data *tdata;2746 2747 status = pjsip_auth_clt_reinit_req(&inv->dlg->auth_sess,2748 e->body.tsx_state.src.rdata,2749 tsx->last_tx,2750 &tdata);2751 2752 if (status != PJ_SUCCESS) {2753 2754 /* Does not have proper credentials.2755 * End the session.2756 */2757 inv_set_cause(inv, tsx->status_code, &tsx->status_text);2758 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);2759 2760 } else {2761 2762 /* Restart session. */2763 inv->state = PJSIP_INV_STATE_NULL;2764 inv->invite_tsx = NULL;2765 if (inv->last_answer) {2766 pjsip_tx_data_dec_ref(inv->last_answer);2767 inv->last_answer = NULL;2768 }2769 2770 /* Send the request. */2771 status = pjsip_inv_send_msg(inv, tdata);2772 }2773 2774 3080 } else { 2775 2776 inv_set_cause(inv, tsx->status_code, &tsx->status_text); 2777 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 2778 3081 handle_uac_call_rejection(inv, e); 2779 3082 } 2780 3083 break; … … 2942 3245 e->body.tsx_state.src.rdata); 2943 3246 } 3247 3248 } else if (tsx->role == PJSIP_ROLE_UAC) { 3249 3250 handle_uac_call_rejection(inv, e); 2944 3251 2945 3252 } else {
Note: See TracChangeset
for help on using the changeset viewer.