Exemple #1
0
int send_leg_msg(struct dlg_cell *dlg,str *method,int src_leg,int dst_leg,
		str *hdrs,str *body,dlg_request_callback func,void *param,dlg_release_func release)
{
	context_p old_ctx;
	dlg_t* dialog_info;
	int result;
	unsigned int method_type;

	if (parse_method(method->s,method->s+method->len,&method_type) == 0)
	{
		LM_ERR("Failed to parse method - [%.*s]\n",method->len,method->s);
		return -1;
	}

	if (method_type == METHOD_INVITE && (body == NULL || body->s == NULL ||
				body->len == 0))
	{
		LM_ERR("Cannot send INVITE without SDP body\n");
		return -1;
	}

	if ((dialog_info = build_dialog_info(dlg, dst_leg, src_leg)) == 0)
	{
		LM_ERR("failed to create dlg_t\n");
		return -1;
	}

	LM_DBG("sending [%.*s] to %s (%d)\n",method->len,method->s,
		(dst_leg==DLG_CALLER_LEG)?"caller":"callee", dst_leg);

	/* set new processing context */
	if (push_new_processing_context( dlg, &old_ctx, NULL)!=0)
		return -1;

	dialog_info->T_flags=T_NO_AUTOACK_FLAG;

	result = d_tmb.t_request_within
		(method,         /* method*/
		hdrs,		    /* extra headers*/
		body,          /* body*/
		dialog_info,   /* dialog structure*/
		func,  /* callback function*/
		param,   /* callback parameter*/
		release);         /* release function*/

	/* reset the processing contect */
	current_processing_ctx = old_ctx;

	if(result < 0)
	{
		LM_ERR("failed to send the in-dialog request\n");
		free_tm_dlg(dialog_info);
		return -1;
	}

	free_tm_dlg(dialog_info);
	return 0;
}
Exemple #2
0
/* send keep-alive
 * dlg - pointer to a struct dlg_cell
 * dir - direction: the request will be sent to:
 * 		DLG_CALLER_LEG (0): caller
 * 		DLG_CALLEE_LEG (1): callee
 */
