Пример #1
0
int dlg_cseq_msg_sent(void *data)
{
	sip_msg_t msg;
	str *obuf;
	unsigned int direction;
	dlg_cell_t *dlg = NULL;
	str nval = STR_NULL;
	char tbuf[BUF_SIZE];
	int tbuf_len = 0;
	struct via_body *via;
	hdr_field_t *hfk = NULL;

	obuf = (str*)data;
	memset(&msg, 0, sizeof(sip_msg_t));
	msg.buf = obuf->s;
	msg.len = obuf->len;

	if(dlg_cseq_prepare_msg(&msg)!=0) {
		goto done;
	}

	if(msg.first_line.type==SIP_REPLY) {
		/* nothing to do for outgoing replies */
		goto done;
	}

	LM_DBG("traking cseq updates\n");
	via = (struct via_body*)msg.h_via1->parsed;

	if(via->branch==NULL || via->branch->value.len<=0) {
		LM_DBG("no branch parameter in top via\n");
		goto done;
	}

	direction = DLG_DIR_NONE;
	dlg = dlg_lookup_msg_dialog(&msg, &direction);

	if(dlg == NULL) {
		LM_DBG("no dialog for this request\n");
		goto done;
	}

	/* supported only for downstrem direction */
	if(direction != DLG_DIR_DOWNSTREAM) {
		LM_DBG("request not going downstream (%u)\n", direction);
		goto done;
	}

	/* check if transaction is marked for a new increment */
	if(get_cseq(&msg)->method_id!=METHOD_ACK) {
		parse_headers(&msg, HDR_EOH_F, 0);
		hfk = sr_hdr_get_z(&msg, "P-K-Auth-CSeq");
		if(hfk!=NULL) {
			LM_DBG("uac auth request - cseq inc needed\n");
			nval = hfk->body;
			trim(&nval);
		} else {
			LM_DBG("uac auth request - cseq inc not needed\n");
			goto done;
		}
	}

	if(nval.len<=0) {
		goto done;
	}

	if(msg.len + 3 + 2*nval.len>=BUF_SIZE) {
		LM_ERR("new messages is too big\n");
		goto done;
	}
	LM_DBG("updating cseq to: %.*s\n", nval.len, nval.s);

	/* new cseq value */
	dlg->iflags |= DLG_IFLAG_CSEQ_DIFF;

	if(via->branch->value.s<get_cseq(&msg)->number.s) {
		/* Via is before CSeq */
		/* copy first part till after via branch */
		tbuf_len = via->branch->value.s + via->branch->value.len - msg.buf;
		memcpy(tbuf, msg.buf, tbuf_len);
		/* complete via branch */
		tbuf[tbuf_len++] = '.';
		tbuf[tbuf_len++] = 'c';
		tbuf[tbuf_len++] = 's';
		memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s, get_cseq(&msg)->number.len);
		tbuf_len += get_cseq(&msg)->number.len;
		/* copy till beginning of cseq number */
		memcpy(tbuf+tbuf_len, via->branch->value.s + via->branch->value.len,
				get_cseq(&msg)->number.s - via->branch->value.s
				- via->branch->value.len);
		tbuf_len += get_cseq(&msg)->number.s - via->branch->value.s
					- via->branch->value.len;
		/* add new value */
		memcpy(tbuf+tbuf_len, nval.s, nval.len);
		tbuf_len += nval.len;
		if(hfk && hfk->name.s > get_cseq(&msg)->number.s) {
			/* copy from after cseq number to the beginning of hfk */
			memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s+get_cseq(&msg)->number.len,
					hfk->name.s - get_cseq(&msg)->number.s
					- get_cseq(&msg)->number.len);
			tbuf_len += hfk->name.s - get_cseq(&msg)->number.s
					- get_cseq(&msg)->number.len;
			/* copy from after hfk to the end of sip message */
			memcpy(tbuf+tbuf_len,  hfk->name.s + hfk->len,
					msg.buf + msg.len - hfk->name.s - hfk->len);
			tbuf_len += msg.buf + msg.len - hfk->name.s - hfk->len;
		} else {
			/* copy from after cseq number to the end of sip message */
			memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s+get_cseq(&msg)->number.len,
					msg.buf + msg.len - get_cseq(&msg)->number.s
					- get_cseq(&msg)->number.len);
			tbuf_len += msg.buf+msg.len - get_cseq(&msg)->number.s
					- get_cseq(&msg)->number.len;
		}
	} else {
		/* CSeq is before Via */
		/* copy till beginning of cseq number */
		tbuf_len = get_cseq(&msg)->number.s - msg.buf;
		memcpy(tbuf, msg.buf, tbuf_len);
		/* add new value */
		memcpy(tbuf+tbuf_len, nval.s, nval.len);
		tbuf_len += nval.len;
		/* copy from after cseq number to the after via branch */
		memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s+get_cseq(&msg)->number.len,
				via->branch->value.s + via->branch->value.len
				- get_cseq(&msg)->number.s - get_cseq(&msg)->number.len);
		tbuf_len += via->branch->value.s + via->branch->value.len
				- get_cseq(&msg)->number.s - get_cseq(&msg)->number.len;
		/* complete via branch */
		tbuf[tbuf_len++] = '.';
		tbuf[tbuf_len++] = 'c';
		tbuf[tbuf_len++] = 's';
		memcpy(tbuf+tbuf_len, get_cseq(&msg)->number.s, get_cseq(&msg)->number.len);
		tbuf_len += get_cseq(&msg)->number.len;
		if(hfk && hfk->name.s > get_cseq(&msg)->number.s) {
			/* copy from after via to the beginning of hfk */
			memcpy(tbuf+tbuf_len, via->branch->value.s + via->branch->value.len,
					hfk->name.s - via->branch->value.s
					- via->branch->value.len);
			tbuf_len += hfk->name.s - via->branch->value.s
					- via->branch->value.len;
			/* copy from after hfk to the end of sip message */
			memcpy(tbuf+tbuf_len,  hfk->name.s + hfk->len,
					msg.buf + msg.len - hfk->name.s - hfk->len);
			tbuf_len += msg.buf + msg.len - hfk->name.s - hfk->len;
		} else {
			/* copy from after via to the end of sip message */
			memcpy(tbuf+tbuf_len, via->branch->value.s + via->branch->value.len,
					msg.buf + msg.len - via->branch->value.s
					- via->branch->value.len);
			tbuf_len += msg.buf+msg.len - via->branch->value.s
					- via->branch->value.len;
		}
	}
	/* replace old msg content */
	obuf->s = pkg_malloc((tbuf_len+1)*sizeof(char));
	if(obuf->s==NULL) {
		LM_ERR("not enough memory for new message\n");
		goto done;
	}
	memcpy(obuf->s, tbuf, tbuf_len);
	obuf->s[tbuf_len] = 0;
	obuf->len = tbuf_len;

