Merge remote branch 'origin/tmp/k3.0_sr_backports' into sr_3.0
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Wed, 3 Feb 2010 22:09:26 +0000 (23:09 +0100)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Wed, 3 Feb 2010 22:09:56 +0000 (23:09 +0100)
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

13 files changed:
core_stats.h [new file with mode: 0644]
events.c
events.h
forward.c
modules_k/kex/core_stats.c
modules_k/uac/auth.c
modules_k/uac/uac_send.c
parser/msg_parser.c
parser/parse_uri.c
receive.c
sr_module.c
ut.c
ut.h

diff --git a/core_stats.h b/core_stats.h
new file mode 100644 (file)
index 0000000..729d73e
--- /dev/null
@@ -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: */
index 0d07395..be98221 100644 (file)
--- a/events.c
+++ b/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;
        }
index 9fda619..9af0d71 100644 (file)
--- a/events.h
+++ b/events.h
 
 #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);
index d7fb827..4b88780 100644 (file)
--- a/forward.c
+++ b/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;
index 121bb15..466dd11 100644 (file)
@@ -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;
 }
index 78f51d5..0fb3e25 100644 (file)
@@ -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;
        }
 
index bd33795..b77317d 100644 (file)
@@ -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;
 }
index 8f3b163..1cb530c 100644 (file)
@@ -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;
index 741258e..47cb1bc 100644 (file)
@@ -50,6 +50,7 @@
 #include "../ut.h"   /* q_memchr */
 /* #endif */
 #include "../error.h"
+#include "../core_stats.h"
 
 /* buf= pointer to begining of uri (sip:x@foo.bar: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;
 }
 
index 49c7c0b..2496e41 100644 (file)
--- a/receive.c
+++ b/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 */
                        }
                }
index b8db2c7..d5dc322 100644 (file)
@@ -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());
diff --git a/ut.c b/ut.c
index 7c63941..11d4fe7 100644 (file)
--- a/ut.c
+++ b/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 */
diff --git a/ut.h b/ut.h
index 6861af7..3d98e11 100644 (file)
--- a/ut.h
+++ b/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)