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

📄 sip_xaction_state_mc.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 3 页
字号:
				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)) {				break;			} 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;		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);}/* * -------------------------- Input Routines --------------------------- *//* Process an incoming SIP message Request or Response */intsip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t **sip_msg){	sip_message_type_t	*sip_msg_info;	int			ret;	sip_msg_info = (*sip_msg)->sip_msg_req_res;	if (sip_msg_info->is_request)		ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg);	else		ret = sip_clnt_xaction_input(conn_obj, sip_trans, sip_msg);	return (ret);}/* Process a Request from the transport */static intsip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t **sip_msg){	sip_message_type_t	*sip_msg_info;	_sip_msg_t		*msg = *sip_msg;	int			prev_state;	boolean_t		isreliable;	sip_msg_info = msg->sip_msg_req_res;	isreliable = sip_is_conn_reliable(conn_obj);	/*	 * Cancel if the original transaction has not yet got a final	 * response and send a 487 response.	 */	if (sip_msg_info->sip_req_method == ACK) {		_sip_msg_t		*sip_last_resp;		const sip_str_t		*resp_to_tag;		const sip_str_t		*req_to_tag;		int			error;		sip_message_type_t	*last_msg_info;		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);		if (sip_trans->sip_xaction_last_msg != NULL)			sip_last_resp = sip_trans->sip_xaction_last_msg;		else			sip_last_resp = sip_trans->sip_xaction_orig_msg;		last_msg_info = sip_last_resp->sip_msg_req_res;		if (last_msg_info->is_request) {			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (0);		}		req_to_tag = sip_get_to_tag((sip_msg_t)msg, &error);		if (req_to_tag == NULL || error != 0) {			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (0);		}		resp_to_tag = sip_get_to_tag((sip_msg_t)sip_last_resp,		    &error);		if (req_to_tag == NULL || error != 0) {			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (0);		}		if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len ||		    strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr,			req_to_tag->sip_str_len) != 0) {			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (0);		}		prev_state = sip_trans->sip_xaction_state;		if (sip_trans->sip_xaction_state == SIPS_SRV_INV_COMPLETED) {			sip_xaction_time_obj_t	*timer_obj_I = NULL;			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);			/*			 * Cancel Timer H and goto TERMINATED state for			 * reliable transports.			 */			if (isreliable) {				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TH);				sip_trans->sip_xaction_state =				    SIPS_SRV_INV_TERMINATED;				(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);			}			/*			 * For unreliable transports, start TIMER I and			 * transition to CONFIRMED state.			 */			timer_obj_I = sip_setup_timer(conn_obj, sip_trans,			    NULL,			    sip_trans->sip_xaction_TI, SIP_XACTION_TIMER_I);			if (timer_obj_I == NULL) {				(void) pthread_mutex_unlock(				    &sip_trans->sip_xaction_mutex);				return (ENOMEM);			}			SIP_SCHED_TIMER(sip_trans->sip_xaction_TI,			    timer_obj_I, sip_xaction_state_timer_fire);			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TI)) {				(void) pthread_mutex_unlock(				    &sip_trans->sip_xaction_mutex);				free(timer_obj_I);				return (ENOMEM);			}			sip_trans->sip_xaction_state = SIPS_SRV_CONFIRMED;		}		(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);	} else if (sip_msg_info->sip_req_method == CANCEL) {		if (sip_trans->sip_xaction_method == INVITE) {			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (0);		}	}	if (sip_msg_info->sip_req_method == INVITE) {		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);		assert(sip_trans->sip_xaction_method == INVITE);		/* Retransmitted invite */		switch (sip_trans->sip_xaction_state) {			case SIPS_SRV_INV_PROCEEDING:			case SIPS_SRV_INV_COMPLETED:				if (sip_trans->sip_xaction_last_msg != NULL) {					_sip_msg_t	*new_msg;					new_msg =					    sip_trans->sip_xaction_last_msg;					(void) sip_stack_send(conn_obj,					    new_msg->sip_msg_buf,					    new_msg->sip_msg_len);				}				break;			default:				(void) pthread_mutex_unlock(				    &sip_trans->sip_xaction_mutex);				return (EPROTO);		}		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);		sip_free_msg((sip_msg_t)msg);		*sip_msg = NULL;		return (0);	}	/* Retransmitted request */	assert(sip_trans->sip_xaction_method != INVITE);	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);	switch (sip_trans->sip_xaction_state) {		case SIPS_SRV_NONINV_PROCEEDING:		case SIPS_SRV_NONINV_COMPLETED:			if (sip_trans->sip_xaction_last_msg != NULL) {				_sip_msg_t	*new_msg;				new_msg = sip_trans->sip_xaction_last_msg;				(void) sip_stack_send(conn_obj,				    new_msg->sip_msg_buf, new_msg->sip_msg_len);			}			break;		default:			(void) pthread_mutex_unlock(			    &sip_trans->sip_xaction_mutex);			return (EPROTO);	}	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);	sip_free_msg((sip_msg_t)msg);	*sip_msg = NULL;	return (0);}/* Process a Response */static intsip_clnt_xaction_input(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_clnt_xaction_inv_res(conn_obj, sip_trans, msg);	else		ret = sip_clnt_xaction_noninv_res(conn_obj, sip_trans, msg);	return (ret);}static intsip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t *msg, boolean_t copy){	_sip_msg_t	*ack_msg;	int		ret = 0;	ack_msg = (_sip_msg_t *)sip_new_msg();	if (ack_msg == NULL)		return (ENOMEM);	if ((ret = sip_create_nonOKack(	    (sip_msg_t)sip_trans->sip_xaction_orig_msg, (sip_msg_t)msg,	    (sip_msg_t)ack_msg)) != 0) {		sip_free_msg((sip_msg_t)ack_msg);		return (ret);	}	if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf,	    ack_msg->sip_msg_len)) != 0) {		sip_free_msg((sip_msg_t)ack_msg);		return (ret);	}	if (copy) {		SIP_MSG_REFCNT_INCR(ack_msg);		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_trans->sip_xaction_last_msg = ack_msg;	}	sip_free_msg((sip_msg_t)ack_msg);	return (0);}/* Process a INVITE Response */static intsip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,    _sip_msg_t **sip_msg){	int			resp_code;	_sip_msg_t		*msg = *sip_msg;	sip_xaction_time_obj_t	*timer_obj_D = NULL;	sip_message_type_t	*sip_msg_info;	int			prev_state;	boolean_t		isreliable;	assert(msg->sip_msg_req_res != NULL);	sip_msg_info = msg->sip_msg_req_res;	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_CLNT_CALLING:			if (SIP_PROVISIONAL_RESP(resp_code)) {				/*				 * sip_trans->sip_xaction_last_msg ?				 */				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TA);				sip_trans->sip_xaction_state =				    SIPS_CLNT_INV_PROCEEDING;			} else if (SIP_OK_RESP(resp_code)) {				/*				 * sip_trans->sip_xaction_last_msg ?				 */				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TA);				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TB);				sip_trans->sip_xaction_state =				    SIPS_CLNT_INV_TERMINATED;			} else if (SIP_NONOK_FINAL_RESP(resp_code)) {				int	ret;				/*				 * sip_trans->sip_xaction_last_msg ?				 */				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TA);				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TB);				if ((ret = sip_create_send_nonOKack(conn_obj,				    sip_trans, msg, B_FALSE)) != 0) {					(void) pthread_mutex_unlock(					    &sip_trans->sip_xaction_mutex);					return (ret);				}				/*				 * start timer D for unreliable transports				 */				if (!isreliable) {					timer_obj_D = sip_setup_timer(					    conn_obj, sip_trans,					    NULL, sip_trans->sip_xaction_TD,					    SIP_XACTION_TIMER_D);					if (timer_obj_D == NULL) {						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						return (ENOMEM);					}					SIP_SCHED_TIMER(					    sip_trans->sip_xaction_TD,					    timer_obj_D,					    sip_xaction_state_timer_fire);					if (!SIP_IS_TIMER_RUNNING(					    sip_trans->sip_xaction_TD)) {						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						free(timer_obj_D);						return (ENOMEM);					}					sip_trans->sip_xaction_state =					    SIPS_CLNT_INV_COMPLETED;				} else {					sip_trans->sip_xaction_state =					    SIPS_CLNT_INV_TERMINATED;				}			} else {				/* Invalid resp_code */				(void) pthread_mutex_unlock(				    &sip_trans->sip_xaction_mutex);				return (EPROTO);			}			break;		case SIPS_CLNT_INV_PROCEEDING:			if (SIP_PROVISIONAL_RESP(resp_code)) {				break;			} else if (SIP_OK_RESP(resp_code)) {				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TB);				sip_trans->sip_xaction_state =				    SIPS_CLNT_INV_TERMINATED;			} else if (SIP_NONOK_FINAL_RESP(resp_code)) {				int	ret;				SIP_CANCEL_TIMER(				    sip_trans->sip_xaction_TB);				if ((ret = sip_create_send_nonOKack(conn_obj,				    sip_trans, msg, B_FALSE)) != 0) {					(void) pthread_mutex_unlock(					    &sip_trans->sip_xaction_mutex);					return (ret);				}				/*				 * start timer D for unreliable transports				 */				if (!isreliable) {					timer_obj_D = sip_setup_timer(					    conn_obj, sip_trans,					    NULL, sip_trans->sip_xaction_TD,					    SIP_XACTION_TIMER_D);					if (timer_obj_D == NULL) {						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						return (ENOMEM);					}					SIP_SCHED_TIMER(					    sip_trans->sip_xaction_TD,					    timer_obj_D,					    sip_xaction_state_timer_fire);					if (!SIP_IS_TIMER_RUNNING(					    sip_trans->sip_xaction_TD)) {						(void) pthread_mutex_unlock(						    &sip_trans->						    sip_xaction_mutex);						free(timer_obj_D);						return (ENOMEM);					}					sip_trans->sip_xaction_state =					    SIPS_CLNT_INV_COMPLETED;				} else {					sip_trans->sip_xaction_state =					    SIPS_CLNT_INV_TERMINATED;				}			} else {				(void) pthread_mutex_unlock(				    &sip_trans->sip_xaction_mutex);				return (EPROTO);			}			break;		case SIPS_CLNT_INV_COMPLETED:			/*			 * Transport error takes it to			 * SIPS_CLNT_INV_TERMINATED			 */			if (SIP_NONOK_FINAL_RESP(resp_code)) {				int	ret;				if ((ret = sip_create_send_nonOKack(conn_obj,				    sip_trans, msg, B_FALSE)) != 0) {					(void) pthread_mutex_unlock(					    &sip_trans->sip_xaction_mutex);					return (ret);				}			} else {				/* Invalid resp_code */				(void) pthread_mutex_unlock(				    &sip_trans->sip_xaction_mutex);				return (EPROTO);			}			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);}/* Process a NON-INVITE Response */static intsip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,    sip_xaction_t *sip_trans, _sip_msg_t **sip_msg){	int			resp_code;

⌨️ 快捷键说明

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