int dlg_send_ka(dlg_cell_t *dlg, int dir, str *hdrs)
{
	uac_req_t uac_r;
	dlg_t* di;
	str met = {"OPTIONS", 7};
	int result;
	dlg_iuid_t *iuid = NULL;

	/* do not send KA request for non-confirmed dialogs (not supported) */
	if (dlg->state != DLG_STATE_CONFIRMED) {
		LM_DBG("skipping non-confirmed dialogs\n");
		return 0;
	}

	/* build tm dlg by direction */
	if ((di = build_dlg_t(dlg, dir)) == 0){
		LM_ERR("failed to create dlg_t\n");
		goto err;
	}

	/* tm increases cseq value, decrease it no to make it invalid
	 * - dialog is ended on timeout (408) or C/L does not exist (481) */
	if(di->loc_seq.value>1)
		di->loc_seq.value -= 2;
	else
		di->loc_seq.value -= 1;

	LM_DBG("sending BYE to %s\n", (dir==DLG_CALLER_LEG)?"caller":"callee");

	iuid = dlg_get_iuid_shm_clone(dlg);
	if(iuid==NULL)
	{
		LM_ERR("failed to create dialog unique id clone\n");
		goto err;
	}

	memset(&uac_r,'\0', sizeof(uac_req_t));
	set_uac_req(&uac_r, &met, hdrs, NULL, di, TMCB_LOCAL_COMPLETED,
				dlg_ka_cb, (void*)iuid);
	result = d_tmb.t_request_within(&uac_r);

	if(result < 0){
		LM_ERR("failed to send the BYE request\n");
		goto err;
	}

	free_tm_dlg(di);

	LM_DBG("keep-alive sent to %s\n", (dir==0)?"caller":"callee");
	return 0;

err:
	if(di)
		free_tm_dlg(di);
	return -1;
}
Exemple #3
0
static int dlg_refer_callee(dlg_transfer_ctx_t *dtc)
{
	/*verify direction*/
	dlg_t* dialog_info = NULL;
	str met = {"REFER", 5};
	int result;
	str hdrs;
	struct dlg_cell *dlg;
	uac_req_t uac_r;

	dlg = dtc->dlg;

	if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){
		LM_ERR("failed to create dlg_t\n");
		goto error;
	}

	hdrs.len = 23 + 2*CRLF_LEN + dlg_bridge_controller.len
		+ dtc->to.len + dlg_bridge_ref_hdrs.len;
	LM_DBG("sending REFER [%d] <%.*s>\n", hdrs.len, dtc->to.len, dtc->to.s);
	hdrs.s = (char*)pkg_malloc(hdrs.len*sizeof(char));
	if(hdrs.s == NULL)
		goto error;
	memcpy(hdrs.s, "Referred-By: ", 13);
	memcpy(hdrs.s+13, dlg_bridge_controller.s, dlg_bridge_controller.len);
	memcpy(hdrs.s+13+dlg_bridge_controller.len, CRLF, CRLF_LEN);
	memcpy(hdrs.s+13+dlg_bridge_controller.len+CRLF_LEN, "Refer-To: ", 10);
	memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN, dtc->to.s,
			dtc->to.len);
	memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN+dtc->to.len,
			CRLF, CRLF_LEN);
	memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN+dtc->to.len+CRLF_LEN,
			dlg_bridge_ref_hdrs.s, dlg_bridge_ref_hdrs.len);

	set_uac_req(&uac_r, &met, &hdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED,
				dlg_refer_tm_callback, (void*)dtc);
	result = d_tmb.t_request_within(&uac_r);

	pkg_free(hdrs.s);
	if(result < 0) {
		LM_ERR("failed to send the REFER request\n");
		/* todo: clean-up dtc */
		goto error;
	}

	free_tm_dlg(dialog_info);

	LM_DBG("REFER sent\n");
	return 0;

error:
	if(dialog_info)
		free_tm_dlg(dialog_info);
	return -1;
}
Exemple #4
0
void dlg_refer_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
{
	dlg_transfer_ctx_t *dtc = NULL;
	dlg_t* dialog_info = NULL;
	str met = {"BYE", 3};
	int result;
	struct dlg_cell *dlg;
	uac_req_t uac_r;

	if(ps->param==NULL || *ps->param==0)
	{
		LM_DBG("message id not received\n");
		return;
	}
	dtc = *((dlg_transfer_ctx_t**)ps->param);
	if(dtc==NULL)
		return;
	LM_DBG("REFER completed with status %d\n", ps->code);

	/* we send the BYE anyhow */
	dlg = dtc->dlg;
	if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){
		LM_ERR("failed to create dlg_t\n");
		goto error;
	}

	/* after REFER, the CSeq must be increased */
	dialog_info->loc_seq.value++;

	set_uac_req(&uac_r, &met, NULL, NULL, dialog_info, 0, NULL, NULL);
	result = d_tmb.t_request_within(&uac_r);

	if(result < 0) {
		LM_ERR("failed to send the REFER request\n");
		/* todo: clean-up dtc */
		goto error;
	}

	free_tm_dlg(dialog_info);
	dlg_transfer_ctx_free(dtc);

	LM_DBG("BYE sent\n");
	return;

error:
	dlg_transfer_ctx_free(dtc);
	if(dialog_info)
		free_tm_dlg(dialog_info);
	return;

}
Exemple #5
0
/* cell- pointer to a struct dlg_cell
 * dir- direction: the request will be sent to:
 * 		DLG_CALLER_LEG (0): caller
 * 		DLG_CALLEE_LEG (1): callee
 */
