summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorgm209912 <none@none>2008-01-15 08:42:39 -0800
committergm209912 <none@none>2008-01-15 08:42:39 -0800
commit943efbc33954e332318b6365bf27037c05bff72c (patch)
tree3e4d8821b5482533452918abf346a5c5624a55fb /usr/src
parent347a77f277285a2c589b756c918c3f40eefbbb8b (diff)
downloadillumos-joyent-943efbc33954e332318b6365bf27037c05bff72c.tar.gz
PSARC 2008/007 SIP Statistics And Logging
6496355 SIP stack should provide Call Tracing, logging and stat counters
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libsip/Makefile.com4
-rw-r--r--usr/src/lib/libsip/common/mapfile-vers10
-rw-r--r--usr/src/lib/libsip/common/sip.h72
-rw-r--r--usr/src/lib/libsip/common/sip_dialog.c135
-rw-r--r--usr/src/lib/libsip/common/sip_dialog.h5
-rw-r--r--usr/src/lib/libsip/common/sip_dialog_ui.c24
-rw-r--r--usr/src/lib/libsip/common/sip_itf.c61
-rw-r--r--usr/src/lib/libsip/common/sip_logging.c638
-rw-r--r--usr/src/lib/libsip/common/sip_miscdefs.h95
-rw-r--r--usr/src/lib/libsip/common/sip_xaction.c25
-rw-r--r--usr/src/lib/libsip/common/sip_xaction.h4
-rw-r--r--usr/src/lib/libsip/common/sip_xaction_state_mc.c214
12 files changed, 1228 insertions, 59 deletions
diff --git a/usr/src/lib/libsip/Makefile.com b/usr/src/lib/libsip/Makefile.com
index e380d8e196..febd458320 100644
--- a/usr/src/lib/libsip/Makefile.com
+++ b/usr/src/lib/libsip/Makefile.com
@@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -31,7 +31,7 @@ OBJECTS = sip_headers.o sip_msg.o sip_gids.o \
sip_hash.o sip_itf.o sip_ui.o sip_reass.o sip_dialog.o \
sip_dialog_ui.o sip_xaction_ui.o sip_parse_generic.o \
sip_parse_uri.o sip_uri_ui.o sip_parse_hdrs.o \
- sip_add_hdrs.o sip_hdrs_ui.o
+ sip_add_hdrs.o sip_hdrs_ui.o sip_logging.o
include ../../Makefile.lib
diff --git a/usr/src/lib/libsip/common/mapfile-vers b/usr/src/lib/libsip/common/mapfile-vers
index 9bbd724b06..df3882a157 100644
--- a/usr/src/lib/libsip/common/mapfile-vers
+++ b/usr/src/lib/libsip/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -77,6 +77,7 @@ SUNW_1.1 {
sip_release_dialog;
sip_delete_dialog;
sip_get_dialog_method;
+ sip_get_dialog_msgcnt;
sip_get_dialog_state;
sip_get_dialog_callid;
sip_get_dialog_local_tag;
@@ -263,6 +264,13 @@ SUNW_1.1 {
sip_get_rack_method;
sip_add_rseq;
sip_get_rseq_resp_num;
+ sip_enable_counters;
+ sip_disable_counters;
+ sip_get_counter_value;
+ sip_enable_trans_logging;
+ sip_disable_trans_logging;
+ sip_enable_dialog_logging;
+ sip_disable_dialog_logging;
local:
*;
};
diff --git a/usr/src/lib/libsip/common/sip.h b/usr/src/lib/libsip/common/sip.h
index c4cc189b9b..b14a04d492 100644
--- a/usr/src/lib/libsip/common/sip.h
+++ b/usr/src/lib/libsip/common/sip.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -35,6 +35,7 @@ extern "C" {
#include <sys/types.h>
#include <netinet/in.h>
+#include <stdio.h>
/* Send a SIP message statefully */
#define SIP_SEND_STATEFUL 0x0001
@@ -232,6 +233,60 @@ typedef enum dialog_state {
#define SIP_URIERR_NOURI 0x00000800 /* No URI */
#define SIP_URIERR_MEMORY 0x00001000 /* out of memory */
+/* SIP traffic counters */
+typedef enum sip_traffic_counter_names {
+ SIP_TOTAL_BYTES_RCVD = 0,
+ SIP_TOTAL_BYTES_SENT,
+ SIP_TOTAL_REQ_RCVD,
+ SIP_TOTAL_REQ_SENT,
+ SIP_TOTAL_RESP_RCVD,
+ SIP_TOTAL_RESP_SENT,
+ SIP_ACK_REQ_RCVD,
+ SIP_ACK_REQ_SENT,
+ SIP_BYE_REQ_RCVD,
+ SIP_BYE_REQ_SENT,
+ SIP_CANCEL_REQ_RCVD,
+ SIP_CANCEL_REQ_SENT,
+ SIP_INFO_REQ_RCVD,
+ SIP_INFO_REQ_SENT,
+ SIP_INVITE_REQ_RCVD,
+ SIP_INVITE_REQ_SENT,
+ SIP_NOTIFY_REQ_RCVD,
+ SIP_NOTIFY_REQ_SENT,
+ SIP_OPTIONS_REQ_RCVD,
+ SIP_OPTIONS_REQ_SENT,
+ SIP_PRACK_REQ_RCVD,
+ SIP_PRACK_REQ_SENT,
+ SIP_REFER_REQ_RCVD,
+ SIP_REFER_REQ_SENT,
+ SIP_REGISTER_REQ_RCVD,
+ SIP_REGISTER_REQ_SENT,
+ SIP_SUBSCRIBE_REQ_RCVD,
+ SIP_SUBSCRIBE_REQ_SENT,
+ SIP_UPDATE_REQ_RCVD,
+ SIP_UPDATE_REQ_SENT,
+ SIP_1XX_RESP_RCVD,
+ SIP_1XX_RESP_SENT,
+ SIP_2XX_RESP_RCVD,
+ SIP_2XX_RESP_SENT,
+ SIP_3XX_RESP_RCVD,
+ SIP_3XX_RESP_SENT,
+ SIP_4XX_RESP_RCVD,
+ SIP_4XX_RESP_SENT,
+ SIP_5XX_RESP_RCVD,
+ SIP_5XX_RESP_SENT,
+ SIP_6XX_RESP_RCVD,
+ SIP_6xx_RESP_SENT,
+ SIP_COUNTER_START_TIME,
+ SIP_COUNTER_STOP_TIME
+} sip_traffic_counter_names_t;
+
+/* SIP Traffic counter group */
+#define SIP_TRAFFIC_COUNTERS 0x0001 /* measures end to end SIP traffic */
+
+/* SIP Logging Levels */
+#define SIP_DETAIL_LOGGING 0x0001 /* logs the entire sip message */
+
#ifdef __linux__
#define B_FALSE 0
#define B_TRUE 1
@@ -629,9 +684,9 @@ extern sip_msg_t sip_create_dialog_req(sip_method_t, sip_dialog_t,
extern sip_msg_t sip_create_dialog_req_nocontact(sip_method_t,
sip_dialog_t, char *, char *, int, char *,
uint32_t, int);
-
extern int sip_get_dialog_state(sip_dialog_t, int *);
extern int sip_get_dialog_method(sip_dialog_t, int *);
+extern int sip_get_dialog_msgcnt(sip_dialog_t, int *);
extern const sip_str_t *sip_get_dialog_callid(sip_dialog_t, int *);
extern const sip_str_t *sip_get_dialog_local_tag(sip_dialog_t, int *);
extern const sip_str_t *sip_get_dialog_remote_tag(sip_dialog_t, int *);
@@ -699,6 +754,19 @@ extern void sip_hold_trans(sip_transaction_t);
extern void sip_release_trans(sip_transaction_t);
extern const struct sip_conn_object *sip_get_trans_conn_obj(
sip_transaction_t, int *);
+
+/* Logging functions */
+extern int sip_enable_trans_logging(FILE *, int);
+extern int sip_enable_dialog_logging(FILE *, int);
+extern void sip_disable_trans_logging();
+extern void sip_disable_dialog_logging();
+
+/* Traffic measurement functions */
+extern int sip_get_counter_value(int, int, void *, size_t);
+extern int sip_enable_counters(int);
+extern int sip_disable_counters(int);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libsip/common/sip_dialog.c b/usr/src/lib/libsip/common/sip_dialog.c
index 5b31349c5a..2f65dfae23 100644
--- a/usr/src/lib/libsip/common/sip_dialog.c
+++ b/usr/src/lib/libsip/common/sip_dialog.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -108,7 +108,14 @@ typedef struct sip_dialog_timer_obj_s {
static void
sip_release_dialog_res(_sip_dialog_t *dialog)
{
+ int count = 0;
+ sip_msg_chain_t *msg_chain;
+ sip_msg_chain_t *nmsg_chain;
+ if (dialog->sip_dlg_ref_cnt != 0) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(dialog->sip_dlg_ref_cnt == 0);
if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
@@ -138,6 +145,16 @@ sip_release_dialog_res(_sip_dialog_t *dialog)
dialog->sip_dlg_rset.sip_str_len = 0;
dialog->sip_dlg_rset.sip_str_ptr = NULL;
}
+ for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
+ msg_chain = dialog->sip_dlg_log[count].sip_msgs;
+ while (msg_chain != NULL) {
+ nmsg_chain = msg_chain->next;
+ if (msg_chain->sip_msg != NULL)
+ free(msg_chain->sip_msg);
+ free(msg_chain);
+ msg_chain = nmsg_chain;
+ }
+ }
(void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);
free(dialog);
}
@@ -312,6 +329,10 @@ sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
int rspl;
int rpl;
+ if (rcnt <= 0) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(rcnt > 0);
dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;
@@ -416,6 +437,11 @@ sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
}
route = route->sip_dlg_route_next;
}
+ if (rsp > dialog->sip_dlg_rset.sip_str_ptr +
+ dialog->sip_dlg_rset.sip_str_len) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +
dialog->sip_dlg_rset.sip_str_len);
dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =
@@ -432,6 +458,10 @@ sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
rpl -= count;
free(uri);
}
+ if (rp > rset + rset_len) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(rp <= rset + rset_len);
(void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,
"%s%s", rset, SIP_CRLF);
@@ -496,6 +526,11 @@ sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
crlf -= strlen(SIP_CRLF);
}
if (rset_head == NULL) {
+ if (rset_tail != NULL) {
+ sip_write_to_log((void *)dialog,
+ SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
+ __FILE__, __LINE__);
+ }
assert(rset_tail == NULL);
rset_head = rset_tail = rset;
} else if (what == SIP_UAS_DIALOG) {
@@ -505,6 +540,9 @@ sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
rset->sip_dlg_route_next = rset_head;
rset_head = rset;
} else {
+ sip_write_to_log((void *)dialog,
+ SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
+ __FILE__, __LINE__);
assert(0);
}
value = (sip_hdr_value_t *)sip_get_next_value(
@@ -724,6 +762,10 @@ sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
const sip_str_t *local_tag;
local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
+ if (local_tag == NULL) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
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,
@@ -739,6 +781,11 @@ sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
goto dia_err;
}
}
+
+ dialog->sip_dlg_msgcnt = 1;
+ sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
+ (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
+
SIP_DLG_REFCNT_INCR(dialog);
return ((sip_dialog_t)dialog);
dia_err:
@@ -975,8 +1022,17 @@ sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
} else {
resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
+ if (dialog->sip_dlg_state != SIP_DLG_NEW) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(dialog->sip_dlg_state == SIP_DLG_NEW);
if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) {
+ if (dialog->sip_dlg_type != SIP_UAC_DIALOG) {
+ sip_write_to_log((void *)dialog,
+ SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
+ __FILE__, __LINE__);
+ }
assert(dialog->sip_dlg_type == SIP_UAC_DIALOG);
if ((dialog->sip_dlg_remote_target =
sip_dup_header(chdr)) == NULL) {
@@ -1072,6 +1128,10 @@ sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
&error);
}
+ if (val == NULL || error != 0) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(val != NULL && error == 0);
remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);
@@ -1186,11 +1246,16 @@ sip_dialog_free(void *obj, void *hindex, int *found)
if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
== 0) {
*found = 1;
+ if (dialog->sip_dlg_state != SIP_DLG_DESTROYED) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
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);
}
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
sip_release_dialog_res(dialog);
return (B_TRUE);
}
@@ -1264,6 +1329,10 @@ sip_dlg_self_destruct(void *args)
int index;
(void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
+ if (dialog->sip_dlg_state != SIP_DLG_NEW) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(dialog->sip_dlg_state == SIP_DLG_NEW);
dialog->sip_dlg_state = SIP_DLG_DESTROYED;
if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
@@ -1317,6 +1386,7 @@ sip_dialog_delete(_sip_dialog_t *dialog)
*/
if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
sip_release_dialog_res(dialog);
return;
}
@@ -1358,10 +1428,17 @@ sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
_sip_dialog_t *_dialog;
int error;
+ _dialog = (_sip_dialog_t *)*sip_dialog;
+
+ (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
+ _dialog->sip_dlg_msgcnt++;
+ sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
+ (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
+ (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
+
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;
sip_method_t method;
@@ -1432,6 +1509,11 @@ sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
return (0);
}
+ if (_dialog->sip_dlg_state != SIP_DLG_EARLY &&
+ _dialog->sip_dlg_state != SIP_DLG_CONFIRMED) {
+ sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||
_dialog->sip_dlg_state == SIP_DLG_CONFIRMED);
/*
@@ -1455,10 +1537,10 @@ sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
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);
+ (void) pthread_mutex_unlock(
+ &_dialog->sip_dlg_mutex);
if (sip_dlg_ulp_state_cb != NULL) {
sip_dlg_ulp_state_cb(
(sip_dialog_t)_dialog,
@@ -1468,6 +1550,13 @@ sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
return (0);
} else if (_dialog->sip_dlg_new_local_contact
!= NULL) {
+ if (_dialog->sip_dlg_local_contact ==
+ NULL) {
+ (void) sip_write_to_log((void *)
+ _dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__,
+ __LINE__);
+ }
assert(_dialog->sip_dlg_local_contact
!= NULL);
sip_free_header(_dialog->
@@ -1511,6 +1600,10 @@ sip_copy_partial_dialog(_sip_dialog_t *dialog)
dialog->sip_dlg_req_uri.sip_str_len;
}
if (dialog->sip_dlg_route_set != NULL) {
+ if (dialog->sip_dlg_rset.sip_str_ptr == NULL) {
+ sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
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);
@@ -1578,10 +1671,16 @@ sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
boolean_t decr_ref = B_FALSE;
int error;
+ _dialog = (_sip_dialog_t *)dialog;
+ (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
+ _dialog->sip_dlg_msgcnt++;
+ sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
+ (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
+ (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
+
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);
@@ -1610,6 +1709,10 @@ sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
* Let the user delete the dialog if it is not a 1XX/2XX resp
* for an early dialog.
*/
+ if (isreq) {
+ sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(!isreq);
if (SIP_OK_RESP(resp_code)) {
_dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
@@ -1633,9 +1736,9 @@ sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
NULL;
}
}
- (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
(void) sip_dlg_recompute_rset(_dialog, sip_msg,
SIP_UAS_DIALOG);
+ (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
if (sip_dlg_ulp_state_cb != NULL) {
sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,
prev_state, dialog->sip_dlg_state);
@@ -1780,3 +1883,23 @@ sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg)
}
(void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
}
+
+/*
+ * Given a state, return the string - This is mostly for debug purposes
+ */
+char *
+sip_get_dialog_state_str(int state)
+{
+ switch (state) {
+ case SIP_DLG_NEW:
+ return ("SIP_DLG_NEW");
+ case SIP_DLG_EARLY:
+ return ("SIP_DLG_EARLY");
+ case SIP_DLG_CONFIRMED:
+ return ("SIP_DLG_CONFIRMED");
+ case SIP_DLG_DESTROYED:
+ return ("SIP_DLG_DESTROYED");
+ default:
+ return ("UNKNOWN");
+ }
+}
diff --git a/usr/src/lib/libsip/common/sip_dialog.h b/usr/src/lib/libsip/common/sip_dialog.h
index b923ecab49..1a468ab2f6 100644
--- a/usr/src/lib/libsip/common/sip_dialog.h
+++ b/usr/src/lib/libsip/common/sip_dialog.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -87,6 +87,8 @@ typedef struct sip_dialog
boolean_t sip_dlg_on_fork;
sip_method_t sip_dlg_method;
void *sip_dlg_ctxt; /* currently unused */
+ int sip_dlg_msgcnt;
+ sip_log_t sip_dlg_log[SIP_DLG_DESTROYED + 1];
} _sip_dialog_t;
void sip_dialog_init(void (*sip_ulp_dlg_del)(sip_dialog_t,
@@ -103,6 +105,7 @@ sip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
boolean_t, int);
char *sip_dialog_req_uri(sip_dialog_t);
void sip_dialog_delete(_sip_dialog_t *);
+extern char *sip_get_dialog_state_str(int);
extern boolean_t sip_incomplete_dialog(sip_dialog_t);
#ifdef __cplusplus
diff --git a/usr/src/lib/libsip/common/sip_dialog_ui.c b/usr/src/lib/libsip/common/sip_dialog_ui.c
index d15d79f56e..998ad45218 100644
--- a/usr/src/lib/libsip/common/sip_dialog_ui.c
+++ b/usr/src/lib/libsip/common/sip_dialog_ui.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -531,6 +531,28 @@ sip_get_dialog_type(sip_dialog_t dialog, int *error)
return (type);
}
+/*
+ * Return the number of messages exchanged within a dialog.
+ */
+int
+sip_get_dialog_msgcnt(sip_dialog_t dialog, int *error)
+{
+ _sip_dialog_t *_dialog;
+ int nmsgs;
+
+ if (error != NULL)
+ *error = 0;
+ if (!sip_manage_dialog || dialog == NULL) {
+ if (error != NULL)
+ *error = EINVAL;
+ return (-1);
+ }
+ _dialog = (_sip_dialog_t *)dialog;
+ (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
+ nmsgs = _dialog->sip_dlg_msgcnt;
+ (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
+ return (nmsgs);
+}
/*
* Partial dialog ?
diff --git a/usr/src/lib/libsip/common/sip_itf.c b/usr/src/lib/libsip/common/sip_itf.c
index a45c8282cf..1e376283a3 100644
--- a/usr/src/lib/libsip/common/sip_itf.c
+++ b/usr/src/lib/libsip/common/sip_itf.c
@@ -20,14 +20,14 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
@@ -41,9 +41,6 @@
#include "sip_dialog.h"
#include "sip_parse_generic.h"
-#define SIP_MSG_BUF_SZ 100
-
-
void (*sip_ulp_recv)(const sip_conn_object_t, sip_msg_t,
const sip_dialog_t) = NULL;
uint_t (*sip_stack_timeout)(void *, void (*func)(void *),
@@ -108,6 +105,9 @@ sip_send_resp(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg, int resp)
sip_free_msg((sip_msg_t)sip_msg_resp);
return;
}
+
+ SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, sip_msg_resp->
+ sip_msg_len);
(void) sip_stack_send(conn_obj, sip_msg_resp->sip_msg_buf,
sip_msg_resp->sip_msg_len);
sip_free_msg((sip_msg_t)sip_msg_resp);
@@ -312,12 +312,37 @@ 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);
+ } else if (dialog != NULL) {
+ /*
+ * Dialog is in CONFIRMED state. If logging is enabled
+ * track the SIP message sent within a dialog.
+ */
+ (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
+ dialog->sip_dlg_msgcnt++;
+ sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
+ (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt,
+ SIP_DIALOG_LOG);
+ (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
+
+ if (sip_msg_info->is_request && sip_msg_info->
+ sip_req_method == INVITE) {
+ (void) sip_dialog_add_new_contact(dialog,
+ _sip_msg);
+ }
}
}
-
+ /*
+ * if measure sip traffic is enabled, capture the measurements
+ * Is this the right place to measure or should I put this after
+ * the call to sip_stack_send()
+ */
+ if (sip_msg_info->is_request) {
+ SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0,
+ B_TRUE, _sip_msg->sip_msg_len);
+ } else {
+ SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code,
+ B_TRUE, _sip_msg->sip_msg_len);
+ }
if ((ret = sip_stack_send(obj, _sip_msg->sip_msg_buf,
_sip_msg->sip_msg_len)) != 0) {
if (sip_trans != NULL) {
@@ -528,6 +553,13 @@ next_msg:
return;
}
}
+ if (sip_msg_info->is_request) {
+ SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0,
+ B_FALSE, sip_msg->sip_msg_len);
+ } else {
+ SIP_UPDATE_COUNTERS(B_FALSE, 0, sip_msg_info->sip_resp_code,
+ B_FALSE, sip_msg->sip_msg_len);
+ }
sip_ulp_recv(conn_object, (sip_msg_t)sip_msg, dialog);
sip_free_msg((sip_msg_t)sip_msg);
if (dialog != NULL && !dialog_created)
@@ -635,6 +667,17 @@ sip_stack_init(sip_stack_init_t *stack_val)
sip_xaction_init(stack_val->sip_ulp_pointers->sip_ulp_trans_error,
stack_val->sip_ulp_pointers->sip_ulp_trans_state_cb);
+ /*
+ * Initialize SIP traffic counter mutex
+ */
+ (void) pthread_mutex_init(&sip_counters.sip_counter_mutex, NULL);
+
+ /*
+ * Initialize SIP logfile structures mutex
+ */
+ (void) pthread_mutex_init(&trans_log.sip_logfile_mutex, NULL);
+ (void) pthread_mutex_init(&dialog_log.sip_logfile_mutex, NULL);
+
#ifdef __linux__
if (clock_gettime(CLOCK_REALTIME, &tspec) != 0)
goto err_ret;
diff --git a/usr/src/lib/libsip/common/sip_logging.c b/usr/src/lib/libsip/common/sip_logging.c
new file mode 100644
index 0000000000..fa9c6c67f4
--- /dev/null
+++ b/usr/src/lib/libsip/common/sip_logging.c
@@ -0,0 +1,638 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sip.h>
+
+#include "sip_msg.h"
+#include "sip_miscdefs.h"
+#include "sip_xaction.h"
+#include "sip_dialog.h"
+
+#define TIME_BUF_SIZE 50
+
+/*
+ * Contains API's which enable/disable transaction or dialog logging,
+ * API's which records/measures SIP Traffic.
+ */
+/*
+ * Needed for measuring SIP traffic counters.
+ */
+sip_traffic_counters_t sip_counters;
+
+/*
+ * Needed for dialog/transaction logging.
+ */
+sip_logfile_t trans_log;
+sip_logfile_t dialog_log;
+
+/*
+ * This function increments the appropriate inbound/outbound counters for
+ * SIP requests/responses.
+ */
+void
+sip_measure_traffic(boolean_t is_request, sip_method_t method, int resp_code,
+ boolean_t outbound, int msg_size)
+{
+#ifdef __solaris__
+ assert(mutex_held(&sip_counters.sip_counter_mutex));
+#endif
+ if (outbound)
+ sip_counters.sip_total_bytes_sent += msg_size;
+ else
+ sip_counters.sip_total_bytes_rcvd += msg_size;
+
+ if (is_request) {
+ if (outbound)
+ ++sip_counters.sip_total_req_sent;
+ else
+ ++sip_counters.sip_total_req_rcvd;
+ switch (method) {
+ case INVITE:
+ if (outbound)
+ ++sip_counters.sip_invite_req_sent;
+ else
+ ++sip_counters.sip_invite_req_rcvd;
+ break;
+ case ACK:
+ if (outbound)
+ ++sip_counters.sip_ack_req_sent;
+ else
+ ++sip_counters.sip_ack_req_rcvd;
+ break;
+ case OPTIONS:
+ if (outbound)
+ ++sip_counters.sip_options_req_sent;
+ else
+ ++sip_counters.sip_options_req_rcvd;
+ break;
+ case BYE:
+ if (outbound)
+ ++sip_counters.sip_bye_req_sent;
+ else
+ ++sip_counters.sip_bye_req_rcvd;
+ break;
+ case CANCEL:
+ if (outbound)
+ ++sip_counters.sip_cancel_req_sent;
+ else
+ ++sip_counters.sip_cancel_req_rcvd;
+ break;
+ case REGISTER:
+ if (outbound)
+ ++sip_counters.sip_register_req_sent;
+ else
+ ++sip_counters.sip_register_req_rcvd;
+ break;
+ case REFER:
+ if (outbound)
+ ++sip_counters.sip_refer_req_sent;
+ else
+ ++sip_counters.sip_refer_req_rcvd;
+ break;
+ case INFO:
+ if (outbound)
+ ++sip_counters.sip_info_req_sent;
+ else
+ ++sip_counters.sip_info_req_rcvd;
+ break;
+ case SUBSCRIBE:
+ if (outbound)
+ ++sip_counters.sip_subscribe_req_sent;
+ else
+ ++sip_counters.sip_subscribe_req_rcvd;
+ break;
+ case NOTIFY:
+ if (outbound)
+ ++sip_counters.sip_notify_req_sent;
+ else
+ ++sip_counters.sip_notify_req_rcvd;
+ break;
+ case PRACK:
+ if (outbound)
+ ++sip_counters.sip_prack_req_sent;
+ else
+ ++sip_counters.sip_prack_req_rcvd;
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (outbound)
+ ++sip_counters.sip_total_resp_sent;
+ else
+ ++sip_counters.sip_total_resp_rcvd;
+ if (SIP_PROVISIONAL_RESP(resp_code)) {
+ if (outbound)
+ ++sip_counters.sip_1xx_resp_sent;
+ else
+ ++sip_counters.sip_1xx_resp_rcvd;
+ } else if (SIP_OK_RESP(resp_code)) {
+ if (outbound)
+ ++sip_counters.sip_2xx_resp_sent;
+ else
+ ++sip_counters.sip_2xx_resp_rcvd;
+ } else if (SIP_REDIRECT_RESP(resp_code)) {
+ if (outbound)
+ ++sip_counters.sip_3xx_resp_sent;
+ else
+ ++sip_counters.sip_3xx_resp_rcvd;
+ } else if (SIP_REQFAIL_RESP(resp_code)) {
+ if (outbound)
+ ++sip_counters.sip_4xx_resp_sent;
+ else
+ ++sip_counters.sip_4xx_resp_rcvd;
+ } else if (SIP_SRVFAIL_RESP(resp_code)) {
+ if (outbound)
+ ++sip_counters.sip_5xx_resp_sent;
+ else
+ ++sip_counters.sip_5xx_resp_rcvd;
+ } else if (SIP_GLOBFAIL_RESP(resp_code)) {
+ if (outbound)
+ ++sip_counters.sip_6xx_resp_sent;
+ else
+ ++sip_counters.sip_6xx_resp_rcvd;
+ }
+ }
+}
+
+/*
+ * Enables Transaction logging. The flags argument controls the detail
+ * of logging.
+ */
+int
+sip_enable_trans_logging(FILE *logfile, int flags)
+{
+ if (logfile == NULL || flags != SIP_DETAIL_LOGGING)
+ return (EINVAL);
+
+ (void) pthread_mutex_lock(&trans_log.sip_logfile_mutex);
+ if (!trans_log.sip_logging_enabled) {
+ trans_log.sip_logfile = logfile;
+ trans_log.sip_logging_enabled = B_TRUE;
+ }
+ (void) pthread_mutex_unlock(&trans_log.sip_logfile_mutex);
+ return (0);
+}
+
+
+/*
+ * Enables dialog logging. The flags argument controls the detail
+ * of logging.
+ */
+int
+sip_enable_dialog_logging(FILE *logfile, int flags)
+{
+ if (logfile == NULL || flags != SIP_DETAIL_LOGGING)
+ return (EINVAL);
+
+ (void) pthread_mutex_lock(&dialog_log.sip_logfile_mutex);
+ if (!dialog_log.sip_logging_enabled) {
+ dialog_log.sip_logfile = logfile;
+ dialog_log.sip_logging_enabled = B_TRUE;
+ }
+ (void) pthread_mutex_unlock(&dialog_log.sip_logfile_mutex);
+ return (0);
+}
+
+void
+sip_disable_trans_logging()
+{
+ (void) pthread_mutex_lock(&trans_log.sip_logfile_mutex);
+ if (trans_log.sip_logging_enabled)
+ trans_log.sip_logging_enabled = B_FALSE;
+ (void) pthread_mutex_unlock(&trans_log.sip_logfile_mutex);
+}
+
+void
+sip_disable_dialog_logging()
+{
+ (void) pthread_mutex_lock(&dialog_log.sip_logfile_mutex);
+ if (dialog_log.sip_logging_enabled)
+ dialog_log.sip_logging_enabled = B_FALSE;
+ (void) pthread_mutex_unlock(&dialog_log.sip_logfile_mutex);
+}
+
+static void
+sip_print_digest(uint16_t *digest, int len, FILE *fp)
+{
+ int cnt;
+
+ for (cnt = 0; cnt < len; cnt++)
+ (void) fprintf(fp, "%u ", digest[cnt]);
+ (void) fprintf(fp, "\n\n");
+}
+
+/*
+ * Logs all the messages exchanged within a transaction to the transaction
+ * log file. Logged messages are then freed.
+ */
+static void
+sip_write_xaction_to_log(void *obj)
+{
+ sip_xaction_t *trans = (sip_xaction_t *)obj;
+ sip_log_t *sip_log;
+ int count;
+ sip_msg_chain_t *msg_chain;
+ sip_msg_chain_t *nmsg_chain;
+ char timebuf[TIME_BUF_SIZE];
+ struct tm tms;
+ FILE *sip_trans_logfile = trans_log.sip_logfile;
+
+ assert(trans != NULL && sip_trans_logfile != NULL);
+ (void) fprintf(sip_trans_logfile, "************* Begin Transaction"
+ " *************\n");
+ (void) fprintf(sip_trans_logfile, "Branchid\t\t: %s\n",
+ trans->sip_xaction_branch_id);
+ (void) fprintf(sip_trans_logfile, "Digest\t\t\t: ");
+ sip_print_digest(trans->sip_xaction_hash_digest, 8, sip_trans_logfile);
+ (void) fprintf(sip_trans_logfile, "-----------------------------\n");
+ for (count = 0; count <= SIP_SRV_NONINV_TERMINATED; count++) {
+ sip_log = &trans->sip_xaction_log[count];
+ if (sip_log->sip_msgcnt == 0)
+ continue;
+ (void) fprintf(sip_trans_logfile, "Transaction State\t: %s\n\n",
+ sip_get_xaction_state(count));
+ msg_chain = sip_log->sip_msgs;
+ while (msg_chain != NULL) {
+ nmsg_chain = msg_chain->next;
+ (void) strftime(timebuf, sizeof (timebuf), NULL,
+ localtime_r(&msg_chain->msg_timestamp, &tms));
+ (void) fprintf(sip_trans_logfile, "%s| Message -"
+ " %d\n%s", timebuf, msg_chain->msg_seq, msg_chain->
+ sip_msg);
+ free(msg_chain->sip_msg);
+ free(msg_chain);
+ --sip_log->sip_msgcnt;
+ msg_chain = nmsg_chain;
+ }
+ (void) fprintf(sip_trans_logfile,
+ "-----------------------------\n");
+ (trans->sip_xaction_log[count]).sip_msgs = NULL;
+ }
+ (void) fprintf(sip_trans_logfile, "************* End Transaction "
+ "*************\n");
+ (void) fflush(sip_trans_logfile);
+}
+
+/*
+ * Logs all the messages exchanged within a dialog to the dialog
+ * log file. Logged messages are then freed.
+ */
+static void
+sip_write_dlg_to_log(void *obj)
+{
+ _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
+ sip_log_t *sip_log;
+ int count;
+ sip_msg_chain_t *msg_chain;
+ sip_msg_chain_t *nmsg_chain;
+ char timebuf[TIME_BUF_SIZE];
+ struct tm tms;
+ FILE *sip_dialog_logfile = dialog_log.sip_logfile;
+
+ assert(dialog != NULL && sip_dialog_logfile != NULL);
+
+ (void) fprintf(sip_dialog_logfile, "************* Begin Dialog "
+ "*************\n");
+ (void) fprintf(sip_dialog_logfile, "Digest\t\t\t: ");
+ sip_print_digest(dialog->sip_dlg_id, 8, sip_dialog_logfile);
+ (void) fprintf(sip_dialog_logfile, "-----------------------------\n");
+ for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
+ sip_log = &dialog->sip_dlg_log[count];
+ if (sip_log->sip_msgcnt == 0)
+ continue;
+ (void) fprintf(sip_dialog_logfile, "Dialog State\t\t: %s\n\n",
+ sip_get_dialog_state_str(count));
+ msg_chain = sip_log->sip_msgs;
+ while (msg_chain != NULL) {
+ nmsg_chain = msg_chain->next;
+ (void) strftime(timebuf, sizeof (timebuf), NULL,
+ localtime_r(&msg_chain->msg_timestamp, &tms));
+ (void) fprintf(sip_dialog_logfile, "%s| Message -"
+ " %d\n%s", timebuf, msg_chain->msg_seq, msg_chain->
+ sip_msg);
+ free(msg_chain->sip_msg);
+ free(msg_chain);
+ --sip_log->sip_msgcnt;
+ msg_chain = nmsg_chain;
+ }
+ (void) fprintf(sip_dialog_logfile,
+ "-----------------------------\n");
+ (dialog->sip_dlg_log[count]).sip_msgs = NULL;
+ }
+ (void) fprintf(sip_dialog_logfile, "************* End Dialog "
+ "*************\n");
+ (void) fflush(sip_dialog_logfile);
+}
+
+/*
+ * Calls the appropriate function to log transaction or dialog messages.
+ * If this function is called because of assertion failure, then the file and
+ * line where the assertion failed is logged to the log file.
+ */
+void
+sip_write_to_log(void *obj, int type, char *file, int line)
+{
+ if (type & SIP_TRANSACTION_LOG) {
+ (void) pthread_mutex_lock(&trans_log.sip_logfile_mutex);
+ if (trans_log.sip_logging_enabled) {
+ if (type & SIP_ASSERT_ERROR) {
+ (void) fprintf(trans_log.sip_logfile,
+ "Assertion Failure at %s:%d\n", file, line);
+ }
+ sip_write_xaction_to_log(obj);
+ }
+ (void) pthread_mutex_unlock(&trans_log.sip_logfile_mutex);
+ } else {
+ (void) pthread_mutex_lock(&dialog_log.sip_logfile_mutex);
+ if (dialog_log.sip_logging_enabled) {
+ if (type & SIP_ASSERT_ERROR) {
+ (void) fprintf(dialog_log.sip_logfile,
+ "Assertion Failure at %s:%d\n", file, line);
+ }
+ sip_write_dlg_to_log(obj);
+ }
+ (void) pthread_mutex_unlock(&dialog_log.sip_logfile_mutex);
+ }
+}
+
+/*
+ * This function records the messages that are exchanged within a dialog or
+ * transaction. If logging is enabled the recorded messages are then dumped
+ * to the log file just before deleting the transaction or dialog.
+ */
+void
+sip_add_log(sip_log_t *sip_log, sip_msg_t sip_msg, int seq, int type)
+{
+ char *msgstr;
+ sip_msg_chain_t *new_msg;
+ sip_msg_chain_t *msg_chain = sip_log->sip_msgs;
+
+ /*
+ * No need to take any locks here. Caller of this function MUST
+ * have already taken the transaction or dialog lock.
+ */
+ if (((type == SIP_DIALOG_LOG) && !dialog_log.sip_logging_enabled) ||
+ ((type == SIP_TRANSACTION_LOG) && !trans_log.sip_logging_enabled)) {
+ return;
+ }
+
+ new_msg = calloc(1, sizeof (sip_msg_chain_t));
+ if (new_msg == NULL)
+ return;
+
+ msgstr = sip_msg_to_str(sip_msg, NULL);
+ if (msgstr == NULL) {
+ free(new_msg);
+ return;
+ }
+
+ new_msg->sip_msg = msgstr;
+ new_msg->msg_seq = seq;
+ new_msg->msg_timestamp = time(NULL);
+ new_msg->next = NULL;
+ if (sip_log->sip_msgcnt == 0) {
+ sip_log->sip_msgs = new_msg;
+ } else {
+ while (msg_chain->next != NULL)
+ msg_chain = msg_chain->next;
+ msg_chain->next = new_msg;
+ }
+ sip_log->sip_msgcnt++;
+}
+
+/*
+ * Given a counter group and counter name within the group, returns the value
+ * associated with the counter in 'cntval'.
+ */
+int
+sip_get_counter_value(int group, int counter, void *cntval, size_t cntlen)
+{
+ if (group != SIP_TRAFFIC_COUNTERS || cntval == NULL)
+ return (EINVAL);
+ if ((counter == SIP_COUNTER_START_TIME || counter ==
+ SIP_COUNTER_STOP_TIME) && (cntlen != sizeof (time_t))) {
+ return (EINVAL);
+ } else if (cntlen != sizeof (uint64_t)) {
+ return (EINVAL);
+ }
+
+ (void) pthread_mutex_lock(&sip_counters.sip_counter_mutex);
+ switch (counter) {
+ case SIP_TOTAL_BYTES_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_total_bytes_rcvd;
+ break;
+ case SIP_TOTAL_BYTES_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_total_bytes_sent;
+ break;
+ case SIP_TOTAL_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_total_req_rcvd;
+ break;
+ case SIP_TOTAL_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_total_req_sent;
+ break;
+ case SIP_TOTAL_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_total_resp_rcvd;
+ break;
+ case SIP_TOTAL_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_total_resp_sent;
+ break;
+ case SIP_ACK_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_ack_req_rcvd;
+ break;
+ case SIP_ACK_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_ack_req_sent;
+ break;
+ case SIP_BYE_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_bye_req_rcvd;
+ break;
+ case SIP_BYE_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_bye_req_sent;
+ break;
+ case SIP_CANCEL_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_cancel_req_rcvd;
+ break;
+ case SIP_CANCEL_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_cancel_req_sent;
+ break;
+ case SIP_INFO_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_info_req_rcvd;
+ break;
+ case SIP_INFO_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_info_req_sent;
+ break;
+ case SIP_INVITE_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_invite_req_rcvd;
+ break;
+ case SIP_INVITE_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_invite_req_sent;
+ break;
+ case SIP_NOTIFY_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_notify_req_rcvd;
+ break;
+ case SIP_NOTIFY_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_notify_req_sent;
+ break;
+ case SIP_OPTIONS_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_options_req_rcvd;
+ break;
+ case SIP_OPTIONS_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_options_req_sent;
+ break;
+ case SIP_PRACK_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_prack_req_rcvd;
+ break;
+ case SIP_PRACK_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_prack_req_sent;
+ break;
+ case SIP_REFER_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_refer_req_rcvd;
+ break;
+ case SIP_REFER_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_refer_req_sent;
+ break;
+ case SIP_REGISTER_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.
+ sip_register_req_rcvd;
+ break;
+ case SIP_REGISTER_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.
+ sip_register_req_sent;
+ break;
+ case SIP_SUBSCRIBE_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.
+ sip_subscribe_req_rcvd;
+ break;
+ case SIP_SUBSCRIBE_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.
+ sip_subscribe_req_sent;
+ break;
+ case SIP_UPDATE_REQ_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_update_req_rcvd;
+ break;
+ case SIP_UPDATE_REQ_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_update_req_sent;
+ break;
+ case SIP_1XX_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_1xx_resp_rcvd;
+ break;
+ case SIP_1XX_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_1xx_resp_sent;
+ break;
+ case SIP_2XX_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_2xx_resp_rcvd;
+ break;
+ case SIP_2XX_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_2xx_resp_sent;
+ break;
+ case SIP_3XX_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_3xx_resp_rcvd;
+ break;
+ case SIP_3XX_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_3xx_resp_sent;
+ break;
+ case SIP_4XX_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_4xx_resp_rcvd;
+ break;
+ case SIP_4XX_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_4xx_resp_sent;
+ break;
+ case SIP_5XX_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_5xx_resp_rcvd;
+ break;
+ case SIP_5XX_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_5xx_resp_sent;
+ break;
+ case SIP_6XX_RESP_RCVD:
+ *(uint64_t *)cntval = sip_counters.sip_6xx_resp_rcvd;
+ break;
+ case SIP_6xx_RESP_SENT:
+ *(uint64_t *)cntval = sip_counters.sip_6xx_resp_sent;
+ break;
+ case SIP_COUNTER_START_TIME:
+ *(time_t *)cntval = sip_counters.starttime;
+ break;
+ case SIP_COUNTER_STOP_TIME:
+ *(time_t *)cntval = sip_counters.stoptime;
+ break;
+ default:
+ (void) pthread_mutex_unlock(&sip_counters.
+ sip_counter_mutex);
+ return (EINVAL);
+ }
+ (void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex);
+ return (0);
+}
+
+/*
+ * Enables the SIP performance/traffic counting. Also reset's the previous
+ * counter values and starts counting afresh.
+ */
+int
+sip_enable_counters(int group)
+{
+ if (group != SIP_TRAFFIC_COUNTERS)
+ return (EINVAL);
+ (void) pthread_mutex_lock(&sip_counters.sip_counter_mutex);
+ /* If it's not enabled, enable it and capture the start time */
+ if (!sip_counters.enabled) {
+ /* zero all the counters except for the mutex at the end */
+ (void) bzero(&sip_counters, sizeof (sip_traffic_counters_t) -
+ sizeof (pthread_mutex_t));
+ sip_counters.enabled = B_TRUE;
+ sip_counters.starttime = time(NULL);
+ sip_counters.stoptime = 0;
+ }
+ (void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex);
+ return (0);
+}
+
+/*
+ * Disables the SIP performance/traffic counting. If already disabled it just
+ * exits without doing anyting. It records the stop time.
+ */
+int
+sip_disable_counters(int group)
+{
+ if (group != SIP_TRAFFIC_COUNTERS)
+ return (EINVAL);
+ (void) pthread_mutex_lock(&sip_counters.sip_counter_mutex);
+ if (sip_counters.enabled) {
+ sip_counters.enabled = B_FALSE;
+ sip_counters.stoptime = time(NULL);
+ }
+ (void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex);
+ return (0);
+}
diff --git a/usr/src/lib/libsip/common/sip_miscdefs.h b/usr/src/lib/libsip/common/sip_miscdefs.h
index c3129d873b..1f5df8f40e 100644
--- a/usr/src/lib/libsip/common/sip_miscdefs.h
+++ b/usr/src/lib/libsip/common/sip_miscdefs.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,6 +36,7 @@ extern "C" {
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <stdio.h>
#define SIP_CR '\r'
#define SIP_SP ' '
@@ -61,6 +62,10 @@ extern "C" {
#define SIP_SIZE_OF_STATUS_CODE 3
#define SIP_SPACE_LEN sizeof (char)
+#define SIP_TRANSACTION_LOG 0x0001
+#define SIP_DIALOG_LOG 0x0002
+#define SIP_ASSERT_ERROR 0x0004
+
#define SIP_MS 1L
#define SIP_SECONDS (1000 * SIP_MS)
#define SIP_MINUTES (60 * SIP_SECONDS)
@@ -126,6 +131,15 @@ typedef struct sip_timer_s {
#define SIP_IS_TIMER_RUNNING(timer) ((timer).sip_timerid != 0)
+#define SIP_UPDATE_COUNTERS(is_request, method, resp_code, outbound, size) { \
+ (void) pthread_mutex_lock(&sip_counters.sip_counter_mutex); \
+ if (sip_counters.enabled) { \
+ (void) sip_measure_traffic((is_request), (method), (resp_code),\
+ (outbound), (size)); \
+ } \
+ (void) pthread_mutex_unlock(&sip_counters.sip_counter_mutex); \
+}
+
/* This is the transaction list */
typedef struct sip_conn_cache_s {
void *obj;
@@ -147,6 +161,81 @@ typedef struct sip_conn_obj_pvt_s {
pthread_mutex_t sip_conn_obj_cache_lock;
} sip_conn_obj_pvt_t;
+/* SIP traffic counters structure */
+
+typedef struct sip_traffic_counters_s {
+ boolean_t enabled;
+ time_t starttime;
+ time_t stoptime;
+ uint64_t sip_total_bytes_rcvd;
+ uint64_t sip_total_bytes_sent;
+ uint64_t sip_total_req_rcvd;
+ uint64_t sip_total_req_sent;
+ uint64_t sip_total_resp_rcvd;
+ uint64_t sip_total_resp_sent;
+ uint64_t sip_ack_req_rcvd;
+ uint64_t sip_ack_req_sent;
+ uint64_t sip_bye_req_rcvd;
+ uint64_t sip_bye_req_sent;
+ uint64_t sip_cancel_req_rcvd;
+ uint64_t sip_cancel_req_sent;
+ uint64_t sip_info_req_rcvd;
+ uint64_t sip_info_req_sent;
+ uint64_t sip_invite_req_rcvd;
+ uint64_t sip_invite_req_sent;
+ uint64_t sip_notify_req_rcvd;
+ uint64_t sip_notify_req_sent;
+ uint64_t sip_options_req_rcvd;
+ uint64_t sip_options_req_sent;
+ uint64_t sip_prack_req_rcvd;
+ uint64_t sip_prack_req_sent;
+ uint64_t sip_refer_req_rcvd;
+ uint64_t sip_refer_req_sent;
+ uint64_t sip_register_req_rcvd;
+ uint64_t sip_register_req_sent;
+ uint64_t sip_subscribe_req_rcvd;
+ uint64_t sip_subscribe_req_sent;
+ uint64_t sip_update_req_rcvd;
+ uint64_t sip_update_req_sent;
+ uint64_t sip_1xx_resp_rcvd;
+ uint64_t sip_1xx_resp_sent;
+ uint64_t sip_2xx_resp_rcvd;
+ uint64_t sip_2xx_resp_sent;
+ uint64_t sip_3xx_resp_rcvd;
+ uint64_t sip_3xx_resp_sent;
+ uint64_t sip_4xx_resp_rcvd;
+ uint64_t sip_4xx_resp_sent;
+ uint64_t sip_5xx_resp_rcvd;
+ uint64_t sip_5xx_resp_sent;
+ uint64_t sip_6xx_resp_rcvd;
+ uint64_t sip_6xx_resp_sent;
+ pthread_mutex_t sip_counter_mutex; /* Mutex should be always at end */
+} sip_traffic_counters_t;
+
+/* SIP logfile structure */
+typedef struct sip_logfile_s {
+ boolean_t sip_logging_enabled;
+ FILE *sip_logfile;
+ pthread_mutex_t sip_logfile_mutex;
+} sip_logfile_t;
+
+typedef struct sip_msg_chain_s {
+ char *sip_msg;
+ int msg_seq;
+ time_t msg_timestamp;
+ struct sip_msg_chain_s *next;
+}sip_msg_chain_t;
+
+typedef struct sip_log_s {
+ sip_msg_chain_t *sip_msgs;
+ int sip_msgcnt;
+}sip_log_t;
+
+extern sip_traffic_counters_t sip_counters;
+
+extern sip_logfile_t trans_log;
+extern sip_logfile_t dialog_log;
+
extern boolean_t sip_manage_dialog;
/* To salt the hash function */
@@ -157,6 +246,10 @@ extern uint_t sip_timeout(void *, void (*)(void *), struct timeval *);
extern boolean_t sip_untimeout(uint_t);
extern void sip_md5_hash(char *, int, char *, int, char *, int,
char *, int, char *, int, char *, int, uchar_t *);
+extern void sip_measure_traffic(boolean_t, sip_method_t, int,
+ boolean_t, int);
+extern void sip_add_log(sip_log_t *, sip_msg_t, int, int);
+extern void sip_write_to_log(void *, int, char *, int);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libsip/common/sip_xaction.c b/usr/src/lib/libsip/common/sip_xaction.c
index 139c9b8402..1fa4f51ea6 100644
--- a/usr/src/lib/libsip/common/sip_xaction.c
+++ b/usr/src/lib/libsip/common/sip_xaction.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -484,6 +484,9 @@ boolean_t
sip_xaction_remove(void *obj, void *hindex, int *found)
{
sip_xaction_t *tmp = (sip_xaction_t *)obj;
+ int count = 0;
+ sip_msg_chain_t *msg_chain;
+ sip_msg_chain_t *nmsg_chain;
*found = 0;
tmp = (sip_xaction_t *)obj;
@@ -506,6 +509,7 @@ sip_xaction_remove(void *obj, void *hindex, int *found)
SIP_CANCEL_TIMER(tmp->sip_xaction_TI);
SIP_CANCEL_TIMER(tmp->sip_xaction_TJ);
SIP_CANCEL_TIMER(tmp->sip_xaction_TK);
+ sip_write_to_log((void *)tmp, SIP_TRANSACTION_LOG, NULL, 0);
free(tmp->sip_xaction_branch_id);
if (tmp->sip_xaction_last_msg != NULL) {
SIP_MSG_REFCNT_DECR(tmp->sip_xaction_last_msg);
@@ -519,6 +523,21 @@ sip_xaction_remove(void *obj, void *hindex, int *found)
sip_del_conn_obj_cache(tmp->sip_xaction_conn_obj,
(void *)tmp);
}
+ /*
+ * If the transaction logging is disabled before we could
+ * write the captured messages into the transaction log, then
+ * we need to free those captured messsages
+ */
+ for (count = 0; count <= SIP_SRV_NONINV_TERMINATED; count++) {
+ msg_chain = tmp->sip_xaction_log[count].sip_msgs;
+ while (msg_chain != NULL) {
+ nmsg_chain = msg_chain->next;
+ if (msg_chain->sip_msg != NULL)
+ free(msg_chain->sip_msg);
+ free(msg_chain);
+ msg_chain = nmsg_chain;
+ }
+ }
free(tmp);
return (B_TRUE);
}
@@ -577,6 +596,8 @@ char *
sip_get_xaction_state(int state)
{
switch (state) {
+ case SIP_NEW_TRANSACTION:
+ return ("SIP_NEW_TRANSACTION");
case SIP_CLNT_CALLING:
return ("SIP_CLNT_CALLING");
case SIP_CLNT_INV_PROCEEDING:
@@ -610,7 +631,7 @@ sip_get_xaction_state(int state)
case SIP_SRV_NONINV_TERMINATED:
return ("SIP_SRV_NONINV_TERMINATED");
default :
- return ("unknown");
+ return ("UNKNOWN");
}
}
diff --git a/usr/src/lib/libsip/common/sip_xaction.h b/usr/src/lib/libsip/common/sip_xaction.h
index e3ccaebbae..a77e1970a4 100644
--- a/usr/src/lib/libsip/common/sip_xaction.h
+++ b/usr/src/lib/libsip/common/sip_xaction.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -102,6 +102,8 @@ typedef struct sip_xaction {
sip_timer_t sip_xaction_TJ;
sip_timer_t sip_xaction_TK;
void *sip_xaction_ctxt; /* currently unused */
+ int sip_xaction_msgcnt;
+ sip_log_t sip_xaction_log[SIP_SRV_NONINV_TERMINATED + 1];
} sip_xaction_t;
extern void sip_xaction_init(int (*ulp_trans_err)(sip_transaction_t,
diff --git a/usr/src/lib/libsip/common/sip_xaction_state_mc.c b/usr/src/lib/libsip/common/sip_xaction_state_mc.c
index af991a2ba4..409d4ba5ea 100644
--- a/usr/src/lib/libsip/common/sip_xaction_state_mc.c
+++ b/usr/src/lib/libsip/common/sip_xaction_state_mc.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -173,9 +173,21 @@ sip_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
sip_message_type_t *sip_msg_info;
int ret;
+ if (conn_obj == NULL) {
+ (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
+ sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
+ }
assert(conn_obj != NULL);
sip_msg_info = msg->sip_msg_req_res;
+ (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
+ sip_trans->sip_xaction_msgcnt++;
+ sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
+ (sip_msg_t)msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
+ (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
+
if (sip_msg_info->is_request)
return (sip_clnt_xaction_output(conn_obj, sip_trans, msg));
@@ -202,6 +214,10 @@ sip_clnt_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
prev_state = sip_trans->sip_xaction_state;
+ if (msg->sip_msg_req_res == NULL) {
+ sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(msg->sip_msg_req_res != NULL);
sip_msg_info = msg->sip_msg_req_res;
isreliable = sip_is_conn_reliable(conn_obj);
@@ -587,6 +603,14 @@ sip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
int ret;
sip_msg_info = (*sip_msg)->sip_msg_req_res;
+
+ (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
+ sip_trans->sip_xaction_msgcnt++;
+ sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
+ (sip_msg_t)*sip_msg, sip_trans->sip_xaction_msgcnt,
+ SIP_TRANSACTION_LOG);
+ (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
+
if (sip_msg_info->is_request)
ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg);
else
@@ -647,7 +671,7 @@ sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
}
if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len ||
strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr,
- req_to_tag->sip_str_len) != 0) {
+ req_to_tag->sip_str_len) != 0) {
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
return (0);
@@ -715,6 +739,11 @@ sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
}
if (sip_msg_info->sip_req_method == INVITE) {
(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
+ if (sip_trans->sip_xaction_method != INVITE) {
+ sip_write_to_log((void *)sip_trans,
+ SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR, __FILE__,
+ __LINE__);
+ }
assert(sip_trans->sip_xaction_method == INVITE);
/*
* Retransmitted invite
@@ -723,10 +752,32 @@ sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
case SIP_SRV_INV_PROCEEDING:
case SIP_SRV_INV_COMPLETED:
if (sip_trans->sip_xaction_last_msg != NULL) {
- _sip_msg_t *new_msg;
+ _sip_msg_t *new_msg;
+ sip_message_type_t *msg_info;
+ int resp;
new_msg =
sip_trans->sip_xaction_last_msg;
+ msg_info = new_msg->sip_msg_req_res;
+ if (msg_info == NULL || msg_info->
+ is_request) {
+ sip_write_to_log((void *)
+ sip_trans,
+ SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__,
+ __LINE__);
+ }
+ assert(msg_info != NULL && !msg_info->
+ is_request);
+ resp = msg_info->sip_resp_code;
+ SIP_UPDATE_COUNTERS(B_FALSE, 0, resp,
+ B_TRUE, new_msg->sip_msg_len);
+ ++sip_trans->sip_xaction_msgcnt;
+ sip_add_log(&sip_trans->sip_xaction_log[
+ sip_trans->sip_xaction_state],
+ new_msg, sip_trans->
+ sip_xaction_msgcnt,
+ SIP_TRANSACTION_LOG);
(void) sip_stack_send(conn_obj,
new_msg->sip_msg_buf,
new_msg->sip_msg_len);
@@ -738,6 +789,12 @@ sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
return (EPROTO);
}
(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
+ /*
+ * We need to account for this invite received by the stack
+ * before we free that message.
+ */
+ SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_FALSE,
+ msg->sip_msg_len);
sip_free_msg((sip_msg_t)msg);
*sip_msg = NULL;
return (0);
@@ -745,15 +802,38 @@ sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
/*
* Retransmitted request
*/
- assert(sip_trans->sip_xaction_method != INVITE);
(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
+ if (sip_trans->sip_xaction_method == INVITE) {
+ sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
+ assert(sip_trans->sip_xaction_method != INVITE);
switch (sip_trans->sip_xaction_state) {
case SIP_SRV_NONINV_PROCEEDING:
case SIP_SRV_NONINV_COMPLETED:
if (sip_trans->sip_xaction_last_msg != NULL) {
- _sip_msg_t *new_msg;
+ _sip_msg_t *new_msg;
+ sip_message_type_t *msg_info;
+ int resp;
new_msg = sip_trans->sip_xaction_last_msg;
+ msg_info = new_msg->sip_msg_req_res;
+ if (msg_info == NULL || msg_info->is_request) {
+ sip_write_to_log((void *)sip_trans,
+ SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__,
+ __LINE__);
+ }
+ assert(msg_info != NULL && !msg_info->
+ is_request);
+ resp = msg_info->sip_resp_code;
+ SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE,
+ new_msg->sip_msg_len);
+ ++sip_trans->sip_xaction_msgcnt;
+ sip_add_log(&sip_trans->sip_xaction_log[
+ sip_trans->sip_xaction_state], new_msg,
+ sip_trans->sip_xaction_msgcnt,
+ SIP_TRANSACTION_LOG);
(void) sip_stack_send(conn_obj,
new_msg->sip_msg_buf, new_msg->sip_msg_len);
}
@@ -764,6 +844,13 @@ sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
return (EPROTO);
}
(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
+ /*
+ * We need to account for the retransmitted non-INVITE request here.
+ * When we return from here the msg will be freed and we will not
+ * be able to capture the details at sip_process_new_packet()
+ */
+ SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, B_FALSE,
+ msg->sip_msg_len);
sip_free_msg((sip_msg_t)msg);
*sip_msg = NULL;
return (0);
@@ -802,6 +889,10 @@ sip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
sip_free_msg((sip_msg_t)ack_msg);
return (ret);
}
+ SIP_UPDATE_COUNTERS(B_TRUE, ACK, 0, B_TRUE, ack_msg->sip_msg_len);
+ ++sip_trans->sip_xaction_msgcnt;
+ sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
+ ack_msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf,
ack_msg->sip_msg_len)) != 0) {
sip_free_msg((sip_msg_t)ack_msg);
@@ -833,13 +924,17 @@ sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
int prev_state;
boolean_t isreliable;
+ (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
+ if (msg->sip_msg_req_res == NULL) {
+ sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(msg->sip_msg_req_res != NULL);
sip_msg_info = msg->sip_msg_req_res;
resp_code = sip_msg_info->sip_resp_code;
isreliable = sip_is_conn_reliable(conn_obj);
- (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
prev_state = sip_trans->sip_xaction_state;
switch (sip_trans->sip_xaction_state) {
case SIP_CLNT_CALLING:
@@ -1026,6 +1121,10 @@ sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,
_sip_msg_t *msg = *sip_msg;
boolean_t isreliable;
+ if (msg->sip_msg_req_res == NULL || sip_trans == NULL) {
+ sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
+ SIP_ASSERT_ERROR, __FILE__, __LINE__);
+ }
assert(msg->sip_msg_req_res != NULL);
assert(sip_trans != NULL);
@@ -1182,6 +1281,9 @@ sip_xaction_state_timer_fire(void *args)
boolean_t destroy_trans = B_FALSE;
sip_conn_object_t conn_obj;
int prev_state;
+ sip_message_type_t *msg_info;
+ int resp;
+ sip_method_t method;
assert(time_obj != NULL);
@@ -1200,6 +1302,13 @@ sip_xaction_state_timer_fire(void *args)
break;
new_msg = sip_trans->sip_xaction_last_msg;
conn_obj = sip_trans->sip_xaction_conn_obj;
+ /* timer A is for INVITE-RETRANSMIT only */
+ SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_TRUE, new_msg->
+ sip_msg_len);
+ ++sip_trans->sip_xaction_msgcnt;
+ sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
+ sip_xaction_state], new_msg, sip_trans->
+ sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
new_msg->sip_msg_len) != 0) {
sip_del_conn_obj_cache(
@@ -1210,9 +1319,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1238,9 +1348,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1261,9 +1372,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1302,6 +1414,22 @@ sip_xaction_state_timer_fire(void *args)
break;
conn_obj = sip_trans->sip_xaction_conn_obj;
new_msg = sip_trans->sip_xaction_last_msg;
+ /* Timer E is for non-INVITE request */
+
+ msg_info = new_msg->sip_msg_req_res;
+ if (msg_info == NULL || !msg_info->is_request) {
+ (void) sip_write_to_log((void *) sip_trans,
+ SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
+ __FILE__, __LINE__);
+ }
+ assert(msg_info != NULL && msg_info->is_request);
+ method = msg_info->sip_req_method;
+ SIP_UPDATE_COUNTERS(B_TRUE, method, 0, B_TRUE, new_msg->
+ sip_msg_len);
+ ++sip_trans->sip_xaction_msgcnt;
+ sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
+ sip_xaction_state], new_msg, sip_trans->
+ sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
new_msg->sip_msg_len) != 0) {
sip_del_conn_obj_cache(
@@ -1312,9 +1440,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1341,9 +1470,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1366,9 +1496,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1393,6 +1524,20 @@ sip_xaction_state_timer_fire(void *args)
}
new_msg = sip_trans->sip_xaction_last_msg;
conn_obj = sip_trans->sip_xaction_conn_obj;
+ msg_info = new_msg->sip_msg_req_res;
+ if (msg_info == NULL || msg_info->is_request) {
+ (void) sip_write_to_log((void *) sip_trans,
+ SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
+ __FILE__, __LINE__);
+ }
+ assert(msg_info != NULL && !msg_info->is_request);
+ resp = msg_info->sip_resp_code;
+ SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, new_msg->
+ sip_msg_len);
+ ++sip_trans->sip_xaction_msgcnt;
+ sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
+ sip_xaction_state], new_msg, sip_trans->
+ sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
new_msg->sip_msg_len) != 0) {
sip_del_conn_obj_cache(
@@ -1403,9 +1548,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1429,9 +1575,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,
@@ -1453,9 +1600,10 @@ sip_xaction_state_timer_fire(void *args)
(void) pthread_mutex_unlock(
&sip_trans->sip_xaction_mutex);
if (sip_xaction_ulp_state_cb != NULL) {
- sip_xaction_ulp_state_cb(
- (sip_transaction_t)sip_trans, NULL,
- prev_state, sip_trans->sip_xaction_state);
+ sip_xaction_ulp_state_cb(
+ (sip_transaction_t)sip_trans, NULL,
+ prev_state, sip_trans->
+ sip_xaction_state);
}
if (sip_xaction_ulp_trans_err != NULL) {
sip_xaction_ulp_trans_err(sip_trans, 0,