Exemplo n.º 1
0
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, &param->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);
}
Exemplo n.º 2
0
/*!
 * \brief Create a new dialog from a sip message
 *
 * Create a new dialog from a SIP message, register a callback
 * to keep track of the dialog with help of the tm module.
 * This function is either called from the request callback, or
 * from the dlg_manage function in the configuration script.
 * \see dlg_onreq
 * \see w_dlg_manage
 * \param msg SIP message
 * \param t transaction
 * \return 0 on success, -1 on failure
 */
int dlg_new_dialog(struct sip_msg *req, struct cell *t, const int run_initial_cbs) {
    struct dlg_cell *dlg;
    str s;
    str callid;
    str ftag;
    str ttag;
    str req_uri;
    unsigned int dir;

    LM_DBG("starting dlg_new_dialog and method is [%.*s]\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);

    if (current_dlg_pointer != NULL)
        return -1;

    if (req->first_line.u.request.method_value == METHOD_CANCEL)
        return -1;

    if (pre_match_parse(req, &callid, &ftag, &ttag, 0) < 0) {
        LM_WARN("pre-matching failed\n");
        return -1;
    }

    if (ttag.s != 0 && ttag.len != 0)
        return -1;

    if (pv_printf_s(req, ruri_param_model, &req_uri) < 0) {
        LM_ERR("error - cannot print the r-uri format\n");
        return -1;
    }
    trim(&req_uri);

    if (detect_spirals) {
        if (spiral_detected == 1)
            return 0;

        dir = DLG_DIR_NONE;

        dlg = get_dlg(&callid, &ftag, &ttag, &dir);
        if (dlg) {
            LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
                    callid.len, callid.s);
            spiral_detected = 1;

            if (run_initial_cbs)
                run_dlg_callbacks(DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0);

            //Add did to rr header for all spiralled requested INVITEs
            if (req->first_line.u.request.method_value == METHOD_INVITE) {
                if (add_dlg_rr_param(dlg, req, dlg->h_entry, dlg->h_id) < 0) {
                    LM_ERR("failed to add RR param\n");

                }
            }

            // get_dlg has incremented the ref count by 1
            unref_dlg(dlg, 1);
            goto finish;
        }
    }
    spiral_detected = 0;


    LM_DBG("Building new Dialog for call-id %.*s\n", callid.len, callid.s);
    LM_DBG("SIP Method: %.*s  \n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
    dlg = build_new_dlg(&callid /*callid*/,
            &(get_from(req)->uri) /*from uri*/,
            &ftag/*from_tag*/,
            &req_uri /*r-uri*/);

    if (dlg == 0) {
        LM_ERR("failed to create new dialog\n");
        return -1;
    }

    /* save caller's tag, cseq, contact and record route*/
    if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
            &(get_from(req)->tag_value)) != 0) {
        LM_ERR("could not add further info to the dialog\n");
        lock_destroy(dlg->dlg_out_entries_lock);
        lock_dealloc(dlg->dlg_out_entries_lock);
        shm_free(dlg);
        return -1;
    }

    dlg->transaction = t;

    /* Populate initial varlist: */
    dlg->vars = get_local_varlist_pointer(req, 1);

    link_dlg(dlg, 0);
    if (run_initial_cbs) run_create_callbacks(dlg, req);

    //Dialog will *always* use DID cookie so no need for match mode anymore
    if (add_dlg_rr_param(dlg, req, dlg->h_entry, dlg->h_id) < 0) {
        LM_ERR("failed to add RR param\n");
        goto error;
    }

    if (d_tmb.register_tmcb(req, t,
            TMCB_RESPONSE_READY | TMCB_RESPONSE_FWDED | TMCB_RESPONSE_OUT,
            dlg_onreply, (void*) dlg, unref_new_dialog) < 0) {
        LM_ERR("failed to register TMCB\n");
        goto error;
    }
    // increase reference counter because of registered callback
    ref_dlg(dlg, 1);

    dlg->lifetime = get_dlg_timeout(req);
    s.s = _dlg_ctx.to_route_name;
    s.len = strlen(s.s);
    dlg_set_toroute(dlg, &s);
    dlg->sflags |= _dlg_ctx.flags;

    if (_dlg_ctx.to_bye != 0)
        dlg->dflags |= DLG_FLAG_TOBYE;

