示例#1
0
static inline struct hdr_field* extract_parsed_hdrs( char *buf, int len)
{
	char *p;
	static struct sip_msg msg;
	struct hdr_field  *hdr;

	/* skip the first line - not interesting */
	p = eat_line( buf, len);
	if (p>=buf+len)
		return 0;

	memset( &msg, 0, sizeof(struct sip_msg) );
	msg.buf = buf;
	msg.len = len;
	msg.unparsed = p;

	/* as we need all Route headers, we need to parse all headers */
	if (parse_headers( &msg, HDR_EOH_F, 0)==-1)
		goto error;

	hdr = msg.headers;
	msg.headers = 0;

	free_sip_msg( &msg );
	return hdr;
error:
	free_sip_msg( &msg );
	return 0;
}
示例#2
0
struct sip_msg* get_request_from_tx(struct cell *t) {
    if (t == NULL) {
        t = tmb.t_gett();
    }
    if (!t || t == (void*) - 1) {
        LM_ERR("Reply without transaction\n");
        return 0;
    }
    if (t) {

        /*  we may need the request message from here on.. if there are headers we need that were not parsed in the original request
        (which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to
        make a private copy of the message and free it when we are done
         */
        if (_pv_treq.label != t->label || _pv_treq.index != t->hash_index) {
            /* make a copy */
            if (_pv_treq.buf == NULL || _pv_treq.buf_size < t->uas.request->len + 1) {
                if (_pv_treq.buf != NULL)
                    pkg_free(_pv_treq.buf);
                if (_pv_treq.tmsgp)
                    free_sip_msg(&_pv_treq.msg);
                _pv_treq.tmsgp = NULL;
                _pv_treq.index = 0;
                _pv_treq.label = 0;
                _pv_treq.buf_size = t->uas.request->len + 1;
                _pv_treq.buf = (char*) pkg_malloc(_pv_treq.buf_size * sizeof (char));
                if (_pv_treq.buf == NULL) {
                    LM_ERR("no more pkg\n");
                    _pv_treq.buf_size = 0;
                    return 0;
                }
            }
            if (_pv_treq.tmsgp)
                free_sip_msg(&_pv_treq.msg);
            memset(&_pv_treq.msg, 0, sizeof (struct sip_msg));
            memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len);
            _pv_treq.buf[t->uas.request->len] = '\0';
            _pv_treq.msg.len = t->uas.request->len;
            _pv_treq.msg.buf = _pv_treq.buf;
            _pv_treq.tmsgp = t->uas.request;
            _pv_treq.index = t->hash_index;
            _pv_treq.label = t->label;


            if (pv_t_copy_msg(t->uas.request, &_pv_treq.msg) != 0) {
                pkg_free(_pv_treq.buf);
                _pv_treq.buf_size = 0;
                _pv_treq.buf = NULL;
                _pv_treq.tmsgp = NULL;
                _pv_treq.index = 0;
                _pv_treq.label = 0;
                return 0;
            }
        }

