static int w_dlg_terminate(struct sip_msg *msg, char *side, char *r) { struct dlg_cell *dlg; str reason = {0, 0}; int n = (int) (long) side; //check if a reason was given if (r) { if (get_str_fparam(&reason, msg, (fparam_t *) r) < 0) { LM_ERR("failed to recover reason parameter\n"); return -1; } } dlg = dlg_get_msg_dialog(msg); //dlg_get_ctx_dialog(); if (!dlg) { LM_DBG("Unable to find dialog for terminate\n"); return -1; } if (!dlg_terminate(dlg, msg, &reason, n, NULL)) { LM_DBG("Failed to terminate dialog\n"); return -1; } return 1; }
/*! * \brief Unset a dialog profile * \param msg SIP message * \param value value * \param profile dialog profile table * \return 1 on success, -1 on failure */ int unset_dlg_profile(sip_msg_t *msg, str *value, dlg_profile_table_t *profile) { dlg_cell_t *dlg; dlg_profile_link_t *linker; dlg_profile_link_t *linker_prev; dlg_entry_t *d_entry; if (is_route_type(REQUEST_ROUTE)) { LM_ERR("dialog delete profile cannot be used in request route\n"); return -1; } /* get current dialog */ dlg = dlg_get_msg_dialog(msg); if (dlg==NULL) { LM_WARN("dialog is NULL for delete profile\n"); return -1; } /* check the dialog linkers */ d_entry = &d_table->entries[dlg->h_entry]; dlg_lock( d_table, d_entry); linker = dlg->profile_links; linker_prev = NULL; for( ; linker ; linker_prev=linker,linker=linker->next) { if (linker->profile==profile) { if (profile->has_value==0) { goto found; } else if (value && value->len==linker->hash_linker.value.len && memcmp(value->s,linker->hash_linker.value.s,value->len)==0){ goto found; } /* allow further search - maybe the dialog is inserted twice in * the same profile, but with different values -bogdan */ } } atomic_or_int((volatile int*)&dlg->dflags, DLG_FLAG_CHANGED_PROF); dlg_unlock( d_table, d_entry); dlg_release(dlg); return -1; found: /* table still locked */ /* remove the linker element from dialog */ if (linker_prev==NULL) { dlg->profile_links = linker->next; } else { linker_prev->next = linker->next; } linker->next = NULL; dlg_unlock( d_table, d_entry); /* remove linker from profile table and free it */ destroy_linkers(linker); dlg_release(dlg); return 1; }
int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { dlg_cell_t *dlg; str * value; str spv; if (param==NULL || param->pvn.type!=PV_NAME_INTSTR || param->pvn.u.isname.type!=AVP_NAME_STR || param->pvn.u.isname.name.s.s==NULL) { LM_CRIT("BUG - bad parameters\n"); return -1; } /* Retrieve the dialog for current message */ dlg=dlg_get_msg_dialog( msg); if (dlg) { /* Lock the dialog */ dlg_lock(d_table, &(d_table->entries[dlg->h_entry])); } else { /* Verify the local list */ get_local_varlist_pointer(msg, 0); } /* dcm: todo - the value should be cloned for safe usage */ value = get_dlg_variable_unsafe(dlg, ¶m->pvn.u.isname.name.s); spv.s = NULL; if(value) { spv.len = pv_get_buffer_size(); if(spv.len<value->len+1) { LM_ERR("pv buffer too small (%d) - needed %d\n", spv.len, value->len); } else { spv.s = pv_get_buffer(); strncpy(spv.s, value->s, value->len); spv.len = value->len; spv.s[spv.len] = '\0'; } } print_lists(dlg); /* unlock dialog */ if (dlg) { dlg_unlock(d_table, &(d_table->entries[dlg->h_entry])); dlg_release(dlg); } if (spv.s) return pv_get_strval(msg, param, res, &spv); return pv_get_null(msg, param, res); }
/* * Determine if message is in a dialog currently being tracked */ int is_known_dlg(struct sip_msg *msg) { dlg_cell_t *dlg; dlg = dlg_get_msg_dialog(msg); if(dlg == NULL) return -1; dlg_release(dlg); return 1; }
/*! * \brief Check if a dialog belongs to a profile * \param msg SIP message * \param profile dialog profile table * \param value value * \return 1 on success, -1 on failure */ int is_dlg_in_profile(struct sip_msg *msg, struct dlg_profile_table *profile, str *value) { struct dlg_cell *dlg; struct dlg_profile_link *linker; struct dlg_entry *d_entry; int ret; LM_DBG("Getting current dialog"); /* get current dialog */ dlg = dlg_get_msg_dialog(msg); if (dlg == NULL) { LM_DBG("Error: Current dlg is null"); return -1; } LM_DBG("Current dlg found"); ret = -1; /* check the dialog linkers */ d_entry = &d_table->entries[dlg->h_entry]; dlg_lock( d_table, d_entry); for (linker = dlg->profile_links; linker; linker = linker->next) { LM_DBG("Running through linkers"); if (linker->profile == profile) { LM_DBG("Profile matches"); if (profile->has_value == 0) { LM_DBG("Profile has value is zero returning true"); dlg_unlock( d_table, d_entry); ret = 1; goto done; } else if (value && value->len == linker->hash_linker.value.len && memcmp(value->s, linker->hash_linker.value.s, value->len) == 0) { LM_DBG("Profile has value equal to passed value returning true"); dlg_unlock( d_table, d_entry); ret = 1; goto done; } /* allow further search - maybe the dialog is inserted twice in * the same profile, but with different values -bogdan */ } } dlg_unlock( d_table, d_entry); done: dlg_release(dlg); return ret; }
/*! * \brief Check if a dialog belongs to a profile * \param msg SIP message * \param profile dialog profile table * \param value value * \return 1 on success, -1 on failure */ int is_dlg_in_profile(struct sip_msg *msg, struct dlg_profile_table *profile, str *value) { struct dlg_cell *dlg; struct dlg_profile_link *linker; struct dlg_entry *d_entry; int ret; /* get current dialog */ dlg = dlg_get_msg_dialog(msg); if (dlg==NULL) return -1; ret = -1; /* check the dialog linkers */ d_entry = &d_table->entries[dlg->h_entry]; dlg_lock( d_table, d_entry); for( linker=dlg->profile_links ; linker ; linker=linker->next) { if (linker->profile==profile) { if (profile->has_value==0) { dlg_unlock( d_table, d_entry); ret = 1; goto done; } else if (value && value->len==linker->hash_linker.value.len && memcmp(value->s,linker->hash_linker.value.s,value->len)==0){ dlg_unlock( d_table, d_entry); ret = 1; goto done; } /* allow further search - maybe the dialog is inserted twice in * the same profile, but with different values -bogdan */ } } dlg_unlock( d_table, d_entry); done: dlg_release(dlg); return ret; }
static int w_dlg_set_timeout(struct sip_msg *msg, char *pto, char *phe, char *phi) { int to = 0; unsigned int he = 0; unsigned int hi = 0; dlg_cell_t *dlg = NULL; if(fixup_get_ivalue(msg, (gparam_p)pto, &to)!=0) { LM_ERR("no timeout value\n"); return -1; } if(phe!=NULL) { if(fixup_get_ivalue(msg, (gparam_p)phe, (int*)&he)!=0) { LM_ERR("no hash entry value value\n"); return -1; } if(fixup_get_ivalue(msg, (gparam_p)phi, (int*)&hi)!=0) { LM_ERR("no hash id value value\n"); return -1; } dlg = dlg_lookup(he, hi); } else { dlg = dlg_get_msg_dialog(msg); } if(dlg==NULL) { LM_DBG("no dialog found\n"); return -1; } if(update_dlg_timeout(dlg, to) != 0) return -1; return 1; }
int pv_set_dlg_variable(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) { dlg_cell_t *dlg = NULL; int ret = -1; if (param==NULL || param->pvn.type!=PV_NAME_INTSTR || param->pvn.u.isname.type!=AVP_NAME_STR || param->pvn.u.isname.name.s.s==NULL ) { LM_CRIT("BUG - bad parameters\n"); goto error; } /* Retrieve the dialog for current message */ dlg=dlg_get_msg_dialog( msg); if (dlg) { /* Lock the dialog */ dlg_lock(d_table, &(d_table->entries[dlg->h_entry])); } else { /* Verify the local list */ get_local_varlist_pointer(msg, 0); } if (val==NULL || val->flags&(PV_VAL_NONE|PV_VAL_NULL|PV_VAL_EMPTY)) { /* if NULL, remove the value */ ret = set_dlg_variable_unsafe(dlg, ¶m->pvn.u.isname.name.s, NULL); if(ret!= 0) { /* unlock dialog */ if (dlg) { dlg_unlock(d_table, &(d_table->entries[dlg->h_entry])); dlg_release(dlg); } return ret; } } else { /* if value, must be string */ if ( !(val->flags&PV_VAL_STR)) { LM_ERR("non-string values are not supported\n"); /* unlock dialog */ if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry])); goto error; } ret = set_dlg_variable_unsafe(dlg, ¶m->pvn.u.isname.name.s, &val->rs); if(ret!= 0) { /* unlock dialog */ if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry])); goto error; } } /* unlock dialog */ if (dlg) { dlg->dflags |= DLG_FLAG_CHANGED_VARS; dlg_unlock(d_table, &(d_table->entries[dlg->h_entry])); if ( dlg_db_mode==DB_MODE_REALTIME ) update_dialog_dbinfo(dlg); } print_lists(dlg); dlg_release(dlg); return 0; error: dlg_release(dlg); return -1; }
/*! * \brief Set a dialog profile * \param msg SIP message * \param value value * \param profile dialog profile table * \return 0 on success, -1 on failure */ int set_dlg_profile(struct sip_msg *msg, str *value, struct dlg_profile_table *profile) { dlg_cell_t *dlg = NULL; dlg_profile_link_t *linker; /* get current dialog */ dlg = dlg_get_msg_dialog(msg); if (dlg==NULL && !is_route_type(REQUEST_ROUTE)) { LM_CRIT("BUG - dialog not found in a non REQUEST route (%d)\n", REQUEST_ROUTE); return -1; } /* build new linker */ linker = (struct dlg_profile_link*)shm_malloc( sizeof(struct dlg_profile_link) + (profile->has_value?value->len:0) ); if (linker==NULL) { LM_ERR("no more shm memory\n"); goto error; } memset(linker, 0, sizeof(struct dlg_profile_link)); /* set backpointers to profile and linker (itself) */ linker->profile = profile; linker->hash_linker.linker = linker; /* set the value */ if (profile->has_value) { linker->hash_linker.value.s = (char*)(linker+1); memcpy( linker->hash_linker.value.s, value->s, value->len); linker->hash_linker.value.len = value->len; } sruid_next_safe(&_dlg_profile_sruid); strcpy(linker->hash_linker.puid, _dlg_profile_sruid.uid.s); linker->hash_linker.puid_len = _dlg_profile_sruid.uid.len; if (dlg!=NULL) { /* add linker directly to the dialog and profile */ link_dlg_profile( linker, dlg); } else { /* if existing linkers are not from current request, just discard them */ if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) { current_dlg_msg_id = msg->id; current_dlg_msg_pid = msg->pid; destroy_linkers(current_pending_linkers); current_pending_linkers = NULL; } /* no dialog yet -> set linker as pending */ if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) { current_dlg_msg_id = msg->id; current_dlg_msg_pid = msg->pid; destroy_linkers(current_pending_linkers); } linker->next = current_pending_linkers; current_pending_linkers = linker; } dlg_release(dlg); return 0; error: dlg_release(dlg); return -1; }
int pv_get_dlg(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { dlg_cell_t *dlg = NULL; int res_type = 0; str sv = { 0 }; unsigned int ui = 0; if(param==NULL) return -1; if(_dlg_ctx.iuid.h_id==0) { /* Retrieve the dialog for current message */ dlg=dlg_get_msg_dialog(msg); } else { /* Retrieve the dialog for current context */ dlg=dlg_get_by_iuid(&_dlg_ctx.iuid); } if(dlg == NULL) return pv_get_null(msg, param, res); switch(param->pvn.u.isname.name.n) { case 1: res_type = 1; ui = (unsigned int)dlg->h_id; break; case 2: res_type = 1; ui = (unsigned int)dlg->state; break; case 3: if(dlg->route_set[DLG_CALLEE_LEG].s==NULL || dlg->route_set[DLG_CALLEE_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->route_set[DLG_CALLEE_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->route_set[DLG_CALLEE_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 4: res_type = 1; ui = (unsigned int)dlg->dflags; break; case 5: res_type = 1; ui = (unsigned int)dlg->sflags; break; case 6: if(dlg->callid.s==NULL || dlg->callid.len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->callid.len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->callid.s, sv.len); sv.s[sv.len] = '\0'; break; case 7: if(dlg->to_uri.s==NULL || dlg->to_uri.len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->to_uri.len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->to_uri.s, sv.len); sv.s[sv.len] = '\0'; break; case 8: if(dlg->tag[DLG_CALLEE_LEG].s==NULL || dlg->tag[DLG_CALLEE_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->tag[DLG_CALLEE_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->tag[DLG_CALLEE_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 9: res_type = 1; ui = (unsigned int)dlg->toroute; break; case 10: if(dlg->cseq[DLG_CALLEE_LEG].s==NULL || dlg->cseq[DLG_CALLEE_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->cseq[DLG_CALLEE_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->cseq[DLG_CALLEE_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 11: if(dlg->route_set[DLG_CALLER_LEG].s==NULL || dlg->route_set[DLG_CALLER_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->route_set[DLG_CALLER_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->route_set[DLG_CALLER_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 12: if(dlg->from_uri.s==NULL || dlg->from_uri.len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->from_uri.len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->from_uri.s, sv.len); sv.s[sv.len] = '\0'; break; case 13: if(dlg->tag[DLG_CALLER_LEG].s==NULL || dlg->tag[DLG_CALLER_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->tag[DLG_CALLER_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->tag[DLG_CALLER_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 14: res_type = 1; ui = (unsigned int)dlg->lifetime; break; case 15: res_type = 1; ui = (unsigned int)dlg->start_ts; break; case 16: if(dlg->cseq[DLG_CALLER_LEG].s==NULL || dlg->cseq[DLG_CALLER_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->cseq[DLG_CALLER_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->cseq[DLG_CALLER_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 17: if(dlg->contact[DLG_CALLEE_LEG].s==NULL || dlg->contact[DLG_CALLEE_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->contact[DLG_CALLEE_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->contact[DLG_CALLEE_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 18: if(dlg->bind_addr[DLG_CALLEE_LEG]==NULL) goto done; sv.s = pv_get_buffer(); sv.len = dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s, sv.len); sv.s[sv.len] = '\0'; break; case 19: if(dlg->contact[DLG_CALLER_LEG].s==NULL || dlg->contact[DLG_CALLER_LEG].len<=0) goto done; sv.s = pv_get_buffer(); sv.len = dlg->contact[DLG_CALLER_LEG].len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->contact[DLG_CALLER_LEG].s, sv.len); sv.s[sv.len] = '\0'; break; case 20: if(dlg->bind_addr[DLG_CALLER_LEG]==NULL) goto done; sv.s = pv_get_buffer(); sv.len = dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len; if(pv_get_buffer_size()<sv.len) goto done; res_type = 2; strncpy(sv.s, dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s, sv.len); sv.s[sv.len] = '\0'; break; case 21: res_type = 1; ui = (unsigned int)dlg->h_entry; break; default: res_type = 1; ui = (unsigned int)dlg->ref; } done: dlg_release(dlg); switch(res_type) { case 1: return pv_get_uintval(msg, param, res, ui); case 2: return pv_get_strval(msg, param, res, &sv); default: return pv_get_null(msg, param, res); } }