finish:
    if (t) {
        // transaction exists ==> keep ref counter large enough to
        // avoid premature cleanup and ensure proper dialog referencing
        if (store_dlg_in_tm(req, t, dlg) < 0) {
            LM_ERR("failed to store dialog in transaction\n");
            goto error;
        }
    } else {
        // no transaction exists ==> postpone work until we see the
        // request being forwarded statefully
        if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED,
                store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) {
            LM_ERR("failed to register callback for storing dialog in transaction\n");
            goto error;
        }
    }

    LM_DBG("Setting current dialog\n");
    set_current_dialog(req, dlg);
    _dlg_ctx.dlg = dlg;
    ref_dlg(dlg, 1);
    return 0;

error:
    LM_DBG("Error in build_new_dlg");
    if (!spiral_detected)
        unref_dlg(dlg, 1); // undo ref regarding linking
    return -1;
}
Exemplo n.º 3
0
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, &param->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, &param->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;
}
Exemplo n.º 4
0
/*!
 * \brief Create a new dialog from a sip message
 *
 * Create a new dialog from a SIP message, register a callback
 * to keep track of the dialog with help of the tm module.
 * This function is either called from the request callback, or
 * from the dlg_manage function in the configuration script.
 * \see dlg_onreq
 * \see w_dlg_manage
 * \param req SIP message
 * \param t transaction
 * \param run_initial_cbs if set zero, initial callbacks are not executed
 * \return 0 on success, -1 on failure
 */ 
int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
{
	dlg_cell_t *dlg;
	str s;
	str callid;
    str ftag;
    str ttag;
    str req_uri;
    unsigned int dir;

	dlg = dlg_get_ctx_dialog();
    if(dlg != NULL) {
		dlg_release(dlg);
        return -1;
	}

	if(req->first_line.u.request.method_value != METHOD_INVITE)
		return -1;

    if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
        LM_WARN("pre-matching failed\n");
        return -1;
    }

    if(ttag.s!=0 && ttag.len!=0)
        return -1;

    if(pv_printf_s(req, ruri_param_model, &req_uri)<0) {
        LM_ERR("error - cannot print the r-uri format\n");
        return -1;
    }
    trim(&req_uri);

	dir = DLG_DIR_NONE;
	/* search dialog by SIP attributes
	 * - hash table slot is left locked  */
	dlg = dlg_search(&callid, &ftag, &ttag, &dir);
	if(dlg) {
		if (detect_spirals) {
			if (spiral_detected == 1) {
				dlg_hash_release(&callid);
				return 0;
			}

			if ( dlg->state != DLG_STATE_DELETED ) {
				LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
					callid.len, callid.s);
				spiral_detected = 1;

				if (run_initial_cbs)
					run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL,
							DLG_DIR_DOWNSTREAM, 0);
				/* set ctx dlg id shortcuts */
				_dlg_ctx.iuid.h_entry = dlg->h_entry;
				_dlg_ctx.iuid.h_id = dlg->h_id;
				/* search_dlg() has incremented the ref count by 1 */
				dlg_release(dlg);
				dlg_hash_release(&callid);
				return 0;
			}
			dlg_release(dlg);
		}
    }
    spiral_detected = 0;

    dlg = build_new_dlg (&callid /*callid*/,
                         &(get_from(req)->uri) /*from uri*/,
                         &(get_to(req)->uri) /*to uri*/,
                         &ftag/*from_tag*/,
                         &req_uri /*r-uri*/ );

	if (dlg==0) {
		dlg_hash_release(&callid);
		LM_ERR("failed to create new dialog\n");
		return -1;
	}

	/* save caller's tag, cseq, contact and record route*/
	if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
			&(get_from(req)->tag_value)) !=0) {
		dlg_hash_release(&callid);
		LM_ERR("could not add further info to the dialog\n");
		shm_free(dlg);
		return -1;
	}

	/* Populate initial varlist: */
	dlg->vars = get_local_varlist_pointer(req, 1);

	/* after dlg_search() slot was kept locked */
	link_dlg(dlg, 0, 1);
	/* unlock after dlg_search() */
	dlg_hash_release(&callid);

	dlg->lifetime = get_dlg_timeout(req);
	s.s   = _dlg_ctx.to_route_name;
	s.len = strlen(s.s);
	dlg_set_toroute(dlg, &s);
	dlg->sflags |= _dlg_ctx.flags;
	dlg->iflags |= _dlg_ctx.iflags;

	if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
		dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;

    if (run_initial_cbs)  run_create_callbacks( dlg, req);

	/* first INVITE seen (dialog created, unconfirmed) */
	if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
			add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
		LM_ERR("failed to add RR param\n");
		goto error;
	}

    if_update_stat( dlg_enable_stats, processed_dlgs, 1);

	_dlg_ctx.cpid = my_pid();
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;
    set_current_dialog(req, dlg);

	return 0;

error:
	if (!spiral_detected)
		dlg_unref(dlg, 1);               // undo ref regarding linking
	return -1;
}