        return &_pv_treq.msg;
    } else
        return 0;

}
示例#3
0
int dlg_th_pre_raw(str *data)
{
	struct sip_msg msg;

	memset(&msg,0,sizeof(struct sip_msg));
	msg.buf=data->s;
	msg.len=data->len;
	if (dlg_th_callid_pre_parse(&msg,0) < 0)
		goto done;

	if (msg.first_line.type==SIP_REQUEST) {
		if (get_to(&msg)->tag_value.len>0) {
			/* sequential request, check if callid needs to be unmasked */
			if (dlg_th_needs_decoding(&msg)) {
				if (dlg_th_decode_callid(&msg) < 0) {
					LM_ERR("Failed to decode callid for sequential request\n");
					goto error;
				}
				goto rebuild_msg;
			}	
		} else {
			/* initial request, don't do anything
			callid masking will be done on the out side */
		}
	} else if (msg.first_line.type==SIP_REPLY) {
		/* we might need to decode callid if mangled */
		if (dlg_th_needs_decoding(&msg)) {
			if (dlg_th_decode_callid(&msg) < 0) {
				LM_ERR("Failed to decode callid for reply\n");
				goto error;
			}
			goto rebuild_rpl;
		} else {
			/* encoding will be done on the out side */
		}	
	} else {
		/* non sip, most likely, let it through */
		return 0;
	}

done:
	free_sip_msg(&msg);
	return 0;

rebuild_msg:
	data->s = dlg_th_rebuild_req(&msg,&data->len);
	free_sip_msg(&msg);
	return 0;

rebuild_rpl:
	data->s = dlg_th_rebuild_rpl(&msg,&data->len);
	free_sip_msg(&msg);
	return 0;
error:
	free_sip_msg(&msg);
	return -1;
}
示例#4
0
static inline struct sip_msg* buf_to_sip_msg(char *buf, unsigned int len,
															dlg_t *dialog)
{
	static struct sip_msg req;

	memset( &req, 0, sizeof(req) );
	req.id = get_next_msg_no();
	req.buf = buf;
	req.len = len;
	if (parse_msg(buf, len, &req)!=0) {
		LM_CRIT("BUG - buffer parsing failed!");
		return NULL;
	}
	/* populate some special fields in sip_msg */
	req.set_global_address=default_global_address;
	req.set_global_port=default_global_port;
	req.force_send_socket = dialog->send_sock; 
	if (set_dst_uri(&req, dialog->hooks.next_hop)) {
		LM_ERR("failed to set dst_uri");
		free_sip_msg(&req);
		return NULL;
	}
	req.rcv.proto = dialog->send_sock->proto;
	req.rcv.src_ip = req.rcv.dst_ip = dialog->send_sock->address;
	req.rcv.src_port = req.rcv.dst_port = dialog->send_sock->port_no;
	req.rcv.bind_address = dialog->send_sock;

	return &req;
}
示例#5
0
文件: timer.c 项目: NormB/opensips
void route_timer_f(unsigned int ticks, void* param)
{
    struct action* a = (struct action*)param;
    static struct sip_msg* req= NULL;

    if(req == NULL)
    {
        req = (struct sip_msg*)pkg_malloc(sizeof(struct sip_msg));
        if(req == NULL)
        {
            LM_ERR("No more memory\n");
            return;
        }
        memset(req, 0, sizeof(struct sip_msg));
        req->first_line.type = SIP_REQUEST;
        req->first_line.u.request.method.s= "DUMMY";
        req->first_line.u.request.method.len= 5;
        req->first_line.u.request.uri.s= "sip:[email protected]";
        req->first_line.u.request.uri.len= 19;
    }

    if(a == NULL) {
        LM_ERR("NULL action\n");
        return;
    }

    run_top_route(a, req);

    /* clean whatever extra structures were added by script functions */
    free_sip_msg(req);
    /* remove all added AVP - here we use all the time the default AVP list */
    reset_avps( );
}
示例#6
0
int gzc_msg_sent(sr_event_param_t *evp)
{
	sip_msg_t msg;
	str *obuf;
	str obody;
	str nbody;
	unsigned long olen;
	unsigned long nlen;
	int ret;

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

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

	if(gzc_skip_msg(&msg))
	{
		goto done;
	}

	obody.s = get_body(&msg);
	if (obody.s==NULL)
	{
		LM_DBG("no body for this SIP message\n");
		goto done;
	}
	obody.len = msg.buf + msg.len - obody.s;

	/* decompress the body */
	nbody.s = _gzc_local_buffer;
	nlen = BUF_SIZE;
	olen = obody.len;
	ret = compress((unsigned char*)nbody.s, &nlen,
			(unsigned char*)obody.s, olen);
	if(ret!=Z_OK)
	{
		LM_ERR("error compressing body (%d)\n", ret);
		goto done;
	}
	nbody.len = (int)nlen;
	LM_DBG("body compressed - old size: %d - new size: %d\n",
			obody.len, nbody.len);

	if(gzc_set_msg_body(&msg, &obody, &nbody)<0)
	{
		LM_ERR("error replacing body\n");
		goto done;
	}

	obuf->s = gzc_msg_update(&msg, (unsigned int*)&obuf->len);

done:
	free_sip_msg(&msg);
	return 0;
}
示例#7
0
static int xhttp_process_request(sip_msg_t* orig_msg, 
							  char* new_buf, unsigned int new_len)
{
	int ret;
	sip_msg_t tmp_msg, *msg;
	struct run_act_ctx ra_ctx;
	
	ret=0;
	if (new_buf && new_len)
	{
		memset(&tmp_msg, 0, sizeof(sip_msg_t));
		tmp_msg.buf = new_buf;
		tmp_msg.len = new_len;
		tmp_msg.rcv = orig_msg->rcv;
		tmp_msg.id = orig_msg->id;
		tmp_msg.set_global_address = orig_msg->set_global_address;
		tmp_msg.set_global_port = orig_msg->set_global_port;
		if (parse_msg(new_buf, new_len, &tmp_msg) != 0)
		{
			LM_ERR("parse_msg failed\n");
			goto error;
		}
		msg = &tmp_msg;
	} else {
		msg = orig_msg;
	}
	
	if ((msg->first_line.type != SIP_REQUEST) || (msg->via1 == 0) ||
		(msg->via1->error != PARSE_OK))
	{
		LM_CRIT("strange message: %.*s\n", msg->len, msg->buf);
		goto error;
	}
	if (exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0)
	{
		goto done;
	}

	init_run_actions_ctx(&ra_ctx);
	if (run_actions(&ra_ctx, event_rt.rlist[xhttp_route_no], msg) < 0)
	{
		ret=-1;
		LM_DBG("error while trying script\n");
		goto done;
	}

done:
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
	if (msg != orig_msg)
	{
		free_sip_msg(msg);
	}
	return ret;

error:
	return -1;
}
示例#8
0
文件: msrp_mod.c 项目: halan/kamailio
static int msrp_frame_received(void *data)
{
	tcp_event_info_t *tev;
	static msrp_frame_t mf;
	sip_msg_t *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;


	tev = (tcp_event_info_t*)data;

	if(tev==NULL || tev->buf==NULL || tev->len<=0)
	{
		LM_DBG("invalid parameters\n");
		return -1;
	}

	memset(&mf, 0, sizeof(msrp_frame_t));
	mf.buf.s = tev->buf;
	mf.buf.len = tev->len;
	mf.tcpinfo = tev;
	if(msrp_parse_frame(&mf)<0)
	{
		LM_ERR("error parsing msrp frame\n");
		return -1;
	}
	msrp_reset_env();
	msrp_set_current_frame(&mf);
	rt = route_get(&event_rt, "msrp:frame-in");
	if(rt>=0 && event_rt.rlist[rt]!=NULL) {
		LM_DBG("executing event_route[msrp:frame-in] (%d)\n", rt);
		fmsg = msrp_fake_sipmsg(&mf);
		if(fmsg!=NULL)
			fmsg->rcv = *tev->rcv;
		rtb = get_route_type();
		set_route_type(REQUEST_ROUTE);
		init_run_actions_ctx(&ctx);
		run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		if(ctx.run_flags&DROP_R_F)
		{
			LM_DBG("exit due to 'drop' in event route\n");
		}
		set_route_type(rtb);
		if(fmsg!=NULL)
			free_sip_msg(fmsg);
	}
	msrp_reset_env();
	msrp_destroy_frame(&mf);
	return 0;
}
示例#9
0
文件: corex_nio.c 项目: 2pac/kamailio
int nio_msg_received(void *data)
{
    sip_msg_t msg;
    str *obuf;
    char *nbuf = NULL;
    int_str avp_value;
    struct usr_avp *avp;
    struct run_act_ctx ra_ctx;

    obuf = (str*)data;

    if (obuf->len < nio_min_msg_len) {
        return -1;
    }

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

    nio_is_incoming = 1;
    init_run_actions_ctx(&ra_ctx);
    run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg);

    if(nio_msg_avp_name.n!=0) {
        avp = NULL;
        avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name,
            &avp_value, 0);
        if(avp!=NULL && is_avp_str_val(avp)) {
            msg.buf = avp_value.s.s;
            msg.len = avp_value.s.len;
            nbuf = nio_msg_update(&msg, (unsigned int*)&obuf->len);
            if(obuf->len>=BUF_SIZE) {
                LM_ERR("new buffer overflow (%d)\n", obuf->len);
                pkg_free(nbuf);
                return -1;
            }
            memcpy(obuf->s, nbuf, obuf->len);
            obuf->s[obuf->len] = '\0';
        } else {
            LM_WARN("no value set for AVP %.*s, using unmodified message\n",
                nio_msg_avp_param.len, nio_msg_avp_param.s);
        }
    }

    if(nbuf!=NULL)
        pkg_free(nbuf);
    free_sip_msg(&msg);
    return 0;
}
示例#10
0
int tps_msg_sent(void *data)
{
	sip_msg_t msg;
	str *obuf;
	int direction;
	int dialog;
	int local;

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

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

	if(tps_skip_msg(&msg)) {
		goto done;
	}

	if(msg.first_line.type==SIP_REQUEST) {
		direction = tps_route_direction(&msg);
		dialog = (get_to(&msg)->tag_value.len>0)?1:0;

		local = 0;
		if(msg.via2==0) {
			local = 1;
			if(direction==0) {
				/* downstream local request (e.g., dlg bye) */
				local = 2;
			}
		}

		tps_request_sent(&msg, dialog, direction, local);
	} else {
		tps_response_sent(&msg);
	}

	obuf->s = tps_msg_update(&msg, (unsigned int*)&obuf->len);

done:
	free_sip_msg(&msg);
	return 0;
}
示例#11
0
/* code not used !*/
int buffered_printer(int infd)
{
   int i,k=0,retval;
   char *missatge=0,*myerror="";
   struct sip_msg msg;
   static char mybuffer[1400];
   static int end=0,last=0;

   while((i=read(infd,&mybuffer[last],1400-last))==1400-last){
      if((end=memstr(mybuffer,last+i,"\n\n\n",3))<0){
	 last+=i;
	 return 0;
      }else{
	 end+=3;
	 while(end<1400 && (mybuffer[end]=='\n' || mybuffer[end]=='.' || mybuffer[end]=='\r'))
	    end++;
	 if((missatge=pkg_malloc(end))==0){
	    myerror="Out of memory !!\n";
	    goto error;
	 }
	 memset(missatge,0,end);
	 memcpy(missatge,mybuffer,end);
	 memset(&msg,0,sizeof(struct sip_msg));
	 msg.buf=missatge;
	 msg.len=end;
	 if(!parse_msg(msg.buf,msg.len,&msg))
	    print_msg_info(1,&msg);
	 printf("PARSED:%d,last=%d,end=%d\n",k++,last,end);
	 free_sip_msg(&msg);
	 pkg_free(missatge);
	 memmove(mybuffer,&mybuffer[end],1400-end);
	 last=1400-end;
      }
   }
   retval=0;
   goto exit;
error:
   printf("Error on %s",myerror);
   retval=1;
exit:
   if(missatge)
      pkg_free(missatge);
   return retval;
}
示例#12
0
int evi_raise_event(event_id_t id, evi_params_t* params)
{
	int status;
	struct sip_msg* req= NULL;
	struct usr_avp *event_avps = 0;
	struct usr_avp **bak_avps = 0;

	/*
	 * because these might be nested, a different message has
	 * to be generated each time
	 */
	req = (struct sip_msg*)pkg_malloc(sizeof(struct sip_msg));
	if(req == NULL)
	{
		LM_ERR("No more memory\n");
		return -1;
	}
	memset(req, 0, sizeof(struct sip_msg));
	
	req->first_line.type = SIP_REQUEST;
	req->first_line.u.request.method.s= "DUMMY";
	req->first_line.u.request.method.len= 5;
	req->first_line.u.request.uri.s= "sip:[email protected]";
	req->first_line.u.request.uri.len= 19;
	
	bak_avps = set_avp_list(&event_avps);

	status = evi_raise_event_msg(req, id, params);

	/* clean whatever extra structures were added by script functions */
	free_sip_msg(req);
	pkg_free(req);

	/* remove all avps added */
	destroy_avp_list(&event_avps);
	set_avp_list(bak_avps);

	return status;
}
示例#13
0
文件: corex_nio.c 项目: 2pac/kamailio
int nio_msg_sent(void *data)
{
    sip_msg_t msg;
    str *obuf;
    int_str avp_value;
    struct usr_avp *avp;
    struct run_act_ctx ra_ctx;

    obuf = (str*)data;

    if (obuf->len < nio_min_msg_len) {
        return -1;
    }

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

    nio_is_incoming = 0;
    init_run_actions_ctx(&ra_ctx);
    run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg);

    if(nio_msg_avp_name.n!=0) {
        avp = NULL;
        avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name,
                &avp_value, 0);
        if(avp!=NULL && is_avp_str_val(avp)) {
            msg.buf = avp_value.s.s;
            msg.len = avp_value.s.len;
            obuf->s = nio_msg_update(&msg, (unsigned int*)&obuf->len);
        } else {
            LM_WARN("no value set for AVP %.*s, using unmodified message\n",
                nio_msg_avp_param.len, nio_msg_avp_param.s);
        }
    }

    free_sip_msg(&msg);
    return 0;
}
示例#14
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su, new_to_su;
	struct cell *new_cell;
	struct cell *backup_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	int sip_msg_len;
	unsigned int hi;
	struct socket_info *new_send_sock;
	str h_to, h_from, h_cseq, h_callid;
	struct proxy_l *proxy, *new_proxy;
	unsigned short dst_changed;

	ret=-1;

	/*** added by dcm
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error3;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	proxy = uri2proxy( dialog->hooks.next_hop,
		dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE );
	if (proxy==0)  {
		ret=E_BAD_ADDRESS;
		goto error3;
	}
	/* use the first address */
	hostent2su( &to_su,
		&proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT);

	/* check/discover the send socket */
	if (dialog->send_sock) {
		/* if already set, the protocol of send sock must have the 
		   the same type as the proto required by destination URI */
		if (proxy->proto != dialog->send_sock->proto)
			dialog->send_sock = NULL;
	}
	if (dialog->send_sock==NULL) {
		/* get the send socket */
		dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto);
		if (!dialog->send_sock) {
			LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family);
			ser_error = E_NO_SOCKET;
			goto error2;
		}
	}
	LM_DBG("sending socket is %.*s \n",
		dialog->send_sock->name.len,dialog->send_sock->name.s);


	/* ***** Create TRANSACTION and all related  ***** */
	new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	if (dialog->forced_to_su.s.sa_family == AF_UNSPEC)
		request->dst.to = to_su;
	else
		request->dst.to = dialog->forced_to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	/* copy AVPs into transaction */
	new_cell->user_avps = dialog->avps;
	dialog->avps = NULL;


	/* ***** Create the message buffer ***** */
	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer\n");
		} else {
			/* set this transaction as active one */
			backup_cell = get_t();
			set_t( new_cell );
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = getb0flags(req);
			/* restore the prevoius active transaction */
			set_t( backup_cell );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer */
			dst_changed = 1;
			if (req->new_uri.s || req->force_send_socket!=dialog->send_sock ||
			req->dst_uri.len != dialog->hooks.next_hop->len ||
			memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) ||
			(dst_changed=0)==0 || req->add_rm || req->body_lumps){

				new_send_sock = NULL;
				/* do we also need to change the destination? */
				if (dst_changed) {
					/* calculate the socket corresponding to next hop */
					new_proxy = uri2proxy(
						req->dst_uri.s ? &(req->dst_uri) : &req->new_uri,
						PROTO_NONE );
					if (new_proxy==0)
						goto abort_update;
					/* use the first address */
					hostent2su( &new_to_su,
						&new_proxy->host, new_proxy->addr_idx,
						new_proxy->port ? new_proxy->port:SIP_PORT);
					/* get the send socket */
					new_send_sock = get_send_socket( req, &new_to_su,
						new_proxy->proto);
					if (!new_send_sock) {
						free_proxy( new_proxy );
						pkg_free( new_proxy );
						LM_ERR("no socket found for the new destination\n");
						goto abort_update;
					}
				}

				/* if interface change, we need to re-build the via */
				if (new_send_sock && new_send_sock != dialog->send_sock) {
					LM_DBG("Interface change in local route -> "
						"rebuilding via\n");
					if (!del_lump(req,req->h_via1->name.s - req->buf,
					req->h_via1->len,0)) {
						LM_ERR("Failed to remove initial via \n");
						goto abort_update;
					}

					memcpy(req->add_to_branch_s,req->via1->branch->value.s,
						req->via1->branch->value.len);
					req->add_to_branch_len = req->via1->branch->value.len;

					/* update also info about new destination and send sock */
					dialog->send_sock = new_send_sock;
					free_proxy( proxy );
					pkg_free( proxy );
					proxy = new_proxy;
					request->dst.send_sock = new_send_sock;
					request->dst.proto = new_send_sock->proto;
					request->dst.proto_reserved1 = 0;

					/* build the shm buffer now */
					set_init_lump_flags(LUMPFLAG_BRANCH);
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						new_send_sock, new_send_sock->proto,
						MSG_TRANS_SHM_FLAG);
					reset_init_lump_flags();
					del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH);

				} else {

					LM_DBG("Change in local route -> rebuilding buffer\n");
					/* build the shm buffer now */
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						dialog->send_sock, dialog->send_sock->proto,
						MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG);
					/* now as it used, hide the original VIA header */
					del_lump(req,req->h_via1->name.s - req->buf,
						req->h_via1->len, 0);

				}

				if (!buf1) {
					LM_ERR("no more shm mem\n");
					/* keep original buffer */
					goto abort_update;
				}
				/* update shortcuts */
				if(!req->add_rm && !req->new_uri.s) {
					/* headers are not affected, simply tranlate */
					new_cell->from.s = new_cell->from.s - buf + buf1;
					new_cell->to.s = new_cell->to.s - buf + buf1;
					new_cell->callid.s = new_cell->callid.s - buf + buf1;
					new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1;
				} else {
					/* use heavy artilery :D */
					if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to,
					&h_cseq, &h_callid)!=0 ) {
						LM_ERR("failed to update shortcut pointers\n");
						shm_free(buf1);
						goto abort_update;
					}
					new_cell->from = h_from;
					new_cell->to = h_to;
					new_cell->callid = h_callid;
					new_cell->cseq_n = h_cseq;
				}
				/* here we rely on how build_uac_req()
				   builds the first line */
				new_cell->uac[0].uri.s = buf1 +
					req->first_line.u.request.method.len + 1;
				new_cell->uac[0].uri.len = GET_RURI(req)->len;

				/* update also info about new destination and send sock */
				if (new_send_sock)
					request->dst.to = new_to_su;

				shm_free(buf);
				buf = buf1;
				buf_len = buf_len1;
				/* use new buffer */
			} else {
				/* no changes over the message, buffer is already generated,
				   just hide the original VIA for potential further branches */
				del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0);
			}
