Bläddra i källkod

Merge remote branch 'origin/tmp/k3.0_sr_backports' into sr_3.0

statistics callback support (enabled only if compiled with
-DUSE_CORE_STATS) and latest kamailio 3.0 fixes

* origin/tmp/k3.0_sr_backports:
  core: new param to give outbut buffer size
  core: use one buffer for int2str
  core: use dlflags to load modules
  uac(k): use header types for detection
  uac(k): proper test for send failure
  uac(k): set type for tm callback
  core: stats events cbs are called only if USE_CORE_STATS is defined
  update drp_reqs statistics
  update drp_rpls statistics
  update fwd_rpls statistics
  update err_reqs statistics
  update err_rpls statistics
  update bad_URIs statistics
  update bad_msg_hdr statistics
  core: update fwd_reqs stat
  kex: support to update core stats via core events
  core: added new event SREV_CORE_STATS
Andrei Pelinescu-Onciul 15 år sedan
förälder
incheckning
cdfedc3c3f
13 ändrade filer med 219 tillägg och 16 borttagningar
  1. 99 0
      core_stats.h
  2. 12 0
      events.c
  3. 2 0
      events.h
  4. 14 1
      forward.c
  5. 45 0
      modules_k/kex/core_stats.c
  6. 3 3
      modules_k/uac/auth.c
  7. 9 6
      modules_k/uac/uac_send.c
  8. 2 0
      parser/msg_parser.c
  9. 2 0
      parser/parse_uri.c
  10. 11 1
      receive.c
  11. 1 1
      sr_module.c
  12. 3 0
      ut.c
  13. 16 4
      ut.h

+ 99 - 0
core_stats.h

@@ -0,0 +1,99 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**  macros used for various core statistics.
+ *  (if USE_CORE_STATS is not defined they won't do anything)
+ * @file core_stats.h
+ * @ingroup core
+ */
+/*
+ * History:
+ * --------
+ *  2010-02-01  initial version (andrei)
+*/
+
+#ifndef __core_stats_h
+#define __core_stats_h
+
+/* define USE_CORE_STATS to enable statistics events 
+   (SREV_CORE_STATS callbacks) */
+/*#define USE_CORE_STATS */
+
+#ifndef USE_CORE_STATS
+
+#define STATS_REQ_FWD_DROP()
+#define STATS_REQ_FWD_OK()
+#define STATS_RPL_FWD_DROP()
+#define STATS_RPL_FWD_OK()
+#define STATS_BAD_MSG()
+#define STATS_BAD_RPL()
+#define STATS_BAD_URI()
+#define STATS_BAD_MSG_HDR()
+
+#else /* USE_CORE_STATS */
+
+#include "events.h"
+
+/** called each time a received request is dropped.
+ * The request might be dropped explicitly (e.g. pre script callback)
+ * or there might be an error while trying to forward it (e.g. send).
+ */
+#define STATS_REQ_FWD_DROP() sr_event_exec(SREV_CORE_STATS, (void*)3)
+
+
+/** called each time forwarding a request succeeds (send).*/
+#define STATS_REQ_FWD_OK() sr_event_exec(SREV_CORE_STATS, (void*)1)
+
+
+/** called each time forwarding a reply fails.
+ * The reply forwarding might fail due to send errors,
+ * pre script callbacks (module denying forwarding) or explicit script
+ * drop (drop or module function returning 0).
+ */
+#define STATS_RPL_FWD_DROP() sr_event_exec(SREV_CORE_STATS, (void*)4)
+
+
+/* called each time forwarding a reply succeeds. */
+#define STATS_RPL_FWD_OK() sr_event_exec(SREV_CORE_STATS, (void*)2)
+
+
+/** called each time a received request is too bad to process.
+  * For now it's called in case the message does not have any via.
+  */
+#define STATS_BAD_MSG() sr_event_exec(SREV_CORE_STATS, (void*)5)
+
+
+/** called each time a received reply is too bad to process.
+  * For now it's called in case the message does not have any via.
+  */
+#define STATS_BAD_RPL() sr_event_exec(SREV_CORE_STATS, (void*)6)
+
+
+/** called each time uri parsing fails. */
+#define STATS_BAD_URI() sr_event_exec(SREV_CORE_STATS, (void*)7)
+
+
+/** called each time parsing some header fails. */
+#define STATS_BAD_MSG_HDR() sr_event_exec(SREV_CORE_STATS, (void*)8)
+
+
+
+#endif /* USE_CORE_STATS */
+
+#endif /*__core_stats_h*/
+
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */

+ 12 - 0
events.c

@@ -48,6 +48,11 @@ int sr_event_register_cb(int type, sr_event_cb_f f)
 					_sr_events_list.net_data_out = f;
 				else return -1;
 			break;
+		case SREV_CORE_STATS:
+				if(_sr_events_list.core_stats==0)
+					_sr_events_list.core_stats = f;
+				else return -1;
+			break;
 		default:
 			return -1;
 	}
