Ignore:
Timestamp:
Feb 19, 2006 1:37:35 AM (19 years ago)
Author:
bennylp
Message:

Fixed premature dialog deletion, causing crash

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r175 r196  
    4242PJ_DEF(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m) 
    4343{ 
    44     pjsip_method subscribe = { PJSIP_OTHER_METHOD, {"SUBSCRIBE", 10}}; 
    45     pjsip_method refer = { PJSIP_OTHER_METHOD, {"REFER", 5}}; 
     44    const pjsip_method subscribe = { PJSIP_OTHER_METHOD, {"SUBSCRIBE", 9}}; 
     45    const pjsip_method refer = { PJSIP_OTHER_METHOD, {"REFER", 5}}; 
     46    const pjsip_method notify = { PJSIP_OTHER_METHOD, {"NOTIFY", 6}}; 
    4647 
    4748    return m->id == PJSIP_INVITE_METHOD || 
    4849           (pjsip_method_cmp(m, &subscribe)==0) || 
    49            (pjsip_method_cmp(m, &refer)==0); 
     50           (pjsip_method_cmp(m, &refer)==0) || 
     51           (pjsip_method_cmp(m, &notify)==0); 
    5052} 
    5153 
     
    598600 
    599601/* 
     602 * Lock dialog and increment session counter temporarily 
     603 * to prevent it from being deleted. 
     604 */ 
     605PJ_DEF(void) pjsip_dlg_inc_lock(pjsip_dialog *dlg) 
     606{ 
     607    pj_mutex_lock(dlg->mutex); 
     608    dlg->sess_count++; 
     609} 
     610 
     611 
     612/* 
     613 * Unlock dialog and decrement session counter. 
     614 * It may delete the dialog! 
     615 */ 
     616PJ_DEF(void) pjsip_dlg_dec_lock(pjsip_dialog *dlg) 
     617{ 
     618    pj_assert(dlg->sess_count > 0); 
     619    --dlg->sess_count; 
     620 
     621    if (dlg->sess_count==0 && dlg->tsx_count==0) 
     622        unregister_and_destroy_dialog(dlg); 
     623    else { 
     624        pj_mutex_unlock(dlg->mutex); 
     625    } 
     626} 
     627 
     628 
     629 
     630/* 
    600631 * Decrement session counter. 
    601632 */ 
     
    603634                                           pjsip_module *mod) 
    604635{ 
    605     pj_status_t status; 
    606  
    607636    PJ_ASSERT_RETURN(dlg, PJ_EINVAL); 
    608637 
     
    611640 
    612641    pj_mutex_lock(dlg->mutex); 
    613  
    614     pj_assert(dlg->sess_count > 0); 
    615     --dlg->sess_count; 
    616  
    617     if (dlg->sess_count==0 && dlg->tsx_count==0) 
    618         status = unregister_and_destroy_dialog(dlg); 
    619     else { 
    620         pj_mutex_unlock(dlg->mutex); 
    621         status = PJ_SUCCESS; 
    622     } 
    623  
    624     return status; 
    625 } 
    626  
     642    pjsip_dlg_dec_lock(dlg); 
     643 
     644    return PJ_SUCCESS; 
     645} 
    627646 
    628647/* 
     
    640659    PJ_ASSERT_RETURN(dlg->usage_cnt < PJSIP_MAX_MODULE, PJ_EBUG); 
    641660 
    642     PJ_LOG(5,(dlg->obj_name, "Module %.*s added as dialog usage", 
    643               (int)mod->name.slen, mod->name.ptr)); 
     661    PJ_LOG(5,(dlg->obj_name,  
     662              "Module %.*s added as dialog usage, data=%p", 
     663              (int)mod->name.slen, mod->name.ptr, mod_data)); 
    644664 
    645665    pj_mutex_lock(dlg->mutex); 
     
    675695 
    676696    return PJ_SUCCESS; 
     697} 
     698 
     699 
     700/* 
     701 * Attach module specific data to the dialog. Application can also set  
     702 * the value directly by accessing dlg->mod_data[module_id]. 
     703 */ 
     704PJ_DEF(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg, 
     705                                            int mod_id, 
     706                                            void *data ) 
     707{ 
     708    PJ_ASSERT_RETURN(dlg, PJ_EINVAL); 
     709    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE, 
     710                     PJ_EINVAL); 
     711    dlg->mod_data[mod_id] = data; 
     712    return PJ_SUCCESS; 
     713} 
     714 
     715/** 
     716 * Get module specific data previously attached to the dialog. Application 
     717 * can also get value directly by accessing dlg->mod_data[module_id]. 
     718 */ 
     719PJ_DEF(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg, 
     720                                      int mod_id) 
     721{ 
     722    PJ_ASSERT_RETURN(dlg, NULL); 
     723    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE, 
     724                     NULL); 
     725    return dlg->mod_data[mod_id]; 
    677726} 
    678727 
     
    814863              pjsip_tx_data_get_info(tdata))); 
    815864 
    816     /* Update CSeq */ 
    817     pj_mutex_lock(dlg->mutex); 
     865    /* Lock and increment session */ 
     866    pjsip_dlg_inc_lock(dlg); 
    818867 
    819868    /* Update dialog's CSeq and message's CSeq if request is not 
     
    870919    } 
    871920 
    872     /* Unlock dialog. */ 
    873     pj_mutex_unlock(dlg->mutex); 
     921    /* Unlock dialog, may destroy dialog. */ 
     922    pjsip_dlg_dec_lock(dlg); 
    874923 
    875924    return PJ_SUCCESS; 
    876925 
    877926on_error: 
    878     /* Unlock dialog. */ 
    879     pj_mutex_unlock(dlg->mutex); 
     927    /* Unlock dialog, may destroy dialog. */ 
     928    pjsip_dlg_dec_lock(dlg); 
    880929    
    881930    /* Whatever happen delete the message. */ 
     
    10041053    PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL); 
    10051054 
    1006     pj_mutex_lock(dlg->mutex); 
     1055    /* Lock and increment session */ 
     1056    pjsip_dlg_inc_lock(dlg); 
    10071057 
    10081058    /* Replace status code and reason */ 
     
    10231073    pjsip_tx_data_invalidate_msg(tdata); 
    10241074 
    1025     pj_mutex_unlock(dlg->mutex); 
     1075    /* Unlock dialog and dec session, may destroy dialog. */ 
     1076    pjsip_dlg_dec_lock(dlg); 
    10261077 
    10271078    return PJ_SUCCESS; 
     
    11041155              pjsip_rx_data_get_info(rdata))); 
    11051156 
    1106     /* Lock the dialog. */ 
    1107     pj_mutex_lock(dlg->mutex); 
     1157    /* Lock dialog and increment session. */ 
     1158    pjsip_dlg_inc_lock(dlg); 
    11081159 
    11091160    /* Check CSeq */ 
     
    11151166         * Respond statelessly with 500 (Internal Server Error) 
    11161167         */ 
    1117         pj_mutex_unlock(dlg->mutex); 
     1168        pj_str_t warn_text; 
     1169 
     1170        /* Unlock dialog and dec session, may destroy dialog. */ 
     1171        pjsip_dlg_dec_lock(dlg); 
     1172 
    11181173        pj_assert(pjsip_rdata_get_tsx(rdata) == NULL); 
     1174        warn_text = pj_str("Invalid CSeq"); 
    11191175        pjsip_endpt_respond_stateless(dlg->endpt, 
    1120                                       rdata, 500, NULL, NULL, NULL); 
     1176                                      rdata, 500, &warn_text, NULL, NULL); 
    11211177        return; 
    11221178    } 
     
    11241180    /* Update CSeq. */ 
    11251181    dlg->remote.cseq = rdata->msg_info.cseq->cseq; 
     1182 
     1183    /* Update To tag if necessary. 
     1184     * This only happens if UAS sends a new request before answering 
     1185     * our request (e.g. UAS sends NOTIFY before answering our 
     1186     * SUBSCRIBE request). 
     1187     */ 
     1188    if (dlg->remote.info->tag.slen == 0) { 
     1189        pj_strdup(dlg->pool, &dlg->remote.info->tag, 
     1190                  &rdata->msg_info.from->tag); 
     1191    } 
    11261192 
    11271193    /* Create UAS transaction for this request. */ 
     
    11571223 
    11581224on_return: 
    1159     /* Unlock dialog. */ 
    1160     pj_mutex_unlock(dlg->mutex); 
     1225    /* Unlock dialog and dec session, may destroy dialog. */ 
     1226    pjsip_dlg_dec_lock(dlg); 
    11611227} 
    11621228 
     
    11721238              pjsip_rx_data_get_info(rdata))); 
    11731239 
    1174     /* Lock the dialog. */ 
    1175     pj_mutex_lock(dlg->mutex); 
     1240    /* Lock the dialog and inc session. */ 
     1241    pjsip_dlg_inc_lock(dlg); 
    11761242 
    11771243    /* Check that rdata already has dialog in mod_data. */ 
     
    12651331    } 
    12661332 
    1267     /* Unlock dialog. */ 
    1268     pj_mutex_unlock(dlg->mutex); 
     1333    /* Unlock dialog and dec session, may destroy dialog. */ 
     1334    pjsip_dlg_dec_lock(dlg); 
    12691335} 
    12701336 
     
    12811347              tsx->obj_name, pjsip_tsx_state_str(tsx->state))); 
    12821348 
    1283     /* Lock the dialog. */ 
    1284     pj_mutex_lock(dlg->mutex); 
    1285  
    1286     if (tsx->state == PJSIP_TSX_STATE_TERMINATED) 
    1287         --dlg->tsx_count; 
    1288  
    1289     /* Increment session to prevent usages from destroying dialog. */ 
    1290     ++dlg->sess_count; 
     1349    /* Lock the dialog and increment session. */ 
     1350    pjsip_dlg_inc_lock(dlg); 
    12911351 
    12921352    /* Pass to dialog usages. */ 
     
    12991359    } 
    13001360 
    1301     /* Decrement temporary session. */ 
    1302     --dlg->sess_count; 
    1303  
    1304     if (tsx->state == PJSIP_TSX_STATE_TERMINATED && dlg->tsx_count == 0 &&  
    1305         dlg->sess_count == 0)  
    1306     { 
    1307         /* Unregister this dialog from the transaction. */ 
     1361 
     1362    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
     1363        --dlg->tsx_count; 
    13081364        tsx->mod_data[dlg->ua->id] = NULL; 
    1309  
    1310         /* Time to destroy dialog. */ 
    1311         unregister_and_destroy_dialog(dlg); 
    1312  
    1313     } else { 
    1314         /* Unlock dialog. */ 
    1315         pj_mutex_unlock(dlg->mutex); 
    1316     } 
    1317 } 
    1318  
     1365    } 
     1366 
     1367    /* Unlock dialog and dec session, may destroy dialog. */ 
     1368    pjsip_dlg_dec_lock(dlg); 
     1369} 
     1370 
Note: See TracChangeset for help on using the changeset viewer.