abort_update:
			/* save the SIP message into transaction */
			new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
			if (new_cell->uas.request==NULL) {
				/* reset any T triggering */
				new_cell->on_negative = 0;
				new_cell->on_reply = 0;
			} else {
				new_cell->uas.end_request=
					((char*)new_cell->uas.request)+sip_msg_len;
			}
			/* no parallel support in UAC transactions */
			new_cell->on_branch = 0;
			free_sip_msg(req);
		}
	}

	/* for DNS based failover, copy the DNS proxy into transaction */
	if (!disable_dns_failover) {
		new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/);
		if (new_cell->uac[0].proxy==NULL)
			LM_ERR("failed to store DNS info -> no DNS based failover\n");
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT) {
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n",
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}

	free_proxy( proxy );
	pkg_free( proxy );

	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	free_proxy( proxy );
	pkg_free( proxy );
error3:
	return ret;
}
示例#15
0
int pv_t_update_req(struct sip_msg *msg)
{
	struct cell * t;
	int branch;

	if(msg==NULL)
		return 1;

	if(msg!=FAKED_REPLY && msg->first_line.type!=SIP_REPLY)
		return 1;

	t = _tmx_tmb.t_gett();

	if(t==NULL || t==T_UNDEFINED)
	{
		if(msg==FAKED_REPLY)
			return 1;
		branch=-1;
		if (_tmx_tmb.t_check(msg, &branch ) == -1)
			return 1;
		t = _tmx_tmb.t_gett();
		if ((t == 0) || (t == T_UNDEFINED))
			return 1;

	}

	if(t->uas.request==NULL)
		return 1;

	if (_pv_treq.label == t->label && _pv_treq.index == t->hash_index)  
		return 0;

	/* make a copy */
	if(_pv_treq.buf==NULL || _pv_treq.buf_size<t->uas.request->len+1)
	{
		if(_pv_treq.buf!=NULL)
			pkg_free(_pv_treq.buf);
		if(_pv_treq.tmsgp)
			free_sip_msg(&_pv_treq.msg);
		_pv_treq.tmsgp = NULL;
		_pv_treq.index = 0;
		_pv_treq.label = 0;
		_pv_treq.buf_size = t->uas.request->len+1;
		_pv_treq.buf = (char*)pkg_malloc(_pv_treq.buf_size*sizeof(char));
		if(_pv_treq.buf==NULL)
		{
			LM_ERR("no more pkg\n");
			_pv_treq.buf_size = 0;
			return -1;
		}
	}
	if(_pv_treq.tmsgp)
		free_sip_msg(&_pv_treq.msg);
	memset(&_pv_treq.msg, 0, sizeof(struct sip_msg));
	memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len);
	_pv_treq.buf[t->uas.request->len] = '\0';
	_pv_treq.msg.len = t->uas.request->len;
	_pv_treq.msg.buf = _pv_treq.buf;
	_pv_treq.tmsgp = t->uas.request;
	_pv_treq.index = t->hash_index;
	_pv_treq.label = t->label;


	if(pv_t_copy_msg(t->uas.request, &_pv_treq.msg)!=0)
	{
		pkg_free(_pv_treq.buf);
		_pv_treq.buf_size = 0;
		_pv_treq.buf = NULL;
		_pv_treq.tmsgp = NULL;
		_pv_treq.index = 0;
		_pv_treq.label = 0;
		return -1;
	}

	return 0;
}
示例#16
0
int pv_t_update_inv(struct sip_msg *msg)
{
	struct cell * t;

	if(msg==NULL)
		return 1;
	if (msg->REQ_METHOD!=METHOD_CANCEL)
		return 1;

	t = _tmx_tmb.t_lookup_original(msg);

	if(t==NULL || t==T_UNDEFINED)
		return 1;

	if(t->uas.request==NULL) {
		_tmx_tmb.unref_cell(t);
		return 1;
	}

	if (_pv_tinv.label == t->label && _pv_tinv.index == t->hash_index)  
		goto done;

	/* make a copy */
	if(_pv_tinv.buf==NULL || _pv_tinv.buf_size<t->uas.request->len+1)
	{
		if(_pv_tinv.buf!=NULL)
			pkg_free(_pv_tinv.buf);
		if(_pv_tinv.tmsgp)
			free_sip_msg(&_pv_tinv.msg);
		_pv_tinv.tmsgp = NULL;
		_pv_tinv.index = 0;
		_pv_tinv.label = 0;
		_pv_tinv.buf_size = t->uas.request->len+1;
		_pv_tinv.buf = (char*)pkg_malloc(_pv_tinv.buf_size*sizeof(char));
		if(_pv_tinv.buf==NULL)
		{
			LM_ERR("no more pkg\n");
			_pv_tinv.buf_size = 0;
			goto error;
		}
	}
	if(_pv_tinv.tmsgp)
		free_sip_msg(&_pv_tinv.msg);
	memset(&_pv_tinv.msg, 0, sizeof(struct sip_msg));
	memcpy(_pv_tinv.buf, t->uas.request->buf, t->uas.request->len);
	_pv_tinv.buf[t->uas.request->len] = '\0';
	_pv_tinv.msg.len = t->uas.request->len;
	_pv_tinv.msg.buf = _pv_tinv.buf;
	_pv_tinv.tmsgp = t->uas.request;
	_pv_tinv.index = t->hash_index;
	_pv_tinv.label = t->label;


	if(pv_t_copy_msg(t->uas.request, &_pv_tinv.msg)!=0)
	{
		pkg_free(_pv_tinv.buf);
		_pv_tinv.buf_size = 0;
		_pv_tinv.buf = NULL;
		_pv_tinv.tmsgp = NULL;
		_pv_tinv.index = 0;
		_pv_tinv.label = 0;
		goto error;
	}

done:
	_tmx_tmb.unref_cell(t);
	return 0;

error:
	_tmx_tmb.unref_cell(t);
	return -1;
}
示例#17
0
int pv_t_update_rpl(struct sip_msg *msg)
{
	struct cell * t;
	int branch;
	int cancel;

	if(msg==NULL)
		return 1;

	if(msg==FAKED_REPLY || msg->first_line.type!=SIP_REQUEST)
		return 1;

	t = _tmx_tmb.t_gett();

	if(t==NULL || t==T_UNDEFINED)
	{
		if(_tmx_tmb.t_lookup_request(msg, 0, &cancel)<=0)
			return 1;
		t = _tmx_tmb.t_gett();

		if(t==NULL || t==T_UNDEFINED)
			return 1;
	}
	if ( (branch=_tmx_tmb.t_get_picked_branch())<0 )
		return 1;
	if(t->uac[branch].reply==NULL || t->uac[branch].reply==FAKED_REPLY)
		return 1;

	if (_pv_trpl.label == t->label && _pv_trpl.index == t->hash_index
			&& _pv_trpl.branch == branch)
		return 0;

	/* make a copy */
	if(_pv_trpl.buf==NULL || _pv_trpl.buf_size<t->uac[branch].reply->len+1)
	{
		if(_pv_trpl.buf!=NULL)
			pkg_free(_pv_trpl.buf);
		if(_pv_trpl.tmsgp)
			free_sip_msg(&_pv_trpl.msg);
		_pv_trpl.tmsgp = NULL;
		_pv_trpl.index = 0;
		_pv_trpl.label = 0;
		_pv_trpl.branch = 0;
		_pv_trpl.buf_size = t->uac[branch].reply->len+1;
		_pv_trpl.buf = (char*)pkg_malloc(_pv_trpl.buf_size*sizeof(char));
		if(_pv_trpl.buf==NULL)
		{
			LM_ERR("no more pkg\n");
			_pv_trpl.buf_size = 0;
			return -1;
		}
	}
	if(_pv_trpl.tmsgp)
		free_sip_msg(&_pv_trpl.msg);
	memset(&_pv_trpl.msg, 0, sizeof(struct sip_msg));
	memcpy(_pv_trpl.buf, t->uac[branch].reply->buf, t->uac[branch].reply->len);
	_pv_trpl.buf[t->uac[branch].reply->len] = '\0';
	_pv_trpl.msg.len = t->uac[branch].reply->len;
	_pv_trpl.msg.buf = _pv_trpl.buf;
	_pv_trpl.tmsgp = t->uac[branch].reply;
	_pv_trpl.index = t->hash_index;
	_pv_trpl.label = t->label;
	_pv_trpl.branch = branch;

	if(pv_t_copy_msg(t->uac[branch].reply, &_pv_trpl.msg)!=0)
	{
		pkg_free(_pv_trpl.buf);
		_pv_trpl.buf_size = 0;
		_pv_trpl.buf = NULL;
		_pv_trpl.tmsgp = NULL;
		_pv_trpl.index = 0;
		_pv_trpl.label = 0;
		_pv_trpl.branch = 0;
		return -1;
	}

	return 0;
}
示例#18
0
文件: async.c 项目: NormB/opensips
int async_launch_resume(int *fd, void *param)
{
	struct sip_msg req;
	async_launch_ctx *ctx = (async_launch_ctx *)param;

	LM_DBG("resume for a launch job\n");
	init_dummy_request( req );

	async_status = ASYNC_DONE; /* assume default status as done */

	/* call the resume function in order to read and handle data */
	return_code = ((async_resume_module*)(ctx->async.resume_f))
		( *fd, &req, ctx->async.resume_param );

	if (async_status==ASYNC_CONTINUE) {
		/* do not run the report route, leave the fd into the reactor*/
		goto restore;

	} else if (async_status==ASYNC_DONE_NO_IO) {
		/* don't do any change on the fd, since the module handled everything*/
		goto run_route;

	} else if (async_status==ASYNC_CHANGE_FD) {
		if (return_code<0) {
			LM_ERR("ASYNC_CHANGE_FD: given file descriptor must be "
				"positive!\n");
			goto restore;
		} else if (return_code>0 && return_code==*fd) {
			/*trying to add the same fd; shall continue*/
			LM_CRIT("You are trying to replace the old fd with the same fd!"
					"Will act as in ASYNC_CONTINUE!\n");
			goto restore;
		}

		/* remove the old fd from the reactor */
		reactor_del_reader( *fd, -1, IO_FD_CLOSING);
		*fd=return_code;

		/* insert the new fd inside the reactor */
		if (reactor_add_reader( *fd, F_LAUNCH_ASYNC, RCT_PRIO_ASYNC,
		(void*)ctx)<0 ) {
			LM_ERR("failed to add async FD to reactor -> act in sync mode\n");
			do {
				async_status = ASYNC_DONE;
				return_code = ((async_resume_module*)(ctx->async.resume_f))
					( *fd, &req, ctx->async.resume_param );
				if (async_status == ASYNC_CHANGE_FD)
					*fd=return_code;
			} while(async_status==ASYNC_CONTINUE||async_status==ASYNC_CHANGE_FD);
			goto run_route;
		} else {

			/* successfully changed fd */
			goto restore;
		}
	}

	/* remove from reactor, we are done */
	reactor_del_reader( *fd, -1, IO_FD_CLOSING);

run_route:
	if (async_status == ASYNC_DONE_CLOSE_FD)
		close(*fd);

	if (ctx->report_route!=-1) {
		LM_DBG("runinng report route for a launch job\n");
		set_route_type( REQUEST_ROUTE );
		run_top_route( rlist[ctx->report_route].a, &req);

		/* remove all added AVP */
		reset_avps( );
	}

	/* no need for the context anymore */
	shm_free(ctx);
	LM_DBG("done with a launch job\n");

restore:
	/* clean whatever extra structures were added by script functions */
	free_sip_msg(&req);

	return 0;
}
示例#19
0
int th_msg_sent(sr_event_param_t *evp)
{
	sip_msg_t msg;
	str *obuf;
	int direction;
	int dialog;
	int local;

	obuf = (str*)evp->data;

	if(th_execute_event_route(NULL, evp)==1) {
		return 0;
	}

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

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

	if(th_skip_msg(&msg)) {
		goto done;
	}

	th_cookie_value.s = th_get_cookie(&msg, &th_cookie_value.len);
	LM_DBG("the COOKIE is [%.*s]\n", th_cookie_value.len, th_cookie_value.s);
	if(th_cookie_value.s[0]!='x') {
		th_del_cookie(&msg);
	}
	if(msg.first_line.type==SIP_REQUEST) {
		direction = (th_cookie_value.s[0]=='u')?1:0; /* upstream/downstram */
		dialog = (get_to(&msg)->tag_value.len>0)?1:0;

		if(msg.via2==0) {
			local = 1;
			if(direction==0 && th_cookie_value.s[1]=='l') {
				/* downstream local request (e.g., dlg bye) */
				local = 2;
			}
		} else {
			/* more than one Via, but no received th cookie */
			local = (th_cookie_value.s[0]!='d' && th_cookie_value.s[0]!='u')?1:0;
		}
		/* local generated requests */
		if(local) {
			/* ACK and CANCEL go downstream */
			if(get_cseq(&msg)->method_id==METHOD_ACK
					|| get_cseq(&msg)->method_id==METHOD_CANCEL
					|| local==2) {
				th_mask_callid(&msg);
				goto ready;
			} else {
				/* should be for upstream */
				goto done;
			}
		}
		th_mask_via(&msg);
		th_mask_contact(&msg);
		th_mask_record_route(&msg);
		if(dialog) {
			/* dialog request */
			if(direction==0) {
				/* downstream */
				th_mask_callid(&msg);
			}
		} else {
			/* initial request */
			th_update_hdr_replaces(&msg);
			th_mask_callid(&msg);
		}
	} else {
		/* reply */
		if(th_cookie_value.s[th_cookie_value.len-1]=='x') {
			/* ?!?! - we should have a cookie in any reply case */
			goto done;
		}
		if(th_cookie_value.s[th_cookie_value.len-1]=='v') {
			/* reply generated locally - direction was set by request */
			if(th_cookie_value.s[0]=='u') {
				th_mask_callid(&msg);
			}
		} else {
			th_flip_record_route(&msg, 1);
			th_mask_contact(&msg);
			if(th_cookie_value.s[0]=='d') {
				th_mask_callid(&msg);
			}
		}
	}

ready:
	obuf->s = th_msg_update(&msg, (unsigned int*)&obuf->len);

done:
	free_sip_msg(&msg);
	return 0;
}
示例#20
0
/*
 * Function to decompress a compressed message
 */