@@ -91,6 +96,13 @@ int sr_event_exec(int type, void *data)
 					return ret;
 				} else return 1;
 			break;
+		case SREV_CORE_STATS:
+				if(unlikely(_sr_events_list.core_stats!=0))
+				{
+					ret = _sr_events_list.core_stats(data);
+					return ret;
+				} else return 1;
+			break;
 		default:
 			return -1;
 	}

+ 2 - 0
events.h

@@ -25,12 +25,14 @@
 
 #define SREV_NET_DATA_IN	1
 #define SREV_NET_DATA_OUT	2
+#define SREV_CORE_STATS		3
 
 typedef int (*sr_event_cb_f)(void *data);
 
 typedef struct sr_event_cb {
 	sr_event_cb_f net_data_in;
 	sr_event_cb_f net_data_out;
+	sr_event_cb_f core_stats;
 } sr_event_cb_t;
 
 void sr_event_cb_init(void);

+ 14 - 1
forward.c

@@ -72,6 +72,7 @@
 #include "config.h"
 #include "parser/msg_parser.h"
 #include "route.h"
+#include "events.h"
 #include "dprint.h"
 #include "globals.h"
 #include "cfg_core.h"
@@ -93,6 +94,7 @@
 #include "dst_blacklist.h"
 #endif
 #include "compiler_opt.h"
+#include "core_stats.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -581,6 +583,12 @@ end:
 #endif
 	if (buf) pkg_free(buf);
 	/* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
+#if defined STATS_REQ_FWD_OK || defined STATS_REQ_FWD_DROP
+	if(ret==0)
+		STATS_REQ_FWD_OK();
+	else
+		STATS_REQ_FWD_DROP();
+#endif /* STATS_REQ_FWD_* */
 	return ret;
 }
 
@@ -733,7 +741,11 @@ int forward_reply(struct sip_msg* msg)
 				
 	} 
 #endif
-	if (msg_send(&dst, new_buf, new_len)<0) goto error;
+	if (msg_send(&dst, new_buf, new_len)<0)
+	{
+		STATS_RPL_FWD_DROP();
+		goto error;
+	}
 #ifdef STATS
 	STATS_TX_RESPONSE(  (msg->first_line.u.reply.statuscode/100) );
 #endif
@@ -742,6 +754,7 @@ int forward_reply(struct sip_msg* msg)
 			msg->via2->host.len, msg->via2->host.s,
 			(unsigned short) msg->via2->port);
 
+	STATS_RPL_FWD_OK();
 	pkg_free(new_buf);
 skip:
 	return 0;

+ 45 - 0
modules_k/kex/core_stats.c

@@ -36,6 +36,7 @@
 
 #include "../../lib/kcore/statistics.h"
 #include "../../lib/kmi/mi.h"
+#include "../../events.h"
 #include "../../dprint.h"
 #include "../../timer.h"
 #include "../../parser/msg_parser.h"
@@ -127,6 +128,49 @@ static int km_cb_rpl_stats(struct sip_msg *msg,
 	return 1;
 }
 
