示例#1
0
/*!
 * \brief Function that is registered as TM callback and called on requests
 * \see dlg_new_dialog
 * \param t transaction, used to created the dialog
 * \param type type of the entered callback
 * \param param saved dialog structure in the callback
 */
void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
{
	sip_msg_t *req = param->req;
	dlg_cell_t *dlg = NULL;

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

	dlg = dlg_get_ctx_dialog();

	if (dlg!=NULL) {
		if (!initial_cbs_inscript) {
			if (spiral_detected == 1)
				run_dlg_callbacks( DLGCB_SPIRALED, dlg,
						req, NULL, DLG_DIR_DOWNSTREAM, 0);
			else if (spiral_detected == 0)
				run_create_callbacks(dlg, req);
		}
	}
	if (dlg==NULL) {
		if((req->flags&dlg_flag)!=dlg_flag)
			return;
		dlg_new_dialog(req, t, 1);
		dlg = dlg_get_ctx_dialog();
	}
	if (dlg!=NULL) {
		dlg_set_tm_callbacks(t, req, dlg, spiral_detected);
		dlg_release(dlg);
	}
}
示例#2
0
void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
{
	/* is the dialog already created? */
	if (current_dlg_pointer!=NULL) {
		/* new, un-initialized dialog ? */
		if ( current_dlg_pointer->flags & DLG_FLAG_ISINIT ) {
			/* fully init dialog -> check if attached to the transaction */
			if (t->dialog_ctx==NULL) {

				/* set a callback to remove the ref when transaction 
				 * is destroied */
				if ( d_tmb.register_tmcb( NULL, t, TMCB_TRANS_DELETED,
				tmcb_unreference_dialog, (void*)current_dlg_pointer, NULL)<0){
					LM_ERR("failed to register TMCB\n");
					return;
				}
				/* and attached the dialog to the transaction */
				t->dialog_ctx = (void*)current_dlg_pointer;
				/* and keep a reference on it */
				ref_dlg( current_dlg_pointer , 1);
			}
			return;
		}

		/* dialog was previously created by create_dialog() 
		   -> just do the last settings */
		run_create_callbacks( current_dlg_pointer, param->req);

		LM_DBG("t hash_index = %u, t label = %u\n",t->hash_index,t->label);
		current_dlg_pointer->initial_t_hash_index = t->hash_index;
		current_dlg_pointer->initial_t_label = t->label;

		current_dlg_pointer->lifetime = get_dlg_timeout(param->req);

		t->dialog_ctx = (void*)current_dlg_pointer;

		/* dialog is fully initialized */
		current_dlg_pointer->flags |= DLG_FLAG_ISINIT;
	}
}
示例#3
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;
}
示例#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;
}
示例#5
0
int dlg_create_dialog(struct cell* t, struct sip_msg *req,unsigned int flags)
{
	struct dlg_cell *dlg;
	str s;
	int extra_ref;

	/* module is stricly designed for dialog calls */
	if (req->first_line.u.request.method_value!=METHOD_INVITE)
		return -1;

	if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
		LM_ERR("bad request or missing TO hdr :-/\n");
		return -1;
	}
	s = get_to(req)->tag_value;
	if (s.s!=0 && s.len!=0)
		return -1;

	if ( parse_from_header(req)) {
		LM_ERR("bad request or missing FROM hdr :-/\n");
		return -1;
	}
	if ((!req->callid && parse_headers(req,HDR_CALLID_F,0)<0) || !req->callid){
		LM_ERR("bad request or missing CALLID hdr :-/\n");
		return -1;
	}
	s = req->callid->body;
	trim(&s);

	/* some sanity checks */
	if (s.len==0 || get_from(req)->tag_value.len==0) {
		LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
			s.len, get_from(req)->tag_value.len);
		return -1;
	}

	dlg = build_new_dlg( &s /*callid*/, &(get_from(req)->uri) /*from uri*/,
		&(get_to(req)->uri) /*to uri*/,
		&(get_from(req)->tag_value)/*from_tag*/ );
	if (dlg==0) {
		LM_ERR("failed to create new dialog\n");
		return -1;
	}

	dlg->flags |= flags;

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

	/* set current dialog */
	set_current_dialog(dlg);
	last_dst_leg = DLG_FIRST_CALLEE_LEG;

	extra_ref=2; /* extra ref for the callback and current dlg hook */
	if (dlg_db_mode == DB_MODE_DELAYED)
		extra_ref++; /* extra ref for the timer to delete the dialog */
	link_dlg( dlg , extra_ref);

	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 ( d_tmb.register_tmcb( req, t,
				TMCB_RESPONSE_PRE_OUT|TMCB_RESPONSE_FWDED|TMCB_TRANS_CANCELLED,
				dlg_onreply, (void*)dlg, unreference_dialog_create)<0 ) {
		LM_ERR("failed to register TMCB\n");
		goto error;
	}

	/* complete the dialog setup only if transaction aleady exists;
	   if not, wait for the TMCB_REQUEST_IN callback to do this job */
	if (t) {
		/* first INVITE seen (dialog created, unconfirmed) */
		run_create_callbacks( dlg, req);
		LM_DBG("t hash_index = %u, t label = %u\n",t->hash_index,t->label);
		dlg->initial_t_hash_index = t->hash_index;
		dlg->initial_t_label = t->label;
		dlg->lifetime = get_dlg_timeout(req);

		t->dialog_ctx = (void*) dlg;
		dlg->flags |= DLG_FLAG_ISINIT;
	}

	if_update_stat( dlg_enable_stats, processed_dlgs, 1);

	return 0;
error:
	unref_dlg(dlg,2);
	dialog_cleanup( req, NULL);
	if_update_stat(dlg_enable_stats, failed_dlgs, 1);
	return -1;
}