static int mc_decompress(struct sip_msg* msg)
{
	#define HDRS_TO_SKIP 4

	int i;
	int j;
	int rc;
	int algo=-1;
	int hdrs_algo=-1;
	int b64_required=-1;

	str msg_body;
	str msg_final;

	str b64_decode={NULL, 0};
	str hdr_b64_decode={NULL,0};
	str uncomp_body={NULL,0};
	str uncomp_hdrs={NULL,0};

	char *new_buf;

	unsigned long temp;

	/* hdr_vec allows to sort the headers. This will help skipping
		these headers when building the new message */
	struct hdr_field *hf;
	struct hdr_field *hdr_vec[HDRS_TO_SKIP];
					/*hdr_vec : 	0 Content-Length
							1 Comp-Hdrs
							2 Headers-Algo
							3 Content-Encoding*/

	memset(hdr_vec, 0, HDRS_TO_SKIP * sizeof(struct hdr_field*));

	if (parse_headers(msg, HDR_EOH_F, 0) != 0) {
		LM_ERR("failed to parse SIP message\n");
		return -1;
	}

	/*If compressed with this module there are great chances that Content-Encoding is last*/
	hdr_vec[3] = msg->last_header;

	if (!is_content_encoding(hdr_vec[3])) {
		hdr_vec[3] = NULL;
		for (hf = msg->headers; hf; hf = hf->next) {
			if (is_content_encoding(hf)) {
				hdr_vec[3] = hf;
				continue;
			}
			if (hf->type == HDR_OTHER_T &&
				!strncasecmp(hf->name.s, COMP_HDRS,COMP_HDRS_LEN)) {
				hdr_vec[1] = hf;
				continue;
			}

			if (hf->type == HDR_OTHER_T &&
				!strncasecmp(hf->name.s, HDRS_ENCODING,
						sizeof(HDRS_ENCODING)-1)) {
				hdr_vec[2] = hf;
			}

			if (hdr_vec[1] && hdr_vec[2] && hdr_vec[3])
					break;
		}
	} else {
		for (hf = msg->headers; hf; hf = hf->next) {
			if (!hdr_vec[1] && hf->type == HDR_OTHER_T &&
				!strncasecmp(hf->name.s, COMP_HDRS,COMP_HDRS_LEN)) {
				hdr_vec[1] = hf;
				continue;
			}

			if (!hdr_vec[2] && hf->type == HDR_OTHER_T &&
				!strncasecmp(hf->name.s, HDRS_ENCODING,
						sizeof(HDRS_ENCODING)-1))
				hdr_vec[2] = hf;

			if (hdr_vec[2] && hdr_vec[3] && hdr_vec[1])
					break;
		}
	}

	/* Only if content-encoding present, Content-Length will be replaced
		with the one in the compressed body or in compressed headers*/

	if (hdr_vec[3]) {
		hdr_vec[0] = msg->content_length;
		parse_algo_hdr(hdr_vec[3], &algo, &b64_required);
	}


	if (b64_required > 0 && hdr_vec[3]) {
		msg_body.s = msg->last_header->name.s + msg->last_header->len + CRLF_LEN;
		msg_body.len = strlen(msg_body.s);

		/* Cutting CRLF'S at the end of the message */
		while (WORD(msg_body.s + msg_body.len-CRLF_LEN) == PARSE_CRLF) {
			msg_body.len -= CRLF_LEN;
		}

		if (wrap_realloc(&body_in, calc_max_base64_decode_len(msg_body.len)))
			return -1;

		b64_decode.s = body_in.s;

		b64_decode.len = base64decode((unsigned char*)b64_decode.s,
						(unsigned char*)msg_body.s,
							msg_body.len);
	} else if (hdr_vec[3]) {
		if (get_body(msg, &msg_body) < 0) {
			LM_ERR("failed to get body\n");
			return -1;
		}

		b64_decode.s = msg_body.s;
		b64_decode.len = msg_body.len;
	}

	b64_required=0;
	if (hdr_vec[2]) {
		parse_algo_hdr(hdr_vec[3], &algo, &b64_required);
	}

	if (b64_required > 0 &&  hdr_vec[1]) {
		if (wrap_realloc(&hdr_in, calc_max_base64_decode_len(hdr_vec[1]->body.len)))
			return -1;

		hdr_b64_decode.s = hdr_in.s;

		hdr_b64_decode.len = base64decode(
					(unsigned char*)hdr_b64_decode.s,
					(unsigned char*)hdr_vec[1]->body.s,
							hdr_vec[1]->body.len
					);
	} else if (hdr_vec[1]) {
		hdr_b64_decode.s = hdr_vec[1]->body.s;
		hdr_b64_decode.len = hdr_vec[1]->body.len;
	}

	switch (hdrs_algo) {
		case 0: /* deflate */
			temp = (unsigned long)BUFLEN;

			rc = uncompress((unsigned char*)hdr_buf,
					&temp,
					(unsigned char*)hdr_b64_decode.s,
					(unsigned long)hdr_b64_decode.len);

			uncomp_hdrs.s = hdr_buf;
			uncomp_hdrs.len = temp;

			if (check_zlib_rc(rc)) {
				LM_ERR("header decompression failed\n");
				return -1;
			}
			break;
		case 1: /* gzip */
			rc = gzip_uncompress(
					(unsigned char*)hdr_b64_decode.s,
					(unsigned long)hdr_b64_decode.len,
					&hdr_out,
					&temp);

			if (check_zlib_rc(rc)) {
				LM_ERR("header decompression failed\n");
				return -1;
			}

			uncomp_hdrs.s = hdr_out.s;
			uncomp_hdrs.len = temp;

			break;
		case -1:
			break;
		default:
			return -1;
	}

	switch (algo) {
		case 0: /* deflate */
			temp = (unsigned long)BUFLEN;

			rc = uncompress((unsigned char*)body_buf,
					&temp,
					(unsigned char*)b64_decode.s,
					(unsigned long)b64_decode.len);

			if (check_zlib_rc(rc)) {
				LM_ERR("body decompression failed\n");
				return -1;
			}

			uncomp_body.s = body_buf;
			uncomp_body.len = temp;

			break;
		case 1: /* gzip */
			rc = gzip_uncompress(
					(unsigned char*)b64_decode.s,
					(unsigned long)b64_decode.len,
					&body_out,
					&temp);

			if (check_zlib_rc(rc)) {
				LM_ERR("body decompression failed\n");
				return -1;
			}

			uncomp_body.s = body_out.s;
			uncomp_body.len = temp;

			break;
		case -1:
			LM_DBG("no body\n");
			break;
		default:
			LM_ERR("invalid algo\n");
			return -1;
	}

	/* Sort to have the headers in order */
	for (i = 0; i < HDRS_TO_SKIP - 1; i++) {
		for (j = i + 1; j < HDRS_TO_SKIP; j++) {
			if (!hdr_vec[j])
				continue;

			if (!hdr_vec[i] && hdr_vec[j]) {
				hdr_vec[i] = hdr_vec[j];
				hdr_vec[j] = NULL;
			}

			if ((hdr_vec[i] && hdr_vec[j]) &&
				(hdr_vec[i]->name.s > hdr_vec[j]->name.s)) {
				hf = hdr_vec[i];
				hdr_vec[i] = hdr_vec[j];
				hdr_vec[j] = hf;
			}
		}
	}

	int msg_final_len = 0;
	int msg_ptr=0;

	for ( i = 0; i < HDRS_TO_SKIP; i++) {
		if (hdr_vec[i]) {
			msg_final_len += hdr_vec[i]->name.s - (msg->buf+msg_ptr);
			msg_ptr += hdr_vec[i]->name.s+hdr_vec[i]->len - (msg->buf+msg_ptr);
		}
	}

	msg_final_len += msg->last_header->name.s + msg->last_header->len -
				(msg->buf + msg_ptr);

	if (hdrs_algo >= 0)
		msg_final_len += uncomp_hdrs.len;

	if (algo >= 0)
		msg_final_len += uncomp_body.len;
	else
		msg_final_len += strlen(msg->eoh);

	if (wrap_realloc(&buf_out, msg_final_len))
		return -1;

	msg_ptr = 0;

	msg_final.len = 0;
	msg_final.s = buf_out.s;

	for ( i = 0; i < HDRS_TO_SKIP; i++) {
		if (hdr_vec[i]) {
			wrap_copy_and_update(&msg_final.s,
					msg->buf+msg_ptr,
					hdr_vec[i]->name.s-(msg->buf+msg_ptr),
					&msg_final.len);

			msg_ptr += (hdr_vec[i]->name.s+hdr_vec[i]->len) -
					(msg->buf+msg_ptr);
		}
	}

	wrap_copy_and_update(
			&msg_final.s,
			msg->buf+msg_ptr,
			(msg->last_header->name.s+msg->last_header->len)-
							(msg->buf+msg_ptr),
			&msg_final.len
		);

	if (hdrs_algo >= 0) {
		wrap_copy_and_update(&msg_final.s, uncomp_hdrs.s,
					uncomp_hdrs.len,&msg_final.len);
	}

	if (algo >= 0) {
		wrap_copy_and_update(&msg_final.s, uncomp_body.s,
					uncomp_body.len, &msg_final.len);
	} else {
		wrap_copy_and_update(&msg_final.s, msg->eoh, strlen(msg->eoh), &msg_final.len);
	}

	/* new buffer because msg_final(out_buf) will
	 * be overwritten at next iteration */
#ifdef DYN_BUF
	new_buf = pkg_malloc(msg_final.len+1);
	if (new_buf == NULL) {
		LM_ERR("no more pkg mem\n");
		return -1;
	}
#else
	new_buf = msg->buf;
#endif

	memcpy(new_buf, msg_final.s, msg_final.len);
	new_buf[msg_final.len] = '\0';

	struct sip_msg tmp;

	memcpy(&tmp, msg, sizeof(struct sip_msg));

	/*reset dst_uri and path_vec to avoid free*/
	if (msg->dst_uri.s != NULL) {
		msg->dst_uri.s = NULL;
		msg->dst_uri.len = 0;
	}
	if (msg->path_vec.s != NULL)
	{
		msg->path_vec.s = NULL;
		msg->path_vec.len = 0;
	}

	free_sip_msg(msg);
	memset(msg, 0, sizeof(struct sip_msg));

	/* restore msg fields */
	msg->id					= tmp.id;
	msg->rcv				= tmp.rcv;
	msg->set_global_address = tmp.set_global_address;
	msg->set_global_port    = tmp.set_global_port;
	msg->flags              = tmp.flags;
	msg->msg_flags          = tmp.msg_flags;
	msg->hash_index         = tmp.hash_index;
	msg->force_send_socket  = tmp.force_send_socket;
	msg->dst_uri            = tmp.dst_uri;
	msg->path_vec           = tmp.path_vec;
	/* set the new ones */
	msg->buf = new_buf;
	msg->len = msg_final.len;

	/* reparse the message */
	if (parse_msg(msg->buf, msg->len, msg) != 0)
		LM_ERR("parse_msg failed\n");

	return 1;
}
示例#21
0
/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
{
	struct sip_msg* msg;
	struct run_act_ctx ctx;
	int ret;
#ifdef STATS
	int skipped = 1;
	struct timeval tvb, tve;	
	struct timezone tz;
	unsigned int diff;
#endif
	str inb;

	inb.s = buf;
	inb.len = len;
	sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
	len = inb.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
		goto error00;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=buf;
	msg->len=len;
	/* zero termination (termination of orig message bellow not that
	   useful as most of the work is done with scratch-pad; -jiri  */
	/* buf[len]=0; */ /* WARNING: zero term removed! */
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->pid=my_pid();
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;
	
	if(likely(sr_msg_time==1)) msg_set_time(msg);

	if (parse_msg(buf,len, msg)!=0){
		if(sr_event_exec(SREV_RCV_NOSIP, (void*)msg)!=0) {
			LOG(cfg_get(core, core_cfg, corelog),
				"core parsing of SIP message failed (%s:%d/%d)\n",
				ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
				(int)msg->rcv.proto);
			sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
		}
		goto error02;
	}
	DBG("After parse_msg...\n");


	/* ... clear branches from previous message */
	clear_branches();

	if (msg->first_line.type==SIP_REQUEST){
		ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
		if (!IS_SIP(msg)){
			if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
				if (unlikely(ret==NONSIP_MSG_ERROR))
					goto error03;
				goto end; /* drop the message */
			}
		}
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
			STATS_BAD_MSG();
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) && 
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
				/* continue */
			}
		}