+
+static int sts_update_core_stats(void *data)
+{
+	int type;
+
+	type = (int)data;
+	switch(type) {
+		case 1:
+			/* fwd_requests */
+			update_stat(fwd_reqs, 1);
+		break;
+		case 2:
+			/* fwd_replies */
+			update_stat(fwd_rpls, 1);
+		break;
+		case 3:
+			/* drop_requests */
+			update_stat(drp_reqs, 1);
+		break;
+		case 4:
+			/* drop_replies */
+			update_stat(drp_rpls, 1);
+		break;
+		case 5:
+			/* err_requests */
+			update_stat(err_reqs, 1);
+		break;
+		case 6:
+			/* err_replies */
+			update_stat(err_rpls, 1);
+		break;
+		case 7:
+			/* bad_URIs_rcvd */
+			update_stat(bad_URIs, 1);
+		break;
+		case 8:
+			/* bad_msg_hdr */
+			update_stat(bad_msg_hdr, 1);
+		break;
+	}
+	return 0;
+}
+
 int register_core_stats(void)
 {
 	/* register core statistics */
@@ -147,6 +191,7 @@ int register_core_stats(void)
 		LM_ERR("failed to register PRE request callback\n");
 		return -1;
 	}
+	sr_event_register_cb(SREV_CORE_STATS, sts_update_core_stats);
 
 	return 0;
 }

+ 3 - 3
modules_k/uac/auth.c

@@ -232,9 +232,9 @@ static inline struct hdr_field *get_autenticate_hdr(struct sip_msg *rpl,
 	}
 	for( hdr=rpl->headers ; hdr ; hdr=hdr->next )
 	{
-		if((rpl_code==WWW_AUTH_CODE && hdr->type==HDR_WWW_AUTHENTICATE_T)
-				|| (rpl_code==PROXY_AUTH_CODE
-					&& hdr->type==HDR_PROXY_AUTHENTICATE_T))
+		if ( rpl_code==WWW_AUTH_CODE && hdr->type==HDR_WWW_AUTHENTICATE_T )
+			return hdr;
+		if ( rpl_code==PROXY_AUTH_CODE && hdr->type==HDR_PROXY_AUTHENTICATE_T )
 			return hdr;
 	}
 

+ 9 - 6
modules_k/uac/uac_send.c

@@ -383,11 +383,14 @@ int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
 	uac_r.method = &_uac_req.s_method;
 	uac_r.headers = (_uac_req.s_hdrs.len <= 0) ? NULL : &_uac_req.s_hdrs;
 	uac_r.body = (_uac_req.s_body.len <= 0) ? NULL : &_uac_req.s_body;
-	uac_r.cb_flags =(_uac_req.onreply > 0) ? TMCB_LOCAL_COMPLETED : 0;
-	uac_r.cb  = (_uac_req.onreply > 0) ? uac_send_tm_callback : NULL;
-	/* Callback function */
-	uac_r.cbp = (_uac_req.onreply > 0) ? (void*)(long)_uac_req.onreply : 0;
-	/* Callback parameter */
+	if(_uac_req.onreply > 0)
+	{
+		uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
+		/* Callback function */
+		uac_r.cb  = uac_send_tm_callback;
+		/* Callback parameter */
+		uac_r.cbp = (void*)(long)_uac_req.onreply;
+	}
 	ret = tmb.t_request(&uac_r,  /* UAC Req */
 						&_uac_req.s_ruri,        /* Request-URI */
 						(_uac_req.s_turi.len<=0)?&_uac_req.s_ruri:&_uac_req.s_turi, /* To */
@@ -395,7 +398,7 @@ int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
 						(_uac_req.s_ouri.len<=0)?NULL:&_uac_req.s_ouri /* outbound uri */
 		);
 
-	if(ret!=0)
+	if(ret<0)
 		return -1;
 	return 1;
 }

+ 2 - 0
parser/msg_parser.c

@@ -54,6 +54,7 @@
 #include "../data_lump_rpl.h"
 #include "../mem/mem.h"
 #include "../error.h"
+#include "../core_stats.h"
 #include "../globals.h"
 #include "parse_hname2.h"
 #include "parse_uri.h"
@@ -278,6 +279,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 	return tmp;
 error:
 	DBG("get_hdr_field: error exit\n");
+	STATS_BAD_MSG_HDR();
 	hdr->type=HDR_ERROR_T;
 	hdr->len=tmp-hdr->name.s;
 	return tmp;

+ 2 - 0
parser/parse_uri.c

@@ -50,6 +50,7 @@
 #include "../ut.h"   /* q_memchr */
 /* #endif */
 #include "../error.h"
