Changeset 1469 for pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
- Timestamp:
- Oct 3, 2007 6:28:49 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
r1463 r1469 32 32 #include <pj/log.h> 33 33 34 /* 35 * Note on offer/answer: 36 * 37 * The offer/answer framework in this implementation assumes the occurence 38 * of SDP in a particular request/response according to this table: 39 40 offer answer Note: 41 ======================================================================== 42 INVITE X INVITE may contain offer 43 18x/INVITE X X Response may contain offer or answer 44 2xx/INVITE X X Response may contain offer or answer 45 ACK X ACK may contain answer 46 47 PRACK X PRACK can only contain answer 48 2xx/PRACK Response may not have offer nor answer 49 50 UPDATE X UPDATE may only contain offer 51 2xx/UPDATE X Response may only contain answer 52 ======================================================================== 53 54 * 55 */ 34 56 35 57 #define THIS_FILE "sip_inv.c" … … 47 69 }; 48 70 71 /* UPDATE method */ 72 const pjsip_method pjsip_update_method = 73 { 74 PJSIP_OTHER_METHOD, 75 { "UPDATE", 6 } 76 }; 77 49 78 /* 50 79 * Static prototypes. … … 67 96 pjsip_transaction *tsx, 68 97 pjsip_rx_data *rdata); 98 static pj_status_t inv_negotiate_sdp( pjsip_inv_session *inv ); 99 static pjsip_msg_body *create_sdp_body(pj_pool_t *pool, 100 const pjmedia_sdp_session *c_sdp); 69 101 static pj_status_t process_answer( pjsip_inv_session *inv, 70 102 int st_code, … … 120 152 static pj_status_t mod_inv_load(pjsip_endpoint *endpt) 121 153 { 122 pj_str_t allowed[] = {{"INVITE", 6}, {"ACK",3}, {"BYE",3}, {"CANCEL",6}}; 154 pj_str_t allowed[] = {{"INVITE", 6}, {"ACK",3}, {"BYE",3}, {"CANCEL",6}, 155 { "UPDATE", 6}}; 123 156 pj_str_t accepted = { "application/sdp", 15 }; 124 157 125 /* Register supported methods: INVITE, ACK, BYE, CANCEL */158 /* Register supported methods: INVITE, ACK, BYE, CANCEL, UPDATE */ 126 159 pjsip_endpt_add_capability(endpt, &mod_inv.mod, PJSIP_H_ALLOW, NULL, 127 160 PJ_ARRAY_SIZE(allowed), allowed); … … 187 220 prev_state != PJSIP_INV_STATE_DISCONNECTED) 188 221 { 222 if (inv->last_ack) { 223 pjsip_tx_data_dec_ref(inv->last_ack); 224 inv->last_ack = NULL; 225 } 226 pjsip_100rel_end_session(inv); 189 227 pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); 190 228 } … … 210 248 211 249 250 /* 251 * Check if outgoing request needs to have SDP answer. 252 * This applies for both ACK and PRACK requests. 253 */ 254 static pjmedia_sdp_session *inv_has_pending_answer(pjsip_inv_session *inv, 255 pjsip_transaction *tsx) 256 { 257 pjmedia_sdp_neg_state neg_state; 258 pjmedia_sdp_session *sdp = NULL; 259 pj_status_t status; 260 261 /* If SDP negotiator is ready, start negotiation. */ 262 263 /* Start nego when appropriate. */ 264 neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) : 265 PJMEDIA_SDP_NEG_STATE_NULL; 266 267 if (neg_state == PJMEDIA_SDP_NEG_STATE_DONE) { 268 269 /* Nothing to do */ 270 271 } else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && 272 pjmedia_sdp_neg_has_local_answer(inv->neg) ) 273 { 274 struct tsx_inv_data *tsx_inv_data; 275 276 /* Get invite session's transaction data */ 277 tsx_inv_data = (struct tsx_inv_data*) tsx->mod_data[mod_inv.mod.id]; 278 279 status = inv_negotiate_sdp(inv); 280 if (status != PJ_SUCCESS) 281 return NULL; 282 283 /* Mark this transaction has having SDP offer/answer done. */ 284 tsx_inv_data->sdp_done = 1; 285 286 status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 287 288 } else { 289 /* This remark is only valid for ACK. 290 PJ_LOG(4,(inv->dlg->obj_name, 291 "FYI, the SDP negotiator state (%s) is in a mess " 292 "when sending this ACK/PRACK request", 293 pjmedia_sdp_neg_state_str(neg_state))); 294 */ 295 } 296 297 return sdp; 298 } 299 212 300 213 301 /* … … 216 304 static pj_status_t inv_send_ack(pjsip_inv_session *inv, pjsip_rx_data *rdata) 217 305 { 218 pjsip_tx_data *tdata;219 306 pj_status_t status; 220 307 … … 222 309 pjsip_rx_data_get_info(rdata))); 223 310 224 status = pjsip_dlg_create_request(inv->dlg, pjsip_get_ack_method(), 225 rdata->msg_info.cseq->cseq, &tdata); 226 if (status != PJ_SUCCESS) { 227 /* Better luck next time */ 228 pj_assert(!"Unable to create ACK!"); 229 return status; 230 } 231 232 status = pjsip_dlg_send_request(inv->dlg, tdata, -1, NULL); 311 /* Check if we have cached ACK request */ 312 if (inv->last_ack && rdata->msg_info.cseq->cseq == inv->last_ack_cseq) { 313 pjsip_tx_data_add_ref(inv->last_ack); 314 } else { 315 pjmedia_sdp_session *sdp = NULL; 316 317 /* Destroy last_ack */ 318 if (inv->last_ack) { 319 pjsip_tx_data_dec_ref(inv->last_ack); 320 inv->last_ack = NULL; 321 } 322 323 /* Create new ACK request */ 324 status = pjsip_dlg_create_request(inv->dlg, pjsip_get_ack_method(), 325 rdata->msg_info.cseq->cseq, 326 &inv->last_ack); 327 if (status != PJ_SUCCESS) { 328 /* Better luck next time */ 329 pj_assert(!"Unable to create ACK!"); 330 return status; 331 } 332 333 /* See if we have pending SDP answer to send */ 334 sdp = inv_has_pending_answer(inv, inv->invite_tsx); 335 if (sdp) { 336 inv->last_ack->msg->body=create_sdp_body(inv->last_ack->pool, sdp); 337 } 338 339 340 /* Keep this for subsequent response retransmission */ 341 inv->last_ack_cseq = rdata->msg_info.cseq->cseq; 342 pjsip_tx_data_add_ref(inv->last_ack); 343 } 344 345 /* Send ACK */ 346 status = pjsip_dlg_send_request(inv->dlg, inv->last_ack, -1, NULL); 233 347 if (status != PJ_SUCCESS) { 234 348 /* Better luck next time */ … … 493 607 options |= PJSIP_INV_SUPPORT_100REL; 494 608 495 #if !PJSIP_HAS_100REL496 /* options cannot specify 100rel if 100rel is disabled */497 PJ_ASSERT_RETURN(498 (options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0,499 PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION));500 501 #endif502 503 609 if (options & PJSIP_INV_REQUIRE_TIMER) 504 610 options |= PJSIP_INV_SUPPORT_TIMER; … … 539 645 pjsip_dlg_inc_session(dlg, &mod_inv.mod); 540 646 541 #if PJSIP_HAS_100REL542 647 /* Create 100rel handler */ 543 648 pjsip_100rel_attach(inv); 544 #endif545 649 546 650 /* Done */ … … 944 1048 options |= PJSIP_INV_SUPPORT_100REL; 945 1049 946 #if !PJSIP_HAS_100REL947 /* options cannot specify 100rel if 100rel is disabled */948 PJ_ASSERT_RETURN(949 (options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0,950 PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION));951 952 #endif953 954 1050 if (options & PJSIP_INV_REQUIRE_TIMER) 955 1051 options |= PJSIP_INV_SUPPORT_TIMER; … … 1021 1117 inv->invite_tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; 1022 1118 1023 #if PJSIP_HAS_100REL1024 1119 /* Create 100rel handler */ 1025 1120 if (inv->options & PJSIP_INV_REQUIRE_100REL) { 1026 1121 pjsip_100rel_attach(inv); 1027 1122 } 1028 #endif1029 1123 1030 1124 /* Done */ … … 1240 1334 1241 1335 /* 1242 * Negotiate SDP.1336 * Initiate SDP negotiation in the SDP negotiator. 1243 1337 */ 1244 1338 static pj_status_t inv_negotiate_sdp( pjsip_inv_session *inv ) … … 1782 1876 PJ_DEF(pj_status_t) pjsip_inv_update ( pjsip_inv_session *inv, 1783 1877 const pj_str_t *new_contact, 1784 const pjmedia_sdp_session * new_offer,1878 const pjmedia_sdp_session *offer, 1785 1879 pjsip_tx_data **p_tdata ) 1786 1880 { 1787 PJ_UNUSED_ARG(inv); 1788 PJ_UNUSED_ARG(new_contact); 1789 PJ_UNUSED_ARG(new_offer); 1790 PJ_UNUSED_ARG(p_tdata); 1791 1792 PJ_TODO(CREATE_UPDATE_REQUEST); 1793 return PJ_ENOTSUP; 1881 pjsip_contact_hdr *contact_hdr = NULL; 1882 pjsip_tx_data *tdata = NULL; 1883 pjmedia_sdp_session *sdp_copy; 1884 pj_status_t status = PJ_SUCCESS; 1885 1886 /* Verify arguments. */ 1887 PJ_ASSERT_RETURN(inv && p_tdata && offer, PJ_EINVAL); 1888 1889 /* Dialog must have been established */ 1890 PJ_ASSERT_RETURN(inv->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED, 1891 PJ_EINVALIDOP); 1892 1893 /* Invite session must not have been disconnected */ 1894 PJ_ASSERT_RETURN(inv->state < PJSIP_INV_STATE_DISCONNECTED, 1895 PJ_EINVALIDOP); 1896 1897 /* Lock dialog. */ 1898 pjsip_dlg_inc_lock(inv->dlg); 1899 1900 /* Process offer */ 1901 if (pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE) { 1902 PJ_LOG(4,(inv->dlg->obj_name, 1903 "Invalid SDP offer/answer state for UPDATE")); 1904 status = PJ_EINVALIDOP; 1905 goto on_error; 1906 } 1907 1908 status = pjmedia_sdp_neg_modify_local_offer(inv->pool,inv->neg, 1909 offer); 1910 if (status != PJ_SUCCESS) 1911 goto on_error; 1912 1913 1914 /* Update Contact if required */ 1915 if (new_contact) { 1916 pj_str_t tmp; 1917 const pj_str_t STR_CONTACT = { "Contact", 7 }; 1918 1919 pj_strdup_with_null(inv->dlg->pool, &tmp, new_contact); 1920 contact_hdr = (pjsip_contact_hdr*) 1921 pjsip_parse_hdr(inv->dlg->pool, &STR_CONTACT, 1922 tmp.ptr, tmp.slen, NULL); 1923 if (!contact_hdr) { 1924 status = PJSIP_EINVALIDURI; 1925 goto on_error; 1926 } 1927 1928 inv->dlg->local.contact = contact_hdr; 1929 } 1930 1931 /* Create request */ 1932 status = pjsip_dlg_create_request(inv->dlg, &pjsip_update_method, 1933 -1, &tdata); 1934 if (status != PJ_SUCCESS) 1935 goto on_error; 1936 1937 /* Attach SDP body */ 1938 sdp_copy = pjmedia_sdp_session_clone(tdata->pool, offer); 1939 pjsip_create_sdp_body(tdata->pool, sdp_copy, &tdata->msg->body); 1940 1941 /* Unlock dialog. */ 1942 pjsip_dlg_dec_lock(inv->dlg); 1943 1944 *p_tdata = tdata; 1945 1946 return PJ_SUCCESS; 1947 1948 on_error: 1949 if (tdata) 1950 pjsip_tx_data_dec_ref(tdata); 1951 1952 /* Unlock dialog. */ 1953 pjsip_dlg_dec_lock(inv->dlg); 1954 1955 return status; 1794 1956 } 1795 1957 … … 1833 1995 PJ_EINVALIDOP); 1834 1996 1835 #if PJSIP_HAS_100REL1836 1997 if (inv->options & PJSIP_INV_REQUIRE_100REL) { 1837 1998 status = pjsip_100rel_tx_response(inv, tdata); 1838 1999 } else 1839 #endif1840 2000 { 1841 2001 status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata); 1842 2002 } 1843 2003 … … 1988 2148 1989 2149 /* 2150 * Respond to incoming UPDATE request. 2151 */ 2152 static void inv_respond_incoming_update(pjsip_inv_session *inv, 2153 pjsip_rx_data *rdata) 2154 { 2155 pjmedia_sdp_neg_state neg_state; 2156 pj_status_t status; 2157 pjsip_tx_data *tdata = NULL; 2158 2159 neg_state = pjmedia_sdp_neg_get_state(inv->neg); 2160 2161 /* Send 491 if we receive UPDATE while we're waiting for an answer */ 2162 if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { 2163 status = pjsip_dlg_create_response(inv->dlg, rdata, 2164 PJSIP_SC_REQUEST_PENDING, NULL, 2165 &tdata); 2166 } 2167 /* Send 500 with Retry-After header set randomly between 0 and 10 if we 2168 * receive UPDATE while we haven't sent answer. 2169 */ 2170 else if (neg_state == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER || 2171 neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) { 2172 status = pjsip_dlg_create_response(inv->dlg, rdata, 2173 PJSIP_SC_INTERNAL_SERVER_ERROR, 2174 NULL, &tdata); 2175 2176 } else { 2177 /* We receive new offer from remote */ 2178 inv_check_sdp_in_incoming_msg(inv, pjsip_rdata_get_tsx(rdata), rdata); 2179 2180 /* Application MUST have supplied the answer by now. 2181 * If so, negotiate the SDP. 2182 */ 2183 neg_state = pjmedia_sdp_neg_get_state(inv->neg); 2184 if (neg_state != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO || 2185 (status=inv_negotiate_sdp(inv)) != PJ_SUCCESS) 2186 { 2187 /* Negotiation has failed */ 2188 status = pjsip_dlg_create_response(inv->dlg, rdata, 2189 PJSIP_SC_NOT_ACCEPTABLE_HERE, 2190 NULL, &tdata); 2191 } else { 2192 /* New media has been negotiated successfully, send 200/OK */ 2193 status = pjsip_dlg_create_response(inv->dlg, rdata, 2194 PJSIP_SC_OK, NULL, &tdata); 2195 if (status == PJ_SUCCESS) { 2196 pjmedia_sdp_session *sdp; 2197 status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 2198 if (status == PJ_SUCCESS) 2199 tdata->msg->body = create_sdp_body(tdata->pool, sdp); 2200 } 2201 } 2202 } 2203 2204 if (status != PJ_SUCCESS) { 2205 if (tdata != NULL) { 2206 pjsip_tx_data_dec_ref(tdata); 2207 tdata = NULL; 2208 } 2209 return; 2210 } 2211 2212 pjsip_dlg_send_response(inv->dlg, pjsip_rdata_get_tsx(rdata), tdata); 2213 } 2214 2215 2216 /* 2217 * Handle incoming response to UAC UPDATE request. 2218 */ 2219 static void inv_handle_update_response( pjsip_inv_session *inv, 2220 pjsip_event *e) 2221 { 2222 pjsip_transaction *tsx = e->body.tsx_state.tsx; 2223 struct tsx_inv_data *tsx_inv_data = NULL; 2224 pj_status_t status = -1; 2225 2226 /* Process 2xx response */ 2227 if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 2228 tsx->status_code/100 == 2 && 2229 e->body.tsx_state.src.rdata->msg_info.msg->body) 2230 { 2231 status = inv_check_sdp_in_incoming_msg(inv, tsx, 2232 e->body.tsx_state.src.rdata); 2233 2234 } else { 2235 /* Get/attach invite session's transaction data */ 2236 tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id]; 2237 if (tsx_inv_data == NULL) { 2238 tsx_inv_data=PJ_POOL_ZALLOC_T(tsx->pool, struct tsx_inv_data); 2239 tsx_inv_data->inv = inv; 2240 tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; 2241 } 2242 } 2243 2244 /* Otherwise if we don't get successful response, cancel 2245 * our negotiator. 2246 */ 2247 if (status != PJ_SUCCESS && 2248 pjmedia_sdp_neg_get_state(inv->neg)==PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER && 2249 tsx_inv_data && tsx_inv_data->sdp_done == PJ_FALSE) 2250 { 2251 pjmedia_sdp_neg_cancel_offer(inv->neg); 2252 2253 /* Prevent from us cancelling different offer! */ 2254 tsx_inv_data->sdp_done = PJ_TRUE; 2255 } 2256 } 2257 2258 2259 /* 2260 * Handle incoming reliable response. 2261 */ 2262 static void inv_handle_incoming_reliable_response(pjsip_inv_session *inv, 2263 pjsip_rx_data *rdata) 2264 { 2265 pjsip_tx_data *tdata; 2266 pjmedia_sdp_session *sdp; 2267 pj_status_t status; 2268 2269 /* Create PRACK */ 2270 status = pjsip_100rel_create_prack(inv, rdata, &tdata); 2271 if (status != PJ_SUCCESS) 2272 return; 2273 2274 /* See if we need to attach SDP answer on the PRACK request */ 2275 sdp = inv_has_pending_answer(inv, pjsip_rdata_get_tsx(rdata)); 2276 if (sdp) { 2277 tdata->msg->body = create_sdp_body(tdata->pool, sdp); 2278 } 2279 2280 /* Send PRACK (must be using 100rel module!) */ 2281 pjsip_100rel_send_prack(inv, tdata); 2282 } 2283 2284 2285 /* 2286 * Handle incoming PRACK. 2287 */ 2288 static void inv_respond_incoming_prack(pjsip_inv_session *inv, 2289 pjsip_rx_data *rdata) 2290 { 2291 pj_status_t status; 2292 2293 /* Run through 100rel module to see if we can accept this 2294 * PRACK request. The 100rel will send 200/OK to PRACK request. 2295 */ 2296 status = pjsip_100rel_on_rx_prack(inv, rdata); 2297 if (status != PJ_SUCCESS) 2298 return; 2299 2300 /* Now check for SDP answer in the PRACK request */ 2301 if (rdata->msg_info.msg->body) { 2302 status = inv_check_sdp_in_incoming_msg(inv, 2303 pjsip_rdata_get_tsx(rdata), rdata); 2304 } else { 2305 /* No SDP body */ 2306 status = -1; 2307 } 2308 2309 /* If SDP negotiation has been successful, also mark the 2310 * SDP negotiation flag in the invite transaction to be 2311 * done too. 2312 */ 2313 if (status == PJ_SUCCESS && inv->invite_tsx) { 2314 struct tsx_inv_data *tsx_inv_data; 2315 2316 /* Get/attach invite session's transaction data */ 2317 tsx_inv_data = (struct tsx_inv_data*) 2318 inv->invite_tsx->mod_data[mod_inv.mod.id]; 2319 if (tsx_inv_data == NULL) { 2320 tsx_inv_data = PJ_POOL_ZALLOC_T(inv->invite_tsx->pool, 2321 struct tsx_inv_data); 2322 tsx_inv_data->inv = inv; 2323 inv->invite_tsx->mod_data[mod_inv.mod.id] = tsx_inv_data; 2324 } 2325 2326 tsx_inv_data->sdp_done = PJ_TRUE; 2327 } 2328 } 2329 2330 2331 /* 1990 2332 * State NULL is before anything is sent/received. 1991 2333 */ … … 2073 2415 e->body.tsx_state.src.rdata); 2074 2416 2417 if (pjsip_100rel_is_reliable(e->body.tsx_state.src.rdata)) { 2418 inv_handle_incoming_reliable_response( 2419 inv, e->body.tsx_state.src.rdata); 2420 } 2421 2075 2422 } else { 2076 2423 /* Ignore 100 (Trying) response, as it doesn't change … … 2167 2514 } 2168 2515 2169 } else if (inv->role == PJSIP_ROLE_UAC && 2170 tsx->role == PJSIP_ROLE_UAC && 2171 tsx->method.id == PJSIP_CANCEL_METHOD) 2172 { 2516 } else if (tsx->role == PJSIP_ROLE_UAC) { 2173 2517 /* 2174 * Handle case when outgoing CANCELis answered with 481 (Call/2518 * Handle case when outgoing request is answered with 481 (Call/ 2175 2519 * Transaction Does Not Exist), 408, or when it's timed out. In these 2176 2520 * cases, disconnect session (i.e. dialog usage only). … … 2285 2629 inv_check_sdp_in_incoming_msg(inv, tsx, 2286 2630 e->body.tsx_state.src.rdata); 2631 2632 if (pjsip_100rel_is_reliable(e->body.tsx_state.src.rdata)) { 2633 inv_handle_incoming_reliable_response( 2634 inv, e->body.tsx_state.src.rdata); 2635 } 2287 2636 } 2288 2637 break; … … 2354 2703 inv_respond_incoming_cancel(inv, tsx, e->body.tsx_state.src.rdata); 2355 2704 2356 } else if ( inv->role == PJSIP_ROLE_UAC&&2357 tsx-> role == PJSIP_ROLE_UAC&&2358 tsx->method.id == PJSIP_CANCEL_METHOD)2705 } else if (tsx->role == PJSIP_ROLE_UAS && 2706 tsx->state == PJSIP_TSX_STATE_TRYING && 2707 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 2359 2708 { 2360 2709 /* 2361 * Handle case when outgoing CANCEL is answered with 481 (Call/ 2710 * Handle incoming UPDATE 2711 */ 2712 inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 2713 2714 2715 } else if (tsx->role == PJSIP_ROLE_UAC && 2716 (tsx->state == PJSIP_TSX_STATE_COMPLETED || 2717 tsx->state == PJSIP_TSX_STATE_TERMINATED) && 2718 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 2719 { 2720 /* 2721 * Handle response to outgoing UPDATE request. 2722 */ 2723 inv_handle_update_response(inv, e); 2724 2725 } else if (tsx->role == PJSIP_ROLE_UAS && 2726 tsx->state == PJSIP_TSX_STATE_TRYING && 2727 pjsip_method_cmp(&tsx->method, &pjsip_prack_method)==0) 2728 { 2729 /* 2730 * Handle incoming PRACK 2731 */ 2732 inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); 2733 2734 } else if (tsx->role == PJSIP_ROLE_UAC) { 2735 /* 2736 * Handle case when outgoing request is answered with 481 (Call/ 2362 2737 * Transaction Does Not Exist), 408, or when it's timed out. In these 2363 2738 * cases, disconnect session (i.e. dialog usage only). … … 2467 2842 if (status != PJ_SUCCESS) return; 2468 2843 2469 } 2844 } else if (tsx->role == PJSIP_ROLE_UAS && 2845 tsx->state == PJSIP_TSX_STATE_TRYING && 2846 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 2847 { 2848 /* 2849 * Handle incoming UPDATE 2850 */ 2851 inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 2852 2853 2854 } else if (tsx->role == PJSIP_ROLE_UAC && 2855 (tsx->state == PJSIP_TSX_STATE_COMPLETED || 2856 tsx->state == PJSIP_TSX_STATE_TERMINATED) && 2857 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 2858 { 2859 /* 2860 * Handle response to outgoing UPDATE request. 2861 */ 2862 inv_handle_update_response(inv, e); 2863 2864 } else if (tsx->role == PJSIP_ROLE_UAS && 2865 tsx->state == PJSIP_TSX_STATE_TRYING && 2866 pjsip_method_cmp(&tsx->method, &pjsip_prack_method)==0) 2867 { 2868 /* 2869 * Handle incoming PRACK 2870 */ 2871 inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); 2872 2873 } else if (tsx->role == PJSIP_ROLE_UAC) { 2874 /* 2875 * Handle case when outgoing request is answered with 481 (Call/ 2876 * Transaction Does Not Exist), 408, or when it's timed out. In these 2877 * cases, disconnect session (i.e. dialog usage only). 2878 */ 2879 if (tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || 2880 tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 2881 tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 2882 tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 2883 { 2884 inv_set_cause(inv, tsx->status_code, &tsx->status_text); 2885 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 2886 } 2887 } 2888 2470 2889 } 2471 2890 … … 2731 3150 } 2732 3151 } 2733 } 3152 3153 } else if (tsx->role == PJSIP_ROLE_UAS && 3154 tsx->state == PJSIP_TSX_STATE_TRYING && 3155 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 3156 { 3157 /* 3158 * Handle incoming UPDATE 3159 */ 3160 inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata); 3161 3162 } else if (tsx->role == PJSIP_ROLE_UAC && 3163 (tsx->state == PJSIP_TSX_STATE_COMPLETED || 3164 tsx->state == PJSIP_TSX_STATE_TERMINATED) && 3165 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0) 3166 { 3167 /* 3168 * Handle response to outgoing UPDATE request. 3169 */ 3170 inv_handle_update_response(inv, e); 3171 3172 } else if (tsx->role == PJSIP_ROLE_UAS && 3173 tsx->state == PJSIP_TSX_STATE_TRYING && 3174 pjsip_method_cmp(&tsx->method, &pjsip_prack_method)==0) 3175 { 3176 /* 3177 * Handle strandled incoming PRACK 3178 */ 3179 inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata); 3180 3181 } else if (tsx->role == PJSIP_ROLE_UAC) { 3182 /* 3183 * Handle case when outgoing request is answered with 481 (Call/ 3184 * Transaction Does Not Exist), 408, or when it's timed out. In these 3185 * cases, disconnect session (i.e. dialog usage only). 3186 */ 3187 if (tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || 3188 tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 3189 tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 3190 tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 3191 { 3192 inv_set_cause(inv, tsx->status_code, &tsx->status_text); 3193 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 3194 } 3195 } 3196 2734 3197 } 2735 3198
Note: See TracChangeset
for help on using the changeset viewer.