static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs)
{
	uac_req_t uac_r;
	dlg_t* dialog_info;
	str met = {"BYE", 3};
	int result;
	dlg_iuid_t *iuid = NULL;

	/* do not send BYE request for non-confirmed dialogs (not supported) */
	if (cell->state != DLG_STATE_CONFIRMED_NA && cell->state != DLG_STATE_CONFIRMED) {
		LM_ERR("terminating non-confirmed dialogs not supported\n");
		return -1;
	}

	/*verify direction*/

	if ((dialog_info = build_dlg_t(cell, dir)) == 0){
		LM_ERR("failed to create dlg_t\n");
		goto err;
	}

	LM_DBG("sending BYE to %s\n", (dir==DLG_CALLER_LEG)?"caller":"callee");

	iuid = dlg_get_iuid_shm_clone(cell);
	if(iuid==NULL)
	{
		LM_ERR("failed to create dialog unique id clone\n");
		goto err;
	}

	memset(&uac_r,'\0', sizeof(uac_req_t));
	set_uac_req(&uac_r, &met, hdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED,
				bye_reply_cb, (void*)iuid);
	result = d_tmb.t_request_within(&uac_r);

	if(result < 0){
		LM_ERR("failed to send the BYE request\n");
		goto err;
	}

	free_tm_dlg(dialog_info);

	LM_DBG("BYE sent to %s\n", (dir==0)?"caller":"callee");
	return 0;

err:
	if(dialog_info)
		free_tm_dlg(dialog_info);
	return -1;
}
Exemple #6
0
dlg_t * build_dlg_t(struct dlg_cell * cell, int dir){

	dlg_t* td = NULL;
	str cseq;
	unsigned int loc_seq;

	td = (dlg_t*)pkg_malloc(sizeof(dlg_t));
	if(!td){
	
		LM_ERR("out of pkg memory\n");
		return NULL;
	}
	memset(td, 0, sizeof(dlg_t));

	/*local sequence number*/
	cseq = (dir == DLG_CALLER_LEG) ?	cell->cseq[DLG_CALLEE_LEG]:
										cell->cseq[DLG_CALLER_LEG];
	if(str2int(&cseq, &loc_seq) != 0){
		LM_ERR("invalid cseq\n");
		goto error;
	}
	/*we don not increase here the cseq as this will be done by TM*/
	td->loc_seq.value = loc_seq;
	td->loc_seq.is_set = 1;

	/*route set*/
	if( cell->route_set[dir].s && cell->route_set[dir].len){
		
		if( parse_rr_body(cell->route_set[dir].s, cell->route_set[dir].len, 
						&td->route_set) !=0){
		 	LM_ERR("failed to parse route set\n");
			goto error;
		}
	} 

	/*remote target--- Request URI*/
	if(cell->contact[dir].s==0 || cell->contact[dir].len==0){

		LM_ERR("no contact available\n");
		goto error;
	}
	td->rem_target = cell->contact[dir];

	td->rem_uri	=   (dir == DLG_CALLER_LEG)?	cell->from_uri: cell->to_uri;
	td->loc_uri	=	(dir == DLG_CALLER_LEG)?	cell->to_uri: cell->from_uri;
	td->id.call_id = cell->callid;
	td->id.rem_tag = cell->tag[dir];
	td->id.loc_tag = (dir == DLG_CALLER_LEG) ? 	cell->tag[DLG_CALLEE_LEG]:
												cell->tag[DLG_CALLER_LEG];
	
	td->state= DLG_CONFIRMED;
	td->send_sock = cell->bind_addr[dir];

	return td;

error:
	free_tm_dlg(td);
	return NULL;
}
Exemple #7
0
/* cell- pointer to a struct dlg_cell
 * leg - a dialog leg to be BYE'ed :
 *     = 0: caller leg
 *     > 0: callee legs
 */
