/*! * \brief add dlg structure to tm callbacks to wait for negative ACK * \param t current transaction * \param dlg current dialog * \return 0 on success, -1 on failure */ int dlg_set_tm_waitack(tm_cell_t *t, dlg_cell_t *dlg) { dlg_iuid_t *iuid = NULL; if(t==NULL) return -1; LM_DBG("registering TMCB to wait for negative ACK\n"); iuid = dlg_get_iuid_shm_clone(dlg); if(iuid==NULL) { LM_ERR("failed to create dialog unique id clone\n"); goto error; } dlg_ref(dlg, 1); if ( d_tmb.register_tmcb( NULL, t, TMCB_DESTROY, dlg_ontdestroy, (void*)iuid, dlg_iuid_sfree)<0 ) { LM_ERR("failed to register TMCB to wait for negative ACK\n"); dlg_unref(dlg, 1); goto error; } return 0; error: dlg_iuid_sfree(iuid); return -1; }
/*! * \brief add dlg structure to tm callbacks * \param t current transaction * \param req current sip request * \param dlg current dialog * \param smode if the sip request was spiraled * \return 0 on success, -1 on failure */ int dlg_set_tm_callbacks(tm_cell_t *t, sip_msg_t *req, dlg_cell_t *dlg, int smode) { dlg_iuid_t *iuid = NULL; if(t==NULL) return -1; if(smode==0) { iuid = dlg_get_iuid_shm_clone(dlg); if(iuid==NULL) { LM_ERR("failed to create dialog unique id clone\n"); goto error; } if ( d_tmb.register_tmcb( req, t, TMCB_RESPONSE_IN|TMCB_RESPONSE_READY|TMCB_RESPONSE_FWDED|TMCB_ON_FAILURE, dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) { LM_ERR("failed to register TMCB\n"); goto error; } } dlg->dflags |= DLG_FLAG_TM; return 0; error: dlg_iuid_sfree(iuid); return -1; }
/* callback function to handle responses to the keep-alive request */ void dlg_ka_cb(struct cell* t, int type, struct tmcb_params* ps){ dlg_cell_t* dlg; dlg_iuid_t *iuid = NULL; if(ps->param == NULL || *ps->param == NULL) { LM_ERR("invalid parameter\n"); return; } if(ps->code < 200) { LM_DBG("receiving a provisional reply\n"); return; } LM_DBG("receiving a final reply %d\n",ps->code); iuid = (dlg_iuid_t*)(*ps->param); dlg = dlg_get_by_iuid(iuid); if(dlg==0) { dlg_iuid_sfree(iuid); return; } if(ps->code==408 || ps->code==481) { if(update_dlg_timer(&dlg->tl, 10)<0) { LM_ERR("failed to update dialog lifetime\n"); goto done; } dlg->lifetime = 10; dlg->dflags |= DLG_FLAG_CHANGED; } done: dlg_unref(dlg, 1); dlg_iuid_sfree(iuid); }
/* callback function to handle responses to the BYE request */ void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps){ struct dlg_cell* dlg; int event, old_state, new_state, unref, ret; dlg_iuid_t *iuid = NULL; if(ps->param == NULL || *ps->param == NULL){ LM_ERR("invalid parameter\n"); return; } if(ps->code < 200){ LM_DBG("receiving a provisional reply\n"); return; } LM_DBG("receiving a final reply %d\n",ps->code); iuid = (dlg_iuid_t*)(*ps->param); dlg = dlg_get_by_iuid(iuid); if(dlg==0) return; event = DLG_EVENT_REQBYE; next_state_dlg(dlg, event, &old_state, &new_state, &unref); if(new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED){ LM_DBG("removing dialog with h_entry %u and h_id %u\n", dlg->h_entry, dlg->h_id); /* remove from timer */ ret = remove_dialog_timer(&dlg->tl); if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); } else if (ret > 0) { LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); } else { unref++; } /* dialog terminated (BYE) */ run_dlg_callbacks( DLGCB_TERMINATED, dlg, ps->req, ps->rpl, DLG_DIR_NONE, 0); LM_DBG("first final reply\n"); /* derefering the dialog */ dlg_unref(dlg, unref+1); if_update_stat( dlg_enable_stats, active_dlgs, -1); } if(new_state == DLG_STATE_DELETED && old_state == DLG_STATE_DELETED ) { /* trash the dialog from DB and memory */ LM_DBG("second final reply\n"); /* delete the dialog from DB */ if (dlg_db_mode) remove_dialog_from_db(dlg); /* force delete from mem */ dlg_unref(dlg, 1); } dlg_iuid_sfree(iuid); }