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

📄 sip_xaction_state_mc.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident	"@(#)sip_xaction_state_mc.c	1.13	06/08/16 SMI"/* * SIP Client/Server Invite/Non-Invite Transaction State machine. */#include "sip_xaction.h"#include "sip_msg.h"#include "sip_miscdefs.h"/* * Some Timer related info from RFC 3261, page 265. * * ---------------------------------------------------------------------- * Timer    Value            Section               Meaning * ---------------------------------------------------------------------- * T1       500ms default    Section 17.1.1.1     RTT Estimate * T2       4s               Section 17.1.2.2     The maximum retransmit *                                                interval for non-INVITE *                                                requests and INVITE *                                                responses * T4       5s               Section 17.1.2.2     Maximum duration a *                                                message will *                                                remain in the network * ---------------------------------------------------------------------- * Timer A  initially T1     Section 17.1.1.2     INVITE request retransmit *                                                interval, for UDP only * Timer B  64*T1            Section 17.1.1.2     INVITE transaction *                                                timeout timer * Timer C  > 3min           Section 16.6         proxy INVITE transaction *                            bullet 11            timeout * Timer D  > 32s for UDP    Section 17.1.1.2     Wait time for response *          0s for TCP/SCTP                       retransmits * Timer E  initially T1     Section 17.1.2.2     non-INVITE request *                                                retransmit interval, *                                                UDP only * Timer F  64*T1            Section 17.1.2.2     non-INVITE transaction *                                                timeout timer * Timer G  initially T1     Section 17.2.1       INVITE response *                                                retransmit interval * Timer H  64*T1            Section 17.2.1       Wait time for *                                                ACK receipt * Timer I  T4 for UDP       Section 17.2.1       Wait time for *          0s for TCP/SCTP                       ACK retransmits * Timer J  64*T1 for UDP    Section 17.2.2       Wait time for *          0s for TCP/SCTP                       non-INVITE request *                                                retransmits * Timer K  T4 for UDP       Section 17.1.2.2     Wait time for *          0s for TCP/SCTP                       response retransmits * ---------------------------------------------------------------------- */#ifndef MIN#define	MIN(a, b)	(((a) < (b)) ? (a):(b))#endif/* Arg to the timer fire routine */typedef	struct sip_xaction_timer_obj_s {	sip_xaction_timer_type_t	sip_xaction_timer_type;	sip_xaction_t			*sip_trans;	int				sip_xaction_timer_xport;} sip_xaction_time_obj_t;int		sip_xaction_output(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t *);int		sip_xaction_input(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t **);void		sip_xaction_terminate(sip_xaction_t *, _sip_msg_t *, int);static int 	sip_clnt_xaction_output(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t *);static int	sip_clnt_xaction_input(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t **);static int	sip_clnt_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t **);static int	sip_clnt_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t **);static int 	sip_srv_xaction_output(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t *);static int	sip_srv_xaction_input(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t **);static int	sip_srv_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t *);static int	sip_srv_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t *);static int	sip_create_send_nonOKack(sip_conn_object_t, sip_xaction_t *,		    _sip_msg_t *, boolean_t);void		sip_xaction_state_timer_fire(void *);static sip_xaction_time_obj_t	*sip_setup_timer(sip_conn_object_t,				    sip_xaction_t *, _sip_msg_t *,				    sip_timer_t, int);/* Return a timer object */static sip_xaction_time_obj_t *sip_setup_timer(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t *sip_msg, sip_timer_t timer, int type){	sip_xaction_time_obj_t	*sip_timer_obj = NULL;	sip_timer_obj = (sip_xaction_time_obj_t *)	    malloc(sizeof (sip_xaction_time_obj_t));	if (sip_timer_obj == NULL)		return (NULL);	if (SIP_IS_TIMER_RUNNING(timer))		SIP_CANCEL_TIMER(timer);	sip_timer_obj->sip_xaction_timer_type = type;	sip_timer_obj->sip_xaction_timer_xport = sip_conn_transport(conn_obj);	sip_timer_obj->sip_trans = sip_trans;	/* Save the message */	if (sip_msg != NULL) {		(void) sip_add_conn_obj_cache(conn_obj, (void *)sip_trans);		if (sip_trans->sip_xaction_last_msg != NULL) {			SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);			sip_trans->sip_xaction_last_msg = NULL;		}		SIP_MSG_REFCNT_INCR(sip_msg);		sip_trans->sip_xaction_last_msg = sip_msg;	}	return (sip_timer_obj);}/* * --------------------------- Output Routines --------------------------- *//* Send a SIP message, request or response, out */intsip_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t *msg){	sip_message_type_t	*sip_msg_info;	int			ret;	assert(conn_obj != NULL);	sip_msg_info = msg->sip_msg_req_res;	if (sip_msg_info->is_request)		return (sip_clnt_xaction_output(conn_obj, sip_trans, msg));	ret = sip_srv_xaction_output(conn_obj, sip_trans, msg);	return (ret);}/* Send a Request out */static intsip_clnt_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t *msg){	sip_xaction_time_obj_t	*timer_obj_A = NULL;	sip_xaction_time_obj_t	*timer_obj_B = NULL;	sip_xaction_time_obj_t	*timer_obj_E = NULL;	sip_xaction_time_obj_t	*timer_obj_F = NULL;	sip_message_type_t	*sip_msg_info;	int			prev_state;	int			error = 0;	boolean_t		isreliable;	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);	prev_state = sip_trans->sip_xaction_state;	assert(msg->sip_msg_req_res != NULL);	sip_msg_info = msg->sip_msg_req_res;	isreliable = sip_is_conn_reliable(conn_obj);	if (sip_msg_info->sip_req_method == INVITE) {		/*		 * if transport is not reliable, start TIMER A.		 */		if (!isreliable) {			timer_obj_A = sip_setup_timer(conn_obj, sip_trans,			    msg, sip_trans->sip_xaction_TA,			    SIP_XACTION_TIMER_A);			if (timer_obj_A == NULL) {				error = ENOMEM;				goto error_ret;			}		}		timer_obj_B = sip_setup_timer(conn_obj, sip_trans, NULL,		    sip_trans->sip_xaction_TB, SIP_XACTION_TIMER_B);		if (timer_obj_B == NULL) {			error = ENOMEM;			goto error_ret;		}		if (timer_obj_A != NULL) {			SIP_SCHED_TIMER(sip_trans->sip_xaction_TA, timer_obj_A,			    sip_xaction_state_timer_fire);			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {				error = ENOMEM;				goto error_ret;			}		}		SIP_SCHED_TIMER(sip_trans->sip_xaction_TB, timer_obj_B,		    sip_xaction_state_timer_fire);		if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TB)) {			if (timer_obj_A != NULL)				SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA)			error = ENOMEM;			goto error_ret;		}		sip_trans->sip_xaction_state = SIPS_CLNT_CALLING;	} else {		/*		 * if transport is not reliable, start rexmit Timer E.		 */		if (!isreliable) {			timer_obj_E = sip_setup_timer(conn_obj, sip_trans, msg,			    sip_trans->sip_xaction_TE, SIP_XACTION_TIMER_E);			if (timer_obj_E == NULL) {				error = ENOMEM;				goto error_ret;			}		}		/* Start transaction Timer F */		timer_obj_F = sip_setup_timer(conn_obj, sip_trans, NULL,		    sip_trans->sip_xaction_TF, SIP_XACTION_TIMER_F);		if (timer_obj_F == NULL) {			error = ENOMEM;			goto error_ret;		}		if (timer_obj_E != NULL) {			SIP_SCHED_TIMER(sip_trans->sip_xaction_TE, timer_obj_E,			    sip_xaction_state_timer_fire);			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {				error = ENOMEM;				goto error_ret;			}		}		SIP_SCHED_TIMER(sip_trans->sip_xaction_TF, timer_obj_F,		    sip_xaction_state_timer_fire);		if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TF)) {			if (timer_obj_E != NULL)				SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE)			error = ENOMEM;			goto error_ret;		}		sip_trans->sip_xaction_state = SIPS_CLNT_TRYING;	}	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);	if (sip_xaction_ulp_state_cb != NULL) {		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);	}	return (0);error_ret:	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);	if (timer_obj_A != NULL)		free(timer_obj_A);	if (timer_obj_B != NULL)		free(timer_obj_B);	if (timer_obj_E != NULL)		free(timer_obj_E);	if (timer_obj_F != NULL)		free(timer_obj_F);	return (error);}/* Send a response out */static intsip_srv_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t *msg){	int		ret;	if (sip_trans->sip_xaction_method == INVITE)		ret = sip_srv_xaction_inv_res(conn_obj, sip_trans, msg);	else		ret = sip_srv_xaction_noninv_res(conn_obj, sip_trans, msg);	return (ret);}/* Send a INVITE response out */static intsip_srv_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t *msg){	int			resp_code;	sip_xaction_time_obj_t	*timer_obj_G = NULL;	sip_xaction_time_obj_t	*timer_obj_H = NULL;	sip_message_type_t	*sip_msg_info = msg->sip_msg_req_res;	int			prev_state;	boolean_t		isreliable;	isreliable = sip_is_conn_reliable(conn_obj);	resp_code = sip_msg_info->sip_resp_code;	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);	prev_state = sip_trans->sip_xaction_state;	switch (sip_trans->sip_xaction_state) {		case SIPS_SRV_INV_PROCEEDING:			if (SIP_PROVISIONAL_RESP(resp_code)) {				if (sip_trans->sip_xaction_last_msg != NULL) {					SIP_MSG_REFCNT_DECR(					    sip_trans->sip_xaction_last_msg);					sip_trans->sip_xaction_last_msg = NULL;				}				SIP_MSG_REFCNT_INCR(msg);				sip_trans->sip_xaction_last_msg = msg;				(void) sip_add_conn_obj_cache(conn_obj,				    (void *)sip_trans);			} else if (SIP_OK_RESP(resp_code)) {				sip_trans->sip_xaction_state =				    SIPS_SRV_INV_TERMINATED;			} else  if (SIP_NONOK_FINAL_RESP(resp_code)) {				if (sip_trans->sip_xaction_last_msg != NULL) {					SIP_MSG_REFCNT_DECR(					    sip_trans->sip_xaction_last_msg);					sip_trans->sip_xaction_last_msg = NULL;				}				SIP_MSG_REFCNT_INCR(msg);				sip_trans->sip_xaction_last_msg = msg;				(void) sip_add_conn_obj_cache(conn_obj,				    (void *)sip_trans);				/* For unreliable transport start timer G */				if (!isreliable) {					timer_obj_G = sip_setup_timer(					    conn_obj, sip_trans,					    NULL, sip_trans->sip_xaction_TG,					    SIP_XACTION_TIMER_G);					if (timer_obj_G == NULL) {						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						return (ENOMEM);					}				}				/* Start Timer H */				timer_obj_H = sip_setup_timer(				    conn_obj, sip_trans,				    NULL, sip_trans->sip_xaction_TH,				    SIP_XACTION_TIMER_H);				if (timer_obj_H == NULL) {					if (timer_obj_G != NULL)						free(timer_obj_G);					(void) pthread_mutex_unlock(					    &sip_trans->sip_xaction_mutex);					return (ENOMEM);				}				if (timer_obj_G != NULL) {					SIP_SCHED_TIMER(					    sip_trans->sip_xaction_TG,					    timer_obj_G,					    sip_xaction_state_timer_fire);					if (!SIP_IS_TIMER_RUNNING(					    sip_trans->sip_xaction_TG)) {						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						free(timer_obj_G);						return (ENOMEM);					}				}				if (timer_obj_H != NULL) {					SIP_SCHED_TIMER(					    sip_trans->sip_xaction_TH,					    timer_obj_H,					    sip_xaction_state_timer_fire);					if (!SIP_IS_TIMER_RUNNING(					    sip_trans->sip_xaction_TH)) {						if (timer_obj_G != NULL) {							SIP_CANCEL_TIMER(							    sip_trans->							    sip_xaction_TG);							free(timer_obj_G);						}						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						free(timer_obj_H);						return (ENOMEM);					}				}				sip_trans->sip_xaction_state =				    SIPS_SRV_INV_COMPLETED;			}			break;		default:			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (EPROTO);	}	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);	if (prev_state != sip_trans->sip_xaction_state &&	    sip_xaction_ulp_state_cb != NULL) {		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);	}	return (0);}/* Send a NON-INVITE response out */static intsip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,    sip_xaction_t *sip_trans, _sip_msg_t *msg){	int			resp_code;	sip_xaction_time_obj_t	*timer_obj_J = NULL;	sip_message_type_t	*sip_msg_info = msg->sip_msg_req_res;	int			prev_state;	boolean_t		isreliable;	resp_code = sip_msg_info->sip_resp_code;	isreliable = sip_is_conn_reliable(conn_obj);	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);	prev_state = sip_trans->sip_xaction_state;	switch (sip_trans->sip_xaction_state) {		case SIPS_SRV_TRYING:			if (sip_trans->sip_xaction_last_msg != NULL) {				SIP_MSG_REFCNT_DECR(				    sip_trans->sip_xaction_last_msg);				sip_trans->sip_xaction_last_msg = NULL;			}			SIP_MSG_REFCNT_INCR(msg);			sip_trans->sip_xaction_last_msg = msg;			(void) sip_add_conn_obj_cache(conn_obj,			    (void *)sip_trans);			if (SIP_PROVISIONAL_RESP(resp_code)) {				sip_trans->sip_xaction_state =				    SIPS_SRV_NONINV_PROCEEDING;			} else if (SIP_FINAL_RESP(resp_code)) {				/* For unreliable transports, start Timer J */				if (!isreliable) {					timer_obj_J = sip_setup_timer(					    conn_obj, sip_trans,					    NULL, sip_trans->sip_xaction_TJ,					    SIP_XACTION_TIMER_J);					if (timer_obj_J == NULL) {						(void) pthread_mutex_unlock(&						    sip_trans->						    sip_xaction_mutex);						return (ENOMEM);					}					SIP_SCHED_TIMER(					    sip_trans->sip_xaction_TJ,					    timer_obj_J,					    sip_xaction_state_timer_fire);					if (!SIP_IS_TIMER_RUNNING(					    sip_trans->sip_xaction_TJ)) {						(void) pthread_mutex_unlock(&						    sip_trans->						    sip_xaction_mutex);						free(timer_obj_J);						return (ENOMEM);					}					sip_trans->sip_xaction_state =					    SIPS_SRV_NONINV_COMPLETED;				} else {					sip_trans->sip_xaction_state =					    SIPS_SRV_NONINV_TERMINATED;				}			}			break;		case SIPS_SRV_NONINV_PROCEEDING:			if (sip_trans->sip_xaction_last_msg != NULL) {				SIP_MSG_REFCNT_DECR(				    sip_trans->sip_xaction_last_msg);

⌨️ 快捷键说明

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