#endif

	/*	skip: */
		DBG("preparing to run routing scripts...\n");
#ifdef  STATS
		gettimeofday( & tvb, &tz );
#endif
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
		{
			STATS_REQ_FWD_DROP();
			goto end; /* drop the request */
		}

		set_route_type(REQUEST_ROUTE);
		/* exec the routing script */
		if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
			LOG(L_WARN, "WARNING: receive_msg: "
					"error while trying script\n");
			goto error_req;
		}

#ifdef STATS
		gettimeofday( & tve, &tz );
		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
		stats->processed_requests++;
		stats->acc_req_time += diff;
		DBG("successfully ran routing scripts...(%d usec)\n", diff);
		STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif

		/* execute post request-script callbacks */
		exec_post_script_cb(msg, REQUEST_CB_TYPE);
	}else if (msg->first_line.type==SIP_REPLY){
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
			STATS_BAD_RPL();
			goto error02;
		}

#ifdef STATS
		gettimeofday( & tvb, &tz );
		STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif
		
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
		{
			STATS_RPL_FWD_DROP();
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		if (onreply_rt.rlist[DEFAULT_RT]){
			set_route_type(CORE_ONREPLY_ROUTE);
			ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
#ifndef NO_ONREPLY_ROUTE_ERROR
			if (unlikely(ret<0)){
				LOG(L_WARN, "WARNING: receive_msg: "
						"error while trying onreply script\n");
				goto error_rpl;
			}else
#endif /* NO_ONREPLY_ROUTE_ERROR */
			if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
				STATS_RPL_FWD_DROP();
				goto skip_send_reply; /* drop the message, no error */
			}
		}
		/* send the msg */
		forward_reply(msg);
	skip_send_reply:
#ifdef STATS
		gettimeofday( & tve, &tz );
		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
		stats->processed_responses++;
		stats->acc_res_time+=diff;
		DBG("successfully ran reply processing...(%d usec)\n", diff);
#endif

		/* execute post reply-script callbacks */
		exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	DBG("receive_msg: cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	return 0;
#ifndef NO_ONREPLY_ROUTE_ERROR
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	goto error02;
#endif /* NO_ONREPLY_ROUTE_ERROR */
error_req:
	DBG("receive_msg: error:...\n");
	/* execute post request-script callbacks */
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
error03:
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	return -1;
}
示例#22
0
static int msrp_frame_received(sr_event_param_t *evp)
{
	tcp_event_info_t *tev;
	static msrp_frame_t mf;
	sip_msg_t *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;
	sr_kemi_eng_t *keng = NULL;
	str evname = str_init("msrp:frame-in");

	tev = (tcp_event_info_t*)evp->data;

	if(tev==NULL || tev->buf==NULL || tev->len<=0)
	{
		LM_DBG("invalid parameters\n");
		return -1;
	}

	memset(&mf, 0, sizeof(msrp_frame_t));
	mf.buf.s = tev->buf;
	mf.buf.len = tev->len;
	mf.tcpinfo = tev;
	if(msrp_parse_frame(&mf)<0)
	{
		LM_ERR("error parsing msrp frame\n");
		return -1;
	}
	msrp_reset_env();
	msrp_set_current_frame(&mf);
	fmsg = msrp_fake_sipmsg(&mf);
	if(fmsg != NULL)
		fmsg->rcv = *tev->rcv;
	rtb = get_route_type();
	set_route_type(EVENT_ROUTE);
	init_run_actions_ctx(&ctx);
	if(msrp_event_callback.s == NULL || msrp_event_callback.len <= 0) {
		/* native cfg script execution */
		rt = route_get(&event_rt, evname.s);
		LM_DBG("executing event_route[msrp:frame-in] (%d)\n", rt);
		if(rt >= 0 && event_rt.rlist[rt] != NULL) {
			run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		} else {
			LM_ERR("empty event route block for msrp handling\n");
		}
	} else {
		/* kemi script execution */
		keng = sr_kemi_eng_get();
		if(keng==NULL) {
			LM_ERR("event callback (%s) set, but no cfg engine\n",
					msrp_event_callback.s);
		} else {
			if(sr_kemi_ctx_route(keng, &ctx, fmsg, EVENT_ROUTE,
						&msrp_event_callback, &evname)<0) {
				LM_ERR("error running event route kemi callback\n");
			}
		}
	}
	if(ctx.run_flags & DROP_R_F) {
		LM_DBG("exit due to 'drop' in event route\n");
	}
	set_route_type(rtb);
	if(fmsg != NULL)
		free_sip_msg(fmsg);
	msrp_reset_env();
	msrp_destroy_frame(&mf);
	return 0;
}
示例#23
0
void async_http_cb(struct http_m_reply *reply, void *param)
{
	async_query_t *aq;
	cfg_action_t *act;
	unsigned int tindex;
	unsigned int tlabel;
	struct cell *t = NULL;
	char *p;
	sip_msg_t *fmsg;

	if (reply->result != NULL) {
		LM_DBG("query result = %.*s [%d]\n", reply->result->len, reply->result->s, reply->result->len);
	}

	/* clean process-local result variables */
	ah_error.s = NULL;
	ah_error.len = 0;
	memset(ah_reply, 0, sizeof(struct sip_msg));

	/* set process-local result variables */
	if (reply->result == NULL) {
		/* error */
		ah_error.s = reply->error;
		ah_error.len = strlen(ah_error.s);
	} else {
		/* success */
		
		/* check for HTTP Via header
     	 * - HTTP Via format is different that SIP Via
     	 * - workaround: replace with Hia to be ignored by SIP parser
     	 */
    	if((p=strfindcasestrz(reply->result, "\nVia:"))!=NULL)
    	{
        	p++;
        	*p = 'H';
        	LM_DBG("replaced HTTP Via with Hia [[\n%.*s]]\n", reply->result->len, reply->result->s);
    	}

		ah_reply->buf = reply->result->s;
		ah_reply->len = reply->result->len;

		if (parse_msg(reply->result->s, reply->result->len, ah_reply) != 0) {
			LM_DBG("failed to parse the http_reply\n");
		} else {
			LM_DBG("successfully parsed http reply %p\n", ah_reply);
		}
	}

	aq = param;
	strncpy(q_id, aq->id, strlen(aq->id));
	
	act = (cfg_action_t*)aq->param;

	if (aq->query_params.suspend_transaction) {
		tindex = aq->tindex;
		tlabel = aq->tlabel;

		if (tmb.t_lookup_ident(&t, tindex, tlabel) < 0) {
			LM_ERR("transaction not found %d:%d\n", tindex, tlabel);
			LM_DBG("freeing query %p\n", aq);
			free_async_query(aq);
			return;
		}
		// we bring the list of AVPs of the transaction to the current context
		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
		set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
		set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
		set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

		if (t)
			tmb.unref_cell(t);

		LM_DBG("resuming transaction (%d:%d)\n", tindex, tlabel);

		if(act!=NULL)
			tmb.t_continue(tindex, tlabel, act);
	} else {
		fmsg = faked_msg_next();
		if (run_top_route(act, fmsg, 0)<0)
			LM_ERR("failure inside run_top_route\n");
	}

	free_sip_msg(ah_reply);
	free_async_query(aq);

	return;
}
示例#24
0
static inline int do_dns_failover(struct cell *t)
{
	static struct sip_msg faked_req;
	struct sip_msg *shmem_msg;
	struct sip_msg *req;
	struct ua_client *uac;
	dlg_t dialog;
	int ret, sip_msg_len;

	uac = &t->uac[picked_branch];

	/* check if the DNS resolver can get at least one new IP */
	if ( get_next_su( uac->proxy, &uac->request.dst.to, 1)!=0 )
		return -1;

	LM_DBG("new destination available\n");

	if (t->uas.request==NULL) {
		if (!is_local(t)) {
			LM_CRIT("BUG: proxy transaction without UAS request :-/\n");
			return -1;
		}
		/* create the cloned SIP msg -> first create a new SIP msg */
		memset( &dialog, 0, sizeof(dialog));
		dialog.send_sock = uac->request.dst.send_sock;
		dialog.hooks.next_hop = &uac->uri;
		req = buf_to_sip_msg(uac->request.buffer.s, uac->request.buffer.len,
			&dialog);
		if (req==NULL) {
			LM_ERR("failed to generate SIP msg from previous buffer\n");
			return -1;
		}
		/* now do the actual cloning of the SIP message */
		t->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
		if (t->uas.request==NULL) {
			LM_ERR("cloning failed\n");
			free_sip_msg(req);
			return -1;
		}
		t->uas.end_request = ((char*)t->uas.request) + sip_msg_len;
		/* free the actual SIP message, keep the clone only */
		free_sip_msg(req);
		/* the sip_msg structure is static in buf_to_sip_msg,
		   so no need to free it */
	}
	shmem_msg = t->uas.request;

	if (!fake_req(&faked_req, shmem_msg, &t->uas, uac, 1/*with dst_uri*/)) {
		LM_ERR("fake_req failed\n");
		return -1;
	}
	/* fake also the env. conforming to the fake msg */
	faked_env( t, &faked_req);
	ret = -1;

	/* set info as current destination */
	if ( set_ruri( &faked_req, &uac->uri)!= 0)
		goto done;

	setb0flags( &faked_req, uac->br_flags );
	faked_req.force_send_socket = shmem_msg->force_send_socket;

	/* send it out */
	if (t_forward_nonack( t, &faked_req, uac->proxy)==1)
		ret = 0;

done:
	/* restore original environment and free the fake msg */
	faked_env( t, 0);
	free_faked_req(&faked_req,t);
	return ret;
}
示例#25
0
文件: uac.c 项目: tsudot/kamailio
/* WARNING: - dst_cell contains the created cell, but it is un-referenced
 *            (before using it make sure you REF() it first)
 *          - if  ACK (method==ACK), a cell will be created but it will not
 *            be added in the hash table (should be either deleted by the 
 *            caller) 
 */
