00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #include "../../dprint.h"
00032 #include "../../ut.h"
00033 #include "../../db/db.h"
00034 #include "../../dprint.h"
00035 #include "../../config.h"
00036 #include "../../socket_info.h"
00037 #include "../tm/dlg.h"
00038 #include "../tm/tm_load.h"
00039 #include "../../mi/tree.h"
00040 #include "dlg_timer.h"
00041 #include "dlg_hash.h"
00042 #include "dlg_req_within.h"
00043 #include "dlg_db_handler.h"
00044
00045
00046 #define MAX_FWD_HDR "Max-Forwards: " MAX_FWD CRLF
00047 #define MAX_FWD_HDR_LEN (sizeof(MAX_FWD_HDR) - 1)
00048
00049 extern str dlg_extra_hdrs;
00050
00051
00052
00053 int free_tm_dlg(dlg_t *td)
00054 {
00055 if(td)
00056 {
00057 if(td->route_set)
00058 free_rr(&td->route_set);
00059 pkg_free(td);
00060 }
00061 return 0;
00062 }
00063
00064
00065
00066 dlg_t * build_dlg_t(struct dlg_cell * cell, int dir){
00067
00068 dlg_t* td = NULL;
00069 str cseq;
00070 unsigned int loc_seq;
00071
00072 td = (dlg_t*)pkg_malloc(sizeof(dlg_t));
00073 if(!td){
00074
00075 LM_ERR("out of pkg memory\n");
00076 return NULL;
00077 }
00078 memset(td, 0, sizeof(dlg_t));
00079
00080
00081 cseq = (dir == DLG_CALLER_LEG) ? cell->cseq[DLG_CALLEE_LEG]:
00082 cell->cseq[DLG_CALLER_LEG];
00083 if(str2int(&cseq, &loc_seq) != 0){
00084 LM_ERR("invalid cseq\n");
00085 goto error;
00086 }
00087
00088 td->loc_seq.value = loc_seq;
00089 td->loc_seq.is_set = 1;
00090
00091
00092 if( cell->route_set[dir].s && cell->route_set[dir].len){
00093
00094 if( parse_rr_body(cell->route_set[dir].s, cell->route_set[dir].len,
00095 &td->route_set) !=0){
00096 LM_ERR("failed to parse route set\n");
00097 goto error;
00098 }
00099 }
00100
00101
00102 if(cell->contact[dir].s==0 || cell->contact[dir].len==0){
00103
00104 LM_ERR("no contact available\n");
00105 goto error;
00106 }
00107 td->rem_target = cell->contact[dir];
00108
00109 td->rem_uri = (dir == DLG_CALLER_LEG)? cell->from_uri: cell->to_uri;
00110 td->loc_uri = (dir == DLG_CALLER_LEG)? cell->to_uri: cell->from_uri;
00111 td->id.call_id = cell->callid;
00112 td->id.rem_tag = cell->tag[dir];
00113 td->id.loc_tag = (dir == DLG_CALLER_LEG) ? cell->tag[DLG_CALLEE_LEG]:
00114 cell->tag[DLG_CALLER_LEG];
00115
00116 td->state= DLG_CONFIRMED;
00117 td->send_sock = cell->bind_addr[dir];
00118
00119 return td;
00120
00121 error:
00122 free_tm_dlg(td);
00123 return NULL;
00124 }
00125
00126
00127
00128
00129 void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps){
00130
00131 struct dlg_cell* dlg;
00132 int event, old_state, new_state, unref, ret;
00133
00134 if(ps->param == NULL || *ps->param == NULL){
00135 LM_ERR("invalid parameter\n");
00136 return;
00137 }
00138
00139 if(ps->code < 200){
00140 LM_DBG("receiving a provisional reply\n");
00141 return;
00142 }
00143
00144 LM_DBG("receiving a final reply %d\n",ps->code);
00145
00146 dlg = (struct dlg_cell *)(*(ps->param));
00147 event = DLG_EVENT_REQBYE;
00148 next_state_dlg(dlg, event, &old_state, &new_state, &unref);
00149
00150
00151 if(new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED){
00152
00153 LM_DBG("removing dialog with h_entry %u and h_id %u\n",
00154 dlg->h_entry, dlg->h_id);
00155
00156
00157 ret = remove_dialog_timer(&dlg->tl);
00158 if (ret < 0) {
00159 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
00160 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00161 dlg, dlg->h_entry, dlg->h_id,
00162 dlg->callid.len, dlg->callid.s,
00163 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00164 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00165 } else if (ret > 0) {
00166 LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
00167 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00168 dlg, dlg->h_entry, dlg->h_id,
00169 dlg->callid.len, dlg->callid.s,
00170 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00171 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00172 } else {
00173 unref++;
00174 }
00175
00176 run_dlg_callbacks( DLGCB_TERMINATED, dlg, ps->req, DLG_DIR_NONE, 0);
00177
00178 LM_DBG("first final reply\n");
00179
00180 unref_dlg(dlg, unref+1);
00181
00182 if_update_stat( dlg_enable_stats, active_dlgs, -1);
00183 }
00184
00185 if(new_state == DLG_STATE_DELETED && old_state == DLG_STATE_DELETED ) {
00186
00187 LM_DBG("second final reply\n");
00188
00189 if (dlg_db_mode)
00190 remove_dialog_from_db(dlg);
00191
00192 unref_dlg(dlg, 1);
00193 }
00194
00195 }
00196
00197
00198
00199 static inline int build_extra_hdr(struct dlg_cell * cell, str *extra_hdrs,
00200 str *str_hdr)
00201 {
00202 char *p;
00203
00204 str_hdr->len = MAX_FWD_HDR_LEN + dlg_extra_hdrs.len;
00205 if(extra_hdrs && extra_hdrs->len>0)
00206 str_hdr->len += extra_hdrs->len;
00207
00208 str_hdr->s = (char*)pkg_malloc( str_hdr->len * sizeof(char) );
00209 if(!str_hdr->s){
00210 LM_ERR("out of pkg memory\n");
00211 goto error;
00212 }
00213
00214 memcpy(str_hdr->s , MAX_FWD_HDR, MAX_FWD_HDR_LEN );
00215 p = str_hdr->s + MAX_FWD_HDR_LEN;
00216 if (dlg_extra_hdrs.len) {
00217 memcpy( p, dlg_extra_hdrs.s, dlg_extra_hdrs.len);
00218 p += dlg_extra_hdrs.len;
00219 }
00220 if (extra_hdrs && extra_hdrs->len>0)
00221 memcpy( p, extra_hdrs->s, extra_hdrs->len);
00222
00223 return 0;
00224
00225 error:
00226 return -1;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs)
00237 {
00238
00239 dlg_t* dialog_info;
00240 str met = {"BYE", 3};
00241 int result;
00242
00243 if ((dialog_info = build_dlg_t(cell, dir)) == 0){
00244 LM_ERR("failed to create dlg_t\n");
00245 goto err;
00246 }
00247
00248 LM_DBG("sending BYE to %s\n", (dir==DLG_CALLER_LEG)?"caller":"callee");
00249
00250 ref_dlg(cell, 1);
00251
00252 result = d_tmb.t_request_within
00253 (&met,
00254 hdrs,
00255 NULL,
00256 dialog_info,
00257 bye_reply_cb,
00258 (void*)cell);
00259
00260 if(result < 0){
00261 LM_ERR("failed to send the BYE request\n");
00262 goto err1;
00263 }
00264
00265 free_tm_dlg(dialog_info);
00266
00267 LM_DBG("BYE sent to %s\n", (dir==0)?"caller":"callee");
00268 return 0;
00269
00270 err1:
00271 unref_dlg(cell, 1);
00272 err:
00273 if(dialog_info)
00274 free_tm_dlg(dialog_info);
00275 return -1;
00276 }
00277
00278
00279
00280
00281 struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param ){
00282
00283 struct mi_node* node;
00284 unsigned int h_entry, h_id;
00285 struct dlg_cell * dlg = NULL;
00286 str mi_extra_hdrs = {NULL,0};
00287 int status, msg_len;
00288 char *msg;
00289
00290
00291 if( d_table ==NULL)
00292 goto end;
00293
00294 node = cmd_tree->node.kids;
00295 h_entry = h_id = 0;
00296
00297 if (node==NULL || node->next==NULL)
00298 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00299
00300 if (!node->value.s|| !node->value.len|| strno2int(&node->value,&h_entry)<0)
00301 goto error;
00302
00303 node = node->next;
00304 if ( !node->value.s || !node->value.len || strno2int(&node->value,&h_id)<0)
00305 goto error;
00306
00307 if (node->next) {
00308 node = node->next;
00309 if (node->value.len && node->value.s)
00310 mi_extra_hdrs = node->value;
00311 }
00312
00313 LM_DBG("h_entry %u h_id %u\n", h_entry, h_id);
00314
00315 dlg = lookup_dlg(h_entry, h_id);
00316
00317
00318
00319 if(dlg){
00320 if(dlg_bye_all(dlg,(mi_extra_hdrs.len>0)?&mi_extra_hdrs:NULL)<0) {
00321 status = 500;
00322 msg = MI_DLG_OPERATION_ERR;
00323 msg_len = MI_DLG_OPERATION_ERR_LEN;
00324 } else {
00325 status = 200;
00326 msg = MI_OK_S;
00327 msg_len = MI_OK_LEN;
00328 }
00329
00330 unref_dlg(dlg, 1);
00331
00332 return init_mi_tree(status, msg, msg_len);
00333 }
00334
00335 end:
00336 return init_mi_tree(404, MI_DIALOG_NOT_FOUND, MI_DIALOG_NOT_FOUND_LEN);
00337
00338 error:
00339 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00340
00341 }
00342
00343 int dlg_bye(struct dlg_cell *dlg, str *hdrs, int side)
00344 {
00345 str all_hdrs = { 0, 0 };
00346 int ret;
00347
00348 if(side==DLG_CALLER_LEG)
00349 {
00350 if(dlg->dflags&DLG_FLAG_CALLERBYE)
00351 return -1;
00352 dlg->dflags |= DLG_FLAG_CALLERBYE;
00353 } else {
00354 if(dlg->dflags&DLG_FLAG_CALLEEBYE)
00355 return -1;
00356 dlg->dflags |= DLG_FLAG_CALLEEBYE;
00357 }
00358 if ((build_extra_hdr(dlg, hdrs, &all_hdrs)) != 0)
00359 {
00360 LM_ERR("failed to build dlg headers\n");
00361 return -1;
00362 }
00363 ret = send_bye(dlg, side, &all_hdrs);
00364 pkg_free(all_hdrs.s);
00365 return ret;
00366 }
00367
00368 int dlg_bye_all(struct dlg_cell *dlg, str *hdrs)
00369 {
00370 str all_hdrs = { 0, 0 };
00371 int ret;
00372
00373 if ((build_extra_hdr(dlg, hdrs, &all_hdrs)) != 0)
00374 {
00375 LM_ERR("failed to build dlg headers\n");
00376 return -1;
00377 }
00378
00379 ret = send_bye(dlg, DLG_CALLER_LEG, &all_hdrs);
00380 ret |= send_bye(dlg, DLG_CALLEE_LEG, &all_hdrs);
00381
00382 pkg_free(all_hdrs.s);
00383 return ret;
00384
00385 }
00386