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

📄 sip_dialog.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 4 页
字号:
		sstate = sip_get_substate((sip_msg_t)sip_msg, &error);		if (sstate == NULL || error != 0) {			return (NULL);		}		if ((sstate->sip_str_len != strlen("pending") &&		    sstate->sip_str_len != strlen("active")) ||		    ((sstate->sip_str_len == strlen("pending") &&		    strncasecmp(sstate->sip_str_ptr, "pending",		    strlen("pending")) != 0) ||		    (sstate->sip_str_len == strlen("active") &&		    strncasecmp(sstate->sip_str_ptr, "active",		    strlen("active")) != 0))) {			return (NULL);		}		ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);	} else {		if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {			thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,			    SIP_DLG_XCHG_TO);		} else {			(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);			thdr = sip_search_for_header(sip_msg, SIP_TO, NULL);			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);		}		if (thdr == NULL) {			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);			return (NULL);		}		ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL);	}	if (ttag == NULL)		return (NULL);	prev_state = dialog->sip_dlg_state;	if (method == NOTIFY) {		int			error;		const sip_str_t		*dlg_id_val = NULL;		const sip_str_t		*event;		const sip_str_t		*id_val = NULL;		sip_header_value_t	ev_val;		sip_hdr_value_t		*dlg_ev_val = NULL;		event = sip_get_event((sip_msg_t)sip_msg, &error);		if (event == NULL || error != 0)			return (NULL);		ev_val = (sip_header_value_t)sip_get_header_value(evhdr,		    &error);		if (ev_val != NULL)			id_val = sip_get_param_value(ev_val, "id", &error);		if (error == 0) {			dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value(			    dialog->sip_dlg_event, &error);		}		if (dlg_ev_val == NULL || error != 0)			return (NULL);		dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val,		    "id", &error);		if (error != 0 ||		    dlg_ev_val->str_val_len != event->sip_str_len ||		    strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr,		    event->sip_str_len != 0)) {			return (NULL);		}		if ((dlg_id_val == NULL && id_val != NULL) ||		    (dlg_id_val != NULL && id_val == NULL)) {			return (NULL);		} else if (dlg_id_val != NULL && id_val != NULL) {			if (dlg_id_val->sip_str_len != id_val->sip_str_len ||			    strncasecmp(dlg_id_val->sip_str_ptr,			    id_val->sip_str_ptr, dlg_id_val->sip_str_len) !=			    0) {				return (NULL);			}		}		dialog->sip_dlg_state = SIP_DLG_CONFIRMED;		if (dialog->sip_dlg_type == SIP_UAC_DIALOG)			dialog->sip_dlg_remote_uri_tag = thdr;		else			dialog->sip_dlg_local_uri_tag = thdr;	} else {		resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);		(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);		assert(dialog->sip_dlg_state == SIP_DLG_NEW);		if (SIP_PROVISIONAL_RESP(resp_code)) {			dialog->sip_dlg_state = SIP_DLG_EARLY;		} else if (SIP_OK_RESP(resp_code)) {			dialog->sip_dlg_state = SIP_DLG_CONFIRMED;		} else {			dialog->sip_dlg_state = SIP_DLG_DESTROYED;			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);			if (func != NULL)				func(dialog, (sip_msg_t)sip_msg, NULL);			sip_release_dialog_res(dialog);			return (NULL);		}		if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {			dialog->sip_dlg_local_uri_tag = thdr;		} else {			if ((dialog->sip_dlg_remote_uri_tag =			    sip_dup_header(thdr)) == NULL) {				(void) pthread_mutex_unlock(				    &dialog->sip_dlg_mutex);				return (NULL);	/* XXXDestroy dialog? */			}		}	}	/* Cancel the partial dialog timer */	if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))		SIP_CANCEL_TIMER(dialog->sip_dlg_timer);	if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {		val =  sip_get_header_value(dialog->sip_dlg_local_uri_tag,		    &error);	} else {		val =  sip_get_header_value(dialog->sip_dlg_remote_uri_tag,		    &error);	}	assert(val != NULL && error == 0);	remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);	val = sip_get_header_value(dialog->sip_dlg_call_id, &error);	callid = &((sip_hdr_value_t *)val)->str_val;	/* Get an ID for this dialog */	if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {		sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len,		    ttag->sip_str_ptr, ttag->sip_str_len,		    callid->sip_str_ptr, callid->sip_str_len,		    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);	} else {		sip_md5_hash(ttag->sip_str_ptr, ttag->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 *)dialog->sip_dlg_id);	}	SIP_DLG_REFCNT_INCR(dialog);	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);	/* Add it to the hash table */	if (sip_hash_add(sip_dialog_hash, (void *)dialog,	    SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {		sip_release_dialog_res(dialog);		return (NULL);	}	if (sip_dlg_ulp_state_cb != NULL) {		sip_dlg_ulp_state_cb((sip_dialog_t)dialog,		    (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state);	}	return ((sip_dialog_t)dialog);}/* * For a UAC just giving the RESPONSE/NOTIFY to the INVITE/SUBSCRIBE is enough, * we can get all the info. from it. However, on the UAS side we would need * the original request INVITE/SUBSCRIBE and the response RESPONSE/NOTIFY * since we don't have the remote target (CONTACT) info. in the response/notify. */sip_dialog_tsip_dialog_create(_sip_msg_t *resp, _sip_msg_t *req, int what){	_sip_dialog_t		*dialog;	_sip_header_t		*fhdr;	_sip_header_t		*thdr;	_sip_header_t		*chdr;	_sip_header_t		*cihdr;	const sip_str_t		*ltag;	const sip_str_t		*ttag;	const sip_str_t		*callid;	int			cseq;	const struct sip_value	*value;	int			resp_code;	int			error = 0;	int			prev_state;	sip_method_t		method = 0;	if (what == SIP_UAS_DIALOG) {		if (req == NULL ||		    !sip_msg_is_request((sip_msg_t)req, &error) || error != 0 ||		    (sip_get_request_method((sip_msg_t)req, &error) != INVITE &&		    sip_get_request_method((sip_msg_t)req, &error) !=		    SUBSCRIBE)) {			return (NULL);		}	}	if (sip_msg_is_request((sip_msg_t)resp, &error)) {		/* Only NOTIFY request can create a dialog */		method = sip_get_request_method((sip_msg_t)resp, &error);		if (method != NOTIFY)			return (NULL);	} else {		/* Only response to an INVITE/SUBSCRIBE can create a dialog */		resp_code = sip_get_response_code((sip_msg_t)resp, &error);		if (error == 0) {			method = sip_get_callseq_method((sip_msg_t)resp,			    &error);		}		if (error != 0 || (!SIP_PROVISIONAL_RESP(resp_code) &&		    !SIP_OK_RESP(resp_code)) || (method != INVITE &&		    method != SUBSCRIBE)) {			return (NULL);		}	}	(void) pthread_mutex_lock(&resp->sip_msg_mutex);	if (what == SIP_UAS_DIALOG) {		if (method == NOTIFY) {			fhdr = sip_search_for_header(resp, SIP_FROM, NULL);			thdr = sip_search_for_header(resp, SIP_TO, NULL);		} else {			fhdr = sip_search_for_header(resp, SIP_TO, NULL);			thdr = sip_search_for_header(resp, SIP_FROM, NULL);		}		(void) pthread_mutex_lock(&req->sip_msg_mutex);		chdr = sip_search_for_header(req, SIP_CONTACT, NULL);		(void) pthread_mutex_unlock(&req->sip_msg_mutex);	} else {		if (method == NOTIFY) {			thdr = sip_search_for_header(resp, SIP_FROM, NULL);			fhdr = sip_search_for_header(resp, SIP_TO, NULL);		} else {			fhdr = sip_search_for_header(resp, SIP_FROM, NULL);			thdr = sip_search_for_header(resp, SIP_TO, NULL);		}		chdr = sip_search_for_header(resp, SIP_CONTACT, NULL);	}	cihdr = sip_search_for_header(resp, SIP_CALL_ID, NULL);	(void) pthread_mutex_unlock(&resp->sip_msg_mutex);	if (fhdr == NULL || thdr == NULL || cihdr == NULL)		return (NULL);	/* Sanity check since we just store the headers in the dialog */	if (((ltag = sip_get_from_tag((sip_msg_t)resp, NULL)) == NULL) ||	    sip_get_from_uri_str((sip_msg_t)resp, NULL) == NULL ||	    ((ttag = sip_get_to_tag((sip_msg_t)resp, NULL)) == NULL) ||	    sip_get_to_uri_str((sip_msg_t)resp, NULL) == NULL ||	    ((cseq = sip_get_callseq_num((sip_msg_t)resp, NULL)) == -1) ||	    ((callid = sip_get_callid((sip_msg_t)resp, NULL)) == NULL) ||	    ((value = sip_get_header_value(chdr, NULL)) == NULL) ||	    sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {		return (NULL);	}	dialog = calloc(1, sizeof (_sip_dialog_t));	if (dialog == NULL)		return (NULL);	dialog->sip_dlg_local_cseq = cseq;	dialog->sip_dlg_type = what;	dialog->sip_dlg_method = method == NOTIFY ? SUBSCRIBE : method;	/* this is just 0 */	prev_state = dialog->sip_dlg_state;	if ((dialog->sip_dlg_remote_uri_tag = sip_dup_header(thdr)) == NULL ||	    (dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) == NULL ||	    (dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL ||	    (dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL) {		goto error;	}	dialog->sip_dlg_rset.sip_str_ptr = NULL;	dialog->sip_dlg_rset.sip_str_len = 0;	dialog->sip_dlg_req_uri.sip_str_ptr = NULL;	dialog->sip_dlg_req_uri.sip_str_len = 0;	if (sip_dialog_get_route_set(dialog, resp, what) != 0)		goto error;	/* Get an ID for this dialog */	sip_md5_hash(ltag->sip_str_ptr, ltag->sip_str_len,	    ttag->sip_str_ptr, ttag->sip_str_len,	    callid->sip_str_ptr, callid->sip_str_len,	    NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);	SIP_DLG_REFCNT_INCR(dialog);	(void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);	/* Add it to the hash table */	if (sip_hash_add(sip_dialog_hash, (void *)dialog,	    SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {		sip_release_dialog_res(dialog);		return (NULL);	}	if (sip_dlg_ulp_state_cb != NULL) {		sip_dlg_ulp_state_cb((sip_dialog_t)dialog,		    (sip_msg_t)resp, prev_state, dialog->sip_dlg_state);	}	return ((sip_dialog_t)dialog);error:	sip_release_dialog_res(dialog);	return (NULL);}/* * Check if this dialog is a match. */boolean_tsip_dialog_match(void *obj, void *hindex){	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);	if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) {		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);		return (B_FALSE);	}	if (bcmp(dialog->sip_dlg_id, hindex,	    sizeof (dialog->sip_dlg_id)) == 0) {		SIP_DLG_REFCNT_INCR(dialog);		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);		return (B_TRUE);	}	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);	return (B_FALSE);}/* Don't delete, just take it out of the hash */boolean_tsip_dialog_dontfree(void *obj, void *hindex, int *found){	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;	*found = 0;	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);	if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))	    == 0) {		*found = 1;		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);		return (B_TRUE);	}	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);	return (B_FALSE);}/* * Free resources associated with the dialog, the object will be removed * from the hash list by sip_hash_delete. */boolean_tsip_dialog_free(void *obj, void *hindex, int *found){	_sip_dialog_t	*dialog = (_sip_dialog_t *)obj;	*found = 0;	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);	if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))	    == 0) {		*found = 1;		assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED);		if (dialog->sip_dlg_ref_cnt != 0) {			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);			return (B_FALSE);		}		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);		sip_release_dialog_res(dialog);		return (B_TRUE);	}	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);	return (B_FALSE);}/* * The UAS will receive the request from the transaction layer.  If the * request has a tag in the To header field, the UAS core computes the * dialog identifier corresponding to the request and compares it with * existing dialogs.  If there is a match, this is a mid-dialog request. */sip_dialog_tsip_dialog_find(_sip_msg_t *sip_msg){	const sip_str_t	*localtag;	const sip_str_t	*remtag;	const sip_str_t	*callid;	uint16_t	digest[8];	_sip_dialog_t	*dialog;	boolean_t	is_request;	int		error;	is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error);	if (error != 0)		return (NULL);	if (is_request) {		localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);		if (error == 0)			remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);	} else {		remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);		if (error == 0)			localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);

⌨️ 快捷键说明

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