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

📄 sip_dialog.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	if (error != 0)		return (NULL);	callid = sip_get_callid((sip_msg_t)sip_msg, &error);	if (error != 0 || remtag == NULL || localtag == NULL ||	    callid == NULL) {		return (NULL);	}	sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,	    remtag->sip_str_ptr, remtag->sip_str_len,	    callid->sip_str_ptr, callid->sip_str_len,	    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);	dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash,	    (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match);	if (dialog == NULL) {		sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,		    NULL, 0, callid->sip_str_ptr, callid->sip_str_len,		    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);		dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash,		    (void *)digest, SIP_DIGEST_TO_HASH(digest),		    sip_dialog_match);	}	return ((sip_dialog_t)dialog);}/* * We keep this partial dialog for the duration of the INVITE * transaction timeout duration, i.e. Timer B. */voidsip_dlg_self_destruct(void *args){	sip_dialog_timer_obj_t	*tim_obj = (sip_dialog_timer_obj_t *)args;	_sip_dialog_t		*dialog = (_sip_dialog_t *)tim_obj->dialog;	int			index;	if (dialog->sip_dlg_type == SIP_UAC_DIALOG)		SIP_DLG_REFCNT_DECR(dialog);	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);	assert(dialog->sip_dlg_state == SIP_DLG_NEW);	dialog->sip_dlg_state = SIP_DLG_DESTROYED;	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);	if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {		index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);		sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id,		    index, sip_dialog_dontfree);	}	if (tim_obj->func != NULL)		tim_obj->func(dialog, NULL, NULL);	sip_release_dialog_res(dialog);	free(tim_obj);}/* Terminate a dialog */voidsip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg){	int	prev_state;	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);	prev_state = dialog->sip_dlg_state;	dialog->sip_dlg_state = SIP_DLG_DESTROYED;	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);	if (sip_dlg_ulp_state_cb != NULL) {		sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state,		    dialog->sip_dlg_state);	}	SIP_DLG_REFCNT_DECR(dialog);}/* Delete a dialog */voidsip_dialog_delete(_sip_dialog_t *dialog){	int	index;	index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);	sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index,	    sip_dialog_free);}/* Process an incoming request/response *//* ARGSUSED */intsip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog,    void (*func)(sip_dialog_t, sip_msg_t, void *)){	boolean_t	request;	_sip_dialog_t	*_dialog;	int		error;	request = sip_msg_is_request((sip_msg_t)sip_msg, &error);	if (error != 0)		return (EINVAL);	_dialog = (_sip_dialog_t *)*sip_dialog;	if (request) {		uint32_t	cseq;		(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);		cseq = sip_get_callseq_num(sip_msg, &error);		if (error != 0 ||		    ((_dialog->sip_dlg_remote_cseq != 0) &&		    (SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)))) {			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);			/* Send CALL_NON_EXISTANT response?? */			return (EPROTO);		}		_dialog->sip_dlg_remote_cseq = cseq;		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);	} else {		int		resp_code;		sip_method_t	method;		int		error;		resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);		if (error == 0) {			method = sip_get_callseq_method((sip_msg_t)sip_msg,			    &error);		}		if (error != 0)			return (error);		(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);		assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||		    _dialog->sip_dlg_state == SIP_DLG_CONFIRMED);		/*		 * Let the user delete the dialog if it is not a 1XX/2XX resp		 * for an early INVITE dialog.		 */		if (SIP_OK_RESP(resp_code)) {			if (method == INVITE) {				if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {					_dialog->sip_dlg_state =					    SIP_DLG_CONFIRMED;					(void) pthread_mutex_unlock(					    &_dialog->sip_dlg_mutex);					(void) sip_dlg_recompute_rset(_dialog,					    sip_msg, SIP_UAC_DIALOG);					if (sip_dlg_ulp_state_cb != NULL) {						sip_dlg_ulp_state_cb(						    (sip_dialog_t)_dialog,						    sip_msg, SIP_DLG_EARLY,						    _dialog->sip_dlg_state);					}					return (0);				}			}		}		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);	}	return (0);}/* Copy partial dialog to create a complete dialog */_sip_dialog_t *sip_copy_partial_dialog(_sip_dialog_t *dialog){	_sip_dialog_t	*new_dlg;	new_dlg =  calloc(1, sizeof (_sip_dialog_t));	if (new_dlg == NULL)		return (NULL);	if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {		new_dlg->sip_dlg_req_uri.sip_str_ptr =		    malloc(dialog->sip_dlg_req_uri.sip_str_len + 1);		if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) {			free(new_dlg);			return (NULL);		}		(void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr,		    dialog->sip_dlg_req_uri.sip_str_ptr,		    dialog->sip_dlg_req_uri.sip_str_len);		new_dlg->sip_dlg_req_uri.sip_str_ptr[		    dialog->sip_dlg_req_uri.sip_str_len] = '\0';		new_dlg->sip_dlg_req_uri.sip_str_len =		    dialog->sip_dlg_req_uri.sip_str_len;	}	if (dialog->sip_dlg_route_set != NULL) {		assert(dialog->sip_dlg_rset.sip_str_ptr != NULL);		new_dlg->sip_dlg_rset.sip_str_ptr =		    malloc(dialog->sip_dlg_rset.sip_str_len + 1);		if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) {			if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)				free(new_dlg->sip_dlg_req_uri.sip_str_ptr);			free(new_dlg);			return (NULL);		}		(void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr,		    dialog->sip_dlg_rset.sip_str_ptr,		    dialog->sip_dlg_rset.sip_str_len);		new_dlg->sip_dlg_rset.sip_str_ptr[		    dialog->sip_dlg_rset.sip_str_len] = '\0';		new_dlg->sip_dlg_rset.sip_str_len =		    dialog->sip_dlg_rset.sip_str_len;		new_dlg->sip_dlg_route_set =		    sip_dup_header(dialog->sip_dlg_route_set);		if (new_dlg->sip_dlg_route_set == NULL) {			free(new_dlg->sip_dlg_rset.sip_str_ptr);			if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)				free(new_dlg->sip_dlg_req_uri.sip_str_ptr);			free(new_dlg);			return (NULL);		}	}	if ((new_dlg->sip_dlg_local_uri_tag =	    sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL ||	    (new_dlg->sip_dlg_remote_target =	    sip_dup_header(dialog->sip_dlg_remote_target)) == NULL ||	    (new_dlg->sip_dlg_call_id =	    sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {		sip_release_dialog_res(new_dlg);		return (NULL);	}	if (dialog->sip_dlg_event != NULL) {		new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event);		if (new_dlg->sip_dlg_event == NULL) {			sip_release_dialog_res(new_dlg);			return (NULL);		}	}	new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq;	new_dlg->sip_dlg_type = dialog->sip_dlg_type;	new_dlg->sip_dlg_on_fork = B_FALSE;	(void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL);	return (new_dlg);}/* * Update the dialog using the response */sip_dialog_tsip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg,    void (*func)(sip_dialog_t, sip_msg_t, void *)){	_sip_dialog_t	*_dialog;	boolean_t	isreq;	sip_method_t	method;	int		resp_code = 0;	int		prev_state;	boolean_t	decr_ref = B_FALSE;	int		error;	isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error);	if (error != 0)		return (dialog);	_dialog = (_sip_dialog_t *)dialog;	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);	if (isreq) {		method = sip_get_request_method((sip_msg_t)sip_msg, &error);		if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE ||		    method != NOTIFY) {			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);			return (dialog);		}	} else {		resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);		if (error != 0) {			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);			return (dialog);		}	}	prev_state = _dialog->sip_dlg_state;	if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) {		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);	} else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {		/*		 * Let the user delete the dialog if it is not a 1XX/2XX resp		 * for an early dialog.		 */		assert(!isreq);		if (SIP_OK_RESP(resp_code)) {			_dialog->sip_dlg_state = SIP_DLG_CONFIRMED;			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);			(void) sip_dlg_recompute_rset(_dialog, sip_msg,			    SIP_UAS_DIALOG);			if (sip_dlg_ulp_state_cb != NULL) {				sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,				    prev_state, dialog->sip_dlg_state);			}		} else {			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);		}	} else if (_dialog->sip_dlg_state == SIP_DLG_NEW) {		if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE &&		    SIP_PROVISIONAL_RESP(resp_code)) {			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);			return (dialog);		}		if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) {			_sip_dialog_t	*new_dlg;			if (_dialog->sip_dlg_on_fork) {				new_dlg = sip_copy_partial_dialog(_dialog);				if (new_dlg == NULL) {					(void) pthread_mutex_unlock(					    &_dialog->sip_dlg_mutex);					return (dialog);				}				/*				 * This decr/incr dance is because the caller				 * has incremented the ref on the partial				 * dialog, we release it here and incr the				 * ref on the new dialog which will be				 * released by the caller.				 */				(void) pthread_mutex_unlock(				    &_dialog->sip_dlg_mutex);				SIP_DLG_REFCNT_DECR(_dialog);				_dialog = new_dlg;				(void) pthread_mutex_lock(				    &_dialog->sip_dlg_mutex);				SIP_DLG_REFCNT_INCR(_dialog);			} else {				int	index;				/*				 * take it out of the list so that further				 * responses will not result in a dialog.				 * We will have an extra refcount when we				 * come back from sip_complete_dialog(), i.e.				 * one when the partial dialog was created -				 * in sip_seed_dialog(), one held by the caller				 * and one that will be added by				 * sip_complete_dialog(). We need to release				 * the one added by the sip_seed_dialog(),				 * since the one in sip_complete_dialog()				 * is for the same purpose.				 */				/* Cancel the timer */				if (SIP_IS_TIMER_RUNNING(				    _dialog->sip_dlg_timer)) {					SIP_CANCEL_TIMER(					    dialog->sip_dlg_timer);				}				index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);				(void) pthread_mutex_unlock(				    &_dialog->sip_dlg_mutex);				sip_hash_delete(sip_dialog_phash,				    (void *)_dialog->sip_dlg_id,				    index, sip_dialog_dontfree);				(void) pthread_mutex_lock(				    &_dialog->sip_dlg_mutex);				decr_ref = B_TRUE;			}		}		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);		if ((dialog = sip_complete_dialog(sip_msg, _dialog, func)) ==		    NULL) {			return (NULL);		}		if (decr_ref)			SIP_DLG_REFCNT_DECR(_dialog);	} else {		(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);	}	return (dialog);}/* Initialize the hash table */voidsip_dialog_init(void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int)){	int	cnt;	for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {		sip_dialog_hash[cnt].hash_count = 0;		sip_dialog_hash[cnt].hash_head = NULL;		sip_dialog_hash[cnt].hash_tail = NULL;		(void) pthread_mutex_init(		    &sip_dialog_hash[cnt].sip_hash_mutex, NULL);		sip_dialog_phash[cnt].hash_count = 0;		sip_dialog_phash[cnt].hash_head = NULL;		sip_dialog_phash[cnt].hash_tail = NULL;		(void) pthread_mutex_init(		    &sip_dialog_phash[cnt].sip_hash_mutex, NULL);	}	if (ulp_state_cb != NULL)		sip_dlg_ulp_state_cb = ulp_state_cb;}

⌨️ 快捷键说明

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