static inline int send_leg_bye(struct dlg_cell *cell, int dst_leg, int src_leg,
														str *extra_hdrs)
{
	context_p old_ctx;
	context_p *new_ctx;
	dlg_t* dialog_info;
	str met = {"BYE", 3};
	int result;

	if ((dialog_info = build_dlg_t(cell, dst_leg, src_leg)) == 0){
		LM_ERR("failed to create dlg_t\n");
		goto err;
	}

	LM_DBG("sending BYE to %s (%d)\n",
		(dst_leg==DLG_CALLER_LEG)?"caller":"callee", dst_leg);

	/* set new processing context */
	if (push_new_processing_context( cell, &old_ctx, &new_ctx, NULL)!=0)
		goto err;

	ctx_lastdstleg_set(dst_leg);

	ref_dlg(cell, 1);

	result = d_tmb.t_request_within
		(&met,         /* method*/
		extra_hdrs,    /* extra headers*/
		NULL,          /* body*/
		dialog_info,   /* dialog structure*/
		bye_reply_cb,  /* callback function*/
		(void*)cell,   /* callback parameter*/
		NULL);         /* release function*/

	/* reset the processing contect */
	if (current_processing_ctx == NULL)
		*new_ctx = NULL;
	else
		context_destroy(CONTEXT_GLOBAL, *new_ctx);
	current_processing_ctx = old_ctx;

	if(result < 0){
		LM_ERR("failed to send the BYE request\n");
		goto err1;
	}

	free_tm_dlg(dialog_info);

	LM_DBG("BYE sent to %s\n", (dst_leg==DLG_CALLER_LEG)?"caller":"callee");
	return 0;

err1:
	unref_dlg(cell, 1);
err:
	return -1;
}
Exemple #8
0
/* cell- pointer to a struct dlg_cell
 * leg - a dialog leg to be BYE'ed :
 *     = 0: caller leg
 *     > 0: callee legs
 */
