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

📄 sip_dialog.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 4 页
字号:
	dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =	    '\0';	if (uri != NULL) {		if (first) {			count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT,			    uri, SIP_RAQUOT);		} else {			count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA,			    SIP_LAQUOT, uri, SIP_RAQUOT);		}		rp += count;		rpl -= count;		free(uri);	}	assert(rp <= rset + rset_len);	(void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,	    "%s%s", rset, SIP_CRLF);	free(rset);	dialog->sip_dlg_route_set = (sip_header_t)rhdr;	sip_dialog_free_rset(rset_head);	return (0);}/* * UAC Behavior * The route set MUST be set to the list of URIs in the Record-Route * header field from the response, taken in reverse order and preserving * all URI parameters. * * UAS behavior * The route set MUST be set to the list of URIs in the Record-Route * header field from the request, taken in order and preserving all URI * parameters. */static intsip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what){	sip_header_t		rrhdr;	sip_hdr_value_t		*value;	int			error;	sip_dlg_route_set_t	*rset_head = NULL;	sip_dlg_route_set_t	*rset_tail = NULL;	sip_dlg_route_set_t	*rset;	int			rset_cnt = 0;	int			rset_len = 0;	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);	rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL);	while (rrhdr != NULL) {		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);		value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error);		while (value != NULL && error == 0) {			char	*crlf;			if (value->sip_value_state == SIP_VALUE_BAD) {				value = (sip_hdr_value_t *)sip_get_next_value(				    (sip_header_value_t)value, &error);				continue;			}			rset = sip_add_route_to_set(value);			if (rset == NULL)				goto r_error;			/* Add one for COMMA */			rset_cnt++;			rset_len += (value->sip_value_end -			    value->sip_value_start);			/* Check for CRLF */			crlf = value->sip_value_end - strlen(SIP_CRLF);			while (crlf != NULL &&			    strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {				rset_len -= strlen(SIP_CRLF);				crlf -= strlen(SIP_CRLF);			}			if (rset_head == NULL) {				assert(rset_tail == NULL);				rset_head = rset_tail = rset;			} else if (what == SIP_UAS_DIALOG) {				rset_tail->sip_dlg_route_next = rset;				rset_tail = rset;			} else if (what == SIP_UAC_DIALOG) {				rset->sip_dlg_route_next = rset_head;				rset_head = rset;			} else {				assert(0);			}			value = (sip_hdr_value_t *)sip_get_next_value(			    (sip_header_value_t)value, &error);		}		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);		rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr);	}	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);	if (rset_cnt == 0)		return (0);	if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt,	    rset_len) != 0) {		goto r_error;	}	return (0);r_error:	sip_dialog_free_rset(rset_head);	return (ENOMEM);}/* * UAS behavior: * The remote sequence number MUST be set to the value of the sequence * number in the CSeq header field of the request.  The local sequence * number MUST be empty.  The call identifier component of the dialog ID * MUST be set to the value of the Call-ID in the request.  The local * tag component of the dialog ID MUST be set to the tag in the To field * in the response to the request (which always includes a tag), and the * remote tag component of the dialog ID MUST be set to the tag from the * From field in the request.  A UAS MUST be prepared to receive a * request without a tag in the From field, in which case the tag is * considered to have a value of null. * The remote URI MUST be set to the URI in the From field, and the * local URI MUST be set to the URI in the To field. * The remote target MUST be set to the URI from the Contact header field * of the request. * * UAC behavior: * The local sequence number MUST be set to the value of the sequence * number in the CSeq header field of the request.  The remote sequence * number MUST be empty (it is established when the remote UA sends a * request within the dialog).  The call identifier component of the * dialog ID MUST be set to the value of the Call-ID in the request. * The local tag component of the dialog ID MUST be set to the tag in * the From field in the request, and the remote tag component of the * dialog ID MUST be set to the tag in the To field of the response.  A * UAC MUST be prepared to receive a response without a tag in the To * field, in which case the tag is considered to have a value of null. * The remote URI MUST be set to the URI in the To field, and the local * URI MUST be set to the URI in the From field. * The remote target MUST be set to the URI from the Contact header field * of the response. *//* * This is the routine that seeds a dialog. */sip_dialog_tsip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,    void (*func)(sip_dialog_t, sip_msg_t, void *), boolean_t dlg_on_fork,    int dlg_type){	_sip_dialog_t		*dialog;	int			cseq;	sip_header_t		fhdr = NULL;	sip_header_t		thdr = NULL;	sip_header_t		chdr;	sip_header_t		cihdr;	sip_header_t		evhdr = NULL;	const struct sip_value	*value;	sip_dialog_timer_obj_t	*tim_obj = NULL;	const sip_str_t		*callid;	sip_method_t		method;	int			timer1 = sip_timer_T1;	int			error;	if (!sip_msg_is_request((sip_msg_t)sip_msg, &error))		return (NULL);	method = sip_get_request_method((sip_msg_t)sip_msg, &error);	/* Only INVITE and SUBSCRIBE supported */	if (error != 0 || (method != INVITE && method != SUBSCRIBE))		return (NULL);	if (dlg_type == SIP_UAS_DIALOG) {		thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,		    SIP_DLG_XCHG_FROM);		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);	} else {		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);		fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL);	}	cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL);	chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);	if (method == SUBSCRIBE)		evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);	if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL ||	    (method == SUBSCRIBE && evhdr == NULL)) {		return (NULL);	}	/* Sanity check since we just store the headers in the dialog */	if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL ||	    sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||	    ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) ||	    (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL ||	    sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||	    ((value = sip_get_header_value(chdr, NULL)) == NULL) ||	    sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {		return (NULL);	}	tim_obj = malloc(sizeof (sip_dialog_timer_obj_t));	if (tim_obj == NULL)		return (NULL);	dialog = calloc(1, sizeof (_sip_dialog_t));	if (dialog == NULL)		return (NULL);	/*	 * We will take the TO header with the tag when we complete this	 * dialog	 */	if (dlg_type == SIP_UAS_DIALOG) {		dialog->sip_dlg_remote_uri_tag = thdr;	} else {		if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) ==		    NULL) {			goto dia_err;		}	}	if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL ||	    (dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL) {		goto dia_err;	}	if (method == SUBSCRIBE) {		dialog->sip_dlg_event = sip_dup_header(evhdr);		if (dialog->sip_dlg_event == NULL) {			goto dia_err;		}	}	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;	/* Get the route set from the request, if present */	if (sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) {		goto dia_err;	}	if (dlg_type == SIP_UAC_DIALOG)		dialog->sip_dlg_local_cseq = cseq;	else		dialog->sip_dlg_remote_cseq = cseq;	dialog->sip_dlg_type = dlg_type;	dialog->sip_dlg_on_fork = dlg_on_fork;	dialog->sip_dlg_method = method;	/* Set the partial dialog timer with the INVITE timeout val */	if (sip_conn_timer1 != NULL)		timer1 = sip_conn_timer1(obj);	SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1);	tim_obj->dialog = dialog;	tim_obj->func = func;	SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj,	    sip_dlg_self_destruct);	if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))		goto dia_err;	(void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);	if (dlg_type == SIP_UAC_DIALOG) {		const sip_str_t	*local_tag;		local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);		assert(local_tag != NULL);		sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len,		    callid->sip_str_ptr, callid->sip_str_len,		    NULL, 0, NULL, 0, NULL, 0, NULL, 0,		    (uchar_t *)dialog->sip_dlg_id);		SIP_DLG_REFCNT_INCR(dialog);		/* Add it to the partial hash table */		if (sip_hash_add(sip_dialog_phash, (void *)dialog,		    SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {			goto dia_err;		}	}	return ((sip_dialog_t)dialog);dia_err:	sip_release_dialog_res(dialog);	if (tim_obj != NULL)		free(tim_obj);	return (NULL);}/* * When creating a dialog from a NOTIFY request, we need to get the FROM * header for the dialog from the TO header of the NOTIFY. */_sip_header_t *sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what){	int			len;	_sip_header_t		*newhdr;	int			cnt;	const struct sip_header	*hdr;	int			hdrsize;	int			error;	hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM :	    SIP_TO, NULL, &error);	if (error != 0 || hdr == NULL)		return (NULL);	if (sip_parse_goto_values((_sip_header_t *)hdr) != 0)		return (NULL);	len = hdr->sip_hdr_end - hdr->sip_hdr_current;	if (what == SIP_DLG_XCHG_FROM) {		hdrsize = len + strlen(SIP_TO) + SIP_SPACE + sizeof (char) +		    SIP_SPACE;	} else {		hdrsize = len + strlen(SIP_FROM) + SIP_SPACE + sizeof (char) +		    SIP_SPACE;	}	newhdr = sip_new_header(hdrsize);	if (newhdr == NULL)		return (NULL);	if (what == SIP_DLG_XCHG_FROM) {		cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,		    "%s %c ", SIP_TO, SIP_HCOLON);	} else {		cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,		    "%s %c ", SIP_FROM, SIP_HCOLON);	}	newhdr->sip_hdr_current += cnt;	(void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len);	newhdr->sip_hdr_current += len;	assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end);	assert(hdr->sip_header_functions != NULL);	/* FROM and TO have common parsing functions */	newhdr->sip_header_functions = hdr->sip_header_functions;	newhdr->sip_hdr_current = newhdr->sip_hdr_start;	return (newhdr);}/* * This is the response that completes the dialog that was created * in sip_seed_dialog(). */sip_dialog_tsip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog,    void (*func)(sip_dialog_t, sip_msg_t, void *)){	_sip_header_t		*thdr;	_sip_header_t		*evhdr = NULL;	_sip_header_t		*substate = NULL;	int			resp_code;	const sip_str_t		*ttag;	const sip_str_t		*remtag;	const sip_str_t		*callid;	const struct sip_value 	*val;	sip_method_t		method;	int			error = 0;	int			prev_state;	if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0)		method = sip_get_request_method((sip_msg_t)sip_msg, &error);	else		method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);	if (error != 0 || dialog == NULL ||	    (sip_msg_is_request((sip_msg_t)sip_msg, &error) &&	    (dialog->sip_dlg_method == INVITE || method != NOTIFY))) {		return (NULL);	}	if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY &&	    sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=	    dialog->sip_dlg_local_cseq) ||	    (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY &&	    sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=	    dialog->sip_dlg_remote_cseq)) {		return (NULL);	}	if (method == NOTIFY) {		const sip_str_t	*sstate;		thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,		    SIP_DLG_XCHG_FROM);		(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);		evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);		if (evhdr == NULL) {			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);			return (NULL);		}		substate = sip_search_for_header(sip_msg,		    SIP_SUBSCRIPTION_STATE, NULL);		if (substate == NULL) {			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);			return (NULL);		}		(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);

⌨️ 快捷键说明

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