static inline int t_uac_prepare(uac_req_t *uac_r, 
		struct retr_buf **dst_req,
		struct cell **dst_cell)
{
	struct dest_info dst;
	struct cell *new_cell;
	struct retr_buf *request;
	char* buf;
	int buf_len, ret;
	unsigned int hi;
	int is_ack;
	ticks_t lifetime;
#ifdef USE_DNS_FAILOVER
	struct dns_srv_handle dns_h;
#endif
	long nhtype;
#ifdef WITH_EVENT_LOCAL_REQUEST
	struct cell *backup_t;
	int backup_branch;
	unsigned int backup_msgid;
	static struct sip_msg lreq;
	char *buf1;
	int buf_len1;
	int sflag_bk;
	int backup_route_type;
#endif
	snd_flags_t snd_flags;
	tm_xlinks_t backup_xd;
	tm_xdata_t local_xd;

	ret=-1;
	hi=0; /* make gcc happy */
	/*if (dst_req) *dst_req = NULL;*/
	is_ack = (((uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0)) ? 1 : 0);
	
	/*** added by dcm 
	 * - needed by external ua to send a request within a dlg
	 */
	if ((nhtype = w_calculate_hooks(uac_r->dialog)) < 0)
		/* if err's returned, the message is incorrect */
		goto error2;

	if (!uac_r->dialog->loc_seq.is_set) {
		/* this is the first request in the dialog,
		set cseq to default value now - Miklos */
		uac_r->dialog->loc_seq.value = DEFAULT_CSEQ;
		uac_r->dialog->loc_seq.is_set = 1;
	}

	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",uac_r->dialog->hooks.next_hop->len,
			uac_r->dialog->hooks.next_hop->s);
	/* new message => take the dialog send_socket if set, or the default
	  send_socket if not*/
	SND_FLAGS_INIT(&snd_flags);