static inline int send_leg_bye(struct dlg_cell *cell, int dst_leg, int src_leg,
														str *extra_hdrs)
{
	dlg_t* dialog_info;
	struct dlg_cell *old_cell;
	str met = {"BYE", 3};
	int result;

	if ((dialog_info = build_dlg_t(cell, dst_leg, src_leg)) == 0){
		LM_ERR("failed to create dlg_t\n");
		goto err;
	}

	LM_DBG("sending BYE to %s (%d)\n",
		(dst_leg==DLG_CALLER_LEG)?"caller":"callee", dst_leg);

	ref_dlg(cell, 1);

	old_cell = current_dlg_pointer;
	current_dlg_pointer = cell;

	result = d_tmb.t_request_within
		(&met,         /* method*/
		extra_hdrs,    /* extra headers*/
		NULL,          /* body*/
		dialog_info,   /* dialog structure*/
		bye_reply_cb,  /* callback function*/
		(void*)cell,   /* callback parameter*/
		NULL);         /* release function*/

	current_dlg_pointer = old_cell;

	if(result < 0){
		LM_ERR("failed to send the BYE request\n");
		goto err1;
	}

	free_tm_dlg(dialog_info);

	LM_DBG("BYE sent to %s\n", (dst_leg==DLG_CALLER_LEG)?"caller":"callee");
	return 0;

err1:
	unref_dlg(cell, 1);
err:
	return -1;
}
Exemple #9
0
dlg_t * build_dlg_t(struct dlg_cell * cell, int dir) {

    dlg_t* td = NULL;
    str cseq;
    unsigned int loc_seq;
    str route_set;
    str contact;

    struct dlg_cell_out *dlg_out = 0;
    struct dlg_entry_out* dlg_entry_out = 0;

    /* if trying to send by to callee we need to get the corresponding dlg_out cell */
    lock_get(cell->dlg_out_entries_lock);
    dlg_entry_out = &cell->dlg_entry_out;

    dlg_out = dlg_entry_out->first;
    //must be concurrent call - lets choose - TODO - ie. check if there is more

    if (!dlg_out) {
        LM_ERR("Trying to send BYE for dialog with no callee leg\n");
        lock_release(cell->dlg_out_entries_lock);
        return NULL;
    }

    td = (dlg_t*) pkg_malloc(sizeof (dlg_t));
    if (!td) {

        LM_ERR("out of pkg memory\n");
        lock_release(cell->dlg_out_entries_lock);
        return NULL;
    }
    memset(td, 0, sizeof (dlg_t));

    if (dir == DLG_CALLER_LEG) {
        cseq = dlg_out->callee_cseq;
        route_set = cell->caller_route_set;
        contact = cell->caller_contact;
        td->rem_uri = cell->from_uri;
        td->loc_uri = dlg_out->to_uri;
        td->id.rem_tag = cell->from_tag;
        td->id.loc_tag = dlg_out->to_tag;
        td->send_sock = cell->caller_bind_addr;
    } else {
        cseq = dlg_out->caller_cseq;
        route_set = dlg_out->callee_route_set;
        contact = dlg_out->callee_contact;
        td->rem_uri = dlg_out->to_uri;
        td->loc_uri = cell->from_uri;
        td->id.rem_tag = dlg_out->to_tag;
        td->id.loc_tag = cell->from_tag;
        td->send_sock = dlg_out->callee_bind_addr;
    }

    if (str2int(&cseq, &loc_seq) != 0) {
        LM_ERR("invalid cseq\n");
        goto error;
    }

    /*we don not increase here the cseq as this will be done by TM*/
    td->loc_seq.value = loc_seq;
    td->loc_seq.is_set = 1;

    LM_DBG("CSeq is '%.*s' (%i)\n", cseq.len, cseq.s, loc_seq);

    /*route set*/
    if (route_set.s && route_set.len) {

        if (parse_rr_body(route_set.s, route_set.len, &td->route_set) != 0) {
            LM_ERR("failed to parse route set\n");
            goto error;
        }
    }

    if (contact.s == 0 || contact.len == 0) {

        LM_ERR("no contact available\n");
        goto error;
    }

    td->id.call_id = cell->callid;
    td->rem_target = contact;
    td->state = DLG_CONFIRMED;

    lock_release(cell->dlg_out_entries_lock);
    return td;

error:
    lock_release(cell->dlg_out_entries_lock);
    free_tm_dlg(td);
    return NULL;
}
Exemple #10
0
dlg_t * build_dlg_t(struct dlg_cell * cell, int dst_leg, int src_leg)
{
	dlg_t* td = NULL;
	str cseq;
	unsigned int loc_seq;

	td = (dlg_t*)pkg_malloc(sizeof(dlg_t));
	if(!td){
		LM_ERR("out of pkg memory\n");
		return NULL;
	}
	memset(td, 0, sizeof(dlg_t));

	if ((dst_leg == DLG_CALLER_LEG && (cell->flags & DLG_FLAG_PING_CALLER)) ||
		(dst_leg == callee_idx(cell) && (cell->flags & DLG_FLAG_PING_CALLEE)))
	{
		dlg_lock_dlg(cell);
		if (cell->legs[dst_leg].last_gen_cseq == 0)
		{
			/* no OPTIONS pings for this dlg yet */
			dlg_unlock_dlg(cell);
			goto before_strcseq;
		}
		else
		{
			/* OPTIONS pings sent, use new cseq */
			td->loc_seq.value = ++(cell->legs[dst_leg].last_gen_cseq);
			td->loc_seq.is_set=1;
			dlg_unlock_dlg(cell);
			goto after_strcseq;
		}
	}
before_strcseq:
	/*local sequence number*/
	cseq = cell->legs[dst_leg].r_cseq;
	if( !cseq.s || !cseq.len || str2int(&cseq, &loc_seq) != 0){
		LM_ERR("invalid cseq\n");
		goto error;
	}
	/*we don not increase here the cseq as this will be done by TM*/
	td->loc_seq.value = loc_seq;
	td->loc_seq.is_set = 1;

after_strcseq:

	/*route set*/
	if( cell->legs[dst_leg].route_set.s && cell->legs[dst_leg].route_set.len){
		if( parse_rr_body(cell->legs[dst_leg].route_set.s,
			cell->legs[dst_leg].route_set.len, &td->route_set) !=0){
		 	LM_ERR("failed to parse route set\n");
			goto error;
		}
	} 

	/*remote target--- Request URI*/
	if (cell->legs[dst_leg].contact.s==0 || cell->legs[dst_leg].contact.len==0){
		LM_ERR("no contact available\n");
		goto error;
	}
	td->rem_target = cell->legs[dst_leg].contact;

	td->rem_uri = (dst_leg==DLG_CALLER_LEG)? *dlg_leg_from_uri(cell,dst_leg): 
					 *dlg_leg_to_uri(cell,dst_leg);
	td->loc_uri = (dst_leg==DLG_CALLER_LEG)? *dlg_leg_to_uri(cell,dst_leg):
					 *dlg_leg_from_uri(cell,dst_leg);
	td->id.call_id = cell->callid;
	td->id.rem_tag = cell->legs[dst_leg].tag;
	td->id.loc_tag = cell->legs[src_leg].tag;

	td->state= DLG_CONFIRMED;
	td->send_sock = cell->legs[dst_leg].bind_addr;

	return td;

error:
	free_tm_dlg(td);
	return NULL;
}
Exemple #11
0
dlg_t * build_dialog_info(struct dlg_cell * cell, int dst_leg, int src_leg)
{
	dlg_t* td = NULL;
	str cseq;
	unsigned int loc_seq;

	td = (dlg_t*)pkg_malloc(sizeof(dlg_t));
	if(!td){
		LM_ERR("out of pkg memory\n");
		return NULL;
	}
	memset(td, 0, sizeof(dlg_t));

	/*local sequence number*/
	cseq = cell->legs[dst_leg].r_cseq;
	if( !cseq.s || !cseq.len || str2int(&cseq, &loc_seq) != 0){
		LM_ERR("invalid cseq\n");
		goto error;
	}

	if (cell->legs[dst_leg].last_gen_cseq == 0)
		cell->legs[dst_leg].last_gen_cseq = loc_seq+1;
	else
		cell->legs[dst_leg].last_gen_cseq++;

	cell->legs[dst_leg].reply_received = 0;

	td->loc_seq.value = cell->legs[dst_leg].last_gen_cseq -1;

	td->loc_seq.is_set = 1;

	/*route set*/
	if( cell->legs[dst_leg].route_set.s && cell->legs[dst_leg].route_set.len){
		if( parse_rr_body(cell->legs[dst_leg].route_set.s,
			cell->legs[dst_leg].route_set.len, &td->route_set) !=0){
		 	LM_ERR("failed to parse route set\n");
			goto error;
		}
	} 

	/*remote target--- Request URI*/
	if (cell->legs[dst_leg].contact.s==0 || cell->legs[dst_leg].contact.len==0){
		LM_ERR("no contact available\n");
		goto error;
	}
	td->rem_target = cell->legs[dst_leg].contact;

	td->rem_uri = (dst_leg==DLG_CALLER_LEG)? *dlg_leg_from_uri(cell,dst_leg): 
					 *dlg_leg_to_uri(cell,dst_leg);
	td->loc_uri = (dst_leg==DLG_CALLER_LEG)? *dlg_leg_to_uri(cell,dst_leg):
					 *dlg_leg_from_uri(cell,dst_leg);
	td->id.call_id = cell->callid;
	td->id.rem_tag = cell->legs[dst_leg].tag;
	td->id.loc_tag = cell->legs[src_leg].tag;

	td->state= DLG_CONFIRMED;
	td->send_sock = cell->legs[dst_leg].bind_addr;

	return td;

error:
	free_tm_dlg(td);
	return NULL;
}