⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t_reply.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 4 页
字号:
	memcpy( b, t->uas.response.buffer, len );	UNLOCK_REPLIES( t );	SEND_PR_BUFFER( & t->uas.response, b, len );	DBG("DEBUG: reply retransmitted. buf=%p: %.9s..., shmem=%p: %.9s\n", 		b, b, t->uas.response.buffer, t->uas.response.buffer );	return 1;error:	UNLOCK_REPLIES(t);	return -1;}int t_reply( struct cell *t, struct sip_msg* p_msg, unsigned int code, 	char * text ){	return _reply( t, p_msg, code, text, 1 /* lock replies */ );}int t_reply_unsafe( struct cell *t, struct sip_msg* p_msg, unsigned int code, 	char * text ){	return _reply( t, p_msg, code, text, 0 /* don't lock replies */ );}void set_final_timer( /* struct s_table *h_table, */ struct cell *t ){	if ( !is_local(t) && t->uas.request->REQ_METHOD==METHOD_INVITE ) {		/* crank timers for negative replies */		if (t->uas.status>=300) {			start_retr(&t->uas.response);			return;		}		/* local UAS retransmits too */		if (t->relaied_reply_branch==-2 && t->uas.status>=200) {			/* we retransmit 200/INVs regardless of transport --			   even if TCP used, UDP could be used upstream and			   loose the 200, which is not retransmitted by proxies			*/			force_retr( &t->uas.response );			return;		}	} 	put_on_wait(t);}void cleanup_uac_timers( struct cell *t ){	int i;	/* reset FR/retransmission timers */	for (i=0; i<t->nr_of_outgoings; i++ )  {		reset_timer( &t->uac[i].request.retr_timer );		reset_timer( &t->uac[i].request.fr_timer );	}	DBG("DEBUG: cleanup_uac_timers: RETR/FR timers reset\n");}static int store_reply( struct cell *trans, int branch, struct sip_msg *rpl){#		ifdef EXTRA_DEBUG		if (trans->uac[branch].reply) {			LOG(L_ERR, "ERROR: replacing stored reply; aborting\n");			abort();		}#		endif		/* when we later do things such as challenge aggregation,	   	   we should parse the message here before we conserve		   it in shared memory; -jiri		*/		if (rpl==FAKED_REPLY)			trans->uac[branch].reply=FAKED_REPLY;		else			trans->uac[branch].reply = sip_msg_cloner( rpl, 0 );		if (! trans->uac[branch].reply ) {			LOG(L_ERR, "ERROR: store_reply: can't alloc' clone memory\n");			return 0;		}		return 1;}/* this is the code which decides what and when shall be relayed   upstream; note well -- it assumes it is entered locked with    REPLY_LOCK and it returns unlocked!*/enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, 	unsigned int msg_status, branch_bm_t *cancel_bitmap ){	int relay;	int save_clone;	char *buf;	/* length of outbound reply */	unsigned int res_len;	int relayed_code;	struct sip_msg *relayed_msg;	struct bookmark bm;	int totag_retr;	enum rps reply_status;	/* retransmission structure of outbound reply and request */	struct retr_buf *uas_rb;	/* keep compiler warnings about use of uninit vars silent */	res_len=0;	buf=0;	relayed_msg=0;	relayed_code=0;	totag_retr=0;	/* remember, what was sent upstream to know whether we are	 * forwarding a first final reply or not */	/* *** store and relay message as needed *** */	reply_status = t_should_relay_response(t, msg_status, branch, 		&save_clone, &relay, cancel_bitmap, p_msg );	DBG("DEBUG: relay_reply: branch=%d, save=%d, relay=%d\n",		branch, save_clone, relay );	/* store the message if needed */	if (save_clone) /* save for later use, typically branch picking */	{		if (!store_reply( t, branch, p_msg ))			goto error01;	}	uas_rb = & t->uas.response;	if (relay >= 0 ) {		/* initialize sockets for outbound reply */		uas_rb->activ_type=msg_status;		/* only messages known to be relayed immediately will be		 * be called on; we do not evoke this callback on messages		 * stored in shmem -- they are fixed and one cannot change them		 * anyway */		if (msg_status<300 && branch==relay		&& has_tran_tmcbs(t,TMCB_RESPONSE_FWDED) ) {			run_trans_callbacks( TMCB_RESPONSE_FWDED, t, t->uas.request,				p_msg, msg_status );		}		/* try building the outbound reply from either the current		 * or a stored message */		relayed_msg = branch==relay ? p_msg :  t->uac[relay].reply;		if (relayed_msg==FAKED_REPLY) {			tm_stats->replied_localy++;			relayed_code = branch==relay				? msg_status : t->uac[relay].last_received;			if (relayed_code>=180 && t->uas.request->to 					&& (get_to(t->uas.request)->tag_value.s==0 			    		|| get_to(t->uas.request)->tag_value.len==0)) {				calc_crc_suffix( t->uas.request, tm_tag_suffix );				buf = build_res_buf_from_sip_req(						relayed_code,						error_text(relayed_code),						&tm_tag,						t->uas.request, &res_len, &bm );			} else {				buf = build_res_buf_from_sip_req( relayed_code,					error_text(relayed_code), 0/* no to-tag */,					t->uas.request, &res_len, &bm );			}		} else {			relayed_code=relayed_msg->REPLY_STATUS;			buf = build_res_buf_from_sip_res( relayed_msg, &res_len );			/* if we build a message from shmem, we need to remove			   via delete lumps which are now stirred in the shmem-ed			   structure			*/			if (branch!=relay) {				free_via_clen_lump(&relayed_msg->add_rm);			}		}		update_reply_stats( relayed_code );		if (!buf) {			LOG(L_ERR, "ERROR: relay_reply: "				"no mem for outbound reply buffer\n");			goto error02;		}		/* attempt to copy the message to UAS's shmem:		   - copy to-tag for ACK matching as well		   -  allocate little a bit more for provisional as		      larger messages are likely to follow and we will be 		      able to reuse the memory frag 		*/		uas_rb->buffer = (char*)shm_resize( uas_rb->buffer, res_len +			(msg_status<200 ?  REPLY_OVERBUFFER_LEN : 0));		if (!uas_rb->buffer) {			LOG(L_ERR, "ERROR: relay_reply: cannot alloc reply shmem\n");			goto error03;		}		uas_rb->buffer_len = res_len;		memcpy( uas_rb->buffer, buf, res_len );		if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */			update_local_tags(t, &bm, uas_rb->buffer, buf);		}		tm_stats->replied_localy++;		/* update the status ... */		t->uas.status = relayed_code;		t->relaied_reply_branch = relay;		if (is_invite(t) && relayed_msg!=FAKED_REPLY		&& relayed_code>=200 && relayed_code < 300		&& has_tran_tmcbs( t, TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) ) {			totag_retr=update_totag_set(t, relayed_msg);		}	}; /* if relay ... */	UNLOCK_REPLIES( t );	     /* Setup retransmission timer _before_ the reply is sent	      * to avoid race conditions	      */	if (reply_status == RPS_COMPLETED) {		set_final_timer(t);	}	/* send it now (from the private buffer) */	if (relay >= 0) {		SEND_PR_BUFFER( uas_rb, buf, res_len );		DBG("DEBUG: reply relayed. buf=%p: %.9s..., shmem=%p: %.9s\n", 			buf, buf, uas_rb->buffer, uas_rb->buffer );		if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) {			run_trans_callbacks( TMCB_RESPONSE_OUT, t, t->uas.request,				relayed_msg, relayed_code);		}		pkg_free( buf );	}	/* success */	return reply_status;error03:	pkg_free( buf );error02:	if (save_clone) {		if (t->uac[branch].reply!=FAKED_REPLY)			sip_msg_free( t->uac[branch].reply );		t->uac[branch].reply = NULL;		}error01:	t_reply_unsafe( t, t->uas.request, 500, "Reply processing error" );	UNLOCK_REPLIES(t);	if (is_invite(t)) cancel_uacs( t, *cancel_bitmap );	/* a serious error occurred -- attempt to send an error reply;	   it will take care of clean-ups  */	/* failure */	return RPS_ERROR;}/* this is the "UAC" above transaction layer; if a final reply   is received, it triggers a callback; note well -- it assumes   it is entered locked with REPLY_LOCK and it returns unlocked!*/enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, 	unsigned int msg_status, branch_bm_t *cancel_bitmap){	/* how to deal with replies for local transaction */	int local_store, local_winner;	enum rps reply_status;	struct sip_msg *winning_msg;	int winning_code;	int totag_retr;	/* branch_bm_t cancel_bitmap; */	/* keep warning 'var might be used un-inited' silent */		winning_msg=0;	winning_code=0;	totag_retr=0;	*cancel_bitmap=0;	reply_status=t_should_relay_response( t, msg_status, branch,		&local_store, &local_winner, cancel_bitmap, p_msg );	DBG("DEBUG: local_reply: branch=%d, save=%d, winner=%d\n",		branch, local_store, local_winner );	if (local_store) {		if (!store_reply(t, branch, p_msg))			goto error;	}	if (local_winner>=0) {		winning_msg= branch==local_winner 			? p_msg :  t->uac[local_winner].reply;		if (winning_msg==FAKED_REPLY) {			tm_stats->replied_localy++;			winning_code = branch==local_winner				? msg_status : t->uac[local_winner].last_received;		} else {			winning_code=winning_msg->REPLY_STATUS;		}		t->uas.status = winning_code;		update_reply_stats( winning_code );		if (is_invite(t) && winning_msg!=FAKED_REPLY		&& winning_code>=200 && winning_code <300		&& has_tran_tmcbs(t,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) )  {			totag_retr=update_totag_set(t, winning_msg);		}	}	UNLOCK_REPLIES(t);	if (local_winner>=0 && winning_code>=200 ) {		DBG("DEBUG: local transaction completed\n");		if (!totag_retr) {			if ( has_tran_tmcbs(t,TMCB_LOCAL_COMPLETED) )				run_trans_callbacks( TMCB_LOCAL_COMPLETED, t, 0,					winning_msg, winning_code );		}	}	return reply_status;error:	which_cancel(t, cancel_bitmap);	UNLOCK_REPLIES(t);	cleanup_uac_timers(t);	if ( get_cseq(p_msg)->method.len==INVITE_LEN 		&& memcmp( get_cseq(p_msg)->method.s, INVITE, INVITE_LEN)==0)		cancel_uacs( t, *cancel_bitmap );	put_on_wait(t);	return RPS_ERROR;}/*  This function is called whenever a reply for our module is received;   * we need to register  this function on module initialization;  *  Returns :   0 - core router stops  *              1 - core router relay statelessly  */int reply_received( struct sip_msg  *p_msg ){	int msg_status, last_uac_status, branch, reply_status;	char *ack;	unsigned int ack_len, timer;	     /* has the transaction completed now and we need to clean-up? */	branch_bm_t cancel_bitmap;	struct ua_client *uac;	struct cell *t;	str next_hop;	struct usr_avp **backup_list;	     /* make sure we know the associated transaction ... */	if (t_check(p_msg, &branch ) == -1) return 1;		     /*... if there is none, tell the core router to fwd statelessly */	t = get_t();	if ((t == 0) || (t == T_UNDEFINED)) return 1;	cancel_bitmap=0;	msg_status=p_msg->REPLY_STATUS;	uac=&t->uac[branch];	DBG("DEBUG: reply_received: org. status uas=%d, "		"uac[%d]=%d local=%d is_invite=%d)\n",		t->uas.status, branch, uac->last_received, 		is_local(t), is_invite(t));	last_uac_status=uac->last_received;	     /* it's a cancel ... ? */	if (get_cseq(p_msg)->method.len == CANCEL_LEN 	    && memcmp( get_cseq(p_msg)->method.s, CANCEL, CANCEL_LEN) == 0		 /* .. which is not e2e ? ... */	    && is_invite(t) ) {		     /* ... then just stop timers */		reset_timer( &uac->local_cancel.retr_timer);		if ( msg_status >= 200 ) {				reset_timer( &uac->local_cancel.fr_timer);		}		DBG("DEBUG: reply to local CANCEL processed\n");		goto done;	}	     /* *** stop timers *** */	     /* stop retransmission */	reset_timer(&uac->request.retr_timer);		     /* stop final response timer only if I got a final response */	if ( msg_status >= 200 ) {		reset_timer( &uac->request.fr_timer);	}	     /* acknowledge negative INVITE replies (do it before detailed	      * on_reply processing, which may take very long, like if it	      * is attempted to establish a TCP connection to a fail-over dst */	if (is_invite(t)) {		if (msg_status >= 300) {			ack = build_ack(p_msg, t, branch, &ack_len);			if (ack) {				SEND_PR_BUFFER(&uac->request, ack, ack_len);				shm_free(ack);			}		} else if (is_local(t) && msg_status >= 200) {			ack = build_local_ack(p_msg, t, branch, &ack_len, &next_hop);			if (ack) {				if (send_local_ack(p_msg, &next_hop, ack, ack_len) < 0) {					LOG(L_ERR, "Error while sending local ACK\n");				}				shm_free(ack);			}		}	}	     /* processing of on_reply block */	if (t->on_reply) {		rmode = MODE_ONREPLY;		     /* transfer transaction flag to message context */		if (t->uas.request) p_msg->flags = t->uas.request->flags;		     /* set the as avp_list the one from transaction */		backup_list = set_avp_list(&t->user_avps);		if (run_actions(onreply_rlist[t->on_reply], p_msg)<0) {			LOG(L_ERR, "ERROR: on_reply processing failed\n");		}		     /* transfer current message context back to t */		if (t->uas.request) t->uas.request->flags=p_msg->flags;		     /* restore original avp list */		set_avp_list( backup_list );	}		LOCK_REPLIES( t );	if (is_local(t)) {		reply_status = local_reply(t, p_msg, branch, msg_status, &cancel_bitmap);		if (reply_status == RPS_COMPLETED) {			cleanup_uac_timers(t);			if (is_invite(t)) cancel_uacs(t, cancel_bitmap);			     /* There is no need to call set_final_timer because we know			      * that the transaction is local */			put_on_wait(t);		}	} else {		reply_status = relay_reply(t, p_msg, branch, msg_status, &cancel_bitmap);		     /* clean-up the transaction when transaction completed */		if (reply_status == RPS_COMPLETED) {			     /* no more UAC FR/RETR (if I received a 2xx, there may			      * be still pending branches ...			      */			cleanup_uac_timers(t);	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -