changeset 4702:655cbe4c8575

6583537 sip_create_dialog_req() should add correct value to the Contact header
author gm209912
date Mon, 23 Jul 2007 11:24:09 -0700
parents 077ceba22807
children bb31c50bb3ab
files usr/src/lib/libsip/common/sip_dialog.c usr/src/lib/libsip/common/sip_dialog.h usr/src/lib/libsip/common/sip_dialog_ui.c usr/src/lib/libsip/common/sip_itf.c
diffstat 4 files changed, 112 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libsip/common/sip_dialog.c	Mon Jul 23 10:53:09 2007 -0700
+++ b/usr/src/lib/libsip/common/sip_dialog.c	Mon Jul 23 11:24:09 2007 -0700
@@ -120,6 +120,10 @@
 		sip_free_header(dialog->sip_dlg_remote_uri_tag);
 	if (dialog->sip_dlg_remote_target != NULL)
 		sip_free_header(dialog->sip_dlg_remote_target);
+	if (dialog->sip_dlg_local_contact != NULL)
+		sip_free_header(dialog->sip_dlg_local_contact);
+	if (dialog->sip_dlg_new_local_contact != NULL)
+		sip_free_header(dialog->sip_dlg_new_local_contact);
 	if (dialog->sip_dlg_route_set != NULL)
 		sip_free_header(dialog->sip_dlg_route_set);
 	if (dialog->sip_dlg_event != NULL)
@@ -660,6 +664,16 @@
 		    NULL) {
 			goto dia_err;
 		}
+		/*
+		 * We take the local contact from the originating request on
+		 * UAC. For the UAS, we will take it from the response.
+		 */
+		if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) ==
+		    NULL) {
+			goto dia_err;
+		} else {
+			dialog->sip_dlg_new_local_contact = NULL;
+		}
 	}
 	if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL)
 		goto dia_err;
@@ -1024,6 +1038,28 @@
 	}
 
 	/*
+	 * We take the local contact for UAS Dialog from the response (either
+	 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE
+	 * request)
+	 */
+	if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state
+	    == SIP_DLG_CONFIRMED)) {
+		if (chdr == NULL) {
+			(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
+			chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
+			    NULL);
+			(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
+		}
+		if ((chdr == NULL) || ((dialog->sip_dlg_local_contact =
+		    sip_dup_header(chdr)) == NULL)) {
+			(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
+			if (alloc_thdr)
+				sip_free_header(thdr);
+			goto terminate_new_dlg;
+		}
+	}
+
+	/*
 	 * Cancel the partial dialog timer
 	 */
 	if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
@@ -1430,6 +1466,16 @@
 						    _dialog->sip_dlg_state);
 					}
 					return (0);
+				} else if (_dialog->sip_dlg_new_local_contact
+				    != NULL) {
+					assert(_dialog->sip_dlg_local_contact
+					    != NULL);
+					sip_free_header(_dialog->
+						    sip_dlg_local_contact);
+					_dialog->sip_dlg_local_contact =
+					    _dialog->sip_dlg_new_local_contact;
+					_dialog->sip_dlg_new_local_contact =
+					    NULL;
 				}
 			}
 		}
@@ -1496,6 +1542,8 @@
 	    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_local_contact =
