Changeset 2049


Ignore:
Timestamp:
Jun 25, 2008 10:15:01 AM (11 years ago)
Author:
bennylp
Message:

Fixed ticket #550: PRACK is not re-sent on 401/407 challenge (thanks Josh Benson)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r2039 r2049  
    23612361             
    23622362        } else { 
    2363             /* Re-send BYE. */ 
     2363            /* Re-send request. */ 
    23642364            status = pjsip_inv_send_msg(inv, tdata); 
    23652365        } 
     
    25172517    } 
    25182518} 
     2519 
     2520/* 
     2521 * Generic UAC transaction handler: 
     2522 *  - resend request on 401 or 407 response. 
     2523 *  - terminate dialog on 408 and 481 response. 
     2524 */ 
     2525static pj_bool_t handle_uac_tsx_response(pjsip_inv_session *inv,  
     2526                                         pjsip_event *e) 
     2527{ 
     2528    /* RFC 3261 Section 12.2.1.2: 
     2529     *  If the response for a request within a dialog is a 481 
     2530     *  (Call/Transaction Does Not Exist) or a 408 (Request Timeout), the UAC 
     2531     *  SHOULD terminate the dialog.  A UAC SHOULD also terminate a dialog if 
     2532     *  no response at all is received for the request (the client 
     2533     *  transaction would inform the TU about the timeout.) 
     2534     *  
     2535     *  For INVITE initiated dialogs, terminating the dialog consists of 
     2536     *  sending a BYE. 
     2537     * 
     2538     * Note: 
     2539     *  according to X, this should terminate dialog usage only, not the  
     2540     *  dialog. 
     2541     */ 
     2542    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     2543 
     2544    pj_assert(tsx->role == PJSIP_UAC_ROLE); 
     2545 
     2546    /* Note that 481 response to CANCEL does not terminate dialog usage, 
     2547     * but only the transaction. 
     2548     */ 
     2549    if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && 
     2550            tsx->method.id != PJSIP_CANCEL_METHOD) || 
     2551        tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 
     2552        tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 
     2553        tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 
     2554    { 
     2555        pjsip_tx_data *bye; 
     2556        pj_status_t status; 
     2557 
     2558        inv_set_cause(inv, tsx->status_code, &tsx->status_text); 
     2559        inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     2560 
     2561        /* Send BYE */ 
     2562        status = pjsip_dlg_create_request(inv->dlg, pjsip_get_bye_method(),  
     2563                                          -1, &bye); 
     2564        if (status == PJ_SUCCESS) { 
     2565            pjsip_inv_send_msg(inv, bye); 
     2566        } 
     2567 
     2568        return PJ_TRUE; /* Handled */ 
     2569 
     2570    }  
     2571    /* Handle 401/407 challenge. */ 
     2572    else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 
     2573             (tsx->status_code == PJSIP_SC_UNAUTHORIZED || 
     2574              tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED))  
     2575    { 
     2576 
     2577        pjsip_tx_data *tdata; 
     2578        pj_status_t status; 
     2579 
     2580        status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess,  
     2581                                            e->body.tsx_state.src.rdata, 
     2582                                            tsx->last_tx, &tdata); 
     2583     
     2584        if (status != PJ_SUCCESS) { 
     2585            /* Does not have proper credentials. End the session. */ 
     2586            inv_set_cause(inv, PJSIP_SC_OK, NULL); 
     2587            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     2588             
     2589        } else { 
     2590            /* Re-send request. */ 
     2591            if (tsx->method.id == PJSIP_INVITE_METHOD) 
     2592                inv->invite_tsx = NULL; 
     2593 
     2594            status = pjsip_inv_send_msg(inv, tdata); 
     2595        } 
     2596 
     2597        return PJ_TRUE; /* Handled */ 
     2598 
     2599    } else { 
     2600        return PJ_FALSE; /* Unhandled */ 
     2601    } 
     2602} 
     2603 
    25192604 
    25202605/* 
     
    28742959 
    28752960    } else if (tsx->role == PJSIP_ROLE_UAC) { 
    2876         /* 
    2877          * Handle case when outgoing request is answered with 481 (Call/ 
    2878          * Transaction Does Not Exist), 408, or when it's timed out. In these 
    2879          * cases, disconnect session (i.e. dialog usage only). 
    2880          * Note that 481 response to CANCEL does not terminate dialog usage, 
    2881          * but only the transaction. 
    2882          */ 
    2883         if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && 
    2884                 tsx->method.id != PJSIP_CANCEL_METHOD) || 
    2885             tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 
    2886             tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 
    2887             tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 
    2888         { 
    2889             inv_set_cause(inv, tsx->status_code, &tsx->status_text); 
    2890             inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    2891         } 
    2892     } 
    2893 } 
    2894  
    2895 /* 
    2896  * Handle 408, 481, or any other responses that terminates dialog. 
    2897  */ 
    2898 static pj_bool_t handle_408_481_response(pjsip_inv_session *inv,  
    2899                                          pjsip_event *e) 
    2900 { 
    2901     /* RFC 3261 Section 12.2.1.2: 
    2902      *  If the response for a request within a dialog is a 481 
    2903      *  (Call/Transaction Does Not Exist) or a 408 (Request Timeout), the UAC 
    2904      *  SHOULD terminate the dialog.  A UAC SHOULD also terminate a dialog if 
    2905      *  no response at all is received for the request (the client 
    2906      *  transaction would inform the TU about the timeout.) 
    2907      *  
    2908      *  For INVITE initiated dialogs, terminating the dialog consists of 
    2909      *  sending a BYE. 
    2910      * 
    2911      * Note: 
    2912      *  according to X, this should terminate dialog usage only, not the  
    2913      *  dialog. 
    2914      */ 
    2915     pjsip_transaction *tsx = e->body.tsx_state.tsx; 
    2916  
    2917     pj_assert(tsx->role == PJSIP_UAC_ROLE); 
    2918  
    2919     /* Note that 481 response to CANCEL does not terminate dialog usage, 
    2920      * but only the transaction. 
    2921      */ 
    2922     if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && 
    2923             tsx->method.id != PJSIP_CANCEL_METHOD) || 
    2924         tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || 
    2925         tsx->status_code == PJSIP_SC_TSX_TIMEOUT || 
    2926         tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) 
    2927     { 
    2928         pjsip_tx_data *bye; 
    2929         pj_status_t status; 
    2930  
    2931         inv_set_cause(inv, tsx->status_code, &tsx->status_text); 
    2932         inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    2933  
    2934         /* Send BYE */ 
    2935         status = pjsip_dlg_create_request(inv->dlg, pjsip_get_bye_method(),  
    2936                                           -1, &bye); 
    2937         if (status == PJ_SUCCESS) { 
    2938             pjsip_inv_send_msg(inv, bye); 
    2939         } 
    2940  
    2941         return PJ_TRUE; /* Handled */ 
    2942  
    2943     } else { 
    2944         return PJ_FALSE; /* Unhandled */ 
    2945     } 
    2946 } 
    2947  
     2961         
     2962        /* Generic handling for UAC tsx completion */ 
     2963        handle_uac_tsx_response(inv, e); 
     2964    } 
     2965} 
    29482966 
    29492967/* 
     
    30583076         * Handle response to outgoing UPDATE request. 
    30593077         */ 
    3060         if (handle_408_481_response(inv, e) == PJ_FALSE) 
     3078        if (handle_uac_tsx_response(inv, e) == PJ_FALSE) 
    30613079            inv_handle_update_response(inv, e); 
    30623080 
     
    30723090    } else if (tsx->role == PJSIP_ROLE_UAC) { 
    30733091         
    3074         handle_408_481_response(inv, e); 
     3092        /* Generic handling for UAC tsx completion */ 
     3093        handle_uac_tsx_response(inv, e); 
    30753094    } 
    30763095 
     
    33093328            inv_send_ack(inv, e); 
    33103329 
    3311         } else if (handle_408_481_response(inv, e)) { 
     3330        } else if (handle_uac_tsx_response(inv, e)) { 
    33123331 
    33133332            /* Handle response that terminates dialog */ 
    33143333            /* Nothing to do (already handled) */ 
    3315  
    3316         } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 
    3317                    (tsx->status_code==401 || tsx->status_code==407)) 
    3318         { 
    3319             pjsip_tx_data *tdata; 
    3320             pj_status_t status; 
    3321  
    3322             /* Handle authentication challenge. */ 
    3323             status = pjsip_auth_clt_reinit_req( &dlg->auth_sess, 
    3324                                                 e->body.tsx_state.src.rdata, 
    3325                                                 tsx->last_tx, 
    3326                                                 &tdata); 
    3327             if (status != PJ_SUCCESS) 
    3328                 return; 
    3329  
    3330             /* Retry INVITE request */ 
    3331             inv->invite_tsx = NULL; 
    3332  
    3333             /* Send re-INVITE */ 
    3334             status = pjsip_inv_send_msg( inv, tdata); 
    33353334 
    33363335        } else if (tsx->status_code >= 300 && tsx->status_code < 700) { 
     
    33623361         * Handle response to outgoing UPDATE request. 
    33633362         */ 
    3364         if (handle_408_481_response(inv, e) == PJ_FALSE) 
     3363        if (handle_uac_tsx_response(inv, e) == PJ_FALSE) 
    33653364            inv_handle_update_response(inv, e); 
    33663365 
     
    33763375    } else if (tsx->role == PJSIP_ROLE_UAC) { 
    33773376        /* 
    3378          * Handle 408/481 response 
     3377         * Handle 401/407/408/481 response 
    33793378         */ 
    3380         handle_408_481_response(inv, e); 
     3379        handle_uac_tsx_response(inv, e); 
    33813380    } 
    33823381 
Note: See TracChangeset for help on using the changeset viewer.