summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libsip/common/sip_dialog.c104
-rw-r--r--usr/src/lib/libsip/common/sip_dialog.h3
-rw-r--r--usr/src/lib/libsip/common/sip_dialog_ui.c2
-rw-r--r--usr/src/lib/libsip/common/sip_itf.c3
4 files changed, 112 insertions, 0 deletions
diff --git a/usr/src/lib/libsip/common/sip_dialog.c b/usr/src/lib/libsip/common/sip_dialog.c
index 4c8605b8a7..dd92fd794b 100644
--- a/usr/src/lib/libsip/common/sip_dialog.c
+++ b/usr/src/lib/libsip/common/sip_dialog.c
@@ -120,6 +120,10 @@ sip_release_dialog_res(_sip_dialog_t *dialog)
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 @@ sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
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 @@ sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
}
/*
+ * 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 @@ sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
_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_copy_partial_dialog(_sip_dialog_t *dialog)
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 @@ sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
(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 @@ sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
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 @@ sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *),
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);
+}
diff --git a/usr/src/lib/libsip/common/sip_dialog.h b/usr/src/lib/libsip/common/sip_dialog.h
index 6f92f936f4..b923ecab49 100644
--- a/usr/src/lib/libsip/common/sip_dialog.h
+++ b/usr/src/lib/libsip/common/sip_dialog.h
@@ -68,6 +68,8 @@ typedef struct sip_dialog
_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_create(_sip_msg_t *, _sip_msg_t *, int);
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);
diff --git a/usr/src/lib/libsip/common/sip_dialog_ui.c b/usr/src/lib/libsip/common/sip_dialog_ui.c
index 66b5982abd..bdbc588e8c 100644
--- a/usr/src/lib/libsip/common/sip_dialog_ui.c
+++ b/usr/src/lib/libsip/common/sip_dialog_ui.c
@@ -76,6 +76,8 @@ sip_create_dialog_req(sip_method_t method, sip_dialog_t dialog,
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;
diff --git a/usr/src/lib/libsip/common/sip_itf.c b/usr/src/lib/libsip/common/sip_itf.c
index db6f1098bf..a45c8282cf 100644
--- a/usr/src/lib/libsip/common/sip_itf.c
+++ b/usr/src/lib/libsip/common/sip_itf.c
@@ -312,6 +312,9 @@ sip_sendmsg(sip_conn_object_t obj, sip_msg_t sip_msg, sip_dialog_t dialog,
} 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);
}
}