+	    sip_dup_header(dialog->sip_dlg_local_contact)) == NULL ||
 	    (new_dlg->sip_dlg_call_id =
 	    sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {
 		sip_release_dialog_res(new_dlg);
@@ -1548,6 +1596,11 @@
 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
 			return (dialog);
 		}
+		method = sip_get_callseq_method((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) {
@@ -1560,6 +1613,26 @@
 		assert(!isreq);
 		if (SIP_OK_RESP(resp_code)) {
 			_dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
+			/*
+			 * If we recieved provisional response before we would
+			 * not have captured local contact. So store it now.
+			 */
+			if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog->
+			    sip_dlg_method == INVITE && method == INVITE) {
+				sip_header_t chdr;
+				(void) pthread_mutex_lock(&sip_msg->
+				    sip_msg_mutex);
+				chdr = sip_search_for_header(sip_msg,
+				    SIP_CONTACT, NULL);
+				(void) pthread_mutex_unlock(&sip_msg->
+				    sip_msg_mutex);
+				if (chdr != NULL) {
+					_dialog->sip_dlg_local_contact
+					    = sip_dup_header(chdr);
+					_dialog->sip_dlg_new_local_contact =
+					    NULL;
+				}
+			}
 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
 			(void) sip_dlg_recompute_rset(_dialog, sip_msg,
 			    SIP_UAS_DIALOG);
@@ -1676,3 +1749,34 @@
 	if (ulp_state_cb != NULL)
 		sip_dlg_ulp_state_cb = ulp_state_cb;
 }
+
+/*
+ * Copy the new contact header of re-INVITE
+ */
+void
+sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg)
+{
+	sip_header_t chdr = NULL;
+	sip_header_t nhdr = NULL;
+
+	(void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
+	chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
+	(void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
+
+	if (chdr == NULL)
+		return;
+
+	(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
+	if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state
+	    != SIP_DLG_CONFIRMED) {
+		(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
+		return;
+	}
+
+	if (((nhdr = sip_dup_header(chdr)) != NULL)) {
+		if (dialog->sip_dlg_new_local_contact != NULL)
+			sip_free_header(dialog->sip_dlg_new_local_contact);
+		dialog->sip_dlg_new_local_contact = nhdr;
+	}
+	(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
+}
--- a/usr/src/lib/libsip/common/sip_dialog.h	Mon Jul 23 10:53:09 2007 -0700
+++ b/usr/src/lib/libsip/common/sip_dialog.h	Mon Jul 23 11:24:09 2007 -0700
@@ -68,6 +68,8 @@
 	_sip_header_t		*sip_dlg_remote_uri_tag;
 	_sip_header_t		*sip_dlg_local_uri_tag;
 	_sip_header_t		*sip_dlg_remote_target;
+	_sip_header_t		*sip_dlg_local_contact;
+	_sip_header_t		*sip_dlg_new_local_contact; /* for re-INVITE */
 	_sip_header_t		*sip_dlg_route_set;
 	_sip_header_t		*sip_dlg_event;
 	sip_str_t		sip_dlg_rset;
@@ -95,6 +97,7 @@
 sip_dialog_t		sip_dialog_find(_sip_msg_t *);
 int			sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
 sip_dialog_t		sip_update_dialog(sip_dialog_t, _sip_msg_t *);
+void			sip_dialog_add_new_contact(sip_dialog_t, _sip_msg_t *);
 void			sip_dialog_terminate(sip_dialog_t, sip_msg_t);
 sip_dialog_t		sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
 			    boolean_t, int);
--- a/usr/src/lib/libsip/common/sip_dialog_ui.c	Mon Jul 23 10:53:09 2007 -0700
+++ b/usr/src/lib/libsip/common/sip_dialog_ui.c	Mon Jul 23 11:24:09 2007 -0700
@@ -76,6 +76,8 @@
 	    0) {
 		goto err_ret;
 	}
+	if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_contact, NULL) != 0)
+		goto err_ret;
 	if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) !=
 	    0) {
 		goto err_ret;
--- a/usr/src/lib/libsip/common/sip_itf.c	Mon Jul 23 10:53:09 2007 -0700
+++ b/usr/src/lib/libsip/common/sip_itf.c	Mon Jul 23 11:24:09 2007 -0700
@@ -312,6 +312,9 @@
 		} else if (dialog != NULL && (!sip_msg_info->is_request ||
 		    sip_msg_info->sip_req_method == NOTIFY)) {
 			(void) sip_update_dialog(dialog, _sip_msg);
+		} else if (dialog != NULL && sip_msg_info->is_request &&
+		    sip_msg_info->sip_req_method == INVITE) {
+			(void) sip_dialog_add_new_contact(dialog, _sip_msg);
 		}
 	}