diff options
author | gm209912 <none@none> | 2008-01-15 08:42:39 -0800 |
---|---|---|
committer | gm209912 <none@none> | 2008-01-15 08:42:39 -0800 |
commit | 943efbc33954e332318b6365bf27037c05bff72c (patch) | |
tree | 3e4d8821b5482533452918abf346a5c5624a55fb /usr/src | |
parent | 347a77f277285a2c589b756c918c3f40eefbbb8b (diff) | |
download | illumos-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.com | 4 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/mapfile-vers | 10 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip.h | 72 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_dialog.c | 135 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_dialog.h | 5 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_dialog_ui.c | 24 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_itf.c | 61 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_logging.c | 638 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_miscdefs.h | 95 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_xaction.c | 25 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_xaction.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libsip/common/sip_xaction_state_mc.c | 214 |
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, |