#ifdef USE_DNS_FAILOVER
	if (cfg_get(core, core_cfg, use_dns_failover)){
		dns_srv_handle_init(&dns_h);
		if ((uri2dst2(&dns_h, &dst, uac_r->dialog->send_sock, snd_flags,
							uac_r->dialog->hooks.next_hop, PROTO_NONE)==0)
				|| (dst.send_sock==0)){
			dns_srv_handle_put(&dns_h);
			ser_error = E_NO_SOCKET;
			ret=ser_error;
			LOG(L_ERR, "t_uac: no socket found\n");
			goto error2;
		}
		dns_srv_handle_put(&dns_h); /* not needed anymore */
	}else{
		if ((uri2dst2(0, &dst, uac_r->dialog->send_sock, snd_flags,
						uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
				(dst.send_sock==0)){
			ser_error = E_NO_SOCKET;
			ret=ser_error;
			LOG(L_ERR, "t_uac: no socket found\n");
			goto error2;
		}
	}
#else /* USE_DNS_FAILOVER */
	if ((uri2dst2(&dst, uac_r->dialog->send_sock, snd_flags,
					uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
			(dst.send_sock==0)){
		ser_error = E_NO_SOCKET;
		ret=ser_error;
		LOG(L_ERR, "t_uac: no socket found\n");
		goto error2;
	}
#endif /* USE_DNS_FAILOVER */

	/* build cell sets X/AVP lists to new transaction structure
	 * => bakup in a tmp struct and restore afterwards */
	memset(&local_xd, 0, sizeof(tm_xdata_t));
	tm_xdata_replace(&local_xd, &backup_xd);
	new_cell = build_cell(0); 
	tm_xdata_replace(0, &backup_xd);

	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LOG(L_ERR, "t_uac: short of cell shmem\n");
		goto error2;
	}
	if (uac_r->method->len==INVITE_LEN && memcmp(uac_r->method->s, INVITE, INVITE_LEN)==0){
		new_cell->flags |= T_IS_INVITE_FLAG;
		new_cell->flags|=T_AUTO_INV_100 &
				(!cfg_get(tm, tm_cfg, tm_auto_inv_100) -1);
#ifdef WITH_AS_SUPPORT
		if (uac_r->cb_flags & TMCB_DONT_ACK)
			new_cell->flags |= T_NO_AUTO_ACK;
#endif
		lifetime=cfg_get(tm, tm_cfg, tm_max_inv_lifetime);
	}else
		lifetime=cfg_get(tm, tm_cfg, tm_max_noninv_lifetime);
	new_cell->flags |= T_IS_LOCAL_FLAG;
	/* init timers hack, new_cell->fr_timer and new_cell->fr_inv_timer
	 * must be set, or else the fr will happen immediately
	 * we can't call init_new_t() because we don't have a sip msg
	 * => we'll ignore t_set_fr() or avp timer value and will use directly the
	 * module params fr_inv_timer and fr_timer -- andrei */
	new_cell->fr_timeout=cfg_get(tm, tm_cfg, fr_timeout);
	new_cell->fr_inv_timeout=cfg_get(tm, tm_cfg, fr_inv_timeout);
	new_cell->end_of_life=get_ticks_raw()+lifetime;
#ifdef TM_DIFF_RT_TIMEOUT
	/* same as above for retransmission intervals */
	new_cell->rt_t1_timeout_ms = cfg_get(tm, tm_cfg, rt_t1_timeout_ms);
	new_cell->rt_t2_timeout_ms = cfg_get(tm, tm_cfg, rt_t2_timeout_ms);
#endif

	set_kr(REQ_FWDED);

	request = &new_cell->uac[0].request;
	request->dst = dst;
	request->flags |= nhtype;

	if (!is_ack) {
#ifdef TM_DEL_UNREF
		INIT_REF(new_cell, 1); /* ref'ed only from the hash */
#endif
		hi=dlg2hash(uac_r->dialog);
		LOCK_HASH(hi);
		insert_into_hash_table_unsafe(new_cell, hi);
		UNLOCK_HASH(hi);
	}

	buf = build_uac_req(uac_r->method, uac_r->headers, uac_r->body, uac_r->dialog, 0, new_cell,
		&buf_len, &dst);
	if (!buf) {
		LOG(L_ERR, "t_uac: Error while building message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

#ifdef WITH_EVENT_LOCAL_REQUEST
	if (unlikely(goto_on_local_req>=0)) {
		DBG("executing event_route[tm:local-request]\n");
		if(likely(build_sip_msg_from_buf(&lreq, buf, buf_len, inc_msg_no())
					== 0)) {
			/* fill some field in sip_msg */
			if (unlikely(set_dst_uri(&lreq, uac_r->dialog->hooks.next_hop))) {
				LM_ERR("failed to set dst_uri");
				free_sip_msg(&lreq);
			} else {
				struct onsend_info onsnd_info;

				lreq.force_send_socket = uac_r->dialog->send_sock;
				lreq.rcv.proto = dst.send_sock->proto;
				lreq.rcv.src_ip = dst.send_sock->address;
				lreq.rcv.src_port = dst.send_sock->port_no;
				lreq.rcv.dst_port = su_getport(&dst.to);
				su2ip_addr(&lreq.rcv.dst_ip, &dst.to);
				lreq.rcv.src_su=dst.send_sock->su;
				lreq.rcv.bind_address=dst.send_sock;
			#ifdef USE_COMP
				lreq.rcv.comp=dst.comp;
			#endif /* USE_COMP */
				sflag_bk = getsflags();
				tm_xdata_swap(new_cell, &backup_xd, 0);

				onsnd_info.to=&dst.to;
				onsnd_info.send_sock=dst.send_sock;
				onsnd_info.buf=buf;
				onsnd_info.len=buf_len;
				p_onsend=&onsnd_info;

				/* run the route */
				backup_route_type = get_route_type();
				set_route_type(LOCAL_ROUTE);
				/* set T to the current transaction */
				backup_t=get_t();
				backup_branch=get_t_branch();
				backup_msgid=global_msg_id;
				/* fake transaction and message id */
				global_msg_id=lreq.id;
				set_t(new_cell, T_BR_UNDEFINED);
				run_top_route(event_rt.rlist[goto_on_local_req], &lreq, 0);
				/* restore original environment */
				set_t(backup_t, backup_branch);
				global_msg_id=backup_msgid;
				set_route_type( backup_route_type );
				p_onsend=0;

				/* restore original environment */
				tm_xdata_swap(new_cell, &backup_xd, 1);
				setsflagsval(sflag_bk);

				if (unlikely(lreq.new_uri.s))
				{
					pkg_free(lreq.new_uri.s);
					lreq.new_uri.s=0;
					lreq.new_uri.len=0;
				}
				if (unlikely(lreq.dst_uri.s))
				{
					pkg_free(lreq.dst_uri.s);
					lreq.dst_uri.s=0;
					lreq.dst_uri.len=0;
				}

				if (unlikely(lreq.add_rm || lreq.body_lumps)) {
					LM_DBG("apply new updates to sip msg\n");
					buf1 = build_req_buf_from_sip_req(&lreq,
							(unsigned int*)&buf_len1,
							&dst, BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE|
							BUILD_IN_SHM);
					if (likely(buf1)){
						shm_free(buf);
						buf = buf1;
						buf_len = buf_len1;
						/* a possible change of the method is not handled! */
					}
				}
				lreq.buf=0; /* covers the obsolete DYN_BUF */
				free_sip_msg(&lreq);
			}
		}
	}
#endif

	new_cell->method.s = buf;
	new_cell->method.len = uac_r->method->len;

	request->buffer = buf;
	request->buffer_len = buf_len;
	new_cell->nr_of_outgoings++;

	/* Register the callbacks after everything is successful and nothing can fail.
	Otherwise the callback parameter would be freed twise, once from TMCB_DESTROY,
	and again because of the negative return code. */
	if(uac_r->cb && insert_tmcb(&(new_cell->tmcb_hl), uac_r->cb_flags, 
								*(uac_r->cb), uac_r->cbp, NULL)!=1){
		ret=E_OUT_OF_MEM; 
		LOG(L_ERR, "t_uac: short of tmcb shmem\n");
		goto error1;
	}
	if (has_local_reqin_tmcbs())
			run_local_reqin_callbacks(new_cell, 0, 0);
#ifdef DIALOG_CALLBACKS
	run_trans_dlg_callbacks(uac_r->dialog, new_cell, request);
#endif /* DIALOG_CALLBACKS */
	if (dst_req) *dst_req = request;
	if (dst_cell) *dst_cell = new_cell;
	else if(is_ack && dst_req==0){
		free_cell(new_cell);
	}
	
	return 1;

 error1:
 	if (!is_ack) {
		LOCK_HASH(hi);
		remove_from_hash_table_unsafe(new_cell);
		UNLOCK_HASH(hi);
#ifdef TM_DEL_UNREF
		UNREF_FREE(new_cell);
	}else
#else
	}
#endif
		free_cell(new_cell);
error2:
	return ret;
}
示例#26
0
/**
 * Evaluates the routing elements in locally originated request or reply to
 * locally originated request.
 * If original INVITE was in-dialog (had to-tag), it uses the
 * routes present there (b/c the 2xx for it does not have a RR set, normally).
 * Otherwise, use the reply (b/c the INVITE does not have yet the complete
 * route set).
 *
 * @return: negative for failure; out params:
 *  - list: route set;
 *  - ruri: RURI to be used in ACK;
 *  - nexthop: where to first send the ACK.
 *
 *  NOTE: assumes rpl's parsed to EOF!
 *
 */
static int eval_uac_routing(sip_msg_t *rpl, const struct retr_buf *inv_rb,
		str* contact, struct rte **list, str *ruri, str *next_hop)
{
	sip_msg_t orig_inv, *sipmsg; /* reparse original INVITE */
	rte_t *t, *prev_t, *rtset = NULL;
	int is_req;
	struct sip_uri puri;
	static size_t chklen;

	/* parse the retr. buffer */
	memset(&orig_inv, 0, sizeof(struct sip_msg));
	orig_inv.buf = inv_rb->buffer;
	orig_inv.len = inv_rb->buffer_len;
	LM_DBG("reparsing retransmission buffer of original INVITE:\n%.*s\n",
			(int)orig_inv.len, orig_inv.buf);
	if (parse_msg(orig_inv.buf, orig_inv.len, &orig_inv) != 0) {
		LM_ERR("failed to parse retr buffer (weird!): \n%.*s\n",
				(int)orig_inv.len, orig_inv.buf);
		return -1;
	}

	/* check if we need to look at request or reply */
	if ((parse_headers(&orig_inv, HDR_TO_F, 0) < 0) || (! orig_inv.to)) {
		/* the bug is at message assembly */
		LM_BUG("failed to parse INVITE retr. buffer and/or extract 'To' HF:"
				"\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
		goto error;
	}
	if (((struct to_body *)orig_inv.to->parsed)->tag_value.len) {
		LM_DBG("building ACK for in-dialog INVITE (using RS in orig. INV.)\n");
		if (parse_headers(&orig_inv, HDR_EOH_F, 0) < 0) {
			LM_BUG("failed to parse INVITE retr. buffer to EOH:"
					"\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
			goto error;
		}
		sipmsg = &orig_inv;
		is_req = 1;
	} else {
		LM_DBG("building ACK for out-of-dialog INVITE (using RS in RR set).\n");
		sipmsg = rpl;
		is_req = 0;
	}

	/* extract the route set */
	if (get_uac_rs(sipmsg, is_req, &rtset) < 0) {
		LM_ERR("failed to extract route set.\n");
		goto error;
	}

	if (! rtset) { /* No routes */
		*ruri = *contact;
		*next_hop = *contact;
	} else if (! is_req) { /* out of dialog req. */
		if (parse_uri(rtset->ptr->nameaddr.uri.s, rtset->ptr->nameaddr.uri.len,
				&puri) < 0) {
			LM_ERR("failed to parse first route in set.\n");
			goto error;
		}

		if (puri.lr.s) { /* Next hop is loose router */
			*ruri = *contact;
			*next_hop = rtset->ptr->nameaddr.uri;
		} else { /* Next hop is strict router */
			*ruri = rtset->ptr->nameaddr.uri;
			*next_hop = *ruri;
			/* consume first route, b/c it will be put in RURI */
			t = rtset;
			rtset = rtset->next;
			pkg_free(t);
		}
	} else {
		unsigned long route_flags = inv_rb->flags;
		LM_DBG("UAC rb flags: 0x%x.\n", (unsigned int)route_flags);
eval_flags:
		switch (route_flags & (F_RB_NH_LOOSE|F_RB_NH_STRICT)) {
		case 0:
			LM_WARN("calculate_hooks() not called when built the local UAC of "
					"in-dialog request, or called with empty route set.\n");
			/* try to figure out what kind of hop is the next one
			 * (strict/loose) by reading the original invite */
			if ((route_flags = nhop_type(&orig_inv, rtset, &inv_rb->dst,
					contact))) {
				LM_DBG("original request's next hop type evaluated to: 0x%x.\n",
						(unsigned int)route_flags);
				goto eval_flags;
			} else {
				LM_ERR("failed to establish what kind of router the next "
						"hop is.\n");
				goto error;
			}
			break;
		case F_RB_NH_LOOSE:
			*ruri = *contact;
			*next_hop = rtset->ptr->nameaddr.uri;
			break;
		case F_RB_NH_STRICT:
			/* find ptr to last route body that contains the (possibly) old
			 * remote target
			 */
			for (t = rtset, prev_t = NULL; t->next; prev_t = t, t = t->next)
				;
			if ((t->ptr->len == contact->len) &&
					(memcmp(t->ptr->nameaddr.name.s, contact->s,
							contact->len) == 0)){
				/* the remote target didn't update -> keep the whole route set,
				 * including the last entry */
				/* do nothing */
			} else {
				/* trash last entry and replace with new remote target */
				free_rte_list(t);
				/* compact the rr_t struct along with rte. this way, free'ing
				 * it can be done along with rte chunk, independent of Route
				 * header parser's allocator (using pkg/shm) */
				chklen = sizeof(struct rte) + sizeof(rr_t);
				if (! (t = pkg_malloc(chklen))) {
					ERR("out of pkg memory (%d required)\n", (int)chklen);
					/* last element was freed, unlink it */
					if(prev_t == NULL) {
						/* there is only one elem in route set: the remote target */
						rtset = NULL;
					} else {
						prev_t->next = NULL;
					}
					goto error;
				}
				/* this way, .free_rr is also set to 0 (!!!) */
				memset(t, 0, chklen);
				((rr_t *)&t[1])->nameaddr.name = *contact;
				((rr_t *)&t[1])->len = contact->len;
				/* chain the new route elem in set */
				if (prev_t == NULL)
					/* there is only one elem in route set: the remote target */
					rtset = t;
				else
					prev_t->next = t;
			}

			*ruri = *GET_RURI(&orig_inv); /* reuse original RURI */
			*next_hop = *ruri;
			break;
		default:
			/* probably a mem corruption */
			LM_BUG("next hop of original request marked as both loose"
					" and strict router (buffer: %.*s).\n",
					inv_rb->buffer_len, inv_rb->buffer);
#ifdef EXTRA_DEBUG
			abort();
#else
			goto error;
#endif
		}
	}

	*list = rtset;
	free_sip_msg(&orig_inv);
	/* all went well */
	return 0;

error:
	free_sip_msg(&orig_inv);
	if (rtset)
		free_rte_list(rtset);
	return -1;
}
示例#27
0
/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
{
    struct sip_msg* msg;
    int ret;
#ifdef STATS
    int skipped = 1;
    struct timeval tvb, tve;
    struct timezone tz;
    unsigned int diff;
#endif

    msg=pkg_malloc(sizeof(struct sip_msg));
    if (msg==0) {
        LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
        goto error00;
    }
    msg_no++;
    /* number of vias parsed -- good for diagnostic info in replies */
    via_cnt=0;

    memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
    /* fill in msg */
    msg->buf=buf;
    msg->len=len;
    /* zero termination (termination of orig message bellow not that
       useful as most of the work is done with scrath-pad; -jiri  */
    /* buf[len]=0; */ /* WARNING: zero term removed! */
    msg->rcv=*rcv_info;
    msg->id=msg_no;
    msg->set_global_address=default_global_address;
    msg->set_global_port=default_global_port;

    if (parse_msg(buf,len, msg)!=0) {
        LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
        goto error02;
    }
    DBG("After parse_msg...\n");


    /* ... clear branches from previous message */
    clear_branches();

    if (msg->first_line.type==SIP_REQUEST) {
        /* sanity checks */
        if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)) {
            /* no via, send back error ? */
            LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
            goto error;
        }
        /* check if neccesarry to add receive?->moved to forward_req */

        DBG("preparing to run routing scripts...\n");
#ifdef  STATS
        gettimeofday( & tvb, &tz );
#endif
        /* execute pre-script callbacks, if any; -jiri */
        /* if some of the callbacks said not to continue with
           script processing, don't do so
           if we are here basic sanity checks are already done
           (like presence of at least one via), so you can count
           on via1 being parsed in a pre-script callback --andrei
        */
        ret=exec_pre_cb(msg);
        if (ret<=0) {
            if (ret<0) goto error;
            else goto end; /* drop the message -- no error -- andrei */
        }
        /* exec the routing script */
        if (run_actions(rlist[0], msg)<0) {
            LOG(L_WARN, "WARNING: receive_msg: "
                "error while trying script\n");
            goto error;
        }

#ifdef STATS
        gettimeofday( & tve, &tz );
        diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
        stats->processed_requests++;
        stats->acc_req_time += diff;
        DBG("succesfully ran routing scripts...(%d usec)\n", diff);
        STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif
    } else if (msg->first_line.type==SIP_REPLY) {
        /* sanity checks */
        if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)) {
            /* no via, send back error ? */
            LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
            goto error;
        }
#if 0
        if ((msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
            /* no second via => error? */
            LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
            goto error;
        }
        /* check if via1 == us */
#endif

#ifdef STATS
        gettimeofday( & tvb, &tz );
        STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif

        /* execute pre-script callbacks, if any; -jiri */
        /* if some of the callbacks said not to continue with
           script processing, don't do so
           if we are here basic sanity checks are already done
           (like presence of at least one via), so you can count
           on via1 being parsed in a pre-script callback --andrei
        */
        ret=exec_pre_cb(msg);
        if (ret<=0) {
            if (ret<0) goto error;
            else goto end; /* drop the message -- no error -- andrei */
        }

        /* send the msg */
        forward_reply(msg);

#ifdef STATS
        gettimeofday( & tve, &tz );
        diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
        stats->processed_responses++;
        stats->acc_res_time+=diff;
        DBG("succesfully ran reply processing...(%d usec)\n", diff);
#endif
    }
end:
#ifdef STATS
    skipped = 0;
#endif
    /* execute post-script callbacks, if any; -jiri */
    exec_post_cb(msg);
    /* free possible loaded avps -bogdan */
    reset_avps();
    DBG("receive_msg: cleaning up\n");
    free_sip_msg(msg);
    pkg_free(msg);
#ifdef STATS
    if (skipped) STATS_RX_DROPS;
#endif
    return 0;
error:
    DBG("error:...\n");
    /* execute post-script callbacks, if any; -jiri */
    exec_post_cb(msg);
    /* free possible loaded avps -bogdan */
    reset_avps();
error02:
    free_sip_msg(msg);
    pkg_free(msg);
error00:
    STATS_RX_DROPS;
    return -1;
}
示例#28
0
static ticks_t timer_handler(ticks_t ticks, struct timer_ln* tl, void* data) {
	/*?min length of first line of message is 16 char!?*/
	#define MSG "GET /timer HTTP/0.9\n\n"
	struct sip_msg* msg;
	struct timer_action *a;
	struct run_act_ctx ra_ctx;

	a = data;
	if (!a->disable_itself) {

		DEBUG(MODULE_NAME": handler: called at %d ticks, timer: '%s', pid:%d\n", ticks, a->timer_name, getpid());

		if (a->route_no >= main_rt.idx) {
			BUG(MODULE_NAME": invalid routing table number #%d of %d\n", a->route_no, main_rt.idx);
			goto err2;
		}
		if (!main_rt.rlist[a->route_no]) {
			WARN(MODULE_NAME": route not declared (hash:%d)\n", a->route_no);
			goto err2;
		}
		msg=pkg_malloc(sizeof(struct sip_msg));
		if (msg==0) {
			ERR(MODULE_NAME": handler: no mem for sip_msg\n");
			goto err2;
		}
		timer_msg_no++;
		memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */

		msg->buf=MSG;
		msg->len=sizeof(MSG)-1;

		msg->rcv= rcv_info;
		msg->id=timer_msg_no;
		msg->set_global_address=default_global_address;
		msg->set_global_port=default_global_port;

		if (parse_msg(msg->buf, msg->len, msg)!=0){
			ERR(MODULE_NAME": handler: parse_msg failed\n");
			goto err;
		}
		/* ... clear branches from previous message */
		clear_branches();
		reset_static_buffer();
		if (exec_pre_req_cb(msg)==0 )
			goto end; /* drop the request */
		/* exec the routing script */
		timer_executed = a;
		init_run_actions_ctx(&ra_ctx);
		run_actions(&ra_ctx, main_rt.rlist[a->route_no], msg);
		timer_executed = 0;
		/* execute post request-script callbacks */
		exec_post_req_cb(msg);
	end:
		reset_avps();
		DEBUG(MODULE_NAME": handler: cleaning up\n");
	err:
		free_sip_msg(msg);
		pkg_free(msg);
	err2:	;
	}
        /* begin critical section */
	if (a->disable_itself) {

		timer_allow_del(a->link);
		timer_del(a->link);
		timer_reinit(a->link);
		a->disable_itself = 0;
	        /* end critical section */
		return 0;   /* do no call more */
	}
	else
        	return (ticks_t)(-1); /* periodical */
}
示例#29
0
文件: sip.c 项目: hfreire/sipc
/*****************************************************************************
 * @name
 * @description
 * @param						
 * @return
 */
void handle_sip_msg(sip_session_t *session, char *str)
{
    int l;
    char *s;
    sip_msg_t *msg;
    struct sockaddr_in addr;

    msg = read_sip_msg(str);

    switch(session->curr_state)
    {
    case REGISTERING:
        if(msg->type == ANSWER && msg->code >= 200 && msg->code < 300)
        {
            fprintf(stdout,"Registo efectuado com sucesso.\n");
            session->prev_state = REGISTERING;
            session->curr_state = REGISTERED;
        }
        else if(msg->type == ANSWER && msg->code < 100 && msg->code > 200)
        {
            fprintf(stdout,"Registo não efectuado.\n");
            exit(1);
        }
        free_sip_call(msg->call);
        break;
    case REGISTERED:
        if(msg->type == REQUEST && !strcmp(msg->method,"INVITE") && msg->contact != NULL)
        {
            session->call = msg->call;
            session->seq = msg->cseq;

            session->call->sport = ntohs(addr.sin_port);


            session->call->addr.sin_family = AF_INET;
            session->call->addr.sin_addr.s_addr = inet_addr(session->call->dip);
            session->call->addr.sin_port = htons(session->call->dport);
            session->call->rtp_session.nseqpkt = 0;
            session->call->rtp_session.firstpkt = TRUE;


            session->call->socket = open_udp_socket(session->localip,session->call->sport);

            l = sizeof(addr);
            //if(getsockname(session->call->socket, (struct sockaddr *) &addr, (socklen_t *) &l)) die_with_error("getsockname() //failed");



            s = mk_sip_msg(session, DEFAULT_EXPIRATION, INVITE_OK);

            if((l = sendto(session->socket,s,strlen(s)+1,0,(struct sockaddr *) &(session->addr), sizeof(session->addr))) != strlen(s)+1)
                die_with_error("sendto() failed");

            session->prev_state = REGISTERED;
            session->curr_state = INVITED;

        }
        break;
    case INVITING:
        if(msg->type == ANSWER && msg->code >= 200 && msg->code < 300)
        {
            printf("ACK\n");

            session->call->dport = msg->call->dport;

            session->call->tag = (char *) malloc((strlen(msg->call->tag)+1)*sizeof(char));
            memset(session->call->tag,'\0',strlen(msg->call->tag)+1);
            memcpy(session->call->tag,msg->call->tag,strlen(msg->call->tag));
            session->call->addr.sin_family = AF_INET;
            session->call->addr.sin_addr.s_addr = inet_addr(session->call->dip);
            session->call->addr.sin_port = htons(session->call->dport);



            s = mk_sip_msg(session, DEFAULT_EXPIRATION, ACK);



            if((l = sendto(session->socket,s,strlen(s)+1,0,(struct sockaddr *) &(session->addr), sizeof(session->addr))) != strlen(s)+1)
                die_with_error("sendto() failed");

            free_sip_call(msg->call);

            session->prev_state = INVITING;
            session->curr_state = ONCALL;

        }
        else if(msg->type == ANSWER && msg->code == 404)
        {

            session->call->tag = (char *) malloc((strlen(msg->call->tag)+1)*sizeof(char));
            memset(session->call->tag,'\0',strlen(msg->call->tag)+1);
            memcpy(session->call->tag,msg->call->tag,strlen(msg->call->tag));
            //session->call->addr.sin_family = AF_INET;
            //session->call->addr.sin_addr.s_addr = inet_addr(session->call->dip);
            //session->call->addr.sin_port = htons(session->call->dport);

            s = mk_sip_msg(session, DEFAULT_EXPIRATION, ACK);

            if((l = sendto(session->socket,s,strlen(s)+1,0,(struct sockaddr *) &(session->addr), sizeof(session->addr))) != strlen(s)+1)
                die_with_error("sendto() failed");

            free_sip_call(msg->call);
            free_sip_call(session->call);
            session->call = NULL;

            fprintf(stdout,"\nNão foi encontrada nenhuma aplicação VoIP no destino.\n");
            session->prev_state = INVITING;
            session->curr_state = REGISTERED;
        }
        break;
    case INVITED:
        if(msg->type == REQUEST && !strcmp(msg->method,"ACK"))
        {

            session->prev_state = INVITED;
            session->curr_state = ONCALL;
        }
        free_sip_call(msg->call);
        break;
    case ONCALL:
        if(msg->type == REQUEST && !strcmp(msg->method,"BYE"))
        {
            session->seq = msg->cseq;

            s = mk_sip_msg(session, DEFAULT_EXPIRATION, BYE_OK);

            if((l = sendto(session->socket,s,strlen(s)+1,0,(struct sockaddr *) &(session->addr), sizeof(session->addr))) != strlen(s)+1)
                die_with_error("sendto() failed");

            close(session->call->socket);
            free_sip_call(session->call);
            session->call = NULL;
            free_sip_call(msg->call);

            session->prev_state = ONCALL;
            session->curr_state = REGISTERED;
        }
        break;
    case BYE:
        if(msg->type == ANSWER && msg->code >= 200 && msg->code < 300)
        {

            session->prev_state = BYE;
            session->curr_state = REGISTERED;
            free_sip_call(msg->call);
            free_sip_call(session->call);
            session->call = NULL;
        }
        break;
    case UNREGISTERING:
        if(msg->type == ANSWER && msg->code >= 200 && msg->code < 300)
        {
            session->prev_state = REGISTERED;
            session->curr_state = UNREGISTERED;
            free_sip_call(msg->call);
        }
        break;

    }

    free_sip_msg(msg);

}
示例#30
0
文件: textopsx.c 项目: gbour/kamailio
static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2)
{
	struct dest_info dst;
	str obuf;
	sip_msg_t tmp;

	if(msg->first_line.type!=SIP_REPLY && get_route_type()!=REQUEST_ROUTE)
	{
		LM_ERR("invalid usage - not in request route\n");
		return -1;
	}

	init_dest_info(&dst);
	dst.proto = PROTO_UDP;
	if(msg->first_line.type == SIP_REPLY) {
		obuf.s = generate_res_buf_from_sip_res(msg,
				(unsigned int*)&obuf.len, BUILD_NO_VIA1_UPDATE);
	} else {
		if(msg->msg_flags & FL_RR_ADDED) {
			LM_ERR("cannot apply msg changes after adding record-route"
					" header - it breaks conditional 2nd header\n");
			return -1;
		}
		obuf.s = build_req_buf_from_sip_req(msg,
				(unsigned int*)&obuf.len, &dst,
				BUILD_NO_PATH|BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE);
	}
	if(obuf.s == NULL)
	{
		LM_ERR("couldn't update msg buffer content\n");
		return -1;
	}
	if(obuf.len>=BUF_SIZE)
	{
		LM_ERR("new buffer overflow (%d)\n", obuf.len);
		pkg_free(obuf.s);
		return -1;
	}
	/* temporary copy */
	memcpy(&tmp, msg, sizeof(sip_msg_t));

	/* reset dst uri and path vector to avoid freeing - restored later */
	if(msg->dst_uri.s!=NULL)
	{
		msg->dst_uri.s = NULL;
		msg->dst_uri.len = 0;
	}
	if(msg->path_vec.s!=NULL)
	{
		msg->path_vec.s = NULL;
		msg->path_vec.len = 0;
	}

	/* free old msg structure */
	free_sip_msg(msg);
	memset(msg, 0, sizeof(sip_msg_t));

	/* restore msg fields */
	msg->buf                = tmp.buf;
	msg->id                 = tmp.id;
	msg->rcv                = tmp.rcv;
	msg->set_global_address = tmp.set_global_address;
	msg->set_global_port    = tmp.set_global_port;
	msg->flags              = tmp.flags;
	msg->msg_flags          = tmp.msg_flags;
	msg->hash_index         = tmp.hash_index;
	msg->force_send_socket  = tmp.force_send_socket;
	msg->fwd_send_flags     = tmp.fwd_send_flags;
	msg->rpl_send_flags     = tmp.rpl_send_flags;
	msg->dst_uri            = tmp.dst_uri;
	msg->path_vec           = tmp.path_vec;

	memcpy(msg->buf, obuf.s, obuf.len);
	msg->len = obuf.len;
	msg->buf[msg->len] = '\0';

	/* free new buffer - copied in the static buffer from old sip_msg_t */
	pkg_free(obuf.s);

	/* reparse the message */
	LM_DBG("SIP message content updated - reparsing\n");
	if (parse_msg(msg->buf, msg->len, msg)!=0){
		LM_ERR("parsing new sip message failed\n");
		return -1;
	}

	return 1;
}