done:
	if(dlg!=NULL) dlg_release(dlg);
	free_sip_msg(&msg);
	return 0;
}
Пример #2
0
/*!
 *
 */
dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
{
	return dlg_lookup_msg_dialog(msg, NULL);
}
Пример #3
0
int dlg_cseq_update(sip_msg_t *msg)
{
	dlg_cell_t *dlg = NULL;
	unsigned int direction;
	unsigned int ninc = 0;
	unsigned int vinc = 0;
	str nval;
	str *pval;

	if(dlg_cseq_prepare_msg(msg)!=0) {
		goto error;
	}
	if(msg->first_line.type==SIP_REPLY) {
		/* nothing to do for outgoing replies */
		goto done;
	}

	LM_DBG("initiating cseq updates\n");

	direction = DLG_DIR_NONE;
	dlg = dlg_lookup_msg_dialog(msg, &direction);

	if(dlg == NULL) {
		LM_DBG("no dialog for this request\n");
		goto done;
	}

	/* supported only for downstrem direction */
	if(direction != DLG_DIR_DOWNSTREAM) {
		LM_DBG("request not going downstream (%u)\n", direction);
		goto done;
	}

	ninc = 1;

	/* take the increment value from dialog */
	if((dlg->iflags&DLG_IFLAG_CSEQ_DIFF)==DLG_IFLAG_CSEQ_DIFF) {
		/* get dialog variable holding cseq diff */
		pval = get_dlg_variable(dlg, &_dlg_cseq_diff_var_name);
		if(pval==NULL || pval->s==NULL || pval->len<=0) {
			LM_DBG("dialog marked with cseq diff but no variable set yet\n");
			goto done;
		}
		if(str2int(pval, &vinc)<0) {
			LM_ERR("invalid dlg cseq diff var value: %.*s\n",
					pval->len, pval->s);
			goto done;
		}
	}
	vinc += ninc;
	if(vinc==0) {
		LM_DBG("nothing to increment\n");
		goto done;
	}
	nval.s = int2str(vinc, &nval.len);
	if(set_dlg_variable(dlg, &_dlg_cseq_diff_var_name, &nval) <0) {
		LM_ERR("failed to set the dlg cseq diff var\n");
		goto done;
	}
	str2int(&get_cseq(msg)->number, &ninc);
	vinc += ninc;
	nval.s = int2str(vinc, &nval.len);
	trim(&nval);

	LM_DBG("adding auth cseq header value: %.*s\n", nval.len, nval.s);
	parse_headers(msg, HDR_EOH_F, 0);
	sr_hdr_add_zs(msg, "P-K-Auth-CSeq", &nval);

done:
	if(dlg!=NULL) dlg_release(dlg);
	return 0;

error:
	if(dlg!=NULL) dlg_release(dlg);
	return -1;
}