rem: if (buf) free( buf );
add: if (buf) pkg_free( buf );
context: int t_on_reply( struct sip_msg  *p_msg ){	unsigned int branch,len, msg_status, msg_class, save_clone;	unsigned int local_cancel;	struct sip_msg *clone, *backup;	int relay;	int start_fr = 0;	int is_invite;	/* retransmission structure of outbound reply and request */	struct retrans_buff *orq_rb, *orp_rb, *ack_rb;	char *buf;	/* length of outbound reply */	unsigned int orp_len;	/* buffer length (might be somewhat larger than message size */	unsigned int alloc_len;	/* make sure we know the assosociated tranaction ... */	if (t_check( p_msg  , &branch , &local_cancel)==-1)		return 1;	/* ... if there is no such, tell the core router to forward statelessly */	if ( T<=0 ) return 1;	/* by default, don't store incoming replies */	save_clone = 0;	backup = 0;	DBG("DEBUG: t_on_reply: Original status=%d (%d,%d)\n",		T->status,branch,local_cancel);	/* special cases (local cancel reply and another 100 reply!)*/	if (p_msg->REPLY_STATUS==100 && T->status==100)		goto error;	if (local_cancel==1)	{		reset_timer( hash_table, &(T->outbound_cancel[branch]->retr_timer));		if ( p_msg->REPLY_STATUS>=200 )			reset_timer( hash_table, &(T->outbound_cancel[branch]->fr_timer));		goto error;	}	/* do we have via2 ? - maybe we'll need it for forwarding -bogdan*/	if ((p_msg->via2==0) || (p_msg->via2->error!=VIA_PARSE_OK)){		/* no second via => error */		LOG(L_ERR, "ERROR: t_on_reply: no 2nd via found in reply\n");		goto error2;	}	/* it can take quite long - better do it now than later	inside a reply_lock */	/* CLONE alloc'ed */	if (!(clone=sip_msg_cloner( p_msg ))) {		goto error;	}	msg_status=p_msg->REPLY_STATUS;	msg_class=REPLY_CLASS(p_msg);	is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE;	/*  generate the retrans buffer, make a simplified	assumption everything but 100 will be fwd-ed;	sometimes it will result in useless CPU cycles	but mostly the assumption holds and allows the	work to be done out of criticial lock region */	if (msg_status==100)		buf=0;	else {		/* buf maybe allo'ed*/		buf = build_res_buf_from_sip_res ( p_msg, &orp_len);		if (!buf) {			LOG(L_ERR, "ERROR: t_on_reply_received: "			"no mem for outbound reply buffer\n");			goto error1;		}	}	/* *** stop timers *** */	orq_rb=T->outbound_request[branch];	/* stop retransmission */	reset_timer( hash_table, &(orq_rb->retr_timer));	/* stop final response timer only if I got a final response */	if ( msg_class>1 )		reset_timer( hash_table, &(orq_rb->fr_timer));	LOCK_REPLIES( T );	/* if a got the first prov. response for an INVITE ->	   change FR_TIME_OUT to INV_FR_TIME_UT */	start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite;	/* *** store and relay message as needed *** */	relay = t_should_relay_response( T , msg_status, branch, &save_clone );	if (relay >= 0 ) {		orp_rb= & T->outbound_response;		/* if there is no reply yet, initialize the structure */		if ( ! orp_rb->retr_buffer ) {			/*init retrans buffer*/			memset( orp_rb , 0 , sizeof (struct retrans_buff) );			if (update_sock_struct_from_via( &(orp_rb->to),p_msg->via2 )==-1) {				UNLOCK_REPLIES( T );				start_fr = 1;				LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: "					"cannot lookup reply dst: %s\n",				p_msg->via2->host.s );				save_clone = 0;				goto error2;			}			orp_rb->retr_timer.tg=TG_RT;			orp_rb->fr_timer.tg=TG_FR;			orp_rb->retr_timer.payload = orp_rb;			orp_rb->fr_timer.payload =  orp_rb;			orp_rb->to.sin_family = AF_INET;			orp_rb->my_T = T;			orp_rb->status = p_msg->REPLY_STATUS;			/* allocate something more for the first message;			   subsequent messages will be longer and buffer			   reusing will save us a malloc lock */			alloc_len = orp_len + REPLY_OVERBUFFER_LEN ;		} else {			alloc_len = orp_len;		}		if (! (orp_rb->retr_buffer = (char *)		shm_resize( orp_rb->retr_buffer, alloc_len ))) {			UNLOCK_REPLIES( T );			start_fr = 1;			save_clone = 0;			LOG(L_ERR, "ERROR: t_on_reply: cannot alloc shmem\n");			goto error2;		};		orp_rb->bufflen=orp_len;		memcpy( orp_rb->retr_buffer, buf, orp_len );		/* update the status ... */		if ((T->status = p_msg->REPLY_STATUS) >=200 &&		/* ... and dst for a possible ACK if we are sending final downstream */			T->relaied_reply_branch==-1 ) {				memcpy( & T->ack_to, & T->outbound_request[ branch ]->to,				sizeof( struct sockaddr_in ) );   				T->relaied_reply_branch = branch;		}	}; /* if relay ... */	if (save_clone) {		backup = T->inbound_response[branch];		T->inbound_response[branch]=clone;		T->tag=&(get_to(clone)->tag_value);	}cleanup:	UNLOCK_REPLIES( T );	if (relay >= 0) {		SEND_PR_BUFFER( orp_rb, buf, orp_len );		t_update_timers_after_sending_reply( orp_rb );	}	/* *** ACK handling *** */	if ( is_invite ) {		if ( T->outbound_ack[branch] )		{   /*retransmit*/			/* I don't need any additional syncing here -- after ack			   is introduced it's never changed */			SEND_BUFFER( T->outbound_ack[branch] );		} else if (msg_class>2 ) {			/*on a non-200 reply to INVITE*/			DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE:"				"send ACK\n");			ack_rb = build_ack( p_msg, T, branch );			if (ack_rb) {				SEND_BUFFER( ack_rb );				/* append to transaction structure */				attach_ack( T, branch, ack_rb );			} else {				/* restart FR */				start_fr=1;				DBG("ERROR: t_on_reply: build_ack failed\n");			}		}	} /* is_invite */	/* restart retransmission if a provisional response came for 	   a non_INVITE -> retrasmit at RT_T2*/	if ( msg_class==1 && !is_invite )	{		orq_rb->retr_list = RT_T2;		set_timer( hash_table, &(orq_rb->retr_timer), RT_T2 );	}	if (backup) sip_msg_free( backup );error2:	if (start_fr) 		set_timer( hash_table, &(orq_rb->fr_timer), FR_INV_TIMER_LIST );	if (buf) free( buf );error1:	if (!save_clone) sip_msg_free( clone );error:	T_UNREF( T );	/* don't try to relay statelessly on error; on troubles, simply do nothing;           that will make the other party to retransmit; hopefuly, we'll then            be better off */	return 0;}