+#include "../core_stats.h"
 
 /* buf= pointer to begining of uri (sip:[email protected]:5060;a=b?h=i)
  * len= len of uri
@@ -1223,6 +1224,7 @@ error_bug:
 error_exit:
 	ser_error=E_BAD_URI;
 	uri->type=ERROR_URI_T;
+	STATS_BAD_URI();
 	return E_BAD_URI;
 }
 

+ 11 - 1
receive.c

@@ -64,6 +64,7 @@
 #include "tcp_server.h" /* for tcpconn_add_alias */
 #include "tcp_options.h" /* for access to tcp_accept_aliases*/
 #include "cfg/cfg.h"
+#include "core_stats.h"
 
 #ifdef DEBUG_DMALLOC
 #include <mem/dmalloc.h>
@@ -149,6 +150,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
 			/* no via, send back error ? */
 			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
+			STATS_BAD_MSG();
 			goto error02;
 		}
 		/* check if necessary to add receive?->moved to forward_req */
@@ -182,7 +184,10 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		   on via1 being parsed in a pre-script callback --andrei
 		*/
 		if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
+		{
+			STATS_REQ_FWD_DROP();
 			goto end; /* drop the request */
+		}
 
 		set_route_type(REQUEST_ROUTE);
 		/* exec the routing script */
@@ -208,6 +213,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
 			/* no via, send back error ? */
 			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
+			STATS_BAD_RPL();
 			goto error02;
 		}
 
@@ -224,7 +230,10 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		   on via1 being parsed in a pre-script callback --andrei
 		*/
 		if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
-			goto end; /* drop the request */
+		{
+			STATS_RPL_FWD_DROP();
+			goto end; /* drop the reply */
+		}
 
 		/* exec the onreply routing script */
 		if (onreply_rt.rlist[DEFAULT_RT]){
@@ -238,6 +247,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 			}else
 #endif /* NO_ONREPLY_ROUTE_ERROR */
 			if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
+				STATS_RPL_FWD_DROP();
 				goto skip_send_reply; /* drop the message, no error */
 			}
 		}

+ 1 - 1
sr_module.c

@@ -384,7 +384,7 @@ int load_module(char* mod_path)
 	retries=2;
 	dlflags=RTLD_NOW;
 reload:
-	handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
+	handle=dlopen(path, dlflags); /* resolve all symbols now */
 	if (handle==0){
 		LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
 			path, dlerror());

+ 3 - 0
ut.c

@@ -42,6 +42,9 @@
 #include "mem/mem.h"
 #include "globals.h"
 
+/* global buffer for ut.h int2str() */
+char ut_buf_int2str[INT2STR_MAX_LEN];
+
 
 /* converts a username into uid:gid,
  * returns -1 on error & 0 on success */

+ 16 - 4
ut.h

@@ -292,12 +292,17 @@ static inline char* int2str_base(unsigned int l, int* len, int base)
 
 
 
-/* returns a pointer to a static buffer containing l in asciiz & sets len */
-static inline char* int2str(unsigned int l, int* len)
+/* print int to asciiz in a string buffer
+ * - be sure result buffer is at least INT2STR_MAX_LEN in size */
+static inline char* int2strbuf(unsigned int l, char *r, int r_size, int* len)
 {
-	static char r[INT2STR_MAX_LEN];
 	int i;
-	
+
+	if(unlikely(r_size<INT2STR_MAX_LEN)) {
+		if (len)
+			*len = 0;
+		return 0; /* => if someone misuses it => crash (feature no. 1) */
+	}
 	i=INT2STR_MAX_LEN-2;
 	r[INT2STR_MAX_LEN-1]=0; /* null terminate */
 	do{
@@ -312,6 +317,13 @@ static inline char* int2str(unsigned int l, int* len)
 	return &r[i+1];
 }
 
+extern char ut_buf_int2str[INT2STR_MAX_LEN];
+/* returns a pointer to a static buffer containing l in asciiz & sets len */
+static inline char* int2str(unsigned long l, int* len)
+{
+	return int2strbuf(l, ut_buf_int2str, INT2STR_MAX_LEN, len);
+}
+
 /* Signed INTeger-TO-STRing: convers a long to a string
  * returns a pointer to a static buffer containing l in asciiz & sets len */
 static inline char